develop #23
|
@ -1,4 +1,13 @@
|
|||
# Changelog
|
||||
## [0.13.0] - 2025-05-20
|
||||
### Added
|
||||
- Se ha añadido nuevo campo "SSL_ENABLED" en el apartado configuracion.
|
||||
|
||||
### Improved
|
||||
- Mejoras en el asistente de particionado.
|
||||
- Se han añadido mejoras en los filtros de las trazas.
|
||||
|
||||
---
|
||||
## [0.12.0] - 2025-5-13
|
||||
### Added
|
||||
- Se ha añadido un nuevo modal del detalle de las acciones ejecutadas por cada cliente.
|
||||
|
|
|
@ -16,12 +16,20 @@
|
|||
<ng-container matColumnDef="value">
|
||||
<mat-header-cell *matHeaderCellDef> Valor </mat-header-cell>
|
||||
<mat-cell *matCellDef="let variable">
|
||||
<mat-form-field class="value-input">
|
||||
<!-- Si es booleano, usamos checkbox -->
|
||||
<mat-checkbox *ngIf="isBoolean(variable.value)"
|
||||
[checked]="variable.value === 'true'"
|
||||
(change)="variable.value = $event.checked ? 'true' : 'false'">
|
||||
</mat-checkbox>
|
||||
|
||||
<!-- Si no es booleano, usamos input -->
|
||||
<mat-form-field *ngIf="!isBoolean(variable.value)" class="value-input">
|
||||
<input matInput [(ngModel)]="variable.value" />
|
||||
</mat-form-field>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
</mat-table>
|
||||
|
@ -30,4 +38,4 @@
|
|||
<button class="action-button" (click)="loadEnvVars()">Recargar</button>
|
||||
<button class="submit-button" (click)="saveEnvVars()">Guardar Cambios</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -31,12 +31,15 @@ export class EnvVarsComponent {
|
|||
this.envVars = Object.entries(response.vars).map(([name, value]) => ({ name, value }));
|
||||
},
|
||||
error: (err) => {
|
||||
console.error('Error al cargar las variables de entorno:', err);
|
||||
this.toastService.error('No se pudieron cargar las variables de entorno.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isBoolean(value: string): boolean {
|
||||
return value === 'true' || value === 'false';
|
||||
}
|
||||
|
||||
saveEnvVars(): void {
|
||||
const vars = this.envVars.reduce((acc, variable) => {
|
||||
acc[variable.name] = variable.value;
|
||||
|
|
|
@ -115,6 +115,7 @@ export class CreateTaskScheduleComponent implements OnInit{
|
|||
}
|
||||
|
||||
convertDateToLocalISO(date: Date): string {
|
||||
date = new Date(date);
|
||||
const adjustedDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
||||
return adjustedDate.toISOString();
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ export class CreateCommandComponent implements OnInit{
|
|||
readOnly: this.createCommandForm.value.readOnly,
|
||||
enabled: this.createCommandForm.value.enabled,
|
||||
comments: this.createCommandForm.value.comments,
|
||||
parameters: this.createCommandForm.value.parameters,
|
||||
};
|
||||
|
||||
if (this.commandId) {
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
</h4>
|
||||
</div>
|
||||
<div class="button-row">
|
||||
<button class="action-button" [disabled]="data.status === 'busy' || !selectedModelClient || !allSelected || !selectedDisk" (click)="save()">Ejecutar</button>
|
||||
<button class="action-button" [disabled]="data.status === 'busy' || !selectedModelClient || !allSelected || !selectedDisk || (selectedDisk.totalDiskSize - selectedDisk.used) <= 0" (click)="save()">Ejecutar</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button mat-stroked-button color="accent" [disabled]="data.status === 'busy' || !selectedModelClient || !allSelected || !selectedDisk" (click)="openScheduleModal()">
|
||||
<button mat-stroked-button color="accent" [disabled]="data.status === 'busy' || !selectedModelClient || !allSelected || !selectedDisk || (selectedDisk.totalDiskSize - selectedDisk.used) <= 0" (click)="openScheduleModal()">
|
||||
<mat-icon>schedule</mat-icon> Opciones de programación
|
||||
</button>
|
||||
</div>
|
||||
|
@ -101,15 +101,15 @@
|
|||
|
||||
<div class="disk-space-info-container">
|
||||
<div class="disk-space-info" [ngClass]="selectedDisk.used < selectedDisk.totalDiskSize ? 'chip-free' : 'chip-full'">
|
||||
Espacio usado: {{ selectedDisk.used }} MB
|
||||
Espacio usado: {{ selectedDisk.used | number:'1.2-2' }} MB
|
||||
</div>
|
||||
|
||||
<div class="disk-space-info" [ngClass]="selectedDisk.used < selectedDisk.totalDiskSize ? 'chip-free' : 'chip-full'">
|
||||
Espacio libre: {{ selectedDisk.totalDiskSize - selectedDisk.used}} MB
|
||||
Espacio libre: {{ (selectedDisk.totalDiskSize - selectedDisk.used) | number:'1.2-2' }} MB
|
||||
</div>
|
||||
|
||||
<div class="disk-space-info">
|
||||
Espacio total: {{ selectedDisk.totalDiskSize }} MB
|
||||
Espacio total: {{ selectedDisk.totalDiskSize | number:'1.2-2' }} MB
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -109,8 +109,8 @@ export class PartitionAssistantComponent implements OnInit{
|
|||
this.http.get(url).subscribe(
|
||||
(response) => {
|
||||
this.data = response;
|
||||
this.initializeDisks();
|
||||
this.partitionCode = this.data.partitions[0].partitionCode;
|
||||
this.initializeDisks();
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error al cargar los datos del cliente:', error);
|
||||
|
@ -160,11 +160,11 @@ export class PartitionAssistantComponent implements OnInit{
|
|||
disk!.partitions.push({
|
||||
uuid: partition.uuid,
|
||||
partitionNumber: partition.partitionNumber,
|
||||
size: this.convertBytesToGB(partition.size),
|
||||
size: this.convertBytesToGB(partition.partitionNumber === 1 && this.partitionCode === 'GPT' ? 512 : partition.size),
|
||||
memoryUsage: partition.memoryUsage,
|
||||
partitionCode: partition.partitionCode,
|
||||
partitionCode: partition.partitionNumber === 1 && this.partitionCode === 'GPT' ? 'EFI' : partition.partitionCode,
|
||||
filesystem: partition.filesystem,
|
||||
sizeBytes: partition.size,
|
||||
sizeBytes: partition.partitionNumber === 1 && this.partitionCode === 'GPT' ? 512 : partition.size,
|
||||
format: false,
|
||||
color: '#1f1b91',
|
||||
percentage: 0,
|
||||
|
@ -254,8 +254,6 @@ export class PartitionAssistantComponent implements OnInit{
|
|||
|
||||
if (disk) {
|
||||
const remainingGB = this.getRemainingGB(disk.partitions, disk.totalDiskSize);
|
||||
console.log('Remaining GB:', remainingGB);
|
||||
console.log('Total Disk Size:', disk);
|
||||
|
||||
if (remainingGB > 0) {
|
||||
const removedPartitions = disk.partitions.filter((p) => !p.removed);
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
<div class="script-preview" [innerHTML]="scriptContent"></div>
|
||||
</div>
|
||||
|
||||
<div class="script-params" *ngIf="parameterNames.length > 0">
|
||||
<div class="script-params" *ngIf="parameterNames.length > 0 && selectedScript.parameters">
|
||||
<h3>Ingrese los parámetros:</h3>
|
||||
<div *ngFor="let paramName of parameterNames">
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
|
|
|
@ -77,15 +77,12 @@ export class RunScriptAssistantComponent implements OnInit{
|
|||
if (!ctx) {
|
||||
return '';
|
||||
}
|
||||
// Si es un array de clientes
|
||||
if (Array.isArray(ctx)) {
|
||||
return ctx.map(c => c.name).join(', ');
|
||||
}
|
||||
// Si es un objeto con propiedad name
|
||||
if (typeof ctx === 'object' && 'name' in ctx) {
|
||||
return ctx.name;
|
||||
}
|
||||
// Si es un string plano
|
||||
return String(ctx);
|
||||
}
|
||||
|
||||
|
|
|
@ -177,12 +177,15 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
}
|
||||
|
||||
onParentChange(event: any): void {
|
||||
this.setOrganizationalUnitDefaults(event.value);
|
||||
if (!this.isEditMode) {
|
||||
this.setOrganizationalUnitDefaults(event.value);
|
||||
}
|
||||
}
|
||||
|
||||
setOrganizationalUnitDefaults(unitId: string): void {
|
||||
const selectedUnit: any = this.parentUnitsWithPaths.find(unit => unit.id === unitId);
|
||||
if (selectedUnit) {
|
||||
const exclude = this.generalFormGroup.get('excludeParentChanges')?.value;
|
||||
if (selectedUnit && !exclude) {
|
||||
this.networkSettingsFormGroup.patchValue({
|
||||
repository: selectedUnit.repository || null,
|
||||
hardwareProfile: selectedUnit.hardwareProfile || null,
|
||||
|
@ -204,6 +207,127 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
loadData(uuid: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `${this.baseUrl}/organizational-units/${uuid}`;
|
||||
|
||||
this.http.get<any>(url).subscribe(
|
||||
data => {
|
||||
const exclude = data.excludeParentChanges;
|
||||
|
||||
this.generalFormGroup.patchValue({
|
||||
name: data.name,
|
||||
parent: data.parent ? data.parent['@id'] : '',
|
||||
description: data.description,
|
||||
type: data.type,
|
||||
excludeParentChanges: exclude
|
||||
});
|
||||
|
||||
this.additionalInfoFormGroup.patchValue({
|
||||
comments: data.comments
|
||||
});
|
||||
|
||||
this.networkSettingsFormGroup.patchValue({
|
||||
proxy: data.networkSettings?.proxy,
|
||||
dns: data.networkSettings?.dns,
|
||||
netmask: data.networkSettings?.netmask,
|
||||
router: data.networkSettings?.router,
|
||||
ntp: data.networkSettings?.ntp,
|
||||
netiface: data.networkSettings?.netiface,
|
||||
p2pMode: data.networkSettings?.p2pMode,
|
||||
p2pTime: data.networkSettings?.p2pTime,
|
||||
mcastIp: data.networkSettings?.mcastIp,
|
||||
mcastSpeed: data.networkSettings?.mcastSpeed,
|
||||
mcastPort: data.networkSettings?.mcastPort,
|
||||
mcastMode: data.networkSettings?.mcastMode,
|
||||
menu: data.networkSettings?.menu ? data.networkSettings.menu['@id'] : null,
|
||||
hardwareProfile: data.networkSettings?.hardwareProfile ? data.networkSettings.hardwareProfile['@id'] : null,
|
||||
ogLive: data.networkSettings?.ogLive ? data.networkSettings.ogLive['@id'] : null,
|
||||
repository: data.networkSettings?.repository ? data.networkSettings.repository['@id'] : null,
|
||||
pxeTemplate: data.networkSettings?.pxeTemplate ? data.networkSettings.pxeTemplate['@id'] : null
|
||||
});
|
||||
|
||||
this.classroomInfoFormGroup.patchValue({
|
||||
location: data.location,
|
||||
projector: data.projector,
|
||||
board: data.board,
|
||||
capacity: data.capacity,
|
||||
remoteCalendar: data.remoteCalendar ? data.remoteCalendar['@id'] : null
|
||||
});
|
||||
|
||||
resolve();
|
||||
},
|
||||
|
||||
error => {
|
||||
console.error('Error fetching data for edit:', error);
|
||||
this.toastService.error('Error fetching data');
|
||||
reject(error);
|
||||
this.onNoClick();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
if (this.generalFormGroup.valid && this.additionalInfoFormGroup.valid && this.networkSettingsFormGroup.valid) {
|
||||
const parentValue = this.generalFormGroup.value.parent;
|
||||
const formData = {
|
||||
name: this.generalFormGroup.value.name,
|
||||
excludeParentChanges: this.generalFormGroup.value.excludeParentChanges,
|
||||
parent: parentValue || null,
|
||||
description: this.generalFormGroup.value.description,
|
||||
comments: this.additionalInfoFormGroup.value.comments,
|
||||
remoteCalendar: this.generalFormGroup.value.remoteCalendar,
|
||||
type: this.generalFormGroup.value.type,
|
||||
networkSettings: this.networkSettingsFormGroup.value,
|
||||
location: this.classroomInfoFormGroup.value.location,
|
||||
projector: this.classroomInfoFormGroup.value.projector,
|
||||
board: this.classroomInfoFormGroup.value.board,
|
||||
capacity: this.classroomInfoFormGroup.value.capacity,
|
||||
};
|
||||
|
||||
if (this.isEditMode) {
|
||||
const putUrl = `${this.baseUrl}/organizational-units/${this.data.uuid}`;
|
||||
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
|
||||
|
||||
this.http.put<any>(putUrl, formData, { headers }).subscribe(
|
||||
response => {
|
||||
this.unitAdded.emit();
|
||||
this.dialogRef.close({ success: true });
|
||||
this.toastService.success('Editado exitosamente', 'Éxito');
|
||||
},
|
||||
error => {
|
||||
console.error('Error al realizar PUT:', error);
|
||||
const errorMessages = error.error['hydra:description'].split('\n');
|
||||
errorMessages.forEach((message: string) => {
|
||||
const cleanedMessage = message.replace(/networkSettings\.(\w+):/, 'Error $1:');
|
||||
this.toastService.error(cleanedMessage);
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
const postUrl = `${this.baseUrl}/organizational-units`;
|
||||
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
|
||||
|
||||
this.http.post<any>(postUrl, formData, { headers }).subscribe(
|
||||
response => {
|
||||
this.unitAdded.emit(response);
|
||||
this.dialogRef.close({ success: true });
|
||||
this.toastService.success('Creado exitosamente', 'Éxito');
|
||||
},
|
||||
error => {
|
||||
console.error('Error al realizar POST:', error);
|
||||
const errorMessages = error.error['hydra:description'].split('\n');
|
||||
errorMessages.forEach((message: string) => {
|
||||
const cleanedMessage = message.replace(/networkSettings\.(\w+):/, 'Error $1:');
|
||||
this.toastService.error(cleanedMessage);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getSelectedParentName(): string | undefined {
|
||||
const parentId = this.generalFormGroup.get('parent')?.value;
|
||||
return this.parentUnitsWithPaths.find(unit => unit.id === parentId)?.name;
|
||||
|
@ -229,14 +353,14 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
const url = `${this.baseUrl}/pxe-templates?page=1&itemsPerPage=10000`;
|
||||
|
||||
this.http.get<any>(url).subscribe(
|
||||
response => {
|
||||
response => {
|
||||
this.pxeTemplates = response['hydra:member'];
|
||||
resolve();
|
||||
},
|
||||
error => {
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching pxe templates:', error);
|
||||
reject(error);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -325,121 +449,6 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
this.networkSettingsFormGroup.value.pxeTemplate = event.value;
|
||||
}
|
||||
|
||||
loadData(uuid: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `${this.baseUrl}/organizational-units/${uuid}`;
|
||||
|
||||
this.http.get<any>(url).subscribe(
|
||||
data => {
|
||||
this.generalFormGroup.patchValue({
|
||||
name: data.name,
|
||||
parent: data.parent ? data.parent['@id'] : '',
|
||||
description: data.description,
|
||||
type: data.type,
|
||||
excludeParentChanges: data.excludeParentChanges
|
||||
});
|
||||
this.additionalInfoFormGroup.patchValue({
|
||||
comments: data.comments
|
||||
});
|
||||
this.networkSettingsFormGroup.patchValue({
|
||||
proxy: data.networkSettings?.proxy,
|
||||
dns: data.networkSettings?.dns,
|
||||
netmask: data.networkSettings?.netmask,
|
||||
router: data.networkSettings?.router,
|
||||
ntp: data.networkSettings?.ntp,
|
||||
netiface: data.networkSettings?.netiface,
|
||||
p2pMode: data.networkSettings?.p2pMode,
|
||||
p2pTime: data.networkSettings?.p2pTime,
|
||||
mcastIp: data.networkSettings?.mcastIp,
|
||||
mcastSpeed: data.networkSettings?.mcastSpeed,
|
||||
mcastPort: data.networkSettings?.mcastPort,
|
||||
mcastMode: data.networkSettings?.mcastMode,
|
||||
menu: data.networkSettings?.menu ? data.networkSettings.menu['@id'] : null,
|
||||
hardwareProfile: data.networkSettings?.hardwareProfile ? data.networkSettings.hardwareProfile['@id'] : null,
|
||||
ogLive: data.networkSettings?.ogLive ? data.networkSettings.ogLive['@id'] : null,
|
||||
repository: data.networkSettings?.repository ? data.networkSettings.repository['@id'] : null,
|
||||
pxeTemplate: data.networkSettings?.pxeTemplate ? data.networkSettings.pxeTemplate['@id'] : null
|
||||
});
|
||||
this.classroomInfoFormGroup.patchValue({
|
||||
location: data.location,
|
||||
projector: data.projector,
|
||||
board: data.board,
|
||||
capacity: data.capacity,
|
||||
remoteCalendar: data.remoteCalendar ? data.remoteCalendar['@id'] : null
|
||||
});
|
||||
resolve();
|
||||
},
|
||||
|
||||
error => {
|
||||
console.error('Error fetching data for edit:', error);
|
||||
this.toastService.error('Error fetching data');
|
||||
reject(error);
|
||||
this.onNoClick();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
if (this.generalFormGroup.valid && this.additionalInfoFormGroup.valid && this.networkSettingsFormGroup.valid) {
|
||||
const parentValue = this.generalFormGroup.value.parent;
|
||||
const formData = {
|
||||
name: this.generalFormGroup.value.name,
|
||||
excludeParentChanges: this.generalFormGroup.value.excludeParentChanges,
|
||||
parent: parentValue || null,
|
||||
description: this.generalFormGroup.value.description,
|
||||
comments: this.additionalInfoFormGroup.value.comments,
|
||||
remoteCalendar: this.generalFormGroup.value.remoteCalendar,
|
||||
type: this.generalFormGroup.value.type,
|
||||
networkSettings: this.networkSettingsFormGroup.value,
|
||||
location: this.classroomInfoFormGroup.value.location,
|
||||
projector: this.classroomInfoFormGroup.value.projector,
|
||||
board: this.classroomInfoFormGroup.value.board,
|
||||
capacity: this.classroomInfoFormGroup.value.capacity,
|
||||
};
|
||||
|
||||
if (this.isEditMode) {
|
||||
const putUrl = `${this.baseUrl}/organizational-units/${this.data.uuid}`;
|
||||
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
|
||||
|
||||
this.http.put<any>(putUrl, formData, { headers }).subscribe(
|
||||
response => {
|
||||
this.unitAdded.emit();
|
||||
this.dialogRef.close({ success: true });
|
||||
this.toastService.success('Editado exitosamente', 'Éxito');
|
||||
},
|
||||
error => {
|
||||
console.error('Error al realizar PUT:', error);
|
||||
const errorMessages = error.error['hydra:description'].split('\n');
|
||||
errorMessages.forEach((message: string) => {
|
||||
const cleanedMessage = message.replace(/networkSettings\.(\w+):/, 'Error $1:');
|
||||
this.toastService.error(cleanedMessage);
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
const postUrl = `${this.baseUrl}/organizational-units`;
|
||||
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
|
||||
|
||||
this.http.post<any>(postUrl, formData, { headers }).subscribe(
|
||||
response => {
|
||||
this.unitAdded.emit(response);
|
||||
this.dialogRef.close({ success: true });
|
||||
this.toastService.success('Creado exitosamente', 'Éxito');
|
||||
},
|
||||
error => {
|
||||
console.error('Error al realizar POST:', error);
|
||||
const errorMessages = error.error['hydra:description'].split('\n');
|
||||
errorMessages.forEach((message: string) => {
|
||||
const cleanedMessage = message.replace(/networkSettings\.(\w+):/, 'Error $1:');
|
||||
this.toastService.error(cleanedMessage);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onNoClick(): void {
|
||||
this.dialogRef.close({ success: false });
|
||||
}
|
||||
|
|
|
@ -129,8 +129,7 @@ export class CreatePxeTemplateComponent implements OnInit {
|
|||
this.dialogRef.close(true);
|
||||
},
|
||||
error: error => {
|
||||
this.toastService.error('Error al actualizar la plantilla PXE');
|
||||
this.dialogRef.close(false);
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</button>
|
||||
|
||||
<div class="header-container-title">
|
||||
<h2 joyrideStep="titleStep" text="{{ 'titleStepText' | translate }}">{{ 'adminCommandsTitle' |
|
||||
<h2 joyrideStep="tracesTitleStep" text="{{ 'tracesTitleStepText' | translate }}">{{ 'adminCommandsTitle' |
|
||||
translate }}</h2>
|
||||
</div>
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search-container">
|
||||
<div class="search-container" joyrideStep="filtersStep" text="{{ 'filtersStepText' | translate }}">
|
||||
<mat-form-field appearance="fill" class="search-select">
|
||||
<mat-label>{{ 'commandSelectStepText' | translate }}</mat-label>
|
||||
<mat-select (selectionChange)="onOptionCommandSelected($event.value)" #commandSearchInput>
|
||||
|
@ -52,8 +52,8 @@
|
|||
<app-loading [isLoading]="loading"></app-loading>
|
||||
|
||||
<div *ngIf="!loading">
|
||||
<table mat-table [dataSource]="traces" class="mat-elevation-z8" joyrideStep="tableStep"
|
||||
text="{{ 'tableStepText' | translate }}">
|
||||
<table mat-table [dataSource]="traces" class="mat-elevation-z8" joyrideStep="tracesTableStep"
|
||||
text="{{ 'tracesTableStepText' | 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">
|
||||
|
@ -128,8 +128,8 @@
|
|||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions" joyrideStep="actionsStep" text="{{ 'actionsStepText' | translate }}">
|
||||
<th mat-header-cell *matHeaderCellDef style="text-align: center;">{{ 'columnActions' | translate }}</th>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef style="text-align: center;">{{ 'informationLabel' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let trace" style="text-align: center;">
|
||||
<button mat-icon-button color="primary" [disabled]="!trace.input" (click)="openInputModal(trace.input)">
|
||||
<mat-icon>
|
||||
|
|
|
@ -35,7 +35,6 @@ export class ClientTaskLogsComponent implements OnInit {
|
|||
mode: ProgressBarMode = 'buffer';
|
||||
progress = 0;
|
||||
bufferValue = 0;
|
||||
dateRange = new FormControl();
|
||||
|
||||
filteredCommands2 = Object.keys(COMMAND_TYPES).map(key => ({
|
||||
name: key,
|
||||
|
@ -135,7 +134,9 @@ export class ClientTaskLogsComponent implements OnInit {
|
|||
}
|
||||
|
||||
onOptionCommandSelected(selectedCommand: any): void {
|
||||
this.filters['command'] = selectedCommand.id;
|
||||
this.filters['command'] = selectedCommand.id || selectedCommand.uuid;
|
||||
console.log('Comando seleccionado:', selectedCommand);
|
||||
console.log('Valor que se usará para el filtro:', selectedCommand.name);
|
||||
this.loadTraces();
|
||||
}
|
||||
|
||||
|
@ -191,22 +192,13 @@ export class ClientTaskLogsComponent implements OnInit {
|
|||
.set('itemsPerPage', this.itemsPerPage.toString());
|
||||
|
||||
if (this.filters['command']) {
|
||||
params = params.set('command.id', this.filters['command']);
|
||||
params = params.set('command.uuid', this.filters['command']);
|
||||
}
|
||||
|
||||
if (this.filters['status']) {
|
||||
params = params.set('status', this.filters['status']);
|
||||
}
|
||||
|
||||
const range = this.dateRange?.value;
|
||||
if (range?.start && range?.end) {
|
||||
const fromDate = this.datePipe.transform(range.start, 'yyyy-MM-dd');
|
||||
const toDate = this.datePipe.transform(range.end, 'yyyy-MM-dd');
|
||||
|
||||
params = params.set('executedAt[after]', fromDate!);
|
||||
params = params.set('executedAt[before]', toDate!);
|
||||
}
|
||||
|
||||
const url = `${this.baseUrl}/traces`;
|
||||
|
||||
this.http.get<any>(url, { params }).subscribe(
|
||||
|
@ -240,7 +232,6 @@ export class ClientTaskLogsComponent implements OnInit {
|
|||
this.loading = true;
|
||||
clientSearchCommandInput.value = null;
|
||||
clientSearchStatusInput.value = null;
|
||||
this.dateRange.reset();
|
||||
this.filters = {};
|
||||
this.loadTraces();
|
||||
}
|
||||
|
@ -290,11 +281,10 @@ export class ClientTaskLogsComponent implements OnInit {
|
|||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: [
|
||||
'titleStep',
|
||||
'tracesTitleStep',
|
||||
'resetFiltersStep',
|
||||
'clientSelectStep',
|
||||
'commandSelectStep',
|
||||
'tableStep',
|
||||
'filtersStep',
|
||||
'tracesTableStep',
|
||||
'paginationStep'
|
||||
],
|
||||
showPrevButton: true,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
</button>
|
||||
|
||||
<div class="header-container-title">
|
||||
<h2 joyrideStep="titleStep" text="{{ 'titleStepText' | translate }}">{{ 'adminCommandsTitle' |
|
||||
<h2 joyrideStep="tracesTitleStep" text="{{ 'tracesTitleStepText' | translate }}">{{ 'adminCommandsTitle' |
|
||||
translate }}</h2>
|
||||
</div>
|
||||
|
||||
|
@ -16,9 +16,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search-container">
|
||||
<mat-form-field appearance="fill" class="search-select" joyrideStep="clientSelectStep"
|
||||
text="{{ 'clientSelectStepText' | translate }}">
|
||||
<div class="search-container" joyrideStep="filtersStep" text="{{ 'filtersStepText' | translate }}">
|
||||
<mat-form-field appearance="fill" class="search-select">
|
||||
<input type="text" matInput [formControl]="clientControl" [matAutocomplete]="clientAuto" #commandClientInput
|
||||
placeholder="{{ 'filterClientPlaceholder' | translate }}">
|
||||
<mat-autocomplete #clientAuto="matAutocomplete" [displayWith]="displayFnClient"
|
||||
|
@ -74,8 +73,8 @@
|
|||
<app-loading [isLoading]="loading"></app-loading>
|
||||
|
||||
<div *ngIf="!loading">
|
||||
<table mat-table [dataSource]="traces" class="mat-elevation-z8" joyrideStep="tableStep"
|
||||
text="{{ 'tableStepText' | translate }}">
|
||||
<table mat-table [dataSource]="traces" class="mat-elevation-z8" joyrideStep="tracesTableStep"
|
||||
text="{{ 'tracesTableStepText' | 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">
|
||||
|
@ -150,10 +149,11 @@
|
|||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions" joyrideStep="actionsStep" text="{{ 'actionsStepText' | translate }}">
|
||||
<th mat-header-cell *matHeaderCellDef style="text-align: center;">{{ 'columnActions' | translate }}</th>
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef style="text-align: center;">{{ 'informationLabel' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let trace" style="text-align: center;">
|
||||
<button mat-icon-button color="primary" [disabled]="!trace.input" (click)="openInputModal(trace.input)">
|
||||
<button mat-icon-button color="primary" [disabled]="!trace.input || trace.input.length === 0"
|
||||
(click)="openInputModal(trace.input)">
|
||||
<mat-icon>
|
||||
<span class="material-symbols-outlined">
|
||||
mode_comment
|
||||
|
|
|
@ -11,8 +11,8 @@ 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';
|
||||
import {OutputDialogComponent} from "./output-dialog/output-dialog.component";
|
||||
import {TranslationService} from "@services/translation.service";
|
||||
import { OutputDialogComponent } from "./output-dialog/output-dialog.component";
|
||||
import { TranslationService } from "@services/translation.service";
|
||||
import { COMMAND_TYPES } from '../../shared/constants/command-types';
|
||||
|
||||
@Component({
|
||||
|
@ -323,11 +323,10 @@ export class TaskLogsComponent implements OnInit {
|
|||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: [
|
||||
'titleStep',
|
||||
'tracesTitleStep',
|
||||
'resetFiltersStep',
|
||||
'clientSelectStep',
|
||||
'commandSelectStep',
|
||||
'tableStep',
|
||||
'filtersStep',
|
||||
'tracesTableStep',
|
||||
'paginationStep'
|
||||
],
|
||||
showPrevButton: true,
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<span>{{ 'commands' | translate }}</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
<!--
|
||||
<mat-list-item routerLink="/commands-groups" (click)="onItemClick()"
|
||||
matTooltip="{{ 'TOOLTIP_COMMAND_GROUPS' | translate }}" matTooltipShowDelay="1000">
|
||||
<span class="entry">
|
||||
|
@ -41,6 +42,7 @@
|
|||
<span>{{ 'commandGroups' | translate }}</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
-->
|
||||
<mat-list-item routerLink="/commands-task" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_TASKS' | translate }}"
|
||||
matTooltipShowDelay="1000">
|
||||
<span class="entry">
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
"searchGroupNameLabel": "Search group name",
|
||||
"loadingStepText": "Wait while the command groups are loading.",
|
||||
"viewCommands": "View commands",
|
||||
"paginationStepText": "Navigate between command group pages using the paginator.",
|
||||
"paginationStepText": "Navigate through pages using the paginator.",
|
||||
"commandGroupDetailsTitle": "Command Group Details",
|
||||
"createdBy": "Created by",
|
||||
"groupId": "Group ID",
|
||||
|
@ -527,6 +527,8 @@
|
|||
"gitImage": "Git images",
|
||||
"gitImageStep": "Git images",
|
||||
"gitImageStepText": "On this screen you can manage git images.",
|
||||
"partitions": "Particiones",
|
||||
"isDefaultLabel": "Default"
|
||||
}
|
||||
"isDefaultLabel": "Default",
|
||||
"tracesTitleStepText": "In this screen, you can see the execution traces of each client, with its id, command, real-time status, date and actions to be performed.",
|
||||
"filtersStepText": "Here you can see the different filters to apply to the table information.",
|
||||
"tracesTableStepText": "This is the table with the execution traces updated in real time."
|
||||
}
|
|
@ -25,7 +25,7 @@
|
|||
"back": "Atrás",
|
||||
"addClientDialogTitle": "Añadir Cliente",
|
||||
"dialogTitleEditUser": "Editar usuario",
|
||||
"dialogTitleChangePassword": "Change password",
|
||||
"dialogTitleChangePassword": "Cambiar contraseña",
|
||||
"labelCurrentPassword": "Contraseña actual",
|
||||
"labelNewPassword": "Nueva contraseña",
|
||||
"labelRepeatPassword": "Repite la contraseña",
|
||||
|
@ -79,7 +79,7 @@
|
|||
"searchGroupNameLabel": "Buscar nombre de grupo",
|
||||
"loadingStepText": "Espera mientras se cargan los grupos de comandos.",
|
||||
"viewCommands": "Ver comandos",
|
||||
"paginationStepText": "Navega entre las páginas de grupos de comandos usando el paginador.",
|
||||
"paginationStepText": "Navega entre las páginas usando el paginador.",
|
||||
"commandGroupDetailsTitle": "Detalles del Grupo de Comandos",
|
||||
"createdBy": "Creado por",
|
||||
"groupId": "ID del Grupo",
|
||||
|
@ -521,7 +521,7 @@
|
|||
"remoteAccess": "Disponible acceso remoto",
|
||||
"noRemoteAccess": "No disponible acceso remoto",
|
||||
"capacityWarning": "El aforo no puede ser",
|
||||
"procedimientosCliente": "Procedimientos",
|
||||
"procedimientosCliente": "Histórico acciones",
|
||||
"tableDateRepositoryText": "Esta tabla muestra los datos asociados a los repositorios existentes.",
|
||||
"repositoryTitleStepText": "En esta pantalla se pueden gestionar los repositorios de imágenes.",
|
||||
"monolithicImageStep": "Imagen monolítica",
|
||||
|
@ -530,6 +530,8 @@
|
|||
"monolithicImage": "Imagenes monolíticas",
|
||||
"gitImage": "Imágenes Git",
|
||||
"gitImageStepText": "Esta opción permite visualizar las imágenes Git disponibles en el servidor.",
|
||||
"partitions": "Particiones",
|
||||
"isDefaultLabel": "Por defecto"
|
||||
"isDefaultLabel": "Por defecto",
|
||||
"tracesTitleStepText": "En esta pantalla, puedes ver las trazas de ejecución de cada cliente, con su id, comando, estado en tiempo real, fecha y acciones a realizar.",
|
||||
"filtersStepText": "Aquí puedes ver los diferentes filtros que aplicar a la información de la tabla.",
|
||||
"tracesTableStepText": "Esta es la tabla con las trazas de ejecución actualizadas en tiempo real."
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue