Fixed wrong dir
testing/ogGui-multibranch/pipeline/head This commit looks good
Details
testing/ogGui-multibranch/pipeline/head This commit looks good
Details
parent
9a84e45cb8
commit
81766471ee
|
@ -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 class="ordinary-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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
.header-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px 10px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-container-title {
|
||||||
|
flex-grow: 1;
|
||||||
|
text-align: left;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-button-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lists-container {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imagesLists-container {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.unidad-card {
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin: 1.5rem 0rem 1.5rem 0rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-string {
|
||||||
|
flex: 1;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-boolean {
|
||||||
|
flex: 1;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-select {
|
||||||
|
flex: 2;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-elevation-z8 {
|
||||||
|
box-shadow: 0px 0px 0px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paginator-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: end;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-failed {
|
||||||
|
background-color: #e87979 !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-success {
|
||||||
|
background-color: #46c446 !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-pending {
|
||||||
|
background-color: #bebdbd !important;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip-in-progress {
|
||||||
|
background-color: #f5a623 !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-progress-flex {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.cancel-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-button {
|
||||||
|
color: red;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-button mat-icon {
|
||||||
|
color: red;
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
<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="titleStep" text="{{ 'titleStepText' | translate }}">{{ 'adminCommandsTitle' |
|
||||||
|
translate }}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="images-button-row">
|
||||||
|
<button class="action-button" (click)="resetFilters()" joyrideStep="resetFiltersStep"
|
||||||
|
text="{{ 'resetFiltersStepText' | translate }}">
|
||||||
|
{{ 'resetFilters' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search-container">
|
||||||
|
<mat-form-field appearance="fill" class="search-select" joyrideStep="clientSelectStep"
|
||||||
|
text="{{ 'clientSelectStepText' | translate }}">
|
||||||
|
<input type="text" matInput [formControl]="clientControl" [matAutocomplete]="clientAuto"
|
||||||
|
placeholder="{{ 'filterClientPlaceholder' | translate }}">
|
||||||
|
<mat-autocomplete #clientAuto="matAutocomplete" [displayWith]="displayFnClient"
|
||||||
|
(optionSelected)="onOptionClientSelected($event.option.value)">
|
||||||
|
<mat-option *ngFor="let client of filteredClients | async" [value]="client">
|
||||||
|
{{ client.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="fill" class="search-select" joyrideStep="commandSelectStep"
|
||||||
|
text="{{ 'commandSelectStepText' | translate }}">
|
||||||
|
<input type="text" matInput [formControl]="commandControl" [matAutocomplete]="commandAuto"
|
||||||
|
placeholder="{{ 'filterCommandPlaceholder' | translate }}">
|
||||||
|
<mat-autocomplete #commandAuto="matAutocomplete" [displayWith]="displayFnCommand"
|
||||||
|
(optionSelected)="onOptionCommandSelected($event.option.value)">
|
||||||
|
<mat-option *ngFor="let command of filteredCommands | async" [value]="command">
|
||||||
|
{{ command.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="fill" class="search-boolean">
|
||||||
|
<mat-label i18n="@@searchLabel">Estado</mat-label>
|
||||||
|
<mat-select [(ngModel)]="filters['status']" (selectionChange)="loadTraces()" placeholder="Seleccionar opción">
|
||||||
|
<mat-option [value]="undefined">Todos</mat-option>
|
||||||
|
<mat-option [value]="'failed'">Fallido</mat-option>
|
||||||
|
<mat-option [value]="'pending'">Pendiente de ejecutar</mat-option>
|
||||||
|
<mat-option [value]="'in-progress'">Ejecutando</mat-option>
|
||||||
|
<mat-option [value]="'success'">Completado con éxito</mat-option>
|
||||||
|
<mat-option [value]="'cancelled'">Cancelado</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<app-loading [isLoading]="loading"></app-loading>
|
||||||
|
|
||||||
|
<div *ngIf="!loading">
|
||||||
|
<table mat-table [dataSource]="traces" class="mat-elevation-z8" joyrideStep="tableStep"
|
||||||
|
text="{{ 'tableStepText' | translate }}">
|
||||||
|
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||||
|
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||||
|
<td mat-cell *matCellDef="let trace">
|
||||||
|
|
||||||
|
<ng-container [ngSwitch]="column.columnDef">
|
||||||
|
<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]="trace.progress" [bufferValue]="bufferValue">
|
||||||
|
</mat-progress-bar>
|
||||||
|
<span>{{trace.progress}}%</span>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #statusChip>
|
||||||
|
<div class="status-progress-flex">
|
||||||
|
<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',
|
||||||
|
'chip-cancelled': trace.status === 'cancelled'
|
||||||
|
}">
|
||||||
|
{{
|
||||||
|
trace.status === 'failed' ? 'Fallido' :
|
||||||
|
trace.status === 'in-progress' ? 'En ejecución' :
|
||||||
|
trace.status === 'success' ? 'Finalizado con éxito' :
|
||||||
|
trace.status === 'pending' ? 'Pendiente de ejecutar' :
|
||||||
|
trace.status === 'cancelled' ? 'Cancelado' :
|
||||||
|
trace.status
|
||||||
|
}}
|
||||||
|
</mat-chip>
|
||||||
|
<button *ngIf="trace.status === 'in-progress' && trace.command === 'deploy-image'"
|
||||||
|
mat-icon-button
|
||||||
|
(click)="cancelTrace(trace)"
|
||||||
|
class="cancel-button"
|
||||||
|
matTooltip="Cancelar transmisión de imagen">
|
||||||
|
<mat-icon>cancel</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'input'">
|
||||||
|
<button mat-icon-button (click)="openInputModal(trace.input)">
|
||||||
|
<mat-icon>info</mat-icon>
|
||||||
|
</button>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="paginator-container" joyrideStep="paginationStep" text="{{ 'paginationStepText' | translate }}">
|
||||||
|
<mat-paginator [length]="length" [pageSize]="itemsPerPage" [pageIndex]="page" [pageSizeOptions]="pageSizeOptions"
|
||||||
|
(page)="onPageChange($event)">
|
||||||
|
</mat-paginator>
|
||||||
|
</div>
|
|
@ -0,0 +1,309 @@
|
||||||
|
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Observable, forkJoin } from 'rxjs';
|
||||||
|
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";
|
||||||
|
import { ProgressBarMode } from '@angular/material/progress-bar';
|
||||||
|
import { DeleteModalComponent } from "../../shared/delete_modal/delete-modal/delete-modal.component";
|
||||||
|
import { ToastrService } from "ngx-toastr";
|
||||||
|
import { ConfigService } from '@services/config.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-task-logs',
|
||||||
|
templateUrl: './task-logs.component.html',
|
||||||
|
styleUrls: ['./task-logs.component.css']
|
||||||
|
})
|
||||||
|
export class TaskLogsComponent implements OnInit {
|
||||||
|
baseUrl: string;
|
||||||
|
mercureUrl: string;
|
||||||
|
traces: any[] = [];
|
||||||
|
groupedTraces: any[] = [];
|
||||||
|
commands: any[] = [];
|
||||||
|
clients: any[] = [];
|
||||||
|
length: number = 0;
|
||||||
|
itemsPerPage: number = 20;
|
||||||
|
page: number = 0;
|
||||||
|
loading: boolean = true;
|
||||||
|
pageSizeOptions: number[] = [10, 20, 30, 50];
|
||||||
|
datePipe: DatePipe = new DatePipe('es-ES');
|
||||||
|
mode: ProgressBarMode = 'buffer';
|
||||||
|
progress = 0;
|
||||||
|
bufferValue = 0;
|
||||||
|
|
||||||
|
columns = [
|
||||||
|
{
|
||||||
|
columnDef: 'id',
|
||||||
|
header: 'ID',
|
||||||
|
cell: (trace: any) => `${trace.id}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'command',
|
||||||
|
header: 'Comando',
|
||||||
|
cell: (trace: any) => trace.command
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'client',
|
||||||
|
header: 'Client',
|
||||||
|
cell: (trace: any) => trace.client?.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'status',
|
||||||
|
header: 'Estado',
|
||||||
|
cell: (trace: any) => trace.status
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'jobId',
|
||||||
|
header: 'Hilo de trabajo',
|
||||||
|
cell: (trace: any) => trace.jobId
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'input',
|
||||||
|
header: 'Input',
|
||||||
|
cell: (trace: any) => trace.input
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'output',
|
||||||
|
header: 'Logs',
|
||||||
|
cell: (trace: any) => trace.output
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'executedAt',
|
||||||
|
header: 'Programación de ejecución',
|
||||||
|
cell: (trace: any) => this.datePipe.transform(trace.executedAt, 'dd/MM/yyyy hh:mm:ss'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'finishedAt',
|
||||||
|
header: 'Finalización',
|
||||||
|
cell: (trace: any) => this.datePipe.transform(trace.finishedAt, 'dd/MM/yyyy hh:mm:ss'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
displayedColumns = [...this.columns.map(column => column.columnDef)];
|
||||||
|
|
||||||
|
filters: { [key: string]: string } = {};
|
||||||
|
filteredClients!: Observable<any[]>;
|
||||||
|
clientControl = new FormControl();
|
||||||
|
filteredCommands!: Observable<any[]>;
|
||||||
|
commandControl = new FormControl();
|
||||||
|
|
||||||
|
constructor(private http: HttpClient,
|
||||||
|
private joyrideService: JoyrideService,
|
||||||
|
private dialog: MatDialog,
|
||||||
|
private cdr: ChangeDetectorRef,
|
||||||
|
private configService: ConfigService,
|
||||||
|
private toastService: ToastrService
|
||||||
|
) {
|
||||||
|
this.baseUrl = this.configService.apiUrl;
|
||||||
|
this.mercureUrl = this.configService.mercureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.loadTraces();
|
||||||
|
this.loadCommands();
|
||||||
|
//this.loadClients();
|
||||||
|
this.filteredCommands = this.commandControl.valueChanges.pipe(
|
||||||
|
startWith(''),
|
||||||
|
map(value => (typeof value === 'string' ? value : value?.name)),
|
||||||
|
map(name => (name ? this._filterCommands(name) : this.commands.slice()))
|
||||||
|
);
|
||||||
|
this.filteredClients = this.clientControl.valueChanges.pipe(
|
||||||
|
startWith(''),
|
||||||
|
map(value => (typeof value === 'string' ? value : value?.name)),
|
||||||
|
map(name => (name ? this._filterClients(name) : this.clients.slice()))
|
||||||
|
);
|
||||||
|
|
||||||
|
const eventSource = new EventSource(`${this.mercureUrl}?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();
|
||||||
|
return this.clients.filter(client => client.name.toLowerCase().includes(filterValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _filterCommands(name: string): any[] {
|
||||||
|
const filterValue = name.toLowerCase();
|
||||||
|
return this.commands.filter(command => command.name.toLowerCase().includes(filterValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
displayFnClient(client: any): string {
|
||||||
|
return client && client.name ? client.name : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
displayFnCommand(command: any): string {
|
||||||
|
return command && command.name ? command.name : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
onOptionCommandSelected(selectedCommand: any): void {
|
||||||
|
this.filters['command.id'] = selectedCommand.id;
|
||||||
|
this.loadTraces();
|
||||||
|
}
|
||||||
|
|
||||||
|
onOptionClientSelected(selectedClient: any): void {
|
||||||
|
this.filters['client.id'] = selectedClient.id;
|
||||||
|
this.loadTraces();
|
||||||
|
}
|
||||||
|
|
||||||
|
openInputModal(inputData: any): void {
|
||||||
|
this.dialog.open(InputDialogComponent, {
|
||||||
|
width: '700px',
|
||||||
|
data: { input: inputData }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelTrace(trace: any): void {
|
||||||
|
this.dialog.open(DeleteModalComponent, {
|
||||||
|
width: '300px',
|
||||||
|
data: { name: trace.jobId },
|
||||||
|
}).afterClosed().subscribe((result) => {
|
||||||
|
if (result) {
|
||||||
|
this.http.post(`${this.baseUrl}/traces/server/${trace.uuid}/cancel`, {}).subscribe({
|
||||||
|
next: () => {
|
||||||
|
this.toastService.success('Transmision de imagen cancelada');
|
||||||
|
this.loadTraces();
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
this.toastService.error(error.error['hydra:description']);
|
||||||
|
console.error(error.error['hydra:description']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTraces(): void {
|
||||||
|
this.loading = true;
|
||||||
|
const url = `${this.baseUrl}/traces?page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}`;
|
||||||
|
const params = { ...this.filters };
|
||||||
|
if (params['status'] === undefined) {
|
||||||
|
delete params['status'];
|
||||||
|
}
|
||||||
|
this.http.get<any>(url, { params }).subscribe(
|
||||||
|
(data) => {
|
||||||
|
this.traces = data['hydra:member'];
|
||||||
|
this.length = data['hydra:totalItems'];
|
||||||
|
this.groupedTraces = this.groupByCommandId(this.traces);
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
console.error('Error fetching traces', error);
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCommands() {
|
||||||
|
this.loading = true;
|
||||||
|
this.http.get<any>(`${this.baseUrl}/commands?&page=1&itemsPerPage=10000`).subscribe(
|
||||||
|
response => {
|
||||||
|
this.commands = response['hydra:member'];
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.error('Error fetching commands:', error);
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadClients() {
|
||||||
|
this.loading = true;
|
||||||
|
this.http.get<any>(`${this.baseUrl}/clients?&page=1&itemsPerPage=10000`).subscribe(
|
||||||
|
response => {
|
||||||
|
const clientIds = response['hydra:member'].map((client: any) => client['@id']);
|
||||||
|
const clientDetailsRequests: Observable<any>[] = clientIds.map((id: string) => this.http.get<any>(`${this.baseUrl}${id}`));
|
||||||
|
forkJoin(clientDetailsRequests).subscribe(
|
||||||
|
(clients: any[]) => {
|
||||||
|
this.clients = clients;
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
(error: any) => {
|
||||||
|
console.error('Error fetching client details:', error);
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(error: any) => {
|
||||||
|
console.error('Error fetching clients:', error);
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetFilters() {
|
||||||
|
this.loading = true;
|
||||||
|
this.filters = {};
|
||||||
|
this.loadTraces();
|
||||||
|
}
|
||||||
|
|
||||||
|
groupByCommandId(traces: any[]): any[] {
|
||||||
|
const grouped: { [key: string]: any[] } = {};
|
||||||
|
|
||||||
|
traces.forEach(trace => {
|
||||||
|
const commandId = trace.command.id;
|
||||||
|
if (!grouped[commandId]) {
|
||||||
|
grouped[commandId] = [];
|
||||||
|
}
|
||||||
|
grouped[commandId].push(trace);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.keys(grouped).map(key => ({
|
||||||
|
commandId: key,
|
||||||
|
traces: grouped[key]
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageChange(event: any): void {
|
||||||
|
this.page = event.pageIndex;
|
||||||
|
this.itemsPerPage = event.pageSize;
|
||||||
|
this.length = event.length;
|
||||||
|
this.loadTraces();
|
||||||
|
}
|
||||||
|
|
||||||
|
iniciarTour(): void {
|
||||||
|
this.joyrideService.startTour({
|
||||||
|
steps: [
|
||||||
|
'titleStep',
|
||||||
|
'resetFiltersStep',
|
||||||
|
'clientSelectStep',
|
||||||
|
'commandSelectStep',
|
||||||
|
'tableStep',
|
||||||
|
'paginationStep'
|
||||||
|
],
|
||||||
|
showPrevButton: true,
|
||||||
|
themeColor: '#3f51b5'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue