Updated repo/images UX
testing/ogGui-multibranch/pipeline/head This commit looks good Details

pull/12/head
Manuel Aranda Rosales 2025-02-03 11:14:19 +01:00
parent b81db79237
commit 45bf13e63a
16 changed files with 101 additions and 33 deletions

View File

@ -50,7 +50,6 @@ export class ExecuteCommandComponent implements OnInit {
ngOnChanges(changes: SimpleChanges): void {
if (changes['clientData']) {
console.log(this.clientData.length)
console.log('clientData ha cambiado:', changes['clientData'].currentValue);
}
}
@ -94,13 +93,11 @@ export class ExecuteCommandComponent implements OnInit {
}
powerOnClient(): void {
const payload = {
client: ''
}
this.http.post('', payload).subscribe(
this.http.post(`${this.baseUrl}/image-repositories/wol`, {
clients: this.clientData.map((client: any) => client['@id'])
}).subscribe(
response => {
this.toastService.success('Cliente actualizado correctamente');
this.toastService.success('Petición de encendido enviada correctamente');
},
error => {
this.toastService.error('Error de conexión con el cliente');
@ -113,7 +110,7 @@ export class ExecuteCommandComponent implements OnInit {
clients: this.clientData.map((client: any) => client['@id'])
}).subscribe(
response => {
this.toastService.success('Cliente actualizado correctamente');
this.toastService.success('Petición de apagado enviada correctamente');
},
error => {
this.toastService.error('Error de conexión con el cliente');

View File

@ -130,7 +130,9 @@ export class CreateOrganizationalUnitComponent implements OnInit {
loadOgLives() {
this.dataService.getOgLives().subscribe(
(data: any[]) => this.ogLives = data,
(data: any[]) => {
this.ogLives = data
},
error => console.error('Error fetching ogLives', error)
);
}

View File

@ -5,35 +5,34 @@ h1 {
color: #3f51b5;
margin-bottom: 20px;
}
.network-form {
display: flex;
flex-direction: column;
gap: 15px;
}
.form-field {
width: 100%;
margin-top: 10px;
}
.mat-dialog-content {
padding: 20px;
}
.mat-dialog-actions {
display: flex;
justify-content: flex-end;
padding: 10px 20px;
}
button {
text-transform: none;
font-size: 16px;
font-weight: 500;
}
.mat-slide-toggle {
margin-top: 20px;
}

View File

@ -33,7 +33,7 @@
</form>
<!-- Paso 2: Información del Aula -->
<form *ngIf="generalFormGroup.value.type === 'classroom'" [formGroup]="classroomInfoFormGroup">
<form *ngIf="generalFormGroup.value.type === 'classroom'" [formGroup]="classroomInfoFormGroup">
<mat-form-field class="form-field">
<mat-label>{{ 'locationLabel' | translate }}</mat-label>
<input matInput formControlName="location">

View File

@ -90,11 +90,6 @@ export class CreateImageComponent implements OnInit {
}
saveImage(): void {
if (this.imageForm.invalid) {
this.toastService.error('Por favor, rellena los campos obligatorios');
return;
}
const payload: any = {
name: this.imageForm.value.name,
description: this.imageForm.value.description,

View File

@ -91,6 +91,11 @@ table {
color: white;
}
.chip-transferring {
background-color: #f5a623 !important;
color: white;
}
.header-container-title {
flex-grow: 1;
text-align: left;

View File

@ -40,7 +40,8 @@
'chip-failed': image.status === 'failed',
'chip-success': image.status === 'success',
'chip-pending': image.status === 'pending',
'chip-in-progress': image.status === 'in-progress'
'chip-in-progress': image.status === 'in-progress',
'chip-transferring': image.status === 'transferring',
}">
{{ getStatusLabel(image[column.columnDef]) }}
</mat-chip>
@ -65,8 +66,9 @@
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="toggleAction(image, 'get-aux')">Obtener ficheros auxiliares</button>
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'delete-trash')">Eliminar imagen temporalmente</button>
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'delete-permanent')">Eliminar imagen</button>
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'trash'" (click)="toggleAction(image, 'recover')">Recuperar imagen de la papelera</button>
<button mat-menu-item (click)="toggleAction(image, 'export')">Exportar imagen</button>
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'export')">Exportar imagen</button>
</mat-menu>
</td>
</ng-container>

View File

@ -1,15 +1,13 @@
import { Component, OnInit } from '@angular/core';
import {Component, Input, OnInit} from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { HttpClient } from '@angular/common/http';
import { MatTableDataSource } from '@angular/material/table';
import { ToastrService } from 'ngx-toastr';
import { DatePipe } from '@angular/common';
import { CreateImageComponent } from './create-image/create-image.component';
import {CreateCommandComponent} from "../commands/main-commands/create-command/create-command.component";
import {DeleteModalComponent} from "../../shared/delete_modal/delete-modal/delete-modal.component";
import {ServerInfoDialogComponent} from "../ogdhcp/og-dhcp-subnets/server-info-dialog/server-info-dialog.component";
import {Observable} from "rxjs";
import {InfoImageComponent} from "../ogboot/pxe-images/info-image/info-image/info-image.component";
import { JoyrideService } from 'ngx-joyride';
import {ExportImageComponent} from "./export-image/export-image.component";
@ -68,16 +66,34 @@ export class ImagesComponent implements OnInit {
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
private apiUrl = `${this.baseUrl}/images`;
@Input() repositoryUuid: any
private repositoryId: any;
constructor(
public dialog: MatDialog,
private http: HttpClient,
private toastService: ToastrService,
private joyrideService: JoyrideService
private joyrideService: JoyrideService,
) {}
ngOnInit(): void {
this.search();
if (this.repositoryUuid) {
this.loadRepository()
} else {
this.search();
}
}
loadRepository(): void {
this.http.get<any>(`${this.baseUrl}/image-repositories/${this.repositoryUuid}`, {}).subscribe(
data => {
this.repositoryId = data.id;
this.search();
},
error => {
console.error('Error fetching image repositories', error);
}
)
}
getStatusLabel(status: string): string {
@ -111,7 +127,7 @@ export class ImagesComponent implements OnInit {
search(): void {
this.loading = true;
this.http.get<any>(`${this.apiUrl}?page=${this.page +1 }&itemsPerPage=${this.itemsPerPage}`, { params: this.filters }).subscribe(
this.http.get<any>(`${this.apiUrl}?page=${this.page +1 }&itemsPerPage=${this.itemsPerPage}&repository.id=${this.repositoryId}`, { params: this.filters }).subscribe(
data => {
this.dataSource.data = data['hydra:member'];
this.length = data['hydra:totalItems'];
@ -206,6 +222,17 @@ export class ImagesComponent implements OnInit {
}
});
break;
case 'delete-permanent':
this.http.post(`${this.baseUrl}/images/server/${image.uuid}/delete-permanent`, {}).subscribe({
next: () => {
this.toastService.success('Petición de eliminación de la papelera temporal enviada');
this.search()
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
break;
case 'recover':
this.http.post(`${this.baseUrl}/images/server/${image.uuid}/recover`, {}).subscribe({
next: () => {

View File

@ -20,3 +20,20 @@ mat-dialog-actions {
flex-direction: column;
gap: 10px;
}
.selected-list ul {
list-style: none;
padding: 0;
}
.selected-item {
display: flex;
justify-content: space-between; /* Alinea texto a la izquierda y botón a la derecha */
align-items: center; /* Centra verticalmente */
padding: 8px;
border-bottom: 1px solid #ccc;
}
.selected-item button {
margin-left: 10px;
}

View File

@ -7,6 +7,19 @@
<mat-option *ngFor="let image of images" [value]="image['@id']">{{ image.name }}</mat-option>
</mat-select>
</mat-form-field>
<div *ngIf="selectedClients.length > 0" class="selected-list">
<h3>Imágenes seleccionadas:</h3>
<ul>
<li *ngFor="let imageId of selectedClients" class="selected-item">
<span>{{ getImageName(imageId) }}</span>
<button mat-icon-button color="warn" (click)="removeImage(imageId)">
<mat-icon>delete</mat-icon>
</button>
</li>
</ul>
</div>
</mat-dialog-content>
<mat-dialog-actions>

View File

@ -38,6 +38,15 @@ export class ImportImageComponent implements OnInit{
);
}
getImageName(imageId: string): string {
const image = this.images.find(img => img['@id'] === imageId);
return image ? image.name : 'Desconocido';
}
removeImage(imageId: string) {
this.selectedClients = this.selectedClients.filter(id => id !== imageId);
}
save() {
this.http.post<any>(`${this.baseUrl}${this.data.repository['@id']}/import-image`, {
images: this.selectedClients

View File

@ -123,6 +123,6 @@
</mat-tab>
<mat-tab label="Listado de imágenes">
<app-images />
<app-images [repositoryUuid]="repositoryId"></app-images>
</mat-tab>
</mat-tab-group>

View File

@ -41,7 +41,7 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions" style="text-align: center;">Acciones</th>
<td mat-cell *matCellDef="let repository" style="text-align: center;">
<button mat-icon-button color="primary" (click)="importImage($event, repository)" i18n="@@editImage"> <mat-icon>download</mat-icon></button>
<button mat-icon-button color="primary" (click)="importImage($event, repository)" i18n="@@editImage"> <mat-icon>move_to_inbox</mat-icon></button>
<button mat-icon-button color="primary" (click)="editRepository($event, repository)" i18n="@@editImage"> <mat-icon>edit</mat-icon></button>
<button mat-icon-button color="warn" (click)="deleteRepository($event, repository)">
<mat-icon i18n="@@deleteElementTooltip">delete</mat-icon>

View File

@ -283,6 +283,7 @@
"partitionSizeColumn": "Size (MB)",
"usageColumn": "Usage (%)",
"formatColumn": "Format",
"remotePcLabel": "Remote PC",
"ntfsOption": "NTFS",
"linuxOption": "LINUX",
"cacheOption": "CACHE",

View File

@ -301,6 +301,7 @@
"noResultsMessage": "No hay resultados para mostrar.",
"imagesTitle": "Administrar imágenes",
"repositoryTitle": "Administrar repositorios",
"remotePcLabel": "Remote PC",
"addImageButton": "Añadir imagen",
"searchNameDescription": "Busca imágenes por nombre para encontrar rápidamente una imagen específica.",
"searchDefaultDescription": "Filtra las imágenes para mostrar solo las imágenes por defecto o no por defecto.",