import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import {DatePipe} from "@angular/common"; import {MatTableDataSource} from "@angular/material/table"; import {PartitionAssistantComponent} from "./partition-assistant/partition-assistant.component"; import {MatDialog} from "@angular/material/dialog"; import {Router} from "@angular/router"; import {EditClientComponent} from "../../shared/clients/edit-client/edit-client.component"; import {ToastrService} from "ngx-toastr"; interface ClientInfo { property: string; value: any; } @Component({ selector: 'app-client-main-view', templateUrl: './client-main-view.component.html', styleUrl: './client-main-view.component.css' }) export class ClientMainViewComponent implements OnInit { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; @ViewChild('assistantContainer') assistantContainer!: ElementRef; clientUuid: string; clientData: any = {}; isPartitionAssistantVisible: boolean = false; isBootImageVisible: boolean = false; isDiskUsageVisible: boolean = true; dataSource = new MatTableDataSource(); generalData: ClientInfo[] = []; networkData: ClientInfo[] = []; classroomData: ClientInfo[] = []; diskUsageData: any[] = []; partitions: any[] = []; commands: any[] = []; chartDisk: any[] = []; view: [number, number] = [300, 200]; showLegend: boolean = true; arrayCommands: any[] = [ {name: 'Enceder', slug: 'power-on'}, {name: 'Apagar', slug: 'power-off'}, {name: 'Reiniciar', slug: 'reboot'}, {name: 'Iniciar Sesión', slug: 'login'}, {name: 'Crear Image', slug: 'create-image'}, {name: 'Deploy Image', slug: 'deploy-image'}, {name: 'Eliminar Imagen Cache', slug: 'delete-image-cache'}, {name: 'Particionar y Formatear', slug: 'partition'}, {name: 'Inventario Software', slug: 'software-inventory'}, {name: 'Inventario Hardware', slug: 'hardware-inventory'}, {name: 'Ejecutar script', slug: 'run-script'}, ]; datePipe: DatePipe = new DatePipe('es-ES'); columns = [ { columnDef: 'diskNumber', header: 'Disco', cell: (partition: any) => `${partition.diskNumber}`, }, { columnDef: 'partitionNumber', header: 'Particion', cell: (partition: any) => `${partition.partitionNumber}` }, { columnDef: 'description', header: 'Sistema de ficheros', cell: (partition: any) => `${partition.filesystem}` }, { columnDef: 'size', header: 'Tamaño', cell: (partition: any) => `${(partition.size / 1024).toFixed(2)} GB` }, { columnDef: 'memoryUsage', header: 'Uso', cell: (partition: any) => `${partition.memoryUsage} %` }, { columnDef: 'operativeSystem', header: 'SO', cell: (partition: any) => `${partition.operativeSystem?.name}` }, ]; displayedColumns = [...this.columns.map(column => column.columnDef)]; isDiskUsageEmpty: boolean = true; loading: boolean = true; constructor( private http: HttpClient, private dialog: MatDialog, private router: Router, private toastService: ToastrService ) { const url = window.location.href; const segments = url.split('/'); this.clientUuid = segments[segments.length - 1]; } ngOnInit() { this.clientData = history.state.clientData['@id']; this.loadClient(this.clientData) this.loadCommands() this.calculateDiskUsage(); this.loading = false; } loadClient = (uuid: string) => { this.http.get(`${this.baseUrl}${uuid}`).subscribe({ next: data => { this.clientData = data; this.updateGeneralData(); this.updateNetworkData(); this.loadPartitions() this.loading = false; }, error: error => { console.error('Error al obtener el cliente:', error); } }); } updateGeneralData() { this.generalData = [ { property: 'Nombre', value: this.clientData?.name || '' }, { property: 'IP', value: this.clientData?.ip || '' }, { property: 'MAC', value: this.clientData?.mac || '' }, { property: 'Nº de serie', value: this.clientData?.serialNumber || '' }, { property: 'Netiface', value: this.clientData?.netiface || this.clientData?.organizationalUnit?.networkSettings?.netiface || '' }, { property: 'Perfil hardware', value: this.clientData?.hardwareProfile?.description || '' }, ]; } updateNetworkData() { this.networkData = [ { property: 'Pxe', value: this.clientData?.template?.name || '' }, { property: 'Remote Pc', value: this.clientData.remotePc || '' }, { property: 'Subred', value: this.clientData?.subnet || '' }, { property: 'OGlive', value: this.clientData?.ogLive?.name || '' }, { property: 'Autoexec', value: '' }, { property: 'Repositorio', value: this.clientData?.repository?.name || '' }, ]; } calculateDiskUsage() { const diskUsageMap = new Map(); this.partitions.forEach((partition: any) => { const diskNumber = partition.diskNumber; if (!diskUsageMap.has(diskNumber)) { diskUsageMap.set(diskNumber, { total: 0, used: 0, partitions: [] }); } const diskData = diskUsageMap.get(diskNumber); if (partition.partitionNumber === 0) { diskData!.total = Number((partition.size / 1024).toFixed(2)); } else { diskData!.used += Number((partition.size / 1024).toFixed(2)); diskData!.partitions.push(partition); } }); this.chartDisk = Array.from(diskUsageMap.entries()).map(([diskNumber, { total, used, partitions }]) => { const partitionData = partitions.map(partition => ({ name: `Partición ${partition.partitionNumber}`, value: Number((partition.size / 1024).toFixed(2)) })); const freeSpace = total - used; if (freeSpace > 0) { partitionData.push({ name: 'Espacio libre', value: Number(freeSpace.toFixed(2)) }); } return { diskNumber, chartData: partitionData, total, used, percentage: total > 0 ? Math.round((used / total) * 100) : 0 }; }); this.diskUsageData = this.chartDisk; this.isDiskUsageEmpty = this.diskUsageData.length === 0; } onEditClick(event: MouseEvent, uuid: string): void { event.stopPropagation(); const dialogRef = this.dialog.open(EditClientComponent, { data: { uuid }, width: '900px' } ); dialogRef.afterClosed().subscribe(); } loadPartitions(): void { this.http.get(`${this.baseUrl}/partitions?client.id=${this.clientData?.id}&order[partitionNumber]=ASC`).subscribe({ next: data => { this.dataSource = data['hydra:member']; this.partitions = data['hydra:member']; this.calculateDiskUsage(); }, error: error => { console.error('Error al obtener las particiones:', error); } }); } loadCommands(): void { this.http.get(`${this.baseUrl}/commands?`).subscribe({ next: data => { this.commands = data['hydra:member']; }, error: error => { console.error('Error al obtener las particiones:', error); } }); } onCommandSelect(action: any): void { if (action === 'partition') { this.openPartitionAssistant(); } if (action === 'create-image') { this.openCreateImageAssistant(); } if (action === 'deploy-image') { this.openDeployImageAssistant(); } if (action === 'reboot') { this.rebootClient(); } if (action === 'power-off') { this.powerOffClient(); } if (action === 'power-on') { this.powerOnClient(); } } rebootClient(): void { this.http.post(`${this.baseUrl}/clients/server/${this.clientData.uuid}/reboot`, {}).subscribe( response => { this.toastService.success('Cliente actualizado correctamente'); }, error => { this.toastService.error('Error de conexión con el cliente'); } ); } powerOnClient(): void { const payload = { client: this.clientData['@id'] } this.http.post(`${this.baseUrl}${this.clientData.repository['@id']}/wol`, payload).subscribe( response => { this.toastService.success('Cliente actualizado correctamente'); }, error => { this.toastService.error('Error de conexión con el cliente'); } ); } powerOffClient(): void { this.http.post(`${this.baseUrl}/clients/server/${this.clientData.uuid}/power-off`, {}).subscribe( response => { this.toastService.success('Cliente actualizado correctamente'); }, error => { this.toastService.error('Error de conexión con el cliente'); } ); } openPartitionAssistant(): void { this.router.navigate([`/clients/${this.clientData.uuid}/partition-assistant`]).then(r => { console.log('navigated', r); }); } openCreateImageAssistant(): void { this.router.navigate([`/clients/${this.clientData.uuid}/create-image`]).then(r => { console.log('navigated', r); }); } openDeployImageAssistant(): void { this.router.navigate([`/clients/${this.clientData.uuid}/deploy-image`]).then(r => { console.log('navigated', r); }); } }