File

projects/cobbler-frontend/src/app/signatures/signatures.component.ts

Description

Food data with nested structure. Each node has a name and an optional list of children.

Index

Properties

Properties

children
children: OsNode[]
Type : OsNode[]
Optional
data
data: string | Array<TableRow>
Type : string | Array<TableRow>
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { MatDivider } from '@angular/material/divider';
import { MatList, MatListItem } from '@angular/material/list';
import { MatProgressSpinner } from '@angular/material/progress-spinner';
import { MatSnackBar } from '@angular/material/snack-bar';
import {
  MatCell,
  MatCellDef,
  MatColumnDef,
  MatHeaderCell,
  MatHeaderCellDef,
  MatHeaderRow,
  MatHeaderRowDef,
  MatRow,
  MatRowDef,
  MatTable,
} from '@angular/material/table';
import { filter, repeat, take, takeUntil } from 'rxjs/operators';
import { UserService } from '../services/user.service';
import { CobblerApiService } from 'cobbler-api';
import {
  MatTree,
  MatTreeFlatDataSource,
  MatTreeFlattener,
  MatTreeNode,
  MatTreeNodeDef,
  MatTreeNodePadding,
  MatTreeNodeToggle,
} from '@angular/material/tree';
import { FlatTreeControl } from '@angular/cdk/tree';
import { MatIcon } from '@angular/material/icon';
import { MatIconButton } from '@angular/material/button';
import { Subject } from 'rxjs';
import Utils from '../utils';

interface TableRow {
  key: string;
  value: any;
}

/**
 * Food data with nested structure.
 * Each node has a name and an optional list of children.
 */
interface OsNode {
  data: string | Array<TableRow>;
  children?: OsNode[];
}

/** Flat node with expandable and level information */
interface OsBreedFlatNode {
  expandable: boolean;
  data: string | Array<TableRow>;
  level: number;
}

@Component({
  selector: 'cobbler-signatures',
  standalone: true,
  imports: [
    MatTree,
    MatTreeNode,
    MatIcon,
    MatIconButton,
    MatTreeNodeToggle,
    MatTreeNodePadding,
    MatTreeNodeDef,
    MatTable,
    MatHeaderCell,
    MatCell,
    MatHeaderRow,
    MatRow,
    MatColumnDef,
    MatHeaderCellDef,
    MatCellDef,
    MatHeaderRowDef,
    MatRowDef,
    MatDivider,
    AsyncPipe,
    MatList,
    MatListItem,
    MatProgressSpinner,
    NgForOf,
    NgIf,
  ],
  templateUrl: './signatures.component.html',
  styleUrl: './signatures.component.scss',
})
export class SignaturesComponent implements OnInit, OnDestroy {
  // Unsubscribe
  private ngUnsubscribe = new Subject<void>();

  // Table
  columns = [
    {
      columnDef: 'key',
      header: 'Attribute',
      cell: (element: TableRow) => `${element.key}`,
    },
    {
      columnDef: 'value',
      header: 'Value',
      cell: (element: TableRow) => `${element.value}`,
    },
  ];

  displayedColumns = this.columns.map((c) => c.columnDef);

  // Tree
  private _transformer = (node: OsNode, level: number) => {
    return {
      expandable: !!node.children && node.children.length > 0,
      data: node.data,
      level: level,
    };
  };

  treeControl = new FlatTreeControl<OsBreedFlatNode>(
    (node) => node.level,
    (node) => node.expandable,
  );

  treeFlattener = new MatTreeFlattener(
    this._transformer,
    (node) => node.level,
    (node) => node.expandable,
    (node) => node.children,
  );
  dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

  // Spinner
  public isLoading = true;

  constructor(
    public userService: UserService,
    private cobblerApiService: CobblerApiService,
    private _snackBar: MatSnackBar,
  ) {}

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

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

  hasChild = (_: number, node: OsBreedFlatNode) => node.expandable;

  hasOsVersion = (_: number, node: OsBreedFlatNode) =>
    typeof node.data !== 'string';

  generateSignatureUiData(): void {
    this.cobblerApiService
      .get_signatures(this.userService.token)
      .pipe(takeUntil(this.ngUnsubscribe))
      .subscribe(
        (value) => {
          const newData: Array<OsNode> = [];
          for (const k in value.breeds) {
            const children: Array<OsNode> = [];
            for (const j in value.breeds[k]) {
              const osVersionData: Array<TableRow> = [];
              for (const i in value.breeds[k][j]) {
                osVersionData.push({ key: i, value: value.breeds[k][j][i] });
              }
              children.push({
                data: j,
                children: [{ data: osVersionData, children: [] }],
              });
            }
            newData.push({ data: k, children: children });
          }
          this.dataSource.data = newData;
          this.isLoading = false;
        },
        (error) => {
          // HTML encode the error message since it originates from XML
          this._snackBar.open(Utils.toHTML(error.message), 'Close');
        },
      );
  }

  updateSignatures(): void {
    this.isLoading = true;
    this.cobblerApiService
      .background_signature_update(this.userService.token)
      .pipe(takeUntil(this.ngUnsubscribe))
      .subscribe(
        (value) => {
          this.cobblerApiService
            .get_task_status(value)
            .pipe(
              repeat(),
              filter(
                (data) => data.state === 'failed' || data.state === 'complete',
              ),
              take(1),
            )
            .subscribe((value1) => {
              this.isLoading = false;
              this.generateSignatureUiData();
            });
        },
        (error) => {
          // HTML encode the error message since it originates from XML
          this._snackBar.open(Utils.toHTML(error.message), 'Close');
        },
      );
  }
}

results matching ""

    No results matching ""