Refactor groups component
parent
398e0ffa57
commit
a6797f8f77
|
@ -502,3 +502,94 @@ button[mat-raised-button] {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.view-toggle-container {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.clients-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.clients-list .list-item-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.client-card, .list-item-content {
|
||||
border: 1px solid #ccc;
|
||||
padding: 1rem;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.client-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.client-image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.view-toggle-container {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.clients-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.clients-list .list-item-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.client-card, .list-item-content {
|
||||
border: 1px solid #ccc;
|
||||
padding: 1rem;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.client-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.client-image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.header-actions-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
flex-shrink: 0; /* Asegura que el botón Back no se reduzca */
|
||||
}
|
||||
|
||||
.view-toggle-container {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
<button mat-flat-button color="primary" (click)="addClient($event)" matTooltipShowDelay="1000">
|
||||
{{ 'newClientButton' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button (click)="openBottomSheet()" joyrideStep="keyStep"
|
||||
text="{{ 'keyStepText' | translate }}" matTooltipShowDelay="1000">
|
||||
<button mat-flat-button (click)="openBottomSheet()" joyrideStep="keyStep" text="{{ 'keyStepText' | translate }}"
|
||||
matTooltipShowDelay="1000">
|
||||
{{ 'legendButton' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- LAS CARDS DE LAS FACULTADES -->
|
||||
|
@ -77,10 +78,24 @@
|
|||
<!-- TEMPLATE QUE SALE DDESPUES DE LAS CARDs CON EL ARBOL Y PCS -->
|
||||
|
||||
<ng-template #detailsTemplate>
|
||||
<button mat-raised-button color="primary" (click)="clearSelection()">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
{{ 'Back' | translate }}
|
||||
</button>
|
||||
<div class="header-actions-container">
|
||||
<!-- Botón de Back -->
|
||||
<button mat-raised-button color="primary" (click)="clearSelection()" class="back-button">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
{{ 'Back' | translate }}
|
||||
</button>
|
||||
|
||||
<!-- Botones de alternancia -->
|
||||
<div class="view-toggle-container">
|
||||
<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">
|
||||
<!-- Contenedor del árbol -->
|
||||
|
||||
|
@ -114,7 +129,7 @@
|
|||
|
||||
<mat-tree-node *matTreeNodeDef="let node; when: isLeafNode" matTreeNodePadding (click)="onNodeClick(node)">
|
||||
<button mat-icon-button matTreeNodeToggle [disabled]="true" class="disabled-toggle">
|
||||
|
||||
|
||||
</button>
|
||||
<mat-icon [ngClass]="{
|
||||
'pc-og-live': node.type === 'client' && node.status === 'og-live',
|
||||
|
@ -145,7 +160,7 @@
|
|||
</mat-tree>
|
||||
</div>
|
||||
|
||||
<mat-menu restoreFocus = fasle #commandMenu="matMenu">
|
||||
<mat-menu restoreFocus=fasle #commandMenu="matMenu">
|
||||
<button mat-menu-item *ngFor="let command of commands" (click)="executeCommand(command, selectedNode)">
|
||||
<span>{{ command.name }}</span>
|
||||
</button>
|
||||
|
@ -162,6 +177,10 @@
|
|||
<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>
|
||||
|
@ -170,16 +189,20 @@
|
|||
<mat-icon>edit</mat-icon>
|
||||
<span>Edit</span>
|
||||
</button>
|
||||
<button mat-menu-item (click)="onDeleteClick($event, selectedNode)" >
|
||||
<button mat-menu-item (click)="onDeleteClick($event, selectedNode)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
<span>Delete</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
|
||||
|
||||
<!-- Contenedor de clientes -->
|
||||
<div class="clients-container" *ngIf="selectedClients.length > 0">
|
||||
<h3>Clientes del {{ selectedNode?.name }}</h3>
|
||||
<div class="clients-grid">
|
||||
|
||||
<!-- Vista Tarjeta -->
|
||||
<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" />
|
||||
|
@ -189,28 +212,124 @@
|
|||
|
||||
<button mat-raised-button color="primary" [matMenuTriggerFor]="clientMenu">Acciones</button>
|
||||
<mat-menu #clientMenu="matMenu">
|
||||
<button mat-menu-item>
|
||||
<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>
|
||||
<button mat-menu-item>
|
||||
<mat-icon>visibility</mat-icon>
|
||||
<span>Ver detalles</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Paginador -->
|
||||
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons>
|
||||
</mat-paginator>
|
||||
</div>
|
||||
|
||||
<!-- Vista Tabla -->
|
||||
<div class="clients-table" *ngIf="currentView === 'list'">
|
||||
<table mat-table [dataSource]="selectedClients" class="mat-elevation-z8">
|
||||
|
||||
<!-- Columna: Nombre -->
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef> Nombre </th>
|
||||
<td mat-cell *matCellDef="let client"> {{ client.name }} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Columna: IP -->
|
||||
<ng-container matColumnDef="ip">
|
||||
<th mat-header-cell *matHeaderCellDef> IP </th>
|
||||
<td mat-cell *matCellDef="let client"> {{ client.ip }} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Columna: MAC -->
|
||||
<ng-container matColumnDef="mac">
|
||||
<th mat-header-cell *matHeaderCellDef> MAC </th>
|
||||
<td mat-cell *matCellDef="let client"> {{ client.mac }} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Columna: OG Live -->
|
||||
<ng-container matColumnDef="oglive">
|
||||
<th mat-header-cell *matHeaderCellDef> OG Live </th>
|
||||
<td mat-cell *matCellDef="let client"> {{ client.oglive }} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Columna: Estado -->
|
||||
<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>
|
||||
|
||||
<!-- Columna: Subred -->
|
||||
<ng-container matColumnDef="subnet">
|
||||
<th mat-header-cell *matHeaderCellDef> Subred </th>
|
||||
<td mat-cell *matCellDef="let client"> {{ client.subnet }} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Columna: Plantilla PXE -->
|
||||
<ng-container matColumnDef="pxeTemplate">
|
||||
<th mat-header-cell *matHeaderCellDef> Plantilla PXE </th>
|
||||
<td mat-cell *matCellDef="let client"> {{ client.pxeTemplate }} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Columna: Acciones -->
|
||||
<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>
|
||||
|
||||
<!-- Fila Encabezado -->
|
||||
<tr mat-header-row
|
||||
*matHeaderRowDef="['name', 'ip', 'mac', 'oglive', 'status', 'subnet', 'pxeTemplate', 'actions']"></tr>
|
||||
<!-- Filas de Datos -->
|
||||
<tr mat-row
|
||||
*matRowDef="let row; columns: ['name', 'ip', 'mac', 'oglive', 'status', 'subnet', 'pxeTemplate', 'actions'];">
|
||||
</tr>
|
||||
</table>
|
||||
<!-- Paginador -->
|
||||
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons>
|
||||
</mat-paginator>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
|
||||
<!-- FIN DEL TAB -->
|
||||
</mat-tab>
|
||||
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { DataService } from './services/data.service';
|
||||
import { UnidadOrganizativa } from './model/model';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Router } from '@angular/router';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatBottomSheet } from '@angular/material/bottom-sheet';
|
||||
import { MatTabChangeEvent } from '@angular/material/tabs';
|
||||
import { MatMenuTrigger } from '@angular/material/menu';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { JoyrideService } from 'ngx-joyride';
|
||||
import { FlatTreeControl } from '@angular/cdk/tree';
|
||||
import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree';
|
||||
|
||||
import { DataService } from './services/data.service';
|
||||
import { UnidadOrganizativa } from './model/model';
|
||||
import { CreateOrganizationalUnitComponent } from './shared/organizational-units/create-organizational-unit/create-organizational-unit.component';
|
||||
import { CreateClientComponent } from './shared/clients/create-client/create-client.component';
|
||||
import { EditOrganizationalUnitComponent } from './shared/organizational-units/edit-organizational-unit/edit-organizational-unit.component';
|
||||
|
@ -17,11 +21,8 @@ import { TreeViewComponent } from './shared/tree-view/tree-view.component';
|
|||
import { LegendComponent } from './shared/legend/legend.component';
|
||||
import { ClientTabViewComponent } from './components/client-tab-view/client-tab-view.component';
|
||||
import { OrganizationalUnitTabViewComponent } from './components/organizational-unit-tab-view/organizational-unit-tab-view.component';
|
||||
import { MatMenuTrigger } from '@angular/material/menu';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Router } from '@angular/router';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { DeleteModalComponent } from '../../shared/delete_modal/delete-modal/delete-modal.component';
|
||||
import { ClassroomViewDialogComponent } from './shared/classroom-view/classroom-view-modal';
|
||||
|
||||
interface TreeNode {
|
||||
name: string;
|
||||
|
@ -30,6 +31,7 @@ interface TreeNode {
|
|||
ip?: string;
|
||||
'@id'?: string;
|
||||
hasClients?: boolean;
|
||||
status?: string ;
|
||||
}
|
||||
|
||||
interface FlatNode {
|
||||
|
@ -62,6 +64,8 @@ export class GroupsComponent implements OnInit {
|
|||
commandsLoading: boolean = false;
|
||||
selectedClients: any[] = [];
|
||||
cols: number = 4;
|
||||
currentView: 'card' | 'list' = 'list';
|
||||
|
||||
|
||||
@ViewChild('clientTab') clientTabComponent!: ClientTabViewComponent;
|
||||
@ViewChild('organizationalUnitTab') organizationalUnitTabComponent!: OrganizationalUnitTabViewComponent;
|
||||
|
@ -104,35 +108,26 @@ export class GroupsComponent implements OnInit {
|
|||
this.updateGridCols();
|
||||
window.addEventListener('resize', () => this.updateGridCols());
|
||||
}
|
||||
toggleView(view: 'card' | 'list') {
|
||||
this.currentView = view;
|
||||
}
|
||||
|
||||
updateGridCols(): void {
|
||||
const width = window.innerWidth;
|
||||
if (width <= 600) {
|
||||
this.cols = 1;
|
||||
} else if (width <= 960) {
|
||||
this.cols = 2;
|
||||
} else if (width <= 1280) {
|
||||
this.cols = 3;
|
||||
} else {
|
||||
this.cols = 4;
|
||||
}
|
||||
this.cols = width <= 600 ? 1 : width <= 960 ? 2 : width <= 1280 ? 3 : 4;
|
||||
}
|
||||
|
||||
clearSelection(): void {
|
||||
this.selectedUnidad = null;
|
||||
this.selectedDetail = null;
|
||||
this.selectedClients = [];
|
||||
}
|
||||
|
||||
onTabChange(event: MatTabChangeEvent): void {
|
||||
switch (event.index) {
|
||||
case 2:
|
||||
this.clientTabComponent.search();
|
||||
break;
|
||||
case 3:
|
||||
this.organizationalUnitTabComponent.search();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (event.index === 2) {
|
||||
this.clientTabComponent.search();
|
||||
} else if (event.index === 3) {
|
||||
this.organizationalUnitTabComponent.search();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,8 +155,7 @@ export class GroupsComponent implements OnInit {
|
|||
onSelectUnidad(unidad: UnidadOrganizativa): void {
|
||||
this.selectedUnidad = unidad;
|
||||
this.selectedDetail = unidad;
|
||||
console.log('Selected unidad:', unidad);
|
||||
|
||||
|
||||
this.loadChildrenAndClients(unidad.id).then(fullData => {
|
||||
const treeData = this.convertToTreeData(fullData);
|
||||
this.treeDataSource.data = treeData[0]?.children || [];
|
||||
|
@ -171,7 +165,6 @@ export class GroupsComponent implements OnInit {
|
|||
async loadChildrenAndClients(id: string): Promise<any> {
|
||||
try {
|
||||
const childrenData = await this.dataService.getChildren(id).toPromise();
|
||||
|
||||
const processHierarchy = (nodes: UnidadOrganizativa[]): TreeNode[] => {
|
||||
return nodes.map(node => ({
|
||||
name: node.name,
|
||||
|
@ -181,8 +174,7 @@ export class GroupsComponent implements OnInit {
|
|||
clients: node.clients || []
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
|
||||
return {
|
||||
...this.selectedUnidad,
|
||||
children: childrenData ? processHierarchy(childrenData) : []
|
||||
|
@ -201,21 +193,18 @@ export class GroupsComponent implements OnInit {
|
|||
children: node.children?.map(processNode) || [],
|
||||
hasClients: node.clients && node.clients.length > 0,
|
||||
});
|
||||
|
||||
|
||||
return [processNode(data)];
|
||||
}
|
||||
|
||||
onNodeClick(node: TreeNode): void {
|
||||
console.log('Node clicked:', node);
|
||||
this.selectedNode = node;
|
||||
|
||||
|
||||
if (node.hasClients) {
|
||||
const url = `${this.baseUrl}${node['@id']}`;
|
||||
this.http.get(url).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Clients fetched:', data);
|
||||
this.selectedClients = data.clients || [];
|
||||
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching clients:', error);
|
||||
|
@ -289,41 +278,41 @@ export class GroupsComponent implements OnInit {
|
|||
|
||||
onDeleteClick(event: MouseEvent, node: TreeNode | null, clientNode?: TreeNode | null): void {
|
||||
console.log('Deleting node or client:', node);
|
||||
|
||||
|
||||
const uuid = node && node['@id'] ? node['@id'].split('/').pop() || '' : '';
|
||||
const name = node?.name || 'Elemento desconocido';
|
||||
const type = node?.type || '';
|
||||
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '400px',
|
||||
data: { name }
|
||||
});
|
||||
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result === true) {
|
||||
this.dataService.deleteElement(uuid, type).subscribe(
|
||||
() => {
|
||||
console.log('Entity deleted successfully:', uuid);
|
||||
|
||||
|
||||
this.loadChildrenAndClients(this.selectedUnidad?.id || '').then(updatedData => {
|
||||
const treeData = this.convertToTreeData(updatedData);
|
||||
this.treeDataSource.data = treeData[0]?.children || [];
|
||||
});
|
||||
|
||||
|
||||
if (type === 'client' && clientNode) {
|
||||
console.log('Refreshing clients for node:', clientNode);
|
||||
this.refreshClients(clientNode);
|
||||
}
|
||||
|
||||
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
data => {
|
||||
this.organizationalUnits = data;
|
||||
},
|
||||
error => console.error('Error fetching unidades organizativas:', error)
|
||||
);
|
||||
|
||||
|
||||
this.toastr.success('Entidad eliminada exitosamente');
|
||||
},
|
||||
error => {
|
||||
|
@ -341,10 +330,10 @@ export class GroupsComponent implements OnInit {
|
|||
this.selectedClients = [];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const url = `${this.baseUrl}${node['@id']}`;
|
||||
console.log('Fetching clients for node with URL:', url);
|
||||
|
||||
|
||||
this.http.get(url).subscribe(
|
||||
(data: any) => {
|
||||
console.log('Response data:', data);
|
||||
|
@ -375,6 +364,20 @@ export class GroupsComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
onRoomMap(room: any): void {
|
||||
this.http.get('https://127.0.0.1:8443' + room['@id']).subscribe(
|
||||
(response: any) => {
|
||||
this.dialog.open(ClassroomViewDialogComponent, {
|
||||
width: '90vw',
|
||||
data: { clients: response.clients }
|
||||
});
|
||||
},
|
||||
(error: any) => {
|
||||
console.error('Error en la solicitud HTTP:', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fetchCommands(): void {
|
||||
this.commandsLoading = true;
|
||||
this.http.get('https://127.0.0.1:8443/commands?page=1&itemsPerPage=30').subscribe(
|
||||
|
@ -390,14 +393,18 @@ export class GroupsComponent implements OnInit {
|
|||
}
|
||||
|
||||
executeCommand(command: any, selectedNode: any): void {
|
||||
console.log('Executing command:', command.name);
|
||||
this.toastr.success('Ejecutando comando: ' + command.name+ " en "+ selectedNode.name ) ;
|
||||
this.toastr.success('Ejecutando comando: ' + command.name + " en " + selectedNode.name);
|
||||
}
|
||||
|
||||
onClientActions(client: any): void {
|
||||
console.log('Client actions:', client);
|
||||
}
|
||||
|
||||
onShowClientDetail(event: MouseEvent, client: any): void {
|
||||
event.stopPropagation();
|
||||
this.router.navigate(['clients', client.uuid], { state: { clientData: client } });
|
||||
}
|
||||
|
||||
onShowDetailsClick(event: MouseEvent, data: any): void {
|
||||
event.stopPropagation();
|
||||
if (data.type != 'client') {
|
||||
|
@ -429,4 +436,5 @@ export class GroupsComponent implements OnInit {
|
|||
|
||||
hasChild = (_: number, node: FlatNode): boolean => node.expandable;
|
||||
isLeafNode = (_: number, node: FlatNode): boolean => !node.expandable;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
/* Contenedor principal */
|
||||
.create-client-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 16px;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Títulos */
|
||||
h1, h3, h4 {
|
||||
margin: 0 0 16px;
|
||||
color: #333;
|
||||
|
@ -27,20 +26,21 @@ h4 {
|
|||
margin-top: 16px;
|
||||
}
|
||||
|
||||
/* Espaciado entre contenedores */
|
||||
.inputs-container {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
/* Contenedor de cada sección */
|
||||
.mat-dialog-content {
|
||||
flex: 1;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
min-width: 600px;
|
||||
max-width: 90vw;
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
.create-multiple-client-container {
|
||||
|
@ -51,7 +51,6 @@ h4 {
|
|||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Campos del formulario */
|
||||
.client-form {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
|
@ -66,7 +65,6 @@ h4 {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
/* Tabla */
|
||||
.scrollable-table {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
|
@ -95,7 +93,6 @@ tr:hover {
|
|||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
/* Botones */
|
||||
button {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
@ -115,13 +112,11 @@ button.mat-raised-button {
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Carga */
|
||||
.loading-spinner {
|
||||
margin: 16px auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Alternar formularios */
|
||||
.toggle-button {
|
||||
background: none;
|
||||
border: none;
|
||||
|
@ -135,7 +130,6 @@ button.mat-raised-button {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Mejoras generales */
|
||||
.mat-divider {
|
||||
margin: 0 16px;
|
||||
}
|
||||
|
@ -151,7 +145,6 @@ input[type="file"] {
|
|||
display: none;
|
||||
}
|
||||
|
||||
/* Responsivo */
|
||||
@media (max-width: 768px) {
|
||||
.inputs-container {
|
||||
flex-direction: column;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<div class="create-client-container">
|
||||
<div class="create-client-container mat-elevation-z4">
|
||||
<h1>{{ 'addClientTitle' | translate }}s</h1>
|
||||
<div class="inputs-container">
|
||||
<div class="mat-dialog-content" [ngClass]="{'loading': loading}">
|
||||
|
||||
|
@ -8,7 +9,6 @@
|
|||
<mat-select formControlName="organizationalUnit">
|
||||
<mat-option *ngFor="let unit of parentUnits" [value]="unit['@id']">
|
||||
<div class="unit-name">{{ unit.name }}</div>
|
||||
<div class="unit-path">{{ unit.path }}</div>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
@ -20,8 +20,10 @@
|
|||
<button mat-raised-button color="primary" (click)="fileInput.click()">Subir fichero</button>
|
||||
<input #fileInput type="file" (change)="onFileUpload($event)" accept=".csv" hidden>
|
||||
<p>o añadelos manualmente:</p>
|
||||
<div *ngIf="showTextarea">
|
||||
<textarea #textarea matInput placeholder="host bbaa-it1-1..." rows="20" cols="100"></textarea>
|
||||
<button mat-raised-button color="primary" (click)="onTextarea(textarea.value)">cargar</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 *ngIf="uploadedClients.length > 0">Clientes importados:</h4>
|
||||
|
|
|
@ -23,6 +23,7 @@ export class CreateClientComponent implements OnInit {
|
|||
loading: boolean = false;
|
||||
displayedColumns: string[] = ['name', 'ip'];
|
||||
isSingleClientForm: boolean = false;
|
||||
showTextarea: boolean = true;
|
||||
protected netifaceTypes = [
|
||||
{ name: 'Eth0', value: 'eth0' },
|
||||
{ name: 'Eth1', value: 'eth1' },
|
||||
|
@ -147,8 +148,10 @@ export class CreateClientComponent implements OnInit {
|
|||
if (clients.length > 0) {
|
||||
this.uploadedClients = clients;
|
||||
this.toastService.success('Archivo cargado correctamente, los datos están listos para enviarse.', 'Éxito');
|
||||
this.showTextarea = false;
|
||||
} else {
|
||||
this.toastService.error('No se encontraron datos válidos', 'Error');
|
||||
this.showTextarea = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -172,8 +175,10 @@ export class CreateClientComponent implements OnInit {
|
|||
if (clients.length > 0) {
|
||||
this.uploadedClients = clients;
|
||||
this.toastService.success('Datos cargados correctamente, los datos están listos para enviarse.', 'Éxito');
|
||||
this.showTextarea = false;
|
||||
} else {
|
||||
this.toastService.error('No se encontraron datos válidos', 'Error');
|
||||
this.showTextarea = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue