refs #1472. Changes in images and imageRepo
testing/ogGui-multibranch/pipeline/head This commit looks good
Details
testing/ogGui-multibranch/pipeline/head This commit looks good
Details
parent
c8c1bdd0bd
commit
9669202dbd
|
@ -127,6 +127,8 @@ import { CreateMultipleClientComponent } from './components/groups/shared/client
|
|||
import { ExportImageComponent } from './components/images/export-image/export-image.component';
|
||||
import {ImportImageComponent} from "./components/repositories/import-image/import-image.component";
|
||||
import { LoadingComponent } from './shared/loading/loading.component';
|
||||
import { RepositoryImagesComponent } from './components/repositories/repository-images/repository-images.component';
|
||||
import { InputDialogComponent } from './components/commands/commands-task/task-logs/input-dialog/input-dialog.component';
|
||||
export function HttpLoaderFactory(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, './locale/', '.json');
|
||||
}
|
||||
|
@ -212,6 +214,8 @@ export function HttpLoaderFactory(http: HttpClient) {
|
|||
ExportImageComponent,
|
||||
ImportImageComponent,
|
||||
LoadingComponent,
|
||||
RepositoryImagesComponent,
|
||||
InputDialogComponent,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [BrowserModule,
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<h1 mat-dialog-title>{{ 'inputDetails' | translate }}</h1>
|
||||
<div mat-dialog-content>
|
||||
<pre>{{ data.input | json }}</pre>
|
||||
</div>
|
||||
<div mat-dialog-actions align="end">
|
||||
<button mat-button (click)="close()">{{ 'closeButton' | translate }}</button>
|
||||
</div>
|
|
@ -0,0 +1,47 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { InputDialogComponent } from './input-dialog.component';
|
||||
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from "@angular/material/dialog";
|
||||
import {FormBuilder} from "@angular/forms";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {provideHttpClientTesting} from "@angular/common/http/testing";
|
||||
import {TranslateModule} from "@ngx-translate/core";
|
||||
|
||||
describe('InputDialogComponent', () => {
|
||||
let component: InputDialogComponent;
|
||||
let fixture: ComponentFixture<InputDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [InputDialogComponent],
|
||||
imports: [
|
||||
MatDialogModule,
|
||||
TranslateModule.forRoot(),
|
||||
],
|
||||
providers: [
|
||||
FormBuilder,
|
||||
ToastrService,
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
{
|
||||
provide: MatDialogRef,
|
||||
useValue: {}
|
||||
},
|
||||
{
|
||||
provide: MAT_DIALOG_DATA,
|
||||
useValue: {}
|
||||
}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(InputDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'app-input-dialog',
|
||||
templateUrl: './input-dialog.component.html',
|
||||
styleUrl: './input-dialog.component.css'
|
||||
})
|
||||
export class InputDialogComponent {
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<InputDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { input: any }
|
||||
) {}
|
||||
|
||||
close(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
|
@ -61,30 +61,42 @@
|
|||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||
<td mat-cell *matCellDef="let trace">
|
||||
|
||||
<ng-container *ngIf="column.columnDef === 'status'; else defaultCell">
|
||||
<mat-chip [ngClass]="{
|
||||
'chip-failed': trace.status === 'failed',
|
||||
'chip-success': trace.status === 'success',
|
||||
'chip-pending': trace.status === 'pending',
|
||||
'chip-in-progress': trace.status === 'in-progress'
|
||||
}">
|
||||
{{
|
||||
trace.status === 'failed' ? 'Fallido' :
|
||||
trace.status === 'success' ? 'Finalizado con éxito' :
|
||||
trace.status === 'pending' ? 'Pendiente de ejecutar' :
|
||||
trace.status === 'in-progress' ? 'Ejecutando' :
|
||||
trace.status
|
||||
}}
|
||||
</mat-chip>
|
||||
</ng-container>
|
||||
<ng-container [ngSwitch]="column.columnDef">
|
||||
<!-- Caso para "status" -->
|
||||
<ng-container *ngSwitchCase="'status'">
|
||||
<mat-chip [ngClass]="{
|
||||
'chip-failed': trace.status === 'failed',
|
||||
'chip-success': trace.status === 'success',
|
||||
'chip-pending': trace.status === 'pending',
|
||||
'chip-in-progress': trace.status === 'in-progress'
|
||||
}">
|
||||
{{
|
||||
trace.status === 'failed' ? 'Fallido' :
|
||||
trace.status === 'success' ? 'Finalizado con éxito' :
|
||||
trace.status === 'pending' ? 'Pendiente de ejecutar' :
|
||||
trace.status === 'in-progress' ? 'Ejecutando' :
|
||||
trace.status
|
||||
}}
|
||||
</mat-chip>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #defaultCell>
|
||||
{{ column.cell(trace) }}
|
||||
</ng-template>
|
||||
<!-- Caso para "input" con modal -->
|
||||
<ng-container *ngSwitchCase="'input'">
|
||||
<button mat-icon-button (click)="openInputModal(trace.input)">
|
||||
<mat-icon>info</mat-icon>
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
<!-- Para cualquier otro caso (default) -->
|
||||
<ng-container *ngSwitchDefault>
|
||||
{{ column.cell(trace) }}
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
@ -94,4 +106,4 @@
|
|||
<mat-paginator [length]="length" [pageSize]="itemsPerPage" [pageIndex]="page" [pageSizeOptions]="pageSizeOptions"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,6 +5,8 @@ import { FormControl } from '@angular/forms';
|
|||
import { map, startWith } from 'rxjs/operators';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { JoyrideService } from 'ngx-joyride';
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {InputDialogComponent} from "./input-dialog/input-dialog.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-logs',
|
||||
|
@ -50,6 +52,11 @@ export class TaskLogsComponent implements OnInit {
|
|||
header: 'Hilo de trabajo',
|
||||
cell: (trace: any) => `${trace.jobId}`
|
||||
},
|
||||
{
|
||||
columnDef: 'input',
|
||||
header: 'Input',
|
||||
cell: (trace: any) => `${trace.input}`
|
||||
},
|
||||
{
|
||||
columnDef: 'output',
|
||||
header: 'Logs',
|
||||
|
@ -75,7 +82,9 @@ export class TaskLogsComponent implements OnInit {
|
|||
commandControl = new FormControl();
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private joyrideService: JoyrideService) {}
|
||||
private joyrideService: JoyrideService,
|
||||
private dialog: MatDialog
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadTraces();
|
||||
|
@ -121,6 +130,13 @@ export class TaskLogsComponent implements OnInit {
|
|||
this.loadTraces();
|
||||
}
|
||||
|
||||
openInputModal(inputData: any): void {
|
||||
this.dialog.open(InputDialogComponent, {
|
||||
width: '700px',
|
||||
data: { input: inputData }
|
||||
});
|
||||
}
|
||||
|
||||
loadTraces(): void {
|
||||
this.loading = true;
|
||||
const url = `${this.baseUrl}/traces?page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}`;
|
||||
|
|
|
@ -52,8 +52,9 @@
|
|||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Seleccione imagen</mat-label>
|
||||
<mat-select [(ngModel)]="selectedImage" name="selectedImage">
|
||||
<mat-option *ngFor="let image of images" [value]="image['@id']">{{ image.name }}</mat-option>
|
||||
<mat-option *ngFor="let image of images" [value]="image">{{ image.image?.name }}</mat-option>
|
||||
</mat-select>
|
||||
<mat-hint *ngIf="clientData">Imágenes alojadas en {{ clientData[0].repository?.name }}</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
|
|
|
@ -19,7 +19,7 @@ export class DeployImageComponent {
|
|||
partitions: any[] = [];
|
||||
images: any[] = [];
|
||||
clientName: string = '';
|
||||
selectedImage: string | null = null;
|
||||
selectedImage: any = null;
|
||||
selectedOption: string | null = 'deploy-image';
|
||||
selectedMethod: string | null = null;
|
||||
selectedPartition: any = null;
|
||||
|
@ -139,10 +139,25 @@ export class DeployImageComponent {
|
|||
}
|
||||
|
||||
loadImages() {
|
||||
const url = `${this.baseUrl}/images?status=success&page=1&itemsPerPage=1000`;
|
||||
if (!this.clientData || this.clientData.length === 0 || !this.clientData[0]) {
|
||||
console.error('Error: clientData es nulo, indefinido o vacío.');
|
||||
return;
|
||||
}
|
||||
|
||||
const repositoryId =
|
||||
this.clientData[0]?.repository?.id ??
|
||||
this.clientData[0]?.organizationalUnit?.networkSettings?.repository?.id;
|
||||
|
||||
if (!repositoryId) {
|
||||
console.error('Error: No se encontró repositoryId en clientData.');
|
||||
return;
|
||||
}
|
||||
|
||||
const url = `${this.baseUrl}/image-image-repositories?status=success&repository.id=${repositoryId}&page=1&itemsPerPage=1000`;
|
||||
|
||||
this.http.get(url).subscribe(
|
||||
(response: any) => {
|
||||
this.images = response['hydra:member'];
|
||||
this.images = response?.['hydra:member'] || [];
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error al cargar las imágenes:', error);
|
||||
|
@ -189,7 +204,7 @@ export class DeployImageComponent {
|
|||
maxClients: this.mcastMaxClients,
|
||||
};
|
||||
|
||||
this.http.post(`${this.baseUrl}${this.selectedImage}/deploy-image`, payload)
|
||||
this.http.post(`${this.baseUrl}/image-image-repositories/${this.selectedImage.uuid}/deploy-image`, payload)
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
this.toastService.success('Petición de despliegue enviada correctamente');
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<mat-form-field appearance="fill" class="form-field">
|
||||
<mat-label>{{ 'repositoryLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="imageRepositories" required multiple>
|
||||
<mat-option *ngFor="let imageRepository of repositories" [value]="imageRepository['@id']">
|
||||
<mat-option *ngFor="let imageRepository of repositories" [value]="imageRepository['@id']" [disabled]="imageId !== null">
|
||||
{{ imageRepository.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
|
|
@ -54,7 +54,7 @@ export class CreateImageComponent implements OnInit {
|
|||
remotePc: [response.remotePc],
|
||||
isGlobal: [response.isGlobal],
|
||||
softwareProfile: [response.softwareProfile ? response.softwareProfile['@id'] : null, Validators.required],
|
||||
imageRepositories: [response.imageRepositories ? response.imageRepositories.map((r: any) => r['@id']) : [], Validators.required],
|
||||
imageRepositories: [response.imageRepositories ? response.imageRepositories.map((r: any) => r.imageRepository['@id']) : [], Validators.required],
|
||||
});
|
||||
this.imageId = response['@id'];
|
||||
this.partitionInfo = response.partitionInfo;
|
||||
|
|
|
@ -25,18 +25,6 @@
|
|||
<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)="search()" 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"
|
||||
|
@ -53,7 +41,7 @@
|
|||
<button mat-button [matMenuTriggerFor]="menu">Ver repositorios</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item *ngFor="let repository of image.imageRepositories">
|
||||
{{ repository.name }}
|
||||
{{ repository.imageRepository.name }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
</ng-container>
|
||||
|
@ -62,19 +50,7 @@
|
|||
{{ 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.columnDef !== 'imageRepositories'">
|
||||
<ng-container *ngIf="column.columnDef !== 'remotePc' && column.columnDef !== 'status' && column.columnDef !== 'isGlobal' && column.columnDef !== 'imageRepositories'">
|
||||
{{ column.cell(image) }}
|
||||
</ng-container>
|
||||
</td>
|
||||
|
@ -83,24 +59,15 @@
|
|||
<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="primary" (click)="editImage($event, image)" i18n="@@editImage">
|
||||
<mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="warn" (click)="toggleAction(image, 'delete-trash')">
|
||||
<button mat-icon-button color="primary" (click)="editImage($event, image)" i18n="@@editImage"> <mat-icon>edit</mat-icon></button>
|
||||
<button *ngIf="repositoryUuid" 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 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 [disabled]="!image.imageFullsum || image.status !== 'success'"
|
||||
(click)="toggleAction(image, 'transfer')">Transferir imagen</button>
|
||||
<button mat-menu-item (click)="toggleAction(image, 'transfer')">Transferir imagen</button>
|
||||
</mat-menu>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
@ -112,4 +79,4 @@
|
|||
<mat-paginator [length]="length" [pageSize]="itemsPerPage" [pageIndex]="page" [pageSizeOptions]="[5, 10, 20, 40, 100]"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -52,11 +52,6 @@ export class ImagesComponent implements OnInit {
|
|||
header: 'Imagen Global',
|
||||
cell: (image: any) => `${image.isGlobal}`
|
||||
},
|
||||
{
|
||||
columnDef: 'status',
|
||||
header: 'Estado',
|
||||
cell: (image: any) => `${image.status}`
|
||||
},
|
||||
{
|
||||
columnDef: 'createdAt',
|
||||
header: 'Fecha de creación',
|
||||
|
@ -96,27 +91,6 @@ export class ImagesComponent implements OnInit {
|
|||
)
|
||||
}
|
||||
|
||||
getStatusLabel(status: string): string {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return 'Pendiente';
|
||||
case 'in-progress':
|
||||
return 'En progreso';
|
||||
case 'aux-file-pending':
|
||||
return 'Archivos auxiliares pendientes';
|
||||
case 'success':
|
||||
return 'Creado con éxito';
|
||||
case 'trash':
|
||||
return 'Papelera temporal';
|
||||
case 'failed':
|
||||
return 'Fallido';
|
||||
case 'trasnferring':
|
||||
return 'Transfiriendo';
|
||||
default:
|
||||
return 'Estado desconocido';
|
||||
}
|
||||
}
|
||||
|
||||
addImage(): void {
|
||||
const dialogRef = this.dialog.open(CreateImageComponent, {
|
||||
width: '800px'
|
||||
|
@ -157,78 +131,10 @@ export class ImagesComponent implements OnInit {
|
|||
this.search();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
toggleAction(image: any, action:string): void {
|
||||
switch (action) {
|
||||
case 'get-aux':
|
||||
this.http.post(`${this.baseUrl}/images/server/${image.uuid}/create-aux-files`, {}).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Petición de creación de archivos auxiliares enviada');
|
||||
this.search()
|
||||
},
|
||||
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.search()
|
||||
},
|
||||
error: (error) => {
|
||||
this.toastService.error('Error deleting image');
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.http.post(`${this.baseUrl}/images/server/${image.uuid}/delete-trash`, {}).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 'delete-permanent':
|
||||
this.http.post(`${this.baseUrl}/images/server/${image.uuid}/delete-permanent`, {}).subscribe({
|
||||
this.http.post(`${this.baseUrl}/images/server/${image.uuid}/delete-trash`, {}).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Petición de eliminación de la papelera temporal enviada');
|
||||
this.search()
|
||||
|
@ -238,10 +144,10 @@ export class ImagesComponent implements OnInit {
|
|||
}
|
||||
});
|
||||
break;
|
||||
case 'recover':
|
||||
this.http.post(`${this.baseUrl}/images/server/${image.uuid}/recover`, {}).subscribe({
|
||||
case 'delete-permanent':
|
||||
this.http.post(`${this.baseUrl}/images/server/${image.uuid}/delete-permanent`, {}).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Petición de recuperación de la imagen enviada');
|
||||
this.toastService.success('Petición de eliminación de la papelera temporal enviada');
|
||||
this.search()
|
||||
},
|
||||
error: (error) => {
|
||||
|
|
|
@ -113,6 +113,6 @@
|
|||
</mat-tab>
|
||||
|
||||
<mat-tab label="Listado de imágenes">
|
||||
<app-images [repositoryUuid]="repositoryId"></app-images>
|
||||
<app-repository-images [repositoryUuid] ="repositoryId"></app-repository-images>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
|
@ -119,7 +119,6 @@ export class MainRepositoryViewComponent implements OnInit {
|
|||
comments: [response.comments],
|
||||
});
|
||||
this.loading = false;
|
||||
this.searchImages();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error al cargar los datos del cliente:', error);
|
||||
|
@ -207,21 +206,6 @@ export class MainRepositoryViewComponent implements OnInit {
|
|||
return this.processesStatus ? this.processesStatus : [];
|
||||
}
|
||||
|
||||
searchImages(): void {
|
||||
this.loading = true;
|
||||
this.http.get<any>(`${this.apiUrl}?repositoryId=${this.repositoryData.id}&page=${this.page +1 }&itemsPerPage=${this.itemsPerPage}`, { params: this.filters }).subscribe(
|
||||
data => {
|
||||
this.dataSource.data = data['hydra:member'];
|
||||
this.length = data['hydra:totalItems'];
|
||||
this.loading = false;
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching images', error);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
loadAlert(): Observable<any> {
|
||||
return this.http.get<any>(`${this.baseUrl}/image-repositories/server/get-collection`);
|
||||
}
|
||||
|
|
|
@ -95,4 +95,21 @@ table {
|
|||
|
||||
.example-button-row .mat-mdc-button-base {
|
||||
margin: 8px 8px 8px 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.header-container-title {
|
||||
flex-grow: 1;
|
||||
text-align: left;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.chip-success {
|
||||
background-color: #63d165 !important;
|
||||
color: white ;
|
||||
}
|
||||
|
||||
.chip-failed {
|
||||
background-color: #ff6b63 !important;
|
||||
color: white;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,19 @@
|
|||
<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>
|
||||
{{ column.cell(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>
|
||||
{{ column.cell(repository) }}
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
@ -61,4 +72,4 @@
|
|||
<mat-paginator [length]="length" [pageSize]="itemsPerPage" [pageIndex]="page" [pageSizeOptions]="[5, 10, 20, 40, 100]"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component } from '@angular/core';
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {DatePipe} from "@angular/common";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
|
@ -8,14 +8,13 @@ import {DeleteModalComponent} from "../../shared/delete_modal/delete-modal/delet
|
|||
import { JoyrideService } from 'ngx-joyride';
|
||||
import {CreateRepositoryComponent} from "./create-repository/create-repository.component";
|
||||
import { Router } from '@angular/router';
|
||||
import {ImportImageComponent} from "./import-image/import-image.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-repositories',
|
||||
templateUrl: './repositories.component.html',
|
||||
styleUrl: './repositories.component.css'
|
||||
})
|
||||
export class RepositoriesComponent {
|
||||
export class RepositoriesComponent implements OnInit {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
dataSource = new MatTableDataSource<any>();
|
||||
length: number = 0;
|
||||
|
@ -40,6 +39,11 @@ export class RepositoriesComponent {
|
|||
header: 'Ip',
|
||||
cell: (repository: any) => `${repository.ip}`
|
||||
},
|
||||
{
|
||||
columnDef: 'status',
|
||||
header: 'Estado',
|
||||
cell: (repository: any) => `${repository.status}`
|
||||
},
|
||||
{
|
||||
columnDef: 'createdAt',
|
||||
header: 'Fecha de creación',
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
.title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.images-button-row {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 0 5px;
|
||||
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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
<app-loading [isLoading]="loading"></app-loading>
|
||||
|
||||
<div class="header-container">
|
||||
<button mat-icon-button color="primary" (click)="iniciarTour()">
|
||||
<mat-icon>help</mat-icon>
|
||||
</button>
|
||||
<div class="header-container-title">
|
||||
<h2 joyrideStep="groupsTitleStepText" text="{{ 'groupsTitleStepText' | translate }}">
|
||||
{{ 'imagesTitle' | translate }} en {{ repository?.name }}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
|
||||
<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)="search()" 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)="search()" 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'">
|
||||
<mat-icon [color]="image[column.columnDef] ? 'primary' : 'warn'">
|
||||
{{ 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 *ngIf="repositoryUuid" 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 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 [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'transfer')">Transferir 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>
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { provideHttpClientTesting } from '@angular/common/http/testing';
|
||||
import { ReactiveFormsModule, FormsModule, FormBuilder } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ToastrModule, ToastrService } from 'ngx-toastr';
|
||||
import { JoyrideModule } from 'ngx-joyride';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {MatProgressSpinner} from "@angular/material/progress-spinner";
|
||||
import {RepositoryImagesComponent} from "./repository-images.component";
|
||||
import {LoadingComponent} from "../../../shared/loading/loading.component";
|
||||
import {MatOptionModule} from "@angular/material/core";
|
||||
import {MatSelectModule} from "@angular/material/select";
|
||||
|
||||
describe('RepositoriesComponent', () => {
|
||||
let component: RepositoryImagesComponent;
|
||||
let fixture: ComponentFixture<RepositoryImagesComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [RepositoryImagesComponent, LoadingComponent],
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
MatDialogModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatCheckboxModule,
|
||||
MatButtonModule,
|
||||
MatTableModule,
|
||||
MatPaginatorModule,
|
||||
MatDividerModule,
|
||||
MatIconModule,
|
||||
MatOptionModule,
|
||||
BrowserAnimationsModule,
|
||||
MatProgressSpinner,
|
||||
MatSelectModule ,
|
||||
ToastrModule.forRoot(),
|
||||
TranslateModule.forRoot(),
|
||||
JoyrideModule.forRoot(),
|
||||
CommonModule
|
||||
],
|
||||
providers: [
|
||||
FormBuilder,
|
||||
ToastrService,
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
{
|
||||
provide: MatDialogRef,
|
||||
useValue: {}
|
||||
},
|
||||
{
|
||||
provide: MAT_DIALOG_DATA,
|
||||
useValue: {}
|
||||
}
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(RepositoryImagesComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,257 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {DatePipe} from "@angular/common";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {JoyrideService} from "ngx-joyride";
|
||||
import {CreateImageComponent} from "../../images/create-image/create-image.component";
|
||||
import {Observable} from "rxjs";
|
||||
import {ServerInfoDialogComponent} from "../../ogdhcp/og-dhcp-subnets/server-info-dialog/server-info-dialog.component";
|
||||
import {DeleteModalComponent} from "../../../shared/delete_modal/delete-modal/delete-modal.component";
|
||||
import {ExportImageComponent} from "../../images/export-image/export-image.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-repository-images',
|
||||
templateUrl: './repository-images.component.html',
|
||||
styleUrl: './repository-images.component.css'
|
||||
})
|
||||
export class RepositoryImagesComponent implements OnInit {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
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: 'image.image.name',
|
||||
header: 'Nombre de imagen',
|
||||
cell: (image: any) => `${image.image.name}`
|
||||
},
|
||||
{
|
||||
columnDef: 'remotePc',
|
||||
header: 'Remote Pc',
|
||||
cell: (image: any) => `${image.remotePc}`
|
||||
},
|
||||
{
|
||||
columnDef: 'status',
|
||||
header: 'Estado',
|
||||
cell: (image: any) => `${image.status}`
|
||||
},
|
||||
{
|
||||
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'];
|
||||
|
||||
private apiUrl = `${this.baseUrl}/image-image-repositories`;
|
||||
@Input() repositoryUuid: any
|
||||
private repositoryId: any;
|
||||
|
||||
constructor(
|
||||
public dialog: MatDialog,
|
||||
private http: HttpClient,
|
||||
private toastService: ToastrService,
|
||||
private joyrideService: JoyrideService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
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.repository = data
|
||||
this.search();
|
||||
},
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
search(): void {
|
||||
this.loading = true;
|
||||
this.http.get<any>(`${this.apiUrl}?page=${this.page +1 }&itemsPerPage=${this.itemsPerPage}&repositoryId=${this.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 images', error);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onPageChange(event: any): void {
|
||||
this.page = event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
this.length = event.length;
|
||||
this.search();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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: () => {
|
||||
this.toastService.success('Petición de creación de archivos auxiliares enviada');
|
||||
this.search()
|
||||
},
|
||||
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.search()
|
||||
},
|
||||
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.repositoryUuid}` })
|
||||
.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 'delete-permanent':
|
||||
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.search()
|
||||
},
|
||||
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.search()
|
||||
},
|
||||
error: (error) => {
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'transfer':
|
||||
this.dialog.open(ExportImageComponent, {
|
||||
width: '600px',
|
||||
data: {
|
||||
image: image
|
||||
}
|
||||
});
|
||||
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'
|
||||
});
|
||||
}
|
||||
}
|
|
@ -181,6 +181,7 @@
|
|||
"viewTreeTitle": "View organizational unit tree",
|
||||
"toggleNodeAriaLabel": "Toggle node",
|
||||
"closeButton": "Close",
|
||||
"inputDetails": "Input details",
|
||||
"orgUnitPropertiesTitle": "Organizational unit properties",
|
||||
"generalDataTab": "General data",
|
||||
"propertyHeader": "Property",
|
||||
|
|
|
@ -240,6 +240,7 @@
|
|||
"repositoryLabel": "Repositorios",
|
||||
"serialNumberLabel": "Número de Serie",
|
||||
"netifaceLabel": "Interfaz de red",
|
||||
"inputDetails": "Detalles",
|
||||
"netDriverLabel": "Controlador de red",
|
||||
"macLabel": "MAC",
|
||||
"macError": "Formato de MAC inválido. Ejemplo válido: 00:11:22:33:44:55",
|
||||
|
|
Loading…
Reference in New Issue