310 lines
15 KiB
HTML
310 lines
15 KiB
HTML
<div class="header-container" joyrideStep="tabsStep" text="{{ 'tabsStepText' | translate }}">
|
|
<button mat-icon-button color="primary" (click)="iniciarTour()">
|
|
<mat-icon>help</mat-icon>
|
|
</button>
|
|
<h2 class="title" joyrideStep="groupsTitleStepText" text="{{ 'groupsTitleStepText' | translate }}">
|
|
{{ 'adminGroupsTitle' | translate }}
|
|
</h2>
|
|
<div class="groups-button-row" joyrideStep="addStep" text="{{ 'groupsAddStepText' | translate }}">
|
|
<button mat-flat-button color="primary" (click)="addOU($event)"
|
|
matTooltip="{{ 'newOrganizationalUnitTooltip' | translate }}" matTooltipShowDelay="1000">
|
|
{{ 'newOrganizationalUnitButton' | translate }}
|
|
</button>
|
|
<button mat-flat-button color="primary" (click)="addClient($event)" matTooltipShowDelay="1000">
|
|
{{ 'newClientButton' | translate }}
|
|
</button>
|
|
<button mat-flat-button (click)="openBottomSheet()" joyrideStep="keyStep" text="{{ 'keyStepText' | translate }}"
|
|
matTooltipShowDelay="1000">
|
|
{{ 'legendButton' | translate }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<mat-expansion-panel *ngIf="isTreeViewActive" class="filters-panel">
|
|
<mat-expansion-panel-header>
|
|
<mat-panel-title>Filtros</mat-panel-title>
|
|
</mat-expansion-panel-header>
|
|
<div class="filters-container">
|
|
<mat-form-field appearance="outline">
|
|
<mat-select (selectionChange)="loadSelectedFilter($event.value)" placeholder="Cargar filtro">
|
|
<mat-option *ngFor="let savedFilter of savedFilterNames" [value]="savedFilter">
|
|
{{ savedFilter[0] }}
|
|
</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Buscar en el árbol</mat-label>
|
|
<input matInput (input)="onTreeFilterInput($event)" placeholder="Buscar nombre o tipo">
|
|
</mat-form-field>
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Filtrar por tipo</mat-label>
|
|
<mat-select [(value)]="selectedTreeFilter" (selectionChange)="filterTree(searchTerm, $event.value)">
|
|
<mat-option [value]="">Todos</mat-option>
|
|
<mat-option value="organizational-unit">Grupos de aulas</mat-option>
|
|
<mat-option value="classroom">Aulas</mat-option>
|
|
<mat-option value="group">Grupos de ordenadores</mat-option>
|
|
</mat-select>
|
|
</mat-form-field>
|
|
<mat-form-field appearance="outline">
|
|
<mat-label>Buscar cliente</mat-label>
|
|
<input matInput (input)="onClientFilterInput($event)" placeholder="Buscar nombre, IP, estado o MAC">
|
|
</mat-form-field>
|
|
</div>
|
|
</mat-expansion-panel>
|
|
|
|
<div *ngIf="!selectedUnidad; else detailsTemplate" class="card-container">
|
|
<mat-card *ngFor="let unidad of organizationalUnits"
|
|
[ngClass]="{'selected-item': unidad === selectedUnidad, 'clickable-item': true}"
|
|
(click)="onSelectUnidad(unidad)" class="unidad-card small-card">
|
|
<mat-card-header>
|
|
<mat-card-title>
|
|
<mat-icon>apartment</mat-icon> {{ unidad.name }}
|
|
</mat-card-title>
|
|
</mat-card-header>
|
|
<mat-card-actions>
|
|
<div class="button-container">
|
|
<button mat-raised-button color="primary" [matMenuTriggerFor]="menu" (click)="$event.stopPropagation()">
|
|
<mat-icon>menu</mat-icon>
|
|
{{ 'Menu' | translate }}
|
|
</button>
|
|
</div>
|
|
<mat-menu #menu="matMenu">
|
|
<button mat-menu-item (click)="onEditClick($event, unidad.type, unidad.uuid)">
|
|
<mat-icon matTooltip="{{ 'editUnitTooltip' | translate }}" matTooltipHideDelay="0">edit</mat-icon>
|
|
<span>{{ 'editUnitMenu' | translate }}</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onShowDetailsClick($event, unidad)">
|
|
<mat-icon matTooltip="{{ 'viewUnitTooltip' | translate }}" matTooltipHideDelay="0">visibility</mat-icon>
|
|
<span>{{ 'viewUnitMenu' | translate }}</span>
|
|
</button>
|
|
<button mat-menu-item (click)="addOU($event, unidad)">
|
|
<mat-icon matTooltip="{{ 'addInternalUnitTooltip' | translate }}" matTooltipHideDelay="0">add_home_work</mat-icon>
|
|
<span>{{ 'addInternalUnitMenu' | translate }}</span>
|
|
</button>
|
|
<button mat-menu-item (click)="addClient($event, unidad)">
|
|
<mat-icon matTooltip="{{ 'addClientTooltip' | translate }}" matTooltipHideDelay="0">devices</mat-icon>
|
|
<span>{{ 'addClientMenu' | translate }}</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onTreeClick($event, unidad)">
|
|
<mat-icon matTooltip="{{ 'viewTreeTooltip' | translate }}" matTooltipHideDelay="0">account_tree</mat-icon>
|
|
<span>{{ 'viewTreeMenu' | translate }}</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onDeleteClick($event, unidad)">
|
|
<mat-icon>delete</mat-icon>
|
|
<span>Delete</span>
|
|
</button>
|
|
</mat-menu>
|
|
</mat-card-actions>
|
|
</mat-card>
|
|
</div>
|
|
|
|
<ng-template #detailsTemplate>
|
|
<div class="header-actions-container">
|
|
<button mat-raised-button color="primary" (click)="clearSelection()" class="back-button">
|
|
<mat-icon>arrow_back</mat-icon>
|
|
{{ 'Back' | translate }}
|
|
</button>
|
|
<div class="view-toggle-container" *ngIf="selectedDetail">
|
|
<button mat-button color="primary" (click)="toggleView('card')" [disabled]="currentView === 'card'">
|
|
<mat-icon>grid_view</mat-icon> {{ 'Vista Tarjeta' | translate }}
|
|
</button>
|
|
<button mat-button color="primary" (click)="toggleView('list')" [disabled]="currentView === 'list'">
|
|
<mat-icon>list</mat-icon> {{ 'Vista Lista' | translate }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="main-container">
|
|
<div class="tree-container">
|
|
<h2>{{ selectedUnidad?.name }}</h2>
|
|
<mat-tree [dataSource]="treeDataSource" [treeControl]="treeControl">
|
|
<mat-tree-node [ngClass]="{'selected-node': node === selectedNode}" *matTreeNodeDef="let node; when: hasChild" matTreeNodePadding (click)="onNodeClick(node)">
|
|
<button mat-icon-button matTreeNodeToggle [disabled]="!node.expandable" [ngClass]="{'disabled-toggle': !node.expandable}">
|
|
<mat-icon>{{ treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}</mat-icon>
|
|
</button>
|
|
<mat-icon class="node-icon {{ node.type }}">
|
|
{{
|
|
node.type === 'organizational-unit' ? 'apartment'
|
|
: node.type === 'classrooms-group' ? 'meeting_room'
|
|
: node.type === 'classroom' ? 'school'
|
|
: node.type === 'clients-group' ? 'lan'
|
|
: node.type === 'client' ? 'computer'
|
|
: 'group'
|
|
}}
|
|
</mat-icon>
|
|
<span>{{ node.name }}</span>
|
|
<button mat-icon-button [matMenuTriggerFor]="menu" (click)="setSelectedNode(node); $event.stopPropagation()">
|
|
<mat-icon>more_vert</mat-icon>
|
|
</button>
|
|
</mat-tree-node>
|
|
<mat-tree-node [ngClass]="{'selected-node': node === selectedNode}" *matTreeNodeDef="let node; when: isLeafNode" matTreeNodePadding (click)="onNodeClick(node)">
|
|
<button mat-icon-button matTreeNodeToggle [disabled]="true" class="disabled-toggle"></button>
|
|
<mat-icon style="color: green;">
|
|
{{
|
|
node.type === 'organizational-unit' ? 'apartment'
|
|
: node.type === 'classrooms-group' ? 'meeting_room'
|
|
: node.type === 'classroom' ? 'school'
|
|
: node.type === 'clients-group' ? 'lan'
|
|
: node.type === 'client' ? 'computer'
|
|
: 'group'
|
|
}}
|
|
</mat-icon>
|
|
<span>{{ node.name }}</span>
|
|
<ng-container *ngIf="node.type === 'client'">
|
|
<span> - IP: {{ node.ip }}</span>
|
|
</ng-container>
|
|
<button mat-icon-button [matMenuTriggerFor]="menu" (click)="setSelectedNode(node)">
|
|
<mat-icon>more_vert</mat-icon>
|
|
</button>
|
|
</mat-tree-node>
|
|
</mat-tree>
|
|
</div>
|
|
<mat-menu restoreFocus=false #commandMenu="matMenu">
|
|
<button mat-menu-item *ngFor="let command of commands" (click)="executeCommand(command, selectedNode)">
|
|
<span>{{ command.name }}</span>
|
|
</button>
|
|
</mat-menu>
|
|
<mat-menu #menu="matMenu">
|
|
<button *ngIf="selectedNode?.type === 'classroom'" mat-menu-item [matMenuTriggerFor]="commandMenu" (click)="fetchCommands()">
|
|
<mat-icon>play_arrow</mat-icon>
|
|
<span>Ejecutar Comando</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onShowDetailsClick($event, selectedNode)">
|
|
<mat-icon matTooltip="{{ 'viewUnitTooltip' | translate }}" matTooltipHideDelay="0">visibility</mat-icon>
|
|
<span>{{ 'viewUnitMenu' | translate }}</span>
|
|
</button>
|
|
<button *ngIf="selectedNode?.type === 'classroom'" mat-menu-item (click)="onRoomMap(selectedNode)">
|
|
<mat-icon>map</mat-icon>
|
|
<span>Plano aula</span>
|
|
</button>
|
|
<button mat-menu-item (click)="addClient($event, selectedNode)">
|
|
<mat-icon>add</mat-icon>
|
|
<span>Añadir clientes</span>
|
|
</button>
|
|
<button mat-menu-item (click)="addOU($event, selectedNode)">
|
|
<mat-icon>playlist_add</mat-icon>
|
|
<span>Añadir unidad organizativa</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onEditNode($event, selectedNode)">
|
|
<mat-icon>edit</mat-icon>
|
|
<span>Edit</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onDeleteClick($event, selectedNode)">
|
|
<mat-icon>delete</mat-icon>
|
|
<span>Delete</span>
|
|
</button>
|
|
</mat-menu>
|
|
<div class="clients-container" *ngIf="selectedClients.length > 0">
|
|
<h3>Clientes {{ selectedNode?.name ? 'del ' + selectedNode?.name : '' }}</h3>
|
|
<div class="clients-grid" *ngIf="currentView === 'card'">
|
|
<div *ngFor="let client of selectedClients" class="client-item">
|
|
<div class="client-card">
|
|
<img src="assets/images/client.png" alt="Client Icon" class="client-image" />
|
|
<div class="client-details">
|
|
<span class="client-name">{{ client.name }}</span>
|
|
<span class="client-ip">{{ client.ip }}</span>
|
|
<mat-chip [ngClass]="{
|
|
'chip-og-live': client.status === 'og-live',
|
|
'chip-busy': client.status === 'busy',
|
|
'chip-windows': client.status === 'windows' || client.status === 'windows-session',
|
|
'chip-linux': client.status === 'linux' || client.status === 'linux-session',
|
|
'chip-macos': client.status === 'macos',
|
|
'chip-off': client.status === 'off'
|
|
}">
|
|
{{ client.status || 'off' }}
|
|
</mat-chip>
|
|
<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)">
|
|
<mat-icon>edit</mat-icon>
|
|
<span>Edit</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onShowClientDetail($event, client)">
|
|
<mat-icon>visibility</mat-icon>
|
|
<span>Ver detalles</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onDeleteClick($event, client, selectedNode)">
|
|
<mat-icon>delete</mat-icon>
|
|
<span>Delete</span>
|
|
</button>
|
|
</mat-menu>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
|
|
</div>
|
|
<div class="clients-table" *ngIf="currentView === 'list'">
|
|
<table mat-table [dataSource]="selectedClients" class="mat-elevation-z8">
|
|
<ng-container matColumnDef="name">
|
|
<th mat-header-cell *matHeaderCellDef> Nombre </th>
|
|
<td mat-cell *matCellDef="let client"> {{ client.name }} </td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="ip">
|
|
<th mat-header-cell *matHeaderCellDef> IP </th>
|
|
<td mat-cell *matCellDef="let client"> {{ client.ip }} </td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="mac">
|
|
<th mat-header-cell *matHeaderCellDef> MAC </th>
|
|
<td mat-cell *matCellDef="let client"> {{ client.mac }} </td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="oglive">
|
|
<th mat-header-cell *matHeaderCellDef> OG Live </th>
|
|
<td mat-cell *matCellDef="let client"> {{ client.oglive }} </td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="status">
|
|
<th mat-header-cell *matHeaderCellDef> Estado </th>
|
|
<td mat-cell *matCellDef="let client">
|
|
<mat-chip [ngClass]="{
|
|
'chip-og-live': client.status === 'og-live',
|
|
'chip-busy': client.status === 'busy',
|
|
'chip-windows': client.status === 'windows' || client.status === 'windows-session',
|
|
'chip-linux': client.status === 'linux' || client.status === 'linux-session',
|
|
'chip-macos': client.status === 'macos',
|
|
'chip-off': client.status === 'off'
|
|
}">
|
|
{{ client.status || 'off' }}
|
|
</mat-chip>
|
|
</td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="mantenimiento">
|
|
<th mat-header-cell *matHeaderCellDef> Mantenimiento </th>
|
|
<td mat-cell *matCellDef="let client"> {{ client.mantenimiento }} </td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="subnet">
|
|
<th mat-header-cell *matHeaderCellDef> Subred </th>
|
|
<td mat-cell *matCellDef="let client"> {{ client.subnet }} </td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="pxeTemplate">
|
|
<th mat-header-cell *matHeaderCellDef> Plantilla PXE </th>
|
|
<td mat-cell *matCellDef="let client"> {{ client.pxeTemplate }} </td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="actions">
|
|
<th mat-header-cell *matHeaderCellDef> Acciones </th>
|
|
<td mat-cell *matCellDef="let client">
|
|
<button mat-icon-button [matMenuTriggerFor]="clientMenu">
|
|
<mat-icon>more_vert</mat-icon>
|
|
</button>
|
|
<mat-menu #clientMenu="matMenu">
|
|
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
|
|
<mat-icon>edit</mat-icon>
|
|
<span>Edit</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onShowClientDetail($event, client)">
|
|
<mat-icon>visibility</mat-icon>
|
|
<span>Ver detalles</span>
|
|
</button>
|
|
<button mat-menu-item (click)="onDeleteClick($event, client, selectedNode)">
|
|
<mat-icon>delete</mat-icon>
|
|
<span>Delete</span>
|
|
</button>
|
|
</mat-menu>
|
|
</td>
|
|
</ng-container>
|
|
<tr mat-header-row *matHeaderRowDef="['name', 'ip', 'mac', 'oglive', 'status', 'mantenimiento', 'subnet', 'pxeTemplate', 'actions']"></tr>
|
|
<tr mat-row *matRowDef="let row; columns: ['name', 'ip', 'mac', 'oglive', 'status', 'mantenimiento', 'subnet', 'pxeTemplate', 'actions'];"></tr>
|
|
</table>
|
|
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</ng-template>
|