Refactor Images/Repositories modules
testing/ogGui-multibranch/pipeline/head There was a failure building this commit Details

pull/18/head
Manuel Aranda Rosales 2025-03-18 17:09:25 +01:00
parent a9dd983f53
commit 335f4683fc
17 changed files with 779 additions and 41 deletions

View File

@ -102,7 +102,7 @@ import { OperativeSystemComponent } from './components/operative-system/operativ
import { CreateOperativeSystemComponent } from './components/operative-system/create-operative-system/create-operative-system.component';
import { ShowTemplateContentComponent } from './components/ogboot/pxe/show-template-content/show-template-content.component';
import { RepositoriesComponent } from './components/repositories/repositories.component';
import { CreateRepositoryComponent } from './components/repositories/create-repository/create-repository.component';
import { ManageRepositoryComponent } from './components/repositories/manage-repository/manage-repository.component';
import { ExecuteCommandComponent } from './components/commands/main-commands/execute-command/execute-command.component';
import { DeployImageComponent } from './components/groups/components/client-main-view/deploy-image/deploy-image.component';
import { MainRepositoryViewComponent } from './components/repositories/main-repository-view/main-repository-view.component';
@ -134,6 +134,7 @@ import { ConvertImageComponent } from './components/repositories/convert-image/c
import { registerLocaleData } from '@angular/common';
import localeEs from '@angular/common/locales/es';
import { GlobalStatusComponent } from './components/global-status/global-status.component';
import { ShowImagesComponent } from './components/repositories/show-images/show-images.component';
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './locale/', '.json');
@ -207,7 +208,7 @@ registerLocaleData(localeEs, 'es-ES');
CreateOperativeSystemComponent,
ShowTemplateContentComponent,
RepositoriesComponent,
CreateRepositoryComponent,
ManageRepositoryComponent,
ExecuteCommandComponent,
ExecuteCommandOuComponent,
DeployImageComponent,
@ -227,7 +228,8 @@ registerLocaleData(localeEs, 'es-ES');
ShowClientsComponent,
OperationResultDialogComponent,
ConvertImageComponent,
GlobalStatusComponent
GlobalStatusComponent,
ShowImagesComponent
],
bootstrap: [AppComponent],
imports: [BrowserModule,

View File

@ -456,4 +456,4 @@ mat-button-toggle-group {
padding: 0.5rem 1rem 1rem 1rem;
width: 100%;
box-sizing: border-box;
}
}

View File

@ -172,6 +172,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
};
this.selectedClients.data = updatedClients;
this.arrayClients = updatedClients;
console.log(`Estado actualizado para el cliente ${clientUuid}: ${newStatus}`);
} else {

View File

@ -38,7 +38,7 @@ export class AddClientsToSubnetComponent implements OnInit {
}
loadUnits() {
this.http.get<any>(`${this.baseUrl}/organizational-units?type=classroom&page=1&itemsPerPage=50`).subscribe(
this.http.get<any>(`${this.baseUrl}/organizational-units?page=1&itemsPerPage=500`).subscribe(
response => {
this.units = response['hydra:member'];
this.loading = false;

View File

@ -97,5 +97,5 @@
</mat-dialog-content>
<mat-dialog-actions class="action-container">
<button class="ordinary-button" (click)="onNoClick()">Cancelar</button>
<button class="ordinary-button" (click)="onNoClick()">Cerrar</button>
</mat-dialog-actions>

View File

@ -73,7 +73,6 @@ export class ShowClientsComponent implements OnInit {
this.loading = false;
}
);
console.log(this.dataSource.data)
}
deleteClient(client: any): void {

View File

@ -10,7 +10,7 @@
<mat-hint>El nombre de la imagen tiene que ir con la extensión. </mat-hint>
</mat-form-field>
<mat-form-field appearance="fill" class="full-width">
<mat-label>Filesystem</mat-label>
<mat-label>Sistema de archivos</mat-label>
<input matInput [(ngModel)]="filesystem" placeholder="Introduzca el sistema de archivos."/>
</mat-form-field>
</mat-dialog-content>

View File

@ -1,5 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CreateRepositoryComponent } from './create-repository.component';
import { CreateRepositoryComponent } from './manage-repository.component';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { ReactiveFormsModule, FormBuilder } from '@angular/forms';

View File

@ -1,4 +1,4 @@
import { Component, Inject } from '@angular/core';
import {Component, Inject, OnInit} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { HttpClient } from "@angular/common/http";
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
@ -7,11 +7,11 @@ import { DataService } from "../../images/data.service";
import { ConfigService } from "@services/config.service";
@Component({
selector: 'app-create-repository',
templateUrl: './create-repository.component.html',
styleUrl: './create-repository.component.css'
selector: 'app-manage-repository',
templateUrl: './manage-repository.component.html',
styleUrl: './manage-repository.component.css'
})
export class CreateRepositoryComponent {
export class ManageRepositoryComponent implements OnInit {
baseUrl: string;
imageForm: FormGroup<any>;
repositoryId: string | null = null;
@ -20,7 +20,7 @@ export class CreateRepositoryComponent {
constructor(
private fb: FormBuilder,
private http: HttpClient,
public dialogRef: MatDialogRef<CreateRepositoryComponent>,
public dialogRef: MatDialogRef<ManageRepositoryComponent>,
private toastService: ToastrService,
private dataService: DataService,
private configService: ConfigService,
@ -28,9 +28,9 @@ export class CreateRepositoryComponent {
) {
this.baseUrl = this.configService.apiUrl;
this.imageForm = this.fb.group({
name: ['', Validators.required],
ip: [''],
comments: [''],
name: [null, Validators.required],
ip: [null],
comments: [null],
});
}
@ -66,23 +66,21 @@ export class CreateRepositoryComponent {
if (this.repositoryId) {
this.http.put(`${this.baseUrl}${this.repositoryId}`, payload).subscribe(
(response) => {
this.toastService.success('Imagen editada correctamente');
this.toastService.success('Repositorio editada correctamente');
this.dialogRef.close();
},
(error) => {
this.toastService.error(error['error']['hydra:description']);
console.error('Error al editar la imagen', error);
}
);
} else {
this.http.post(`${this.baseUrl}/image-repositories`, payload).subscribe(
(response) => {
this.toastService.success('Imagen añadida correctamente');
this.toastService.success('Repositorio añadido correctamente');
this.dialogRef.close();
},
(error) => {
this.toastService.error(error['error']['hydra:description']);
console.error('Error al añadir la imagen', error);
}
);
}

View File

@ -37,19 +37,12 @@
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
<td mat-cell *matCellDef="let repository">
<ng-container [ngSwitch]="column.columnDef">
<ng-container *ngSwitchCase="'status'">
<mat-chip [ngClass]="{
'chip-success': repository.status === true ,
'chip-failed': repository.status === false
}">
{{ repository.status === true ? 'Conectado' : 'Fallido' }}
</mat-chip>
</ng-container>
<ng-container *ngSwitchDefault>
<ng-container *ngIf="column.columnDef !== 'images'">
{{ column.cell(repository) }}
</ng-container>
</ng-container>
<ng-container *ngIf="column.columnDef === 'images'">
<button class="action-button" (click)="openShowImagesDialog(repository)">Gestionar Imágenes</button>
</ng-container>
</td>
</ng-container>

View File

@ -6,9 +6,11 @@ import {HttpClient} from "@angular/common/http";
import {ToastrService} from "ngx-toastr";
import {DeleteModalComponent} from "../../shared/delete_modal/delete-modal/delete-modal.component";
import { JoyrideService } from 'ngx-joyride';
import {CreateRepositoryComponent} from "./create-repository/create-repository.component";
import { Router } from '@angular/router';
import { ConfigService } from '@services/config.service';
import {Subnet} from "../ogdhcp/og-dhcp-subnets.component";
import {ShowImagesComponent} from "./show-images/show-images.component";
import {ManageRepositoryComponent} from "./manage-repository/manage-repository.component";
@Component({
selector: 'app-repositories',
@ -42,9 +44,9 @@ export class RepositoriesComponent implements OnInit {
cell: (repository: any) => `${repository.ip}`
},
{
columnDef: 'status',
header: 'Estado',
cell: (repository: any) => `${repository.status}`
columnDef: 'images',
header: 'Imágenes',
cell: (repository: any) => `${repository.images}`
},
{
columnDef: 'createdAt',
@ -52,7 +54,7 @@ export class RepositoriesComponent implements OnInit {
cell: (repository: any) => `${this.datePipe.transform(repository.createdAt, 'dd/MM/yyyy hh:mm:ss')}`
}
];
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
displayedColumns: string[] = ['id', 'name', 'ip', 'images', 'createdAt', 'actions'];
constructor(
public dialog: MatDialog,
@ -71,7 +73,7 @@ export class RepositoriesComponent implements OnInit {
}
addImage(): void {
const dialogRef = this.dialog.open(CreateRepositoryComponent, {
const dialogRef = this.dialog.open(ManageRepositoryComponent, {
width: '600px'
});
@ -97,7 +99,10 @@ export class RepositoriesComponent implements OnInit {
editRepository(event: MouseEvent, repository: any): void {
event.stopPropagation();
this.router.navigate(['repository', repository.uuid]);
this.dialog.open(ManageRepositoryComponent, {
width: '600px',
data: repository['@id']
}).afterClosed().subscribe(() => this.search());
}
deleteRepository(event: MouseEvent,command: any): void {
@ -120,6 +125,21 @@ export class RepositoriesComponent implements OnInit {
});
}
openShowImagesDialog(repository: Subnet) {
const dialogRef = this.dialog.open(ShowImagesComponent, {
width: '100vw',
height: '100vh',
maxWidth: '100vw',
maxHeight: '100vh',
data: { repositoryId: repository.id, repositoryName: repository.name, repositoryUuid: repository.uuid }
});
dialogRef.afterClosed().subscribe(result => {
this.search();
});
}
onPageChange(event: any): void {
this.page = event.pageIndex;
this.itemsPerPage = event.pageSize;

View File

@ -0,0 +1,202 @@
table {
width: 100%;
}
.search-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin: 1.5rem 0rem 1.5rem 0rem;
box-sizing: border-box;
}
.search-string {
flex: 2;
padding: 5px;
}
.search-boolean {
flex: 1;
padding: 5px;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 10px;
border-bottom: 1px solid #ddd;
}
.mat-elevation-z8 {
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
}
.paginator-container {
display: flex;
justify-content: end;
margin-bottom: 30px;
}
.example-headers-align .mat-expansion-panel-header-description {
justify-content: space-between;
align-items: center;
}
.example-headers-align .mat-mdc-form-field + .mat-mdc-form-field {
margin-left: 8px;
}
.button-row {
display: table-cell;
max-width: 600px;
}
.button-row .mat-mdc-button-base {
margin: 8px 8px 8px 0;
}
.chip-failed {
background-color: #e87979 !important;
color: white;
}
.chip-success {
background-color: #46c446 !important;
color: white;
}
.chip-pending {
background-color: lightgrey !important;
color: black;
}
.chip-in-progress {
background-color: #f5a623 !important;
color: white;
}
.chip-transferring {
background-color: #f5a623 !important;
color: white;
}
.header-container-title {
flex-grow: 1;
text-align: left;
margin-left: 1em;
}
.images-button-row {
display: flex;
gap: 15px;
padding: 5px;
}
table {
width: 100%;
}
.search-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin: 1.5rem 0rem 1.5rem 0rem;
box-sizing: border-box;
}
.search-string {
flex: 2;
padding: 5px;
}
.search-boolean {
flex: 1;
padding: 5px;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 10px;
border-bottom: 1px solid #ddd;
}
.mat-elevation-z8 {
box-shadow: 0px 0px 0px rgba(0,0,0,0.2);
}
.paginator-container {
display: flex;
justify-content: end;
margin-bottom: 30px;
}
.example-headers-align .mat-expansion-panel-header-description {
justify-content: space-between;
align-items: center;
}
.example-headers-align .mat-mdc-form-field + .mat-mdc-form-field {
margin-left: 8px;
}
.button-row {
display: table-cell;
max-width: 600px;
}
.button-row .mat-mdc-button-base {
margin: 8px 8px 8px 0;
}
.chip-failed {
background-color: #e87979 !important;
color: white;
}
.chip-success {
background-color: #46c446 !important;
color: white;
}
.chip-pending {
background-color: lightgrey !important;
color: black;
}
.chip-in-progress {
background-color: #f5a623 !important;
color: white;
}
.chip-transferring {
background-color: #f5a623 !important;
color: white;
}
.action-container {
display: flex;
justify-content: flex-end;
gap: 1em;
padding: 1.5em;
}
.header-container-title {
flex-grow: 1;
text-align: left;
margin-left: 1em;
}
.images-button-row {
display: flex;
gap: 15px;
padding: 5px;
}

View File

@ -0,0 +1,116 @@
<app-loading [isLoading]="loading"></app-loading>
<h2 mat-dialog-title>Gestionar imágenes en {{data.repositoryName}}</h2>
<mat-dialog-content>
<div class="header-container">
<button mat-icon-button color="primary" (click)="iniciarTour()">
<mat-icon>help</mat-icon>
</button>
<div class="header-container-title">
</div>
<div class="images-button-row">
<button class="action-button" (click)="openImageInfoDialog()">Ver Información</button>
</div>
<div class="images-button-row">
<button class="action-button" (click)="syncRepository()">Sincronizar base de datos</button>
</div>
<div class="images-button-row">
<button class="action-button" (click)="importImage()">
{{ 'importImageButton' | translate }}
</button>
</div>
<div class="images-button-row">
<button class="action-button" (click)="convertImage()">
{{ 'convertImageButton' | translate }}
</button>
</div>
</div>
<div class="search-container">
<mat-form-field appearance="fill" class="search-string" joyrideStep="searchImagesField" text="Busca una imagen por nombre. Pulsa 'enter' para iniciar la búsqueda.">
<mat-label>{{ 'searchLabel' | translate }}</mat-label>
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" (keyup.enter)="loadData()" i18n-placeholder="@@searchPlaceholder">
<mat-icon matSuffix>search</mat-icon>
<mat-hint>{{ 'searchHint' | translate }}</mat-hint>
</mat-form-field>
<mat-form-field appearance="fill" class="search-boolean">
<mat-label i18n="@@searchLabel">Estado</mat-label>
<mat-select [(ngModel)]="filters['status']" (selectionChange)="loadData()" placeholder="Seleccionar opción" >
<mat-option [value]="'failed'">Fallido</mat-option>
<mat-option [value]="'pending'">Pendiente</mat-option>
<mat-option [value]="'in-progress'">Transfiriendo</mat-option>
<mat-option [value]="'success'">Creado con éxito</mat-option>
<mat-option [value]="'transferring'">En progreso</mat-option>
<mat-option [value]="'trash'">Papelera</mat-option>
<mat-option [value]="'aux-files-pending'">Creando archivos auxiliares</mat-option>
</mat-select>
</mat-form-field>
</div>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8" joyrideStep="imagesTable" text="Esta tabla muestra las imágenes disponibles.">
<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 === 'remotePc' || column.columnDef === 'isGlobal'">
<mat-icon [color]="image.image[column.columnDef] ? 'primary' : 'warn'">
{{ image.image[column.columnDef] ? 'check_circle' : 'cancel' }}
</mat-icon>
</ng-container>
<ng-container *ngIf="column.columnDef === 'status'">
<mat-chip [ngClass]="{
'chip-failed': image.status === 'failed',
'chip-success': image.status === 'success',
'chip-pending': image.status === 'pending',
'chip-in-progress': image.status === 'in-progress',
'chip-transferring': image.status === 'transferring',
}">
{{ getStatusLabel(image[column.columnDef]) }}
</mat-chip>
</ng-container>
<ng-container *ngIf="column.columnDef !== 'remotePc' && column.columnDef !== 'status' && column.columnDef !== 'isGlobal'">
{{ column.cell(image) }}
</ng-container>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions" style="text-align: center;">Acciones</th>
<td mat-cell *matCellDef="let image" style="text-align: center;">
<button mat-icon-button color="info" (click)="showImageInfo($event, image)"><mat-icon i18n="@@deleteElementTooltip">visibility</mat-icon></button>
<button mat-icon-button color="warn" (click)="toggleAction(image, 'delete-trash')">
<mat-icon i18n="@@deleteElementTooltip">delete</mat-icon>
</button>
<button mat-icon-button [matMenuTriggerFor]="menu">
<mat-icon>menu</mat-icon>
</button>
<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-permanent')">Eliminar permanentemente</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 [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'transfer')">Transferir imagen</button>
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'transfer-global')">Transferir imagen globalmente </button>
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'backup')">Realizar backup </button>
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'status')">Checkear estado imagen </button>
</mat-menu>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<div class="paginator-container">
<mat-paginator [length]="length"
[pageSize]="itemsPerPage"
[pageIndex]="page"
[pageSizeOptions]="[5, 10, 20, 40, 100]"
(page)="onPageChange($event)">
</mat-paginator>
</div>
</mat-dialog-content>
<mat-dialog-actions class="action-container">
<button class="ordinary-button" (click)="onNoClick()">Cerrar</button>
</mat-dialog-actions>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ShowImagesComponent } from './show-images.component';
describe('ShowImagesComponent', () => {
let component: ShowImagesComponent;
let fixture: ComponentFixture<ShowImagesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ShowImagesComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ShowImagesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,384 @@
import {Component, Inject, Input, isDevMode, OnInit} from '@angular/core';
import {MatTableDataSource} from "@angular/material/table";
import {DatePipe} from "@angular/common";
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from "@angular/material/dialog";
import {HttpClient} from "@angular/common/http";
import {ToastrService} from "ngx-toastr";
import {JoyrideService} from "ngx-joyride";
import {ConfigService} from "@services/config.service";
import {Router} from "@angular/router";
import {Observable} from "rxjs";
import {ServerInfoDialogComponent} from "../../ogdhcp/server-info-dialog/server-info-dialog.component";
import {ImportImageComponent} from "../import-image/import-image.component";
import {ConvertImageComponent} from "../convert-image/convert-image.component";
import {DeleteModalComponent} from "../../../shared/delete_modal/delete-modal/delete-modal.component";
import {ExportImageComponent} from "../../images/export-image/export-image.component";
import {BackupImageComponent} from "../backup-image/backup-image.component";
@Component({
selector: 'app-show-images',
templateUrl: './show-images.component.html',
styleUrl: './show-images.component.css'
})
export class ShowImagesComponent implements OnInit {
baseUrl: string;
private apiUrl: string;
dataSource = new MatTableDataSource<any>();
length: number = 0;
itemsPerPage: number = 10;
page: number = 0;
loading: boolean = false;
filters: { [key: string]: string } = {};
alertMessage: string | null = null;
repository: any = {};
datePipe: DatePipe = new DatePipe('es-ES');
columns = [
{
columnDef: 'id',
header: 'Id',
cell: (image: any) => `${image.id}`
},
{
columnDef: 'name',
header: 'Nombre de imagen',
cell: (image: any) => `${image.image.name}`
},
{
columnDef: 'remotePc',
header: 'Remote Pc',
cell: (image: any) => `${image.image?.remotePc}`
},
{
columnDef: 'isGlobal',
header: 'Imagen global',
cell: (image: any) => `${image.image?.isGlobal}`
},
{
columnDef: 'status',
header: 'Estado',
cell: (image: any) => `${image.status}`
},
{
columnDef: 'imageFullsum',
header: 'Fullsum',
cell: (image: any) => `${image.imageFullsum}`
},
{
columnDef: 'createdAt',
header: 'Fecha de creación',
cell: (image: any) => `${this.datePipe.transform(image.createdAt, 'dd/MM/yyyy hh:mm:ss')}`
}
];
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
constructor(
public dialog: MatDialog,
private http: HttpClient,
private toastService: ToastrService,
private joyrideService: JoyrideService,
private configService: ConfigService,
private router: Router,
public dialogRef: MatDialogRef<ShowImagesComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {
this.baseUrl = this.configService.apiUrl;
this.apiUrl = `${this.baseUrl}/image-image-repositories`;
}
ngOnInit(): void {
console.error()
if (this.data) {
this.loadData();
}
}
loadData(): void {
this.loading = true;
this.http.get<any>(`${this.apiUrl}?page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}&repository.id=${this.data.repositoryId}`, { params: this.filters }).subscribe(
data => {
this.dataSource.data = data['hydra:member'];
this.length = data['hydra:totalItems'];
this.loading = false;
},
error => {
console.error('Error fetching image repositories', error);
}
)
}
getStatusLabel(status: string): string {
switch (status) {
case 'pending':
return 'Pendiente';
case 'in-progress':
return 'En progreso';
case 'aux-files-pending':
return 'Archivos auxiliares pendientes';
case 'success':
return 'Creado con éxito';
case 'trash':
return 'Papelera temporal';
case 'failed':
return 'Fallido';
case 'transferring':
return 'Transfiriendo';
default:
return 'Estado desconocido';
}
}
onPageChange(event: any): void {
this.page = event.pageIndex;
this.itemsPerPage = event.pageSize;
this.length = event.length;
this.loadData();
}
loadImageAlert(image: any): Observable<any> {
return this.http.get<any>(`${this.apiUrl}/server/${image.uuid}/get`, {});
}
showImageInfo(event: MouseEvent, image:any) {
event.stopPropagation();
this.loading = true;
this.loadImageAlert(image).subscribe(
response => {
this.alertMessage = response;
this.dialog.open(ServerInfoDialogComponent, {
width: '800px',
data: {
message: this.alertMessage
}
});
this.loading = false;
},
error => {
this.toastService.error(error.error['hydra:description']);
this.loading = false;
}
);
}
importImage(): void {
this.dialog.open(ImportImageComponent, {
width: '600px',
data: {
repositoryUuid: this.data.repositoryUuid,
name: this.repository.name
}
}).afterClosed().subscribe((result) => {
if (result) {
this.loadData();
}
});
}
convertImage(): void {
this.dialog.open(ConvertImageComponent, {
width: '600px',
data: {
repositoryUuid: this.data.repositoryUuid,
name: this.repository.name
}
}).afterClosed().subscribe((result) => {
if (result) {
this.loadData();
}
});
}
toggleAction(image: any, action:string): void {
switch (action) {
case 'get-aux':
this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/create-aux-files`, {}).subscribe({
next: (message) => {
this.toastService.success('Petición de creación de archivos auxiliares enviada');
this.loadData()
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
break;
case 'delete-trash':
if (!image.imageFullsum) {
const dialogRef = this.dialog.open(DeleteModalComponent, {
width: '400px',
data: { name: image.name },
});
dialogRef.afterClosed().subscribe((result) => {
this.http.delete(`${this.baseUrl}${image['@id']}`).subscribe({
next: () => {
this.toastService.success('Image deleted successfully');
this.loadData()
},
error: (error) => {
this.toastService.error('Error deleting image');
}
});
});
} else {
this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/delete-trash`,
{ repository: `/image-repositories/${this.data.repositoryUuid}` })
.subscribe({
next: () => {
this.toastService.success('Petición de eliminación de la papelera temporal enviada');
this.loadData()
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
}
break;
case 'delete-permanent':
this.dialog.open(DeleteModalComponent, {
width: '300px',
data: { name: image.name },
}).afterClosed().subscribe((result) => {
if (result) {
this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/delete-permanent`, {}).subscribe({
next: () => {
this.toastService.success('Petición de eliminación de la papelera temporal enviada');
this.loadData()
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
}
});
break;
case 'recover':
this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/recover`, {}).subscribe({
next: () => {
this.toastService.success('Petición de recuperación de la imagen enviada');
this.loadData()
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
break;
case 'status':
this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/status`, {}).subscribe({
next: (response: any) => {
this.toastService.info(response?.output);
this.loadData()
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
break;
case 'transfer':
this.http.get(`${this.baseUrl}${image.image['@id']}`).subscribe({
next: (response) => {
this.dialog.open(ExportImageComponent, {
width: '600px',
data: {
image: response,
imageImageRepository: image
}
});
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
break;
case 'transfer-global':
this.http.post<any>(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/transfer-global`, {
}).subscribe({
next: (response) => {
this.toastService.success('Petición de exportación de imagen realizada correctamente');
this.loading = false;
this.router.navigate(['/commands-logs']);
},
error: error => {
this.loading = false;
this.toastService.error('Error en la petición de exportación de imagen');
}
});
break;
case 'backup':
this.http.get(`${this.baseUrl}${image.image['@id']}`).subscribe({
next: (response) => {
this.dialog.open(BackupImageComponent, {
width: '600px',
data: {
image: response,
imageImageRepository: image
}
});
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
break;
default:
console.error('Acción no soportada:', action);
break;
}
}
iniciarTour(): void {
this.joyrideService.startTour({
steps: [
'imagesTitleStep',
'addImageButton',
'searchImagesField',
'imagesTable',
'actionsHeader',
'editImageButton',
'deleteImageButton',
'imagesPagination'
],
showPrevButton: true,
themeColor: '#3f51b5'
});
}
loadAlert(): Observable<any> {
return this.http.post<any>(`${this.baseUrl}/image-repositories/server/${this.data.repositoryUuid}/get-collection`, {});
}
syncRepository() {
this.http.post(`${this.baseUrl}/image-repositories/server/${this.data.repositoryUuid}/sync`, {})
.subscribe(response => {
this.toastService.success('Sincronización completada');
this.loadData()
}, error => {
console.error('Error al sincronizar', error);
this.toastService.error('Error al sincronizar');
});
}
openImageInfoDialog() {
this.loadAlert().subscribe(
response => {
this.alertMessage = response.output;
this.dialog.open(ServerInfoDialogComponent, {
width: '800px',
data: {
message: this.alertMessage
}
});
},
error => {
console.error('Error al cargar la información del alert', error);
}
);
}
onNoClick(): void {
this.dialogRef.close();
}
protected readonly isDevMode = isDevMode;
}