refs #1931 Refactor ClientDetailsComponent to enhance layout and improve data handling in client details view
testing/ogGui-multibranch/pipeline/head This commit looks good Details

develop
Lucas Lara García 2025-04-23 13:51:45 +02:00
parent a40be684b5
commit 70e21c6ca2
3 changed files with 101 additions and 342 deletions

View File

@ -1,326 +1,88 @@
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
}
.client-container {
flex-grow: 1;
box-sizing: border-box;
overflow: hidden;
.modal-content {
max-height: 80vh;
overflow-y: auto;
background-color: #fff;
display: flex;
flex-direction: column;
padding: 0rem 1rem 0rem 0.5rem;
}
.client-icon {
flex-shrink: 0;
margin-right: 20px;
display: flex;
align-items: center;
justify-content: center;
min-width: 120px;
min-height: 120px;
.section-header {
margin-bottom: 8px;
}
.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;
gap: 20px;
}
.disk-usage {
text-align: center;
flex: 1;
min-width: 200px;
}
.circular-chart {
max-width: 150px;
max-height: 150px;
margin: 0 auto;
}
.chart {
display: flex;
justify-content: center;
}
.icon-pc {
font-size: 25px;
color: #3b82f6;
}
.client-title h1 {
font-size: 2rem;
margin-bottom: 10px;
}
.client-title p {
margin: 2px 0;
font-size: 1rem;
color: #666;
}
.client-info {
margin: 20px 0;
.client-info-card {
background-color: #e4e4e4;
padding: 24px;
border-radius: 12px;
background-color: #f5f7fa;
padding: 20px;
border: 2px solid #d1d9e6;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
margin-bottom: 2em;
margin-top: 1.5em;
}
.info-section {
background-color: #fff;
border-radius: 12px;
}
.two-column-table {
.info-columns {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-top: 15px;
gap: 24px;
}
.mat-elevation-z8 {
box-shadow: 0px 0px 0px rgba(0, 0, 0, 0.2);
}
.table-row {
display: flex;
justify-content: space-between;
padding: 10px;
border-bottom: 1px solid #e0e0e0;
}
.column.property {
font-weight: bold;
text-align: left;
width: 45%;
}
.column.value {
text-align: right;
width: 45%;
}
.mat-tab-group {
min-height: 400px;
}
.mat-tab-body-wrapper {
min-height: inherit;
}
.info-section h2 {
font-size: 1.4rem;
margin-bottom: 10px;
color: #0056b3;
}
.info-section p {
font-size: 1rem;
margin: 5px 0;
}
.second-section {
display: grid;
gap: 20px;
}
.client-button-row {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 20px;
}
.buttons-row {
.info-column {
display: flex;
flex-direction: column;
background-color: #fff;
padding: 20px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
justify-content: flex-start;
gap: 16px;
}
.buttons-row button {
margin-bottom: 10px;
width: 100%;
.info-pair {
display: flex;
flex-direction: column;
}
.circular-chart {
display: block;
margin: 0 auto;
max-width: 100%;
max-height: 150px;
.label {
font-size: 0.9rem;
font-weight: 550;
color: #3f51b5;
}
.circle-bg {
fill: none;
stroke: #f0f0f0;
stroke-width: 3.8;
}
.circle {
fill: none;
stroke-width: 3.8;
stroke: #00bfa5;
stroke-linecap: round;
animation: progress 1s ease-out forwards;
}
.percentage {
fill: #333;
font-size: 0.7rem;
text-anchor: middle;
}
.disk-usage h3 {
margin: 0 0 10px 0;
font-size: 1.2rem;
color: #333;
}
@keyframes progress {
0% {
stroke-dasharray: 0, 100;
}
}
.assistants-container {
background-color: #fff;
margin-top: 10px;
padding: 20px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.circular-chart {
display: block;
margin: 0 auto;
max-width: 100%;
max-height: 150px;
}
.circle-bg {
fill: none;
stroke: #f0f0f0;
stroke-width: 3.8;
}
.circle {
fill: none;
stroke-width: 3.8;
stroke-linecap: round;
animation: progress 1s ease-out forwards;
}
.partition-0 {
stroke: #00bfa5;
}
.partition-1 {
stroke: #ff6f61;
}
.partition-2 {
stroke: #ffb400;
}
.partition-3 {
stroke: #3498db;
}
.percentage {
fill: #333;
font-size: 0.7rem;
text-anchor: middle;
.value {
font-size: 1rem;
color: #222;
word-break: break-word;
}
.disk-container {
display: flex;
flex-direction: row;
gap: 20px;
background-color: #f5f7fa;
border: 2px solid #d1d9e6;
border-radius: 10px;
padding: 20px;
margin-top: 20px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
flex-wrap: wrap;
justify-content: center;
align-items: stretch;
margin-bottom: 20px;
flex-direction: column;
gap: 32px;
}
.table-container {
flex: 3;
display: flex;
justify-content: center;
align-items: center;
}
table.mat-elevation-z8 {
width: 100%;
max-width: 800px;
background-color: white;
overflow-x: auto;
border-radius: 8px;
overflow: hidden;
background: #fff;
padding: 16px;
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
}
.mat-header-cell {
background-color: #d1d9e6 !important;
color: #333;
font-weight: bold;
text-align: center;
}
.mat-cell {
text-align: center;
}
.mat-chip {
font-weight: bold;
color: white;
.mat-elevation-z8 {
width: 100%;
border-radius: 8px;
}
.charts-container {
flex: 2;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 24px;
}
.disk-usage {
background-color: white;
padding: 15px;
border-radius: 8px;
justify-self: center;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
text-align: center;
flex: 1 1 300px;
padding: 16px;
background: #f9f9f9;
border-radius: 12px;
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
}
.chart {
display: flex;
justify-content: center;
}
width: 100%;
height: 200px;
margin-bottom: 12px;
}

View File

@ -1,64 +1,64 @@
<app-loading [isLoading]="loading"></app-loading>
<mat-dialog-content class="modal-content">
<app-loading [isLoading]="loading"></app-loading>
<div class="client-container">
<div class="header-container">
<h2 class="title">{{ 'clientDetailsTitle' | translate }} {{ clientData.name }}</h2>
</div>
<div class="client-container" *ngIf="!loading">
<div class="header-container">
<h2 class="title">{{ 'clientDetailsTitle' | translate }} {{ clientData.name }}</h2>
</div>
<mat-divider></mat-divider>
<div *ngIf="!loading" class="client-info">
<div class="info-section">
<div class="two-column-table">
<div class="table-row" *ngFor="let clientData of generalData">
<div class="column property">{{ clientData?.property }}</div>
<div class="column value">{{ clientData?.value }}</div>
<div class="client-info-card">
<div class="info-columns">
<div class="info-column">
<div class="info-pair" *ngFor="let data of generalData">
<div class="label">{{ data?.property }}</div>
<div class="value">{{ data?.value || '--' }}</div>
</div>
</div>
</div>
<div class="two-column-table">
<div class="table-row" *ngFor="let clientData of networkData">
<div class="column property">{{ clientData?.property }}</div>
<div class="column value">{{ clientData?.value }}</div>
<div class="info-column">
<div class="info-pair" *ngFor="let data of networkData">
<div class="label">{{ data?.property }}</div>
<div class="value">{{ data?.value || '--' }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="header-container">
<h2 class="title" i18n="@@adminImagesTitle">Discos/Particiones</h2>
</div>
<div class="disk-container">
<div class="table-container">
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
<td mat-cell *matCellDef="let image">
<ng-container *ngIf="column.columnDef !== 'size'">
{{ column.cell(image) }}
</ng-container>
<ng-container *ngIf="column.columnDef === 'size'">
<mat-chip color="primary">
{{ (image.size / 1024).toFixed(2) }} GB
</mat-chip>
</ng-container>
</td>
<div class="section-header">
<h2 class="title" i18n="@@adminImagesTitle">Discos/Particiones</h2>
</div>
<div class="disk-container">
<div class="table-container">
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
<td mat-cell *matCellDef="let image">
<ng-container *ngIf="column.columnDef !== 'size'">
{{ column.cell(image) }}
</ng-container>
<ng-container *ngIf="column.columnDef === 'size'">
<mat-chip color="primary">
{{ (image.size / 1024).toFixed(2) }} GB
</mat-chip>
</ng-container>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<div class="charts-container">
<ng-container *ngIf="diskUsageData && diskUsageData.length > 0">
<div *ngFor="let disk of chartDisk" class="disk-usage">
<ngx-charts-pie-chart class="chart" [view]="view" [results]="disk.chartData" [doughnut]="true">
</ngx-charts-pie-chart>
<h3>Disco {{ disk.diskNumber }}</h3>
<p>Usado: {{ (disk.used).toFixed(2) }} GB ({{ disk.percentage }}%)</p>
<p>Total: {{ disk.total }} GB</p>
</div>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
<div class="charts-container">
<ng-container *ngIf="diskUsageData && diskUsageData.length > 0">
<div *ngFor="let disk of chartDisk" class="disk-usage">
<ngx-charts-pie-chart class="chart" [view]="view" [results]="disk.chartData" [doughnut]="true">
</ngx-charts-pie-chart>
<h3>Disco {{ disk.diskNumber }}</h3>
<p>Usado: {{ (disk.used).toFixed(2) }} GB ({{ disk.percentage }}%)</p>
<p>Total: {{ disk.total }} GB</p>
</div>
</ng-container>
</div>
</div>
</div>
</div>
</mat-dialog-content>

View File

@ -198,7 +198,6 @@ export class ClientDetailsComponent {
});
this.diskUsageData = this.chartDisk;
console.log(this.chartDisk)
this.isDiskUsageEmpty = this.diskUsageData.length === 0;
}
@ -216,11 +215,9 @@ export class ClientDetailsComponent {
this.http.get<any>(`${this.baseUrl}/partitions?client.id=${this.clientData.id}&order[diskNumber, partitionNumber]=ASC`).subscribe({
next: data => {
console.log(data)
const filteredPartitions = data['hydra:member'].filter((partition: any) => partition.partitionNumber !== 0);
this.dataSource = filteredPartitions;
this.partitions = filteredPartitions;
console.log(this.partitions)
this.calculateDiskUsage();
},
error: error => {