refs #798 Added task logs view
parent
f2cbb90de5
commit
50fe2d830d
|
@ -19,6 +19,7 @@ import { CalendarComponent } from "./components/calendar/calendar.component";
|
|||
import { CommandsComponent } from './components/commands/main-commands/commands.component';
|
||||
import { CommandsGroupsComponent } from './components/commands/commands-groups/commands-groups.component';
|
||||
import { CommandsTaskComponent } from './components/commands/commands-task/commands-task.component';
|
||||
import { TaskLogsComponent } from './components/commands/commands-task/task-logs/task-logs.component';
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'auth/login', pathMatch: 'full' },
|
||||
{
|
||||
|
@ -39,6 +40,7 @@ const routes: Routes = [
|
|||
{ path: 'commands', component: CommandsComponent },
|
||||
{ path: 'commands-groups', component: CommandsGroupsComponent },
|
||||
{ path: 'commands-task', component: CommandsTaskComponent },
|
||||
{ path: 'commands-logs', component: TaskLogsComponent },
|
||||
{ path: 'calendars', component: CalendarComponent },
|
||||
],
|
||||
},
|
||||
|
|
|
@ -99,6 +99,7 @@ import { CreateTaskComponent } from './components/commands/commands-task/create-
|
|||
import { DetailTaskComponent } from './components/commands/commands-task/detail-task/detail-task.component';
|
||||
import { ClientTabViewComponent } from './components/groups/components/client-tab-view/client-tab-view.component';
|
||||
import { AdvancedSearchComponent } from './components/groups/components/advanced-search/advanced-search.component';
|
||||
import { TaskLogsComponent } from './components/commands/commands-task/task-logs/task-logs.component';
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
|
@ -154,7 +155,8 @@ import { AdvancedSearchComponent } from './components/groups/components/advanced
|
|||
CreateTaskComponent,
|
||||
DetailTaskComponent,
|
||||
ClientTabViewComponent,
|
||||
AdvancedSearchComponent
|
||||
AdvancedSearchComponent,
|
||||
TaskLogsComponent
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [BrowserModule,
|
||||
|
|
|
@ -1,23 +1,58 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CreateCalendarRuleComponent } from './create-calendar-rule.component';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { HttpClientModule } from '@angular/common/http'; // Importar HttpClientModule
|
||||
import { provideHttpClientTesting } from '@angular/common/http/testing'; // Importar el nuevo método
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
|
||||
describe('CreateCalendarRuleComponent', () => {
|
||||
let component: CreateCalendarRuleComponent;
|
||||
let fixture: ComponentFixture<CreateCalendarRuleComponent>;
|
||||
let dialogRefMock: any;
|
||||
let toastrServiceMock: any;
|
||||
|
||||
beforeEach(async () => {
|
||||
dialogRefMock = {
|
||||
close: jasmine.createSpy('close')
|
||||
};
|
||||
|
||||
toastrServiceMock = {
|
||||
success: jasmine.createSpy('success'),
|
||||
error: jasmine.createSpy('error')
|
||||
};
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [CreateCalendarRuleComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
imports: [
|
||||
HttpClientModule, // Importar el módulo HttpClient
|
||||
MatDialogModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatCheckboxModule,
|
||||
MatSlideToggleModule,
|
||||
MatDatepickerModule,
|
||||
MatNativeDateModule
|
||||
],
|
||||
declarations: [CreateCalendarRuleComponent],
|
||||
providers: [
|
||||
provideHttpClientTesting(), // Usar el nuevo método para pruebas de HttpClient
|
||||
{ provide: MatDialogRef, useValue: dialogRefMock },
|
||||
{ provide: MAT_DIALOG_DATA, useValue: {} },
|
||||
{ provide: ToastrService, useValue: toastrServiceMock },
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(CreateCalendarRuleComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
it('should create the component', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,23 +1,63 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { CommandsGroupsComponent } from './commands-groups.component';
|
||||
|
||||
class MockToastrService {
|
||||
success() {}
|
||||
}
|
||||
|
||||
class MockMatDialogRef {
|
||||
close() {}
|
||||
}
|
||||
|
||||
describe('CommandsGroupsComponent', () => {
|
||||
let component: CommandsGroupsComponent;
|
||||
let fixture: ComponentFixture<CommandsGroupsComponent>;
|
||||
let toastService: ToastrService;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [CommandsGroupsComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
declarations: [CommandsGroupsComponent],
|
||||
imports: [
|
||||
HttpClientModule,
|
||||
MatDialogModule,
|
||||
MatPaginatorModule,
|
||||
MatDividerModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatTableModule,
|
||||
MatMenuModule,
|
||||
FormsModule,
|
||||
BrowserAnimationsModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: ToastrService, useClass: MockToastrService },
|
||||
{ provide: MatDialogRef, useClass: MockMatDialogRef }
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(CommandsGroupsComponent);
|
||||
component = fixture.componentInstance;
|
||||
toastService = TestBed.inject(ToastrService);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
it('should create the component', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
<mat-card-content>
|
||||
<p><strong>ID del Grupo:</strong> {{ data.uuid }}</p>
|
||||
<p><strong>Posición:</strong> {{ data.position }}</p>
|
||||
<p><strong>Fecha de Creación:</strong> {{ data.createdAt | date:'short' }}</p>
|
||||
|
||||
<h3>Comandos Incluidos:</h3>
|
||||
|
|
|
@ -57,4 +57,4 @@
|
|||
[pageSize]="itemsPerPage"
|
||||
[pageSizeOptions]="pageSizeOptions"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
</mat-paginator>
|
|
@ -11,6 +11,7 @@
|
|||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
|
||||
<mat-label>Selecciona Comandos</mat-label>
|
||||
<mat-select formControlName="commandGroup" (selectionChange)="onCommandGroupChange()">
|
||||
<mat-option *ngFor="let group of availableCommandGroups" [value]="group.uuid">
|
||||
|
|
|
@ -137,16 +137,21 @@ export class CreateTaskComponent implements OnInit {
|
|||
|
||||
const formData = this.taskForm.value;
|
||||
const dateTime = this.combineDateAndTime(formData.date, formData.time);
|
||||
const selectedCommands = formData.extraCommands.length > 0
|
||||
? formData.extraCommands.map((id: any) => `/commands/${id}`)
|
||||
: [""];
|
||||
const selectedCommands = formData.extraCommands && formData.extraCommands.length > 0
|
||||
? formData.extraCommands.map((id: any) => `/commands/${id}`)
|
||||
: null; // No asignamos nada si no hay comandos seleccionados
|
||||
|
||||
const payload = {
|
||||
commandGroups: [formData.commandGroup ? `/command-groups/${formData.commandGroup}` : [""]],
|
||||
commands: selectedCommands,
|
||||
dateTime: dateTime,
|
||||
notes: formData.notes || ''
|
||||
};
|
||||
// Creamos el objeto payload
|
||||
const payload: any = {
|
||||
commandGroups: formData.commandGroup ? [`/command-groups/${formData.commandGroup}`] : null,
|
||||
dateTime: dateTime,
|
||||
notes: formData.notes || ''
|
||||
};
|
||||
|
||||
// Solo agregamos commands al payload si hay comandos seleccionados
|
||||
if (selectedCommands) {
|
||||
payload.commands = selectedCommands;
|
||||
}
|
||||
|
||||
if (this.editing) {
|
||||
const taskId = this.data.task.uuid;
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<div class="header-container">
|
||||
<h2 class="title">Trazas de ejecuciones</h2>
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="traces" class="mat-elevation-z8">
|
||||
<ng-container matColumnDef="commandName">
|
||||
<th mat-header-cell *matHeaderCellDef> Comando </th>
|
||||
<td mat-cell *matCellDef="let trace"> {{ trace.command.name }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="clientName">
|
||||
<th mat-header-cell *matHeaderCellDef> Cliente </th>
|
||||
<td mat-cell *matCellDef="let trace"> {{ trace.client.name }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef> Estado </th>
|
||||
<td mat-cell *matCellDef="let trace"> {{ trace.status }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="executedAt">
|
||||
<th mat-header-cell *matHeaderCellDef> Ejecutado En </th>
|
||||
<td mat-cell *matCellDef="let trace"> {{ trace.executedAt | date:'short' }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="createdBy">
|
||||
<th mat-header-cell *matHeaderCellDef> Creado Por </th>
|
||||
<td mat-cell *matCellDef="let trace"> {{ trace.createdBy }} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [length]="length"
|
||||
[pageSize]="itemsPerPage"
|
||||
[pageSizeOptions]="pageSizeOptions"
|
||||
(page)="onPageChange($event)">
|
||||
</mat-paginator>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-logs',
|
||||
templateUrl: './task-logs.component.html',
|
||||
styleUrls: ['./task-logs.component.css']
|
||||
})
|
||||
export class TaskLogsComponent implements OnInit {
|
||||
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; // Utilizando baseUrl desde el env
|
||||
traces: any[] = [];
|
||||
length: number = 0;
|
||||
itemsPerPage: number = 20;
|
||||
page: number = 1;
|
||||
pageSizeOptions: number[] = [10, 20, 30, 50];
|
||||
displayedColumns: string[] = ['commandName', 'clientName', 'status', 'executedAt', 'createdBy'];
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadTraces();
|
||||
}
|
||||
|
||||
// Método para cargar las trazas con paginación
|
||||
loadTraces(): void {
|
||||
const url = `${this.baseUrl}/traces?page=${this.page}&itemsPerPage=${this.itemsPerPage}`;
|
||||
|
||||
this.http.get<any>(url).subscribe(
|
||||
(data) => {
|
||||
this.traces = data['hydra:member'];
|
||||
this.length = data['hydra:totalItems'];
|
||||
console.log('Traces:', this.traces);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching traces', error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Método que se llama cuando cambia la paginación
|
||||
onPageChange(event: any): void {
|
||||
this.page = event.pageIndex + 1; // Actualiza el número de página
|
||||
this.itemsPerPage = event.pageSize; // Actualiza los ítems por página
|
||||
this.loadTraces(); // Recarga las trazas con los nuevos parámetros de paginación
|
||||
}
|
||||
}
|
|
@ -16,9 +16,9 @@ export class CommandsComponent implements OnInit {
|
|||
commands: any[] = [];
|
||||
filters: { [key: string]: string | boolean } = {};
|
||||
length: number = 0;
|
||||
itemsPerPage: number = 10;
|
||||
itemsPerPage: number = 20;
|
||||
page: number = 1;
|
||||
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
|
||||
pageSizeOptions: number[] = [10, 20, 40, 100];
|
||||
displayedColumns: string[] = ['name', 'createdBy', 'createdAt', 'actions'];
|
||||
private apiUrl = `${this.baseUrl}/commands`;
|
||||
|
||||
|
@ -80,7 +80,7 @@ export class CommandsComponent implements OnInit {
|
|||
}
|
||||
|
||||
onPageChange(event: any): void {
|
||||
this.page = event.pageIndex;
|
||||
this.page = event.pageIndex === 0 ? 1 : event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
this.search();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
</mat-form-field>
|
||||
|
||||
<div mat-dialog-actions class="action-buttons">
|
||||
<button mat-button (click)="onCancel()" class="cancel-button">Cancelar</button>
|
||||
<button mat-button (click)="onCancel($event)" class="cancel-button">Cancelar</button>
|
||||
<button mat-flat-button color="primary" type="submit" class="submit-button">{{ isEditMode ? 'Guardar' : 'Añadir' }}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -33,7 +33,8 @@ export class CreateCommandComponent {
|
|||
});
|
||||
}
|
||||
|
||||
onCancel(): void {
|
||||
onCancel(event: Event): void {
|
||||
event.preventDefault();
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<mat-form-field appearance="fill">
|
||||
<mat-label>Clientes</mat-label>
|
||||
<mat-select formControlName="selectedClients" multiple (selectionChange)="onClientSelectionChange($event)">
|
||||
<mat-option *ngFor="let client of clients" [value]="client.id">
|
||||
<mat-option *ngFor="let client of clients" [value]="client.uuid">
|
||||
{{ client.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
@ -26,7 +26,7 @@
|
|||
Debes seleccionar al menos un cliente.
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-checkbox formControlName="scheduleExecution" (change)="onScheduleChange($event)">
|
||||
<!-- <mat-checkbox formControlName="scheduleExecution" (change)="onScheduleChange($event)">
|
||||
Programar ejecución
|
||||
</mat-checkbox>
|
||||
<div *ngIf="showDatePicker" class="schedule-container">
|
||||
|
@ -40,7 +40,7 @@
|
|||
<mat-label>Hora</mat-label>
|
||||
<input matInput type="time" formControlName="scheduleTime">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div> -->
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ export class CommandDetailComponent implements OnInit {
|
|||
this.http.get<any>('http://127.0.0.1:8001/clients?page=1&itemsPerPage=30').subscribe(response => {
|
||||
this.clients = response['hydra:member'];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
execute(): void {
|
||||
|
@ -50,11 +51,9 @@ export class CommandDetailComponent implements OnInit {
|
|||
clients: this.form.value.selectedClients.map((uuid: any) => `/clients/${uuid}`)
|
||||
};
|
||||
|
||||
const apiUrl = `${this.baseUrl}/commands/${this.data.command.uuid}/execute`;
|
||||
|
||||
const apiUrl = `${this.baseUrl}/commands/${this.data.uuid}/execute`;
|
||||
this.http.post(apiUrl, payload).subscribe({
|
||||
next: () => {
|
||||
console.log('Command executed successfully');
|
||||
this.dialogRef.close();
|
||||
this.toastService.success('Command executed successfully');
|
||||
},
|
||||
|
@ -95,14 +94,13 @@ export class CommandDetailComponent implements OnInit {
|
|||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
console.log('Comando editado:', result);
|
||||
this.toastService.success('Comando editado' );
|
||||
this.data.command = result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
console.log('Comando cancelado');
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,6 @@
|
|||
<mat-label i18n="@@capacityLabel">Aforo</mat-label>
|
||||
<input matInput formControlName="capacity" type="number">
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Campo nuevo para seleccionar el calendario asociado -->
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Calendario Asociado</mat-label>
|
||||
<mat-select (selectionChange)="onCalendarChange($event)">
|
||||
|
|
|
@ -45,12 +45,24 @@
|
|||
<mat-label i18n="@@capacityLabel">Aforo</mat-label>
|
||||
<input matInput formControlName="capacity" type="number">
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Campo nuevo para seleccionar el calendario asociado -->
|
||||
<!-- <mat-form-field appearance="fill">
|
||||
<mat-label>Calendario Asociado</mat-label>
|
||||
<mat-select (selectionChange)="onCalendarChange($event)">
|
||||
<mat-option *ngFor="let calendar of calendars" [value]="calendar.uuid">
|
||||
{{ calendar.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field> -->
|
||||
|
||||
<div>
|
||||
<button mat-button matStepperPrevious i18n="@@backButton">Atrás</button>
|
||||
<button mat-button matStepperNext i18n="@@nextButton">Siguiente</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
|
||||
|
||||
<!-- Step 3: Información Adicional -->
|
||||
<mat-step [stepControl]="additionalInfoFormGroup">
|
||||
|
|
|
@ -41,6 +41,12 @@
|
|||
<span i18n="@@gallery">Tareas</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="/commands-logs">
|
||||
<span class="entry">
|
||||
<mat-icon class="icon">notifications</mat-icon>
|
||||
<span i18n="@@gallery">Trazas</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
<!-- End commands sub -->
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { DeleteModalComponent } from './delete-modal.component';
|
||||
|
||||
describe('DeleteModalComponent', () => {
|
||||
|
@ -8,16 +8,23 @@ describe('DeleteModalComponent', () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [DeleteModalComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
declarations: [DeleteModalComponent],
|
||||
providers: [
|
||||
{ provide: MatDialogRef, useValue: {} },
|
||||
{ provide: MAT_DIALOG_DATA, useValue: { name: 'Test Name' } }
|
||||
]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DeleteModalComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
it('should create the component', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue