Refactor groups component to update filter option value and improve client status display

pull/10/head
Alvaro Puente Mella 2024-12-05 15:18:16 +01:00
commit 7dcb6ecb1c
5 changed files with 98 additions and 65 deletions

View File

@ -186,7 +186,6 @@ button[mat-raised-button] {
mat-tree { mat-tree {
background-color: #f9f9f9; background-color: #f9f9f9;
border-right: 1px solid #ddd;
padding: 10px; padding: 10px;
} }
@ -317,29 +316,34 @@ mat-tree mat-tree-node.disabled:hover {
margin-bottom: 16px; margin-bottom: 16px;
} }
.pc-og-live { .chip-busy {
color: #4caf50; background-color: indianred !important;
color: black;
} }
.pc-busy { .chip-og-live {
color: #ff9800; background-color: yellow !important;
color: black;
} }
.pc-windows { .chip-windows,
color: #0078d7; .chip-windows-session,
.chip-macos {
background-color: cornflowerblue !important;
color: white;
} }
.pc-linux { .chip-linux,
color: #f0ad4e; .chip-linux-session {
background-color: mediumpurple !important;
color: white;
} }
.pc-macos { .chip-off {
color: #999999; background-color: darkgrey !important;
color: white;
} }
.pc-off {
color: #f44336;
}
.clients-card-container { .clients-card-container {
display: flex; display: flex;
@ -553,7 +557,30 @@ button[mat-raised-button] {
padding: 0 16px; padding: 0 16px;
} }
.mat-elevation-z8 {
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
}
.filters-container mat-form-field { .filters-container mat-form-field {
flex: 1 1 300px; flex: 1 1 300px;
max-width: 300px; max-width: 300px;
} }
.client-info {
display: flex;
flex-direction: column;
gap: 3px;
margin: 5px;
}
.client-name {
font-size: 16px;
font-weight: bold;
}
.flex {
display: flex;
justify-self: center;
align-items: center;
}

View File

@ -49,7 +49,7 @@
<mat-option value="group">{{ 'computerGroups' | translate }}</mat-option> <mat-option value="group">{{ 'computerGroups' | translate }}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
</mat-expansion-panel> </mat-expansion-panel>
@ -159,6 +159,8 @@
</mat-tree-node> </mat-tree-node>
</mat-tree> </mat-tree>
</div> </div>
<mat-divider [vertical]="true"></mat-divider>
<mat-menu restoreFocus=false #commandMenu="matMenu"> <mat-menu restoreFocus=false #commandMenu="matMenu">
<button mat-menu-item *ngFor="let command of commands" (click)="executeCommand(command, selectedNode)"> <button mat-menu-item *ngFor="let command of commands" (click)="executeCommand(command, selectedNode)">
<span>{{ command.name }}</span> <span>{{ command.name }}</span>
@ -203,23 +205,33 @@
<div class="client-details"> <div class="client-details">
<span class="client-name">{{ client.name }}</span> <span class="client-name">{{ client.name }}</span>
<span class="client-ip">{{ client.ip }}</span> <span class="client-ip">{{ client.ip }}</span>
<mat-chip [ngClass]="{ <div class="flex">
'chip-og-live': client.status === 'og-live', <mat-chip [ngClass]="{
'chip-busy': client.status === 'busy', 'chip-og-live': client.status === 'og-live',
'chip-windows': client.status === 'windows' || client.status === 'windows-session', 'chip-busy': client.status === 'busy',
'chip-linux': client.status === 'linux' || client.status === 'linux-session', 'chip-windows': client.status === 'windows' || client.status === 'windows-session',
'chip-macos': client.status === 'macos', 'chip-linux': client.status === 'linux' || client.status === 'linux-session',
'chip-off': client.status === 'off' 'chip-macos': client.status === 'macos',
}"> 'chip-off': client.status === 'off'
{{ client.status || 'off' }} }">
</mat-chip> {{ client.status || 'off' }}
<button mat-raised-button color="primary" [matMenuTriggerFor]="clientMenu">Acciones</button>
<mat-menu #clientMenu="matMenu"> </mat-chip>
<button mat-menu-item *ngIf="(!syncStatus || syncingClientId !== client.uuid)" (click)="getStatus(client)"> <button
*ngIf="(!syncStatus || syncingClientId !== client.uuid)"
mat-icon-button color="primary"
(click)="getStatus(client)">
<mat-icon>sync</mat-icon> <mat-icon>sync</mat-icon>
<span>{{ 'sync' | translate }}</span>
</button> </button>
<button
*ngIf="syncStatus && syncingClientId === client.uuid"
mat-icon-button color="primary">
<mat-spinner diameter="24"></mat-spinner>
</button>
</div>
<button mat-raised-button color="primary" [matMenuTriggerFor]="clientMenu">Acciones</button>
<mat-menu #clientMenu="matMenu">
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)"> <button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
<span>{{ 'edit' | translate }}</span> <span>{{ 'edit' | translate }}</span>
@ -236,25 +248,22 @@
</div> </div>
</div> </div>
</div> </div>
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
</div> </div>
<div class="clients-table" *ngIf="currentView === 'list'"> <div class="clients-table" *ngIf="currentView === 'list'">
<table mat-table matSort [dataSource]="selectedClients" class="mat-elevation-z8"> <table mat-table matSort [dataSource]="selectedClients" class="mat-elevation-z8">
<ng-container matColumnDef="name"> <ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'name' | translate }} </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'name' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.name }} </td> <td mat-cell *matCellDef="let client">
</ng-container> <div class="client-info">
<ng-container matColumnDef="ip"> <div class="client-name">{{ client.name }}</div>
<th mat-header-cell *matHeaderCellDef mat-sort-header> IP </th> <div class="client-ip">{{ client.ip }}</div>
<td mat-cell *matCellDef="let client"> {{ client.ip }} </td> <div class="client-ip">{{ client.mac }}</div>
</ng-container> </div>
<ng-container matColumnDef="mac"> </td>
<th mat-header-cell *matHeaderCellDef mat-sort-header> MAC </th>
<td mat-cell *matCellDef="let client"> {{ client.mac }} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="oglive"> <ng-container matColumnDef="oglive">
<th mat-header-cell *matHeaderCellDef mat-sort-header> OG Live </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> OG Live </th>
<td mat-cell *matCellDef="let client"> {{ client.oglive }} </td> <td mat-cell *matCellDef="let client"> {{ client.ogLive?.name }} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="status"> <ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'status' | translate }} </th>
@ -268,12 +277,25 @@
'chip-off': client.status === 'off' 'chip-off': client.status === 'off'
}"> }">
{{ client.status || 'off' }} {{ client.status || 'off' }}
</mat-chip> </mat-chip>
<button
*ngIf="(!syncStatus || syncingClientId !== client.uuid)"
mat-icon-button color="primary"
(click)="getStatus(client)">
<mat-icon>sync</mat-icon>
</button>
<button
*ngIf="syncStatus && syncingClientId === client.uuid"
mat-icon-button color="primary">
<mat-spinner diameter="24"></mat-spinner>
</button>
</td> </td>
</ng-container> </ng-container>
<ng-container matColumnDef="maintenace"> <ng-container matColumnDef="maintenace">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'maintenance' | translate }} </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'maintenance' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.mantenimiento }} </td> <td mat-cell *matCellDef="let client"> {{ client.maintenance }} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="subnet"> <ng-container matColumnDef="subnet">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'subnet' | translate }} </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'subnet' | translate }} </th>
@ -281,14 +303,14 @@
</ng-container> </ng-container>
<ng-container matColumnDef="pxeTemplate"> <ng-container matColumnDef="pxeTemplate">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'pxeTemplate' | translate }} </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'pxeTemplate' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.pxeTemplate }} </td> <td mat-cell *matCellDef="let client"> {{ client.template?.name }} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="parentName"> <ng-container matColumnDef="parentName">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'parent' | translate }} </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'parent' | translate }} </th>
<td mat-cell *matCellDef="let client"> {{ client.parentName }} </td> <td mat-cell *matCellDef="let client"> {{ client.parentName }} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="actions"> <ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'actions' | translate }} </th> <th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'actions' | translate }} </th>
<td mat-cell *matCellDef="let client"> <td mat-cell *matCellDef="let client">
@ -300,22 +322,6 @@
<mat-menu #clientMenu="matMenu"> <mat-menu #clientMenu="matMenu">
<mat-menu restoreFocus=false #commandMenu="matMenu" xPosition="before">
<button mat-menu-item *ngFor="let command of commands" (click)="executeCommand(command, client)">
<span>{{ command.name }}</span>
</button>
</mat-menu>
<button mat-menu-item [matMenuTriggerFor]="commandMenu" (click)="fetchCommands()">
<mat-icon>play_arrow</mat-icon>
<span>{{ 'executeCommand' | translate }}</span>
</button>
<button mat-menu-item *ngIf="(!syncStatus || syncingClientId !== client.uuid)" (click)="getStatus(client)">
<mat-icon>sync</mat-icon>
<span>{{ 'sync' | translate }}</span>
</button>
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)"> <button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
<mat-icon>edit</mat-icon> <mat-icon>edit</mat-icon>
<span>{{ 'edit' | translate }}</span> <span>{{ 'edit' | translate }}</span>

View File

@ -63,9 +63,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
syncingClientId: string | null = null; syncingClientId: string | null = null;
private originalTreeData: TreeNode[] = []; private originalTreeData: TreeNode[] = [];
displayedColumns: string[] = ['name', 'oglive', 'status', 'maintenace', 'subnet', 'pxeTemplate', 'parentName', 'actions'];
displayedColumns: string[] = ['name', 'ip', 'mac', 'oglive', 'status', 'maintenace', 'subnet', 'pxeTemplate', 'parentName', 'actions'];
private _sort!: MatSort; private _sort!: MatSort;
private _paginator!: MatPaginator; private _paginator!: MatPaginator;
@ -233,7 +231,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
...client, ...client,
parentName: node.name parentName: node.name
})); }));
if (node.children) { if (node.children) {
node.children.forEach((child) => { node.children.forEach((child) => {
clients = clients.concat(this.collectAllClients(child).map(client => ({ clients = clients.concat(this.collectAllClients(child).map(client => ({
@ -244,7 +242,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
} }
return clients; return clients;
} }
private async loadChildrenAndClients(id: string): Promise<UnidadOrganizativa> { private async loadChildrenAndClients(id: string): Promise<UnidadOrganizativa> {
try { try {
@ -310,7 +308,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
this.selectedClients._updateChangeSubscription(); this.selectedClients._updateChangeSubscription();
} }
} }
getNodeIcon(node: TreeNode): string { getNodeIcon(node: TreeNode): string {
switch (node.type) { switch (node.type) {
case NodeType.OrganizationalUnit: case NodeType.OrganizationalUnit:

View File

@ -399,6 +399,7 @@
"ogLive": "ogLive", "ogLive": "ogLive",
"TOOLTIP_PXE_IMAGES": "View available PXE boot images", "TOOLTIP_PXE_IMAGES": "View available PXE boot images",
"pxeTemplates": "PXE Templates", "pxeTemplates": "PXE Templates",
"pxeTemplate" : "Plantilla",
"TOOLTIP_PXE_TEMPLATES": "Manage PXE boot templates", "TOOLTIP_PXE_TEMPLATES": "Manage PXE boot templates",
"pxeBootFiles": "PXE Boot Files", "pxeBootFiles": "PXE Boot Files",
"TOOLTIP_PXE_BOOT_FILES": "Configure PXE boot files", "TOOLTIP_PXE_BOOT_FILES": "Configure PXE boot files",

View File

@ -401,6 +401,7 @@
"ogLive": "ogLive", "ogLive": "ogLive",
"TOOLTIP_PXE_IMAGES": "Ver imágenes disponibles para arranque PXE", "TOOLTIP_PXE_IMAGES": "Ver imágenes disponibles para arranque PXE",
"pxeTemplates": "Plantillas PXE", "pxeTemplates": "Plantillas PXE",
"pxeTemplate": "Plantilla",
"TOOLTIP_PXE_TEMPLATES": "Gestionar plantillas de arranque PXE", "TOOLTIP_PXE_TEMPLATES": "Gestionar plantillas de arranque PXE",
"pxeBootFiles": "Arranque PXE", "pxeBootFiles": "Arranque PXE",
"TOOLTIP_PXE_BOOT_FILES": "Configurar archivos de arranque PXE", "TOOLTIP_PXE_BOOT_FILES": "Configurar archivos de arranque PXE",