diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.css b/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.css
index 897d6e4..0dad576 100644
--- a/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.css
+++ b/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.css
@@ -1,3 +1,10 @@
+.header-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 10px;
+}
+
.client-header {
display: flex;
align-items: center;
@@ -14,10 +21,49 @@
display: flex;
align-items: center;
justify-content: center;
- min-width: 120px;
+ min-width: 120px;
min-height: 120px;
}
+.row-container {
+ justify-content: space-between;
+ width: 100%;
+}
+
+.table-container {
+ padding-right: 10px;
+}
+
+.charts-wrapper {
+ width: 100%;
+ margin-top: 20px;
+}
+
+.charts-row {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between; /* Distribuye el espacio entre los gráficos */
+ gap: 20px; /* Añade espacio entre los gráficos */
+}
+
+.disk-usage {
+ text-align: center;
+ flex: 1;
+ min-width: 200px; /* Ajusta este valor según el tamaño mínimo deseado para cada gráfico */
+}
+
+.circular-chart {
+ max-width: 150px;
+ max-height: 150px;
+ margin: 0 auto; /* Centra el gráfico dentro del contenedor */
+}
+
+.chart {
+ display: flex;
+ justify-content: center;
+}
+
+
.icon-pc {
font-size: 25px;
color: #3b82f6;
@@ -43,7 +89,6 @@
background-color: #fff;
padding: 20px;
border-radius: 12px;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.two-column-table {
@@ -53,6 +98,10 @@
margin-top: 15px;
}
+.mat-elevation-z8 {
+ box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
+}
+
.table-row {
display: flex;
justify-content: space-between;
@@ -72,11 +121,11 @@
}
.mat-tab-group {
- min-height: 400px;
+ min-height: 400px;
}
.mat-tab-body-wrapper {
- min-height: inherit;
+ min-height: inherit;
}
.info-section h2 {
@@ -92,7 +141,6 @@
.second-section {
display: grid;
- grid-template-columns: 1fr 3fr;
gap: 20px;
}
@@ -111,24 +159,6 @@
width: 100%;
}
-.disk-usage {
- display: flex;
- align-items: center;
- justify-content: center;
- flex-direction: column;
- margin-bottom: 20px;
- background-color: #fff;
- padding: 20px;
- border-radius: 12px;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
-}
-
-.chart-container {
- width: 150px;
- height: 150px;
- margin-bottom: 15px;
-}
-
.circular-chart {
display: block;
margin: 0 auto;
diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.html b/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.html
index 0f1d858..b501a14 100644
--- a/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.html
+++ b/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.html
@@ -1,3 +1,14 @@
+
-
-
-
-
{{ clientData?.property }}
-
{{ clientData?.value }}
-
-
-
-
-
-
-
-
+
-
-
Disco
-
0">
+
+
+
+ {{ column.header }} |
+
+
+ {{ column.cell(image) }}
+
+
+
+ {{ (image.size / 1024).toFixed(2) }} GB
+
+
+ |
+
+
+
+
+
+
+
+
0">
+
Disco {{ disk.diskNumber }}
-
+
Usado: {{ disk.used }} GB ({{ disk.percentage }}%)
Total: {{ disk.total }} GB
-
-
+
+
-
-
-
-
diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.ts b/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.ts
index 4f00d86..35c2741 100644
--- a/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.ts
+++ b/ogWebconsole/src/app/components/groups/components/client-main-view/client-main-view.component.ts
@@ -1,5 +1,9 @@
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";
interface ClientInfo {
property: string;
value: any;
@@ -18,13 +22,44 @@ export class ClientMainViewComponent implements OnInit {
isPartitionAssistantVisible: boolean = false;
isBootImageVisible: boolean = false;
isDiskUsageVisible: boolean = true;
-
+ dataSource = new MatTableDataSource
();
generalData: ClientInfo[] = [];
networkData: ClientInfo[] = [];
classroomData: ClientInfo[] = [];
diskUsageData: any[] = [];
+ partitions: any[] = [];
+ commands: any[] = [];
+ 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} %`
+ },
+ ];
+ displayedColumns = [...this.columns.map(column => column.columnDef)];
- constructor(private http: HttpClient) {
+ constructor(private http: HttpClient, private dialog: MatDialog) {
const url = window.location.href;
const segments = url.split('/');
this.clientUuid = segments[segments.length - 1];
@@ -32,10 +67,10 @@ export class ClientMainViewComponent implements OnInit {
ngOnInit() {
this.clientData = history.state.clientData;
+ this.loadPartitions()
this.updateGeneralData();
this.updateNetworkData();
- this.updateClassroomData();
- this.calculateDiskUsage();
+ this.loadCommands()
}
updateGeneralData() {
@@ -48,54 +83,36 @@ export class ClientMainViewComponent implements OnInit {
{ property: 'Netiface', value: this.clientData?.netiface || '' },
{ property: 'Perfil hardware', value: this.clientData?.hardwareProfile?.description || '' },
{ property: 'Menú', value: this.clientData?.menu?.description || '' },
- { property: 'Fecha de creación', value: this.clientData?.createdAt || '' },
- { property: 'Creado por', value: this.clientData?.createdBy || '' }
];
}
updateNetworkData() {
this.networkData = [
- { property: 'Perfil hardware', value: this.clientData?.hardwareProfile?.description || '' },
+ { property: 'Remote Pc', value: this.clientData.remotePc || '' },
{ property: 'Subred', value: this.clientData?.subnet || '' },
{ property: 'OGlive', value: '' },
{ property: 'Autoexec', value: '' },
{ property: 'Repositorio', value: '' },
{ property: 'Validación', value: this.clientData?.organizationalUnit?.networkSettings?.validation || '' },
- { property: 'Fecha de creación', value: this.clientData?.createdAt || '' },
+ { property: 'Pxe', value: this.clientData?.template.name || '' },
{ property: 'Creado por', value: this.clientData?.createdBy || '' }
];
}
- updateClassroomData() {
- this.classroomData = [
- { property: 'Url servidor proxy', value: this.clientData?.organizationalUnit?.networkSettings?.proxy || '' },
- { property: 'IP DNS', value: this.clientData?.organizationalUnit?.networkSettings?.dns || '' },
- { property: 'Máscara de red', value: this.clientData?.organizationalUnit?.networkSettings?.netmask || '' },
- { property: 'Router', value: this.clientData?.organizationalUnit?.networkSettings?.router || '' },
- { property: 'NTP', value: this.clientData?.organizationalUnit?.networkSettings?.ntp || '' },
- { property: 'Modo p2p', value: this.clientData?.organizationalUnit?.networkSettings?.p2pMode || '' },
- { property: 'Tiempo p2p', value: this.clientData?.organizationalUnit?.networkSettings?.p2pTime || '' },
- { property: 'IP multicast', value: this.clientData?.organizationalUnit?.networkSettings?.mcastIp || '' },
- { property: 'Modo multicast', value: this.clientData?.organizationalUnit?.networkSettings?.mcastMode || '' },
- { property: 'Puerto multicast', value: this.clientData?.organizationalUnit?.networkSettings?.mcastPort || '' },
- { property: 'Velocidad multicast', value: this.clientData?.organizationalUnit?.networkSettings?.mcastSpeed || '' },
- { property: 'Perfil hardware', value: this.clientData?.organizationalUnit?.networkSettings?.hardwareProfile?.description || '' }
- ];
- }
-
calculateDiskUsage() {
const diskUsageMap = new Map();
- this.clientData.partitions.forEach((partition: any) => {
+ this.partitions.forEach((partition: any) => {
const diskNumber = partition.diskNumber;
if (!diskUsageMap.has(diskNumber)) {
diskUsageMap.set(diskNumber, { total: 0, used: 0 });
}
const diskData = diskUsageMap.get(diskNumber);
+
if (partition.partitionNumber === 0) {
- diskData!.total = partition.size / (1024 * 1024);
+ diskData!.total = Number((partition.size / 1024).toFixed(2));
} else {
- diskData!.used += partition.size / (1024 * 1024);
+ diskData!.used += Number(((partition.size * (partition.memoryUsage / 100))/ 1024).toFixed(2));
}
});
@@ -105,23 +122,44 @@ export class ClientMainViewComponent implements OnInit {
});
}
- togglePartitionAssistant() {
- this.isPartitionAssistantVisible = !this.isPartitionAssistantVisible;
- this.isBootImageVisible = false
- if (this.isPartitionAssistantVisible) {
- setTimeout(() => {
- this.assistantContainer.nativeElement.scrollIntoView({ behavior: 'smooth' });
- }, 0);
+ loadPartitions(): void {
+ this.http.get(`${this.baseUrl}/partitions?client.id=${this.clientData?.id}`).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(command: any): void {
+ if (command.name === 'Particionar y Formatear') {
+ this.openPartitionDialog();
}
}
- showBootImage() {
- this.isBootImageVisible = !this.isBootImageVisible;
- this.isPartitionAssistantVisible = false;
- if (this.isBootImageVisible) {
- setTimeout(() => {
- this.assistantContainer.nativeElement.scrollIntoView({ behavior: 'smooth' });
- }, 0);
- }
+ openPartitionDialog(): void {
+ const dialogRef = this.dialog.open(PartitionAssistantComponent, {
+ width: '1000px',
+ data: this.clientData['@id']
+ });
+
+ dialogRef.afterClosed().subscribe((result: any) => {
+ console.log('El diálogo se cerró', result);
+ });
}
}
diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.css b/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.css
index fce857e..1615bc2 100644
--- a/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.css
+++ b/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.css
@@ -2,8 +2,6 @@
font-family: 'Roboto', sans-serif;
background-color: #f9f9f9;
padding: 20px;
- border-radius: 10px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
margin: 20px auto;
}
@@ -13,7 +11,7 @@
justify-content: space-between;
margin-bottom: 15px;
padding: 10px;
- background-color: #fff;
+ background-color: #cecbcb;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
@@ -52,8 +50,6 @@
width: 100%;
border-collapse: collapse;
background-color: #fff;
- border-radius: 8px;
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
overflow: hidden;
margin-bottom: 20px;
}
@@ -68,15 +64,12 @@
.partition-table td {
padding: 10px;
text-align: center;
- border-bottom: 1px solid #eee;
}
.partition-table select,
.partition-table input[type="number"],
.partition-table input[type="checkbox"] {
padding: 5px;
- border-radius: 4px;
- border: 1px solid #ccc;
width: 100%;
}
diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.html b/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.html
index 96bec8a..4b24a0d 100644
--- a/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.html
+++ b/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.html
@@ -1,62 +1,73 @@
-
-
Asistente a particionado
-
+
Asistente de particionado
-
-
- {{ partition.type }} ({{ partition.size }} GB)
+
+
+
+
+
+
+
+ {{ partition.type }} ({{ (partition.size / 1024).toFixed(2) }} GB)
+
+
+
+
+
+
-
-
-
-
-
+
{{ errorMessage }}
-
-
-
+
+
+
diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.ts b/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.ts
index 4e066b9..472f7e6 100644
--- a/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.ts
+++ b/ogWebconsole/src/app/components/groups/components/client-main-view/partition-assistant/partition-assistant.component.ts
@@ -1,6 +1,7 @@
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import {Component, EventEmitter, Inject, Input, OnInit, Output} from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ToastrService } from 'ngx-toastr';
+import {MAT_DIALOG_DATA} from "@angular/material/dialog";
interface Partition {
uuid?: string;
@@ -8,6 +9,7 @@ interface Partition {
size: number;
type: string;
sizeBytes: number;
+ memoryUsage: number;
format: boolean;
color: string;
percentage: number;
@@ -20,8 +22,6 @@ interface Partition {
})
export class PartitionAssistantComponent implements OnInit {
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
- @Input() data: any;
- @Input() clientUuid: string | undefined;
@Output() dataChange = new EventEmitter
();
errorMessage = '';
@@ -30,14 +30,18 @@ export class PartitionAssistantComponent implements OnInit {
private apiUrl: string = this.baseUrl + '/partitions';
- constructor(private http: HttpClient, private toastService: ToastrService) {}
+ constructor(
+ private http: HttpClient,
+ private toastService: ToastrService,
+ @Inject(MAT_DIALOG_DATA) public data: any
+ ) {}
ngOnInit() {
- this.loadClientData();
+ this.loadPartitions();
}
- loadClientData() {
- const url = `${this.baseUrl}/clients/${this.clientUuid}`;
+ loadPartitions() {
+ const url = `${this.baseUrl}${this.data}`;
this.http.get(url).subscribe(
(response) => {
this.data = response;
@@ -68,6 +72,7 @@ export class PartitionAssistantComponent implements OnInit {
uuid: partition.uuid,
partitionNumber: partition.partitionNumber,
size: this.convertBytesToGB(partition.size),
+ memoryUsage: partition.memoryUsage,
type: partition.type || partition.filesystem || 'NTFS',
sizeBytes: partition.size,
format: false,
@@ -88,12 +93,12 @@ export class PartitionAssistantComponent implements OnInit {
}
convertBytesToGB(bytes: number): number {
- return bytes / 1024;
+ return bytes
}
updatePartitionPercentages(partitions: Partition[], totalDiskSize: number) {
partitions.forEach((partition) => {
- partition.percentage = (partition.size / totalDiskSize) * 100;
+ partition.percentage = (partition.size / totalDiskSize) * 100
});
}
@@ -102,6 +107,7 @@ export class PartitionAssistantComponent implements OnInit {
if (disk) {
const remainingGB = this.getRemainingGB(disk.partitions, disk.totalDiskSize);
+ console.log(remainingGB)
if (remainingGB > 0) {
const maxPartitionNumber =
disk.partitions.length > 0 ? Math.max(...disk.partitions.map((p) => p.partitionNumber)) : 0;
@@ -111,6 +117,7 @@ export class PartitionAssistantComponent implements OnInit {
partitionNumber: newPartitionNumber,
size: 0,
type: 'NTFS',
+ memoryUsage: 0,
sizeBytes: 0,
format: false,
color: '#' + Math.floor(Math.random() * 16777215).toString(16),
@@ -136,13 +143,14 @@ export class PartitionAssistantComponent implements OnInit {
} else {
this.errorMessage = '';
partition.size = size;
- partition.sizeBytes = size * 1024;
+ partition.sizeBytes = size;
this.updatePartitionPercentages(disk.partitions, disk.totalDiskSize);
}
}
}
getRemainingGB(partitions: Partition[], totalDiskSize: number): number {
+ console.log(totalDiskSize)
const totalUsedGB = partitions.reduce((acc, partition) => acc + partition.size, 0);
return Math.max(0, totalDiskSize - totalUsedGB);
}
@@ -182,6 +190,18 @@ export class PartitionAssistantComponent implements OnInit {
}
save() {
+ const invalidDisks = this.disks.filter(disk => {
+ const totalPartitionSize = disk.partitions.reduce((sum, partition) => sum + partition.size, 0);
+ return totalPartitionSize > disk.totalDiskSize;
+ });
+
+ if (invalidDisks.length > 0) {
+ this.errorMessage = 'El tamaño total de las particiones en uno o más discos excede el tamaño total del disco.';
+ return;
+ } else {
+ this.errorMessage = '';
+ }
+
const modifiedPartitions = this.getModifiedOrNewPartitions();
if (modifiedPartitions.length === 0) {
@@ -193,32 +213,40 @@ export class PartitionAssistantComponent implements OnInit {
const payload = {
diskNumber: diskNumber,
partitionNumber: partitionNumber,
+ memoryUsage: partition.memoryUsage,
size: partition.size,
filesystem: partition.type,
- client: `/clients/${this.clientUuid}`
+ client: this.data['@id']
};
if (isNew) {
this.http.post(this.apiUrl, payload).subscribe(
(response) => {
this.toastService.success('Partición creada exitosamente');
- this.loadClientData();
+ this.loadPartitions();
},
- (error) => {}
+ (error) => {
+ console.error('Error al crear la partición:', error);
+ this.toastService.error('Error al crear la partición');
+ }
);
} else if (partition.uuid) {
const patchUrl = `${this.apiUrl}/${partition.uuid}`;
this.http.patch(patchUrl, payload).subscribe(
(response) => {
this.toastService.success('Partición actualizada exitosamente');
- this.loadClientData();
+ this.loadPartitions();
},
- (error) => {}
+ (error) => {
+ console.error('Error al actualizar la partición:', error);
+ this.toastService.error('Error al actualizar la partición');
+ }
);
}
});
}
+
removePartition(diskNumber: number, partition: Partition) {
const disk = this.disks.find((d) => d.diskNumber === diskNumber);
@@ -233,7 +261,7 @@ export class PartitionAssistantComponent implements OnInit {
this.http.delete(deleteUrl).subscribe(
(response) => {
this.toastService.success('Partición eliminada exitosamente');
- this.loadClientData();
+ this.loadPartitions();
},
(error) => {}
);
diff --git a/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.ts b/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.ts
index 0c34fad..7619310 100644
--- a/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.ts
+++ b/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.ts
@@ -151,8 +151,6 @@ export class ClientTabViewComponent {
handleClientClick(event: MouseEvent, client: any): void {
event.stopPropagation();
- /* const dialogRef = this.dialog.open(ClientViewComponent, { data: { client }, width: '800px', height:'700px' }); */
-
this.router.navigate(['client', client.uuid], { state: { clientData: client } });
}