From 0248067d14a4970cd6a1a81d9606f9a3817f2e69 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Tue, 15 Jul 2025 15:24:53 +0200 Subject: [PATCH] refs #1984. Modify image ogGit --- .../create-image/create-image.component.ts | 47 +- .../deploy-image/deploy-image.component.css | 69 +++ .../deploy-image/deploy-image.component.html | 21 +- .../deploy-image/deploy-image.component.ts | 34 +- .../partition-assistant.component.css | 449 ++++++++++++++++++ .../partition-assistant.component.html | 21 +- .../partition-assistant.component.ts | 133 +++++- 7 files changed, 734 insertions(+), 40 deletions(-) diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.ts b/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.ts index bf413eb..2f4e8d9 100644 --- a/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.ts +++ b/ogWebconsole/src/app/components/groups/components/client-main-view/create-image/create-image.component.ts @@ -263,10 +263,6 @@ export class CreateClientImageComponent implements OnInit{ this.toastService.error('Debes seleccionar un repositorio Git'); return; } - if (this.gitAction === 'update' && !this.selectedExistingImage) { - this.toastService.error('Debes seleccionar un repositorio de imágenes Git'); - return; - } } if (this.imageType === 'monolithic') { @@ -295,24 +291,39 @@ export class CreateClientImageComponent implements OnInit{ if (result !== undefined) { this.loading = true; - let payload: any = { - client: `/clients/${this.clientId}`, - partition: this.selectedPartition['@id'], - source: 'assistant', - type: this.imageType, - queue: result - }; + let endpoint: string; + let payload: any; if (this.imageType === 'git') { - payload.gitRepository = this.selectedGitRepository.name - payload.name = this.selectedGitRepository.name; - - if (this.gitAction === 'create') { - payload.action = 'create'; + if (this.gitAction === 'update') { + endpoint = `${this.baseUrl}/git-repositories/update-image`; + payload = { + client: `/clients/${this.clientId}`, + partition: this.selectedPartition['@id'], + gitRepository: this.selectedGitRepository.name, + queue: result + }; } else { - payload.action = 'update'; + endpoint = `${this.baseUrl}/images`; + payload = { + client: `/clients/${this.clientId}`, + partition: this.selectedPartition['@id'], + type: this.imageType, + gitRepository: this.selectedGitRepository.name, + name: this.selectedGitRepository.name, + action: 'create', + queue: result + }; } } else { + endpoint = `${this.baseUrl}/images`; + payload = { + client: `/clients/${this.clientId}`, + partition: this.selectedPartition['@id'], + type: this.imageType, + queue: result + }; + if (this.monolithicAction === 'create') { payload.name = this.name; payload.action = 'create'; @@ -322,7 +333,7 @@ export class CreateClientImageComponent implements OnInit{ } } - this.http.post(`${this.baseUrl}/images`, payload) + this.http.post(endpoint, payload) .subscribe({ next: (response) => { let actionText = 'creación'; diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.css b/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.css index 8cdb3e0..9c60bbe 100644 --- a/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.css +++ b/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.css @@ -519,4 +519,73 @@ table { } } +.commits-table-container { + margin-top: 20px; +} + +::ng-deep .mat-chip.mat-standard-chip.mat-chip-selected.mat-primary { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + color: white !important; + border-radius: 20px !important; + font-weight: 500 !important; + font-size: 12px !important; + padding: 8px 16px !important; + margin: 2px !important; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3) !important; + transition: all 0.3s ease !important; + border: none !important; +} + +::ng-deep .mat-chip.mat-standard-chip.mat-chip-selected.mat-primary:hover { + transform: translateY(-1px) !important; + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4) !important; +} + +::ng-deep .mat-chip.mat-standard-chip.mat-primary { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; + color: white !important; + border-radius: 20px !important; + font-weight: 500 !important; + font-size: 12px !important; + padding: 8px 16px !important; + margin: 2px !important; + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3) !important; + transition: all 0.3s ease !important; + border: none !important; +} + +::ng-deep .mat-chip.mat-standard-chip.mat-primary:hover { + transform: translateY(-1px) !important; + box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4) !important; +} + +::ng-deep .custom-tag-chip.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary { + background: rgba(102, 126, 234, 0.1) !important; + color: #667eea !important; + border: 1px solid rgba(102, 126, 234, 0.3) !important; + border-radius: 8px !important; + font-weight: 500 !important; + font-size: 10px !important; + padding: 2px 6px !important; + margin: 1px !important; + box-shadow: none !important; + transition: all 0.3s ease !important; +} + +::ng-deep .custom-tag-chip.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary:hover { + background: rgba(102, 126, 234, 0.15) !important; + border-color: rgba(102, 126, 234, 0.5) !important; + transform: translateY(-1px) !important; +} + +.no-tags-text { + color: #999; + font-style: italic; + font-size: 12px; + padding: 4px 8px; + background: #f8f9fa; + border-radius: 12px; + border: 1px dashed #dee2e6; +} + diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.html b/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.html index 442a438..59bf1f5 100644 --- a/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.html +++ b/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.html @@ -129,11 +129,18 @@ hourglass_empty + + + Tag + + No + + + - -
- +
+
@@ -172,7 +182,6 @@
Seleccionar @@ -162,8 +169,11 @@ Tags - {{ tag }} - Sin tags + + {{ tag }} + + Sin tags
-
Seleccione método de deploy diff --git a/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.ts b/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.ts index 707e9e9..54265c6 100644 --- a/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.ts +++ b/ogWebconsole/src/app/components/groups/components/client-main-view/deploy-image/deploy-image.component.ts @@ -109,6 +109,9 @@ export class DeployImageComponent implements OnInit{ selectedCommit: any = null; private initialGitLoad = true; + showOnlyTagged: boolean = false; + filteredCommits: any[] = []; + constructor( private http: HttpClient, private toastService: ToastrService, @@ -387,7 +390,7 @@ export class DeployImageComponent implements OnInit{ } if (this.imageType === 'git') { - if (!this.selectedCommit) { + if (!this.selectedCommit || this.filteredCommits.length === 0) { return false; } } @@ -519,7 +522,9 @@ export class DeployImageComponent implements OnInit{ this.selectedBranch = ''; this.branches = []; this.commits = []; + this.filteredCommits = []; this.selectedCommit = null; + this.showOnlyTagged = false; this.loadGitBranches(); } @@ -545,6 +550,8 @@ export class DeployImageComponent implements OnInit{ onGitBranchChange() { this.selectedCommit = null; this.commits = []; + this.filteredCommits = []; + this.showOnlyTagged = false; this.loadGitCommits(); } @@ -558,6 +565,12 @@ export class DeployImageComponent implements OnInit{ data => { this.commits = data.commits || []; this.loadingCommits = false; + this.filterCommits(); + if (this.filteredCommits.length > 0) { + this.selectedCommit = this.filteredCommits.reduce((a, b) => + new Date(a.committed_date * 1000) > new Date(b.committed_date * 1000) ? a : b + ); + } }, error => { this.toastService.error('Error al cargar los commits'); @@ -565,4 +578,23 @@ export class DeployImageComponent implements OnInit{ } ); } + + filterCommits() { + if (this.showOnlyTagged) { + this.filteredCommits = this.commits.filter(commit => + commit.tags && commit.tags.length > 0 + ); + } else { + this.filteredCommits = this.commits; + } + } + + onTagFilterChange() { + this.filterCommits(); + if (this.filteredCommits.length > 0 && !this.filteredCommits.includes(this.selectedCommit)) { + this.selectedCommit = this.filteredCommits.reduce((a, b) => + new Date(a.committed_date * 1000) > new Date(b.committed_date * 1000) ? a : b + ); + } + } } 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 baaa2b0..87ee533 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 @@ -709,6 +709,454 @@ margin: 5px 0 !important; } +/* ===== LAYOUT PRINCIPAL ===== */ +.partition-layout { + display: flex; + flex-direction: column; + gap: 24px; + margin-top: 20px; +} + +/* ===== BARRA DE PROGRESO DE PARTICIONES ===== */ +.partition-progress-container { + background: white; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + border: 1px solid #e0e0e0; + padding: 24px; + margin-bottom: 20px; +} + +.progress-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + flex-wrap: wrap; + gap: 16px; +} + +.progress-header h3 { + margin: 0; + color: #333; + font-size: 18px; + font-weight: 600; +} + +.disk-info-summary { + display: flex; + gap: 16px; + flex-wrap: wrap; +} + +.disk-info-summary span { + padding: 6px 12px; + border-radius: 6px; + font-size: 14px; + font-weight: 500; +} + +.total-size { + background: #e3f2fd; + color: #1976d2; +} + +.used-size { + background: #fff3e0; + color: #f57c00; +} + +.free-size { + background: #e8f5e8; + color: #388e3c; +} + +.partition-progress-bar { + margin-bottom: 20px; +} + +.progress-segments { + display: flex; + height: 60px; + border-radius: 8px; + overflow: hidden; + border: 2px solid #e0e0e0; + background: #f5f5f5; +} + +.progress-segment { + position: relative; + display: flex; + align-items: center; + justify-content: center; + min-width: 20px; + transition: all 0.3s ease; + cursor: pointer; + border-right: 1px solid rgba(255, 255, 255, 0.3); + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2); +} + +.progress-segment:hover { + filter: brightness(1.2); + transform: scale(1.02); + box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.4), 0 2px 8px rgba(0, 0, 0, 0.2); + z-index: 2; +} + +.progress-segment:last-child { + border-right: none; +} + +.progress-segment.removed { + opacity: 0.3; + background: #ccc !important; +} + +.progress-segment.free-space { + background: linear-gradient(45deg, #e8f5e8, #c8e6c9); + border-left: 1px solid #e0e0e0; +} + +.segment-label { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + color: white; + font-weight: 600; + font-size: 12px; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); + width: 100%; + height: 100%; +} + +.partition-number { + font-size: 14px; + font-weight: bold; +} + +.partition-percentage { + font-size: 10px; + opacity: 0.9; +} + +.free-label { + font-size: 12px; + font-weight: bold; +} + +.free-percentage { + font-size: 10px; + opacity: 0.9; +} + +/* ===== LEYENDA DE PARTICIONES ===== */ +.partition-legend { + display: flex; + flex-wrap: wrap; + gap: 12px; + padding: 20px; + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + border-radius: 12px; + border: 1px solid #e9ecef; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.05); +} + +.legend-item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 16px; + background: white; + border-radius: 8px; + border: 1px solid #e0e0e0; + font-size: 14px; + transition: all 0.3s ease; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.legend-item:hover { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); + transform: translateY(-1px); +} + +.legend-item.removed { + opacity: 0.5; + text-decoration: line-through; +} + +.legend-color { + width: 18px; + height: 18px; + border-radius: 4px; + border: 2px solid rgba(255, 255, 255, 0.8); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transition: all 0.2s ease; +} + +.legend-item:hover .legend-color { + transform: scale(1.1); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); +} + +.legend-color.free-color { + background: linear-gradient(45deg, #e8f5e8, #c8e6c9); +} + +.legend-text { + font-weight: 600; + color: #333; + font-size: 14px; +} + +.legend-size { + font-size: 12px; + color: #666; + font-weight: 500; + background: #f8f9fa; + padding: 2px 6px; + border-radius: 4px; + border: 1px solid #e9ecef; +} + +/* ===== TABLA MAT-TABLE ===== */ +.table-container { + background: white; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + border: 1px solid #e0e0e0; + overflow: hidden; +} + +.table-header { + padding: 20px 24px 16px 24px; + border-bottom: 1px solid #e0e0e0; + background: #f8f9fa; +} + +.table-header h3 { + margin: 0; + color: #333; + font-size: 18px; + font-weight: 600; +} + +.partition-mat-table { + width: 100%; + background: white; +} + +.partition-mat-table .mat-header-cell { + background: #f8f9fa; + color: #495057; + font-weight: 600; + font-size: 14px; + padding: 16px 12px; + border-bottom: 2px solid #e9ecef; +} + +.partition-mat-table .mat-cell { + padding: 12px; + border-bottom: 1px solid #f1f3f4; + vertical-align: middle; +} + +.partition-mat-table .mat-row:hover { + background: #f8f9fa; +} + +/* Campos compactos para la tabla */ +.compact-form-field { + width: 100%; + margin: 0; +} + +.compact-form-field .mat-form-field-wrapper { + padding-bottom: 0; + margin: 0; +} + +.compact-form-field .mat-form-field-infix { + padding: 2px 0; + min-height: 20px; + font-size: 13px; +} + +.compact-form-field .mat-form-field-outline { + border-radius: 4px; +} + +.compact-form-field .mat-form-field-outline-start, +.compact-form-field .mat-form-field-outline-end { + border-width: 1px; +} + +.compact-form-field .mat-form-field-outline-gap { + border-width: 1px; +} + +/* Estilos para inputs y selects compactos */ +.compact-form-field input, +.compact-form-field .mat-select { + line-height: 1.2; +} + +.compact-form-field .mat-select-value { + color: #333; +} + +/* Reducir el padding de las celdas de la tabla */ +.partition-mat-table .mat-cell { + padding: 6px 6px; + vertical-align: middle; +} + +.partition-mat-table .mat-header-cell { + padding: 10px 6px; +} + +/* Hacer los inputs más pequeños */ +.compact-form-field .mat-form-field-infix { + padding: 2px 0; + min-height: 20px; +} + +/* Ajustar el tamaño de los selects */ +.compact-form-field .mat-select-trigger { + height: 20px; +} + +/* Ajustar el tamaño de los inputs numéricos */ +.compact-form-field input[type="number"] { + padding: 2px 6px; +} + +/* Reducir el espacio del wrapper del form field */ +.compact-form-field .mat-form-field-wrapper { + padding-bottom: 0; + margin: 0; + line-height: 1.2; +} + +/* Ajustar el espacio del outline */ +.compact-form-field .mat-form-field-outline { + top: 0; + bottom: 0; +} + +.compact-form-field .mat-form-field-outline-start, +.compact-form-field .mat-form-field-outline-end, +.compact-form-field .mat-form-field-outline-gap { + border-width: 1px; +} + +/* Checkbox en la tabla */ +.partition-mat-table .mat-checkbox { + margin: 0; +} + +/* Botón de eliminar */ +.partition-mat-table .mat-icon-button { + width: 32px; + height: 32px; + line-height: 32px; +} + +.partition-mat-table .mat-icon { + font-size: 18px; + width: 18px; + height: 18px; +} + +/* ===== RESPONSIVE ===== */ +@media (max-width: 768px) { + .partition-layout { + gap: 16px; + } + + .progress-header { + flex-direction: column; + align-items: flex-start; + } + + .disk-info-summary { + width: 100%; + justify-content: space-between; + } + + .partition-legend { + flex-direction: column; + gap: 8px; + } + + .legend-item { + justify-content: space-between; + } + + .partition-mat-table { + font-size: 12px; + } + + .compact-form-field { + font-size: 12px; + } +} + +@media (max-width: 480px) { + .progress-segments { + height: 40px; + } + + .segment-label { + font-size: 10px; + } + + .partition-number { + font-size: 12px; + } + + .partition-percentage { + font-size: 8px; + } + + .partition-mat-table .mat-header-cell, + .partition-mat-table .mat-cell { + padding: 8px 6px; + } +} + +/* ===== ANIMACIONES ===== */ +.progress-segment { + animation: slideIn 0.3s ease-out; +} + +@keyframes slideIn { + from { + opacity: 0; + transform: scaleX(0); + } + to { + opacity: 1; + transform: scaleX(1); + } +} + +.legend-item { + animation: fadeIn 0.3s ease-out; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + /* ===== ESTADOS DE ADVERTENCIA ===== */ /* Advertencia (90% a 99% usado) */ .warning { @@ -847,3 +1295,4 @@ + 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 4624d67..eadd905 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 @@ -256,18 +256,21 @@
-
+

Distribución de Particiones

- - +
+ + +
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 859f0b3..eed1294 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,4 +1,4 @@ -import {Component, EventEmitter, Inject, Input, OnInit, Output} from '@angular/core'; +import {Component, EventEmitter, Inject, Input, OnInit, Output, AfterViewInit, OnDestroy, ViewChild, ElementRef, HostListener} from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { ToastrService } from 'ngx-toastr'; import {ActivatedRoute, Router} from "@angular/router"; @@ -8,6 +8,9 @@ import { ConfigService } from '@services/config.service'; import {CreateTaskComponent} from "../../../../commands/commands-task/create-task/create-task.component"; import {MatDialog} from "@angular/material/dialog"; import {QueueConfirmationModalComponent} from "../../../../../shared/queue-confirmation-modal/queue-confirmation-modal.component"; +import { Subject } from 'rxjs'; +import { takeUntil, debounceTime } from 'rxjs/operators'; +import { MatTableDataSource } from '@angular/material/table'; interface Partition { uuid?: string; @@ -28,7 +31,7 @@ interface Partition { templateUrl: './partition-assistant.component.html', styleUrls: ['./partition-assistant.component.css'] }) -export class PartitionAssistantComponent implements OnInit{ +export class PartitionAssistantComponent implements OnInit, AfterViewInit, OnDestroy{ baseUrl: string; private apiUrl: string; @Output() dataChange = new EventEmitter(); @@ -47,6 +50,10 @@ export class PartitionAssistantComponent implements OnInit{ runScriptContext: any = null; showInstructions = false; + @ViewChild('chartContainer', { static: false }) chartContainer!: ElementRef; + private destroy$ = new Subject(); + private resizeSubject = new Subject(); + view: [number, number] = [300, 200]; showLegend = true; showLabels = true; @@ -55,6 +62,17 @@ export class PartitionAssistantComponent implements OnInit{ selectedModelClient: any = null; partitionCode: string = ''; generatedInstructions: string = ''; + + // Columnas para mat-table + displayedColumns: string[] = ['partitionNumber', 'partitionCode', 'filesystem', 'size', 'percentage', 'format', 'actions']; + + // Paleta de colores para las particiones + private partitionColors = [ + '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', + '#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9', + '#F8C471', '#82E0AA', '#F1948A', '#85C1E9', '#D7BDE2', + '#A8E6CF', '#FFD3B6', '#FFAAA5', '#DCEDC8', '#FFE0B2' + ]; constructor( private http: HttpClient, @@ -90,6 +108,48 @@ export class PartitionAssistantComponent implements OnInit{ this.route.queryParams.subscribe(params => { this.runScriptContext = params['runScriptContext'] ? JSON.parse(params['runScriptContext']) : null; }); + + this.resizeSubject.pipe( + takeUntil(this.destroy$), + debounceTime(100) + ).subscribe(() => { + this.resizeChart(); + }); + } + + ngAfterViewInit(): void { + setTimeout(() => { + this.resizeChart(); + }, 100); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + @HostListener('window:resize') + onResize(): void { + this.resizeSubject.next(); + } + + private resizeChart(): void { + if (this.chartContainer && this.chartContainer.nativeElement) { + const container = this.chartContainer.nativeElement; + const width = container.offsetWidth; + + if (width > 0) { + const height = Math.max(250, Math.min(450, width * 0.7)); + + if (Math.abs(this.view[0] - width) > 10 || Math.abs(this.view[1] - height) > 10) { + this.view = [width, height]; + + setTimeout(() => { + this.view = [...this.view]; + }, 10); + } + } + } } get selectedDisk():any { @@ -135,7 +195,6 @@ export class PartitionAssistantComponent implements OnInit{ initializeDisks() { this.disks = []; - // Verificar que hay datos válidos if (!this.data || !this.data.partitions || !Array.isArray(this.data.partitions)) { console.warn('No hay datos de particiones válidos'); return; @@ -161,10 +220,10 @@ export class PartitionAssistantComponent implements OnInit{ size: this.convertBytesToGB(partition.partitionNumber === 1 && this.partitionCode === 'GPT' ? 512 : partition.size), memoryUsage: partition.memoryUsage, partitionCode: partition.partitionNumber === 1 && this.partitionCode === 'GPT' ? 'EFI' : partition.partitionCode, - filesystem: partition.filesystem, + filesystem: partition.partitionNumber === 1 && this.partitionCode === 'GPT' ? 'FAT32' : partition.filesystem, sizeBytes: partition.partitionNumber === 1 && this.partitionCode === 'GPT' ? 512 : partition.size, format: false, - color: '#1f1b91', + color: this.getColorForPartition(partition.partitionNumber), percentage: 0, removed: false }); @@ -267,12 +326,17 @@ export class PartitionAssistantComponent implements OnInit{ memoryUsage: 0, sizeBytes: 0, format: false, - color: '#' + Math.floor(Math.random() * 16777215).toString(16), + color: this.getNextPartitionColor(), percentage: 0, removed: false }); this.updatePartitionPercentages(disk.partitions, disk.totalDiskSize); this.updateDiskChart(disk); + + // Redimensionar el gráfico después de añadir partición + setTimeout(() => { + this.resizeChart(); + }, 100); } else { this.toastService.error('No hay suficiente espacio libre en el disco para crear una nueva partición.'); } @@ -389,6 +453,11 @@ export class PartitionAssistantComponent implements OnInit{ this.updateDiskChart(disk); this.updatePartitionPercentages(disk.partitions, disk.totalDiskSize); + + // Redimensionar el gráfico después de eliminar partición + setTimeout(() => { + this.resizeChart(); + }, 100); } } @@ -433,6 +502,11 @@ export class PartitionAssistantComponent implements OnInit{ disk.chartData = this.generateChartData(disk.partitions); disk.used = this.calculateUsedSpace(disk.partitions); disk.percentage = (disk.used / disk.totalDiskSize) * 100; + + // Redimensionar el gráfico después de actualizar los datos + setTimeout(() => { + this.resizeChart(); + }, 50); } openScheduleModal(): void { @@ -502,6 +576,11 @@ export class PartitionAssistantComponent implements OnInit{ onDiskSelectionChange() { if (this.selectedDiskNumber) { this.scrollToPartitionTable(); + + // Redimensionar el gráfico después de cambiar de disco + setTimeout(() => { + this.resizeChart(); + }, 150); } } @@ -536,4 +615,46 @@ export class PartitionAssistantComponent implements OnInit{ console.error('No se encontró el botón execute-button'); } } + + getPartitionsDataSource(): MatTableDataSource { + return new MatTableDataSource(this.selectedDisk?.partitions || []); + } + + getPartitionIndex(partition: Partition): number { + return this.selectedDisk?.partitions.findIndex((p: Partition) => p.uuid === partition.uuid) || -1; + } + + getFreeSpacePercentage(): number { + if (!this.selectedDisk) return 0; + return this.selectedDisk.totalDiskSize > 0 ? + ((this.selectedDisk.totalDiskSize - this.selectedDisk.used) / this.selectedDisk.totalDiskSize) * 100 : 0; + } + + /** + * Asigna un color único a una nueva partición + */ + private getNextPartitionColor(): string { + if (!this.selectedDisk) return this.partitionColors[0]; + + const usedColors = this.selectedDisk.partitions + .filter((p: Partition) => !p.removed) + .map((p: Partition) => p.color); + + // Buscar el primer color no usado + for (const color of this.partitionColors) { + if (!usedColors.includes(color)) { + return color; + } + } + + // Si todos están usados, generar uno aleatorio + return this.partitionColors[Math.floor(Math.random() * this.partitionColors.length)]; + } + + /** + * Asigna un color basado en el número de partición + */ + private getColorForPartition(partitionNumber: number): string { + return this.partitionColors[(partitionNumber - 1) % this.partitionColors.length]; + } }