refs #1575. Mercure and notifications
testing/ogGui-multibranch/pipeline/head This commit looks good
Details
testing/ogGui-multibranch/pipeline/head This commit looks good
Details
parent
09f83f6af7
commit
2d9ccd01b4
|
@ -130,6 +130,7 @@ 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';
|
||||
import { ManageOrganizationalUnitComponent } from './components/groups/shared/organizational-units/manage-organizational-unit/manage-organizational-unit.component';
|
||||
import { BackupImageComponent } from './components/repositories/backup-image/backup-image.component';
|
||||
export function HttpLoaderFactory(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, './locale/', '.json');
|
||||
}
|
||||
|
@ -216,6 +217,7 @@ export function HttpLoaderFactory(http: HttpClient) {
|
|||
RepositoryImagesComponent,
|
||||
InputDialogComponent,
|
||||
ManageOrganizationalUnitComponent,
|
||||
BackupImageComponent,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [BrowserModule,
|
||||
|
|
|
@ -67,9 +67,9 @@
|
|||
<ng-container *ngSwitchCase="'status'">
|
||||
<ng-container *ngIf="trace.status === 'in-progress' && trace.progress; else statusChip">
|
||||
<div class="progress-container">
|
||||
<mat-progress-bar class="example-margin" [mode]="mode" [value]="progress" [bufferValue]="bufferValue">
|
||||
<mat-progress-bar class="example-margin" [mode]="mode" [value]="trace.progress" [bufferValue]="bufferValue">
|
||||
</mat-progress-bar>
|
||||
<span>{{progress}}%</span>
|
||||
<span>{{trace.progress}}%</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-template #statusChip>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import {ChangeDetectorRef, Component, OnInit} from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable, forkJoin } from 'rxjs';
|
||||
import { FormControl } from '@angular/forms';
|
||||
|
@ -27,7 +27,7 @@ export class TaskLogsComponent implements OnInit {
|
|||
pageSizeOptions: number[] = [10, 20, 30, 50];
|
||||
datePipe: DatePipe = new DatePipe('es-ES');
|
||||
mode: ProgressBarMode = 'buffer';
|
||||
progress = 65;
|
||||
progress = 0;
|
||||
bufferValue = 0;
|
||||
|
||||
columns = [
|
||||
|
@ -87,13 +87,14 @@ export class TaskLogsComponent implements OnInit {
|
|||
|
||||
constructor(private http: HttpClient,
|
||||
private joyrideService: JoyrideService,
|
||||
private dialog: MatDialog
|
||||
private dialog: MatDialog,
|
||||
private cdr: ChangeDetectorRef
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadTraces();
|
||||
this.loadCommands();
|
||||
this.loadClients();
|
||||
//this.loadClients();
|
||||
this.filteredCommands = this.commandControl.valueChanges.pipe(
|
||||
startWith(''),
|
||||
map(value => (typeof value === 'string' ? value : value?.name)),
|
||||
|
@ -104,7 +105,38 @@ export class TaskLogsComponent implements OnInit {
|
|||
map(value => (typeof value === 'string' ? value : value?.name)),
|
||||
map(name => (name ? this._filterClients(name) : this.clients.slice()))
|
||||
);
|
||||
|
||||
const eventSource = new EventSource('http://localhost:3000/.well-known/mercure?topic='
|
||||
+ encodeURIComponent(`traces`));
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data && data['@id']) {
|
||||
this.updateTracesStatus(data['@id'], data.status, data.progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateTracesStatus(clientUuid: string, newStatus: string, progress: Number): void {
|
||||
const traceIndex = this.traces.findIndex(trace => trace['@id'] === clientUuid);
|
||||
if (traceIndex !== -1) {
|
||||
const updatedTraces = [...this.traces];
|
||||
|
||||
updatedTraces[traceIndex] = {
|
||||
...updatedTraces[traceIndex],
|
||||
status: newStatus,
|
||||
progress: progress
|
||||
};
|
||||
|
||||
this.traces = updatedTraces;
|
||||
this.cdr.detectChanges();
|
||||
|
||||
console.log(`Estado actualizado para la traza ${clientUuid}: ${newStatus}`);
|
||||
} else {
|
||||
console.warn(`Traza con UUID ${clientUuid} no encontrado en la lista.`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private _filterClients(name: string): any[] {
|
||||
const filterValue = name.toLowerCase();
|
||||
|
|
|
@ -126,6 +126,35 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
};
|
||||
|
||||
this.arrayClients = this.selectedClients.data;
|
||||
|
||||
const eventSource = new EventSource('http://localhost:3000/.well-known/mercure?topic='
|
||||
+ encodeURIComponent(`clients`));
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data && data['@id']) {
|
||||
this.updateClientStatus(data['@id'], data.status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateClientStatus(clientUuid: string, newStatus: string): void {
|
||||
const clientIndex = this.selectedClients.data.findIndex(client => client['@id'] === clientUuid);
|
||||
|
||||
if (clientIndex !== -1) {
|
||||
const updatedClients = [...this.selectedClients.data];
|
||||
|
||||
updatedClients[clientIndex] = {
|
||||
...updatedClients[clientIndex],
|
||||
status: newStatus
|
||||
};
|
||||
|
||||
this.selectedClients.data = updatedClients;
|
||||
|
||||
console.log(`Estado actualizado para el cliente ${clientUuid}: ${newStatus}`);
|
||||
} else {
|
||||
console.warn(`Cliente con UUID ${clientUuid} no encontrado en la lista.`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,12 +38,10 @@
|
|||
</mat-icon>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="column.columnDef === 'imageRepositories'">
|
||||
<button class="action-button" [matMenuTriggerFor]="menu">Ver repositorios</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item *ngFor="let repository of image.imageRepositories">
|
||||
{{ repository.imageRepository.name }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
<mat-chip-set>
|
||||
<mat-chip *ngFor="let repository of image.imageRepositories"> {{ repository.imageRepository.name }} </mat-chip>
|
||||
</mat-chip-set>
|
||||
|
||||
</ng-container>
|
||||
<ng-container *ngIf="column.columnDef === 'isGlobal'">
|
||||
<mat-icon [color]="image[column.columnDef] ? 'primary' : 'warn'">
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BackupImageComponent } from './backup-image.component';
|
||||
import {ImportImageComponent} from "../import-image/import-image.component";
|
||||
import {FormBuilder, ReactiveFormsModule} from "@angular/forms";
|
||||
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from "@angular/material/dialog";
|
||||
import {MatFormFieldModule} from "@angular/material/form-field";
|
||||
import {MatInputModule} from "@angular/material/input";
|
||||
import {MatButtonModule} from "@angular/material/button";
|
||||
import {MatSelectModule} from "@angular/material/select";
|
||||
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
|
||||
import {ToastrModule, ToastrService} from "ngx-toastr";
|
||||
import {TranslateModule} from "@ngx-translate/core";
|
||||
import {provideHttpClient} from "@angular/common/http";
|
||||
import {provideHttpClientTesting} from "@angular/common/http/testing";
|
||||
import {LoadingComponent} from "../../../shared/loading/loading.component";
|
||||
|
||||
describe('BackupImageComponent', () => {
|
||||
let component: BackupImageComponent;
|
||||
|
@ -8,7 +21,31 @@ describe('BackupImageComponent', () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [BackupImageComponent]
|
||||
declarations: [BackupImageComponent, LoadingComponent],
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
MatDialogModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
MatSelectModule,
|
||||
BrowserAnimationsModule,
|
||||
ToastrModule.forRoot(),
|
||||
TranslateModule.forRoot()
|
||||
],
|
||||
providers: [
|
||||
FormBuilder,
|
||||
ToastrService,
|
||||
provideHttpClient(),
|
||||
provideHttpClientTesting(),
|
||||
{
|
||||
provide: MatDialogRef,
|
||||
useValue: {}
|
||||
},
|
||||
{
|
||||
provide: MAT_DIALOG_DATA,
|
||||
useValue: {}
|
||||
}]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
|
|
|
@ -70,9 +70,10 @@
|
|||
</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 !== '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, 'backup')">Realizar backup </button>
|
||||
</mat-menu>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
|
|
@ -10,6 +10,7 @@ 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";
|
||||
import {BackupImageComponent} from "../backup-image/backup-image.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-repository-images',
|
||||
|
@ -209,6 +210,11 @@ export class RepositoryImagesComponent implements OnInit {
|
|||
|
||||
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');
|
||||
|
@ -218,6 +224,8 @@ export class RepositoryImagesComponent implements OnInit {
|
|||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'recover':
|
||||
this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/recover`, {}).subscribe({
|
||||
|
@ -246,6 +254,22 @@ export class RepositoryImagesComponent implements OnInit {
|
|||
}
|
||||
});
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue