Compare commits
2 Commits
81766471ee
...
242f7a374c
Author | SHA1 | Date |
---|---|---|
|
242f7a374c | |
|
a5730a1de4 |
|
@ -149,6 +149,7 @@ import { ShowTaskScheduleComponent } from './components/commands/commands-task/s
|
|||
import { ShowTaskScriptComponent } from './components/commands/commands-task/show-task-script/show-task-script.component';
|
||||
import { CreateTaskScriptComponent } from './components/commands/commands-task/create-task-script/create-task-script.component';
|
||||
import { ViewParametersModalComponent } from './components/commands/commands-task/show-task-script/view-parameters-modal/view-parameters-modal.component';
|
||||
import { OutputDialogComponent } from './components/task-logs/output-dialog/output-dialog.component';
|
||||
|
||||
export function HttpLoaderFactory(http: HttpClient) {
|
||||
return new TranslateHttpLoader(http, './locale/', '.json');
|
||||
|
@ -255,7 +256,8 @@ registerLocaleData(localeEs, 'es-ES');
|
|||
ShowTaskScheduleComponent,
|
||||
ShowTaskScriptComponent,
|
||||
CreateTaskScriptComponent,
|
||||
ViewParametersModalComponent
|
||||
ViewParametersModalComponent,
|
||||
OutputDialogComponent
|
||||
],
|
||||
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 class="ordinary-button" (click)="close()">{{ 'closeButton' | translate }}</button>
|
||||
</div>
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { OutputDialogComponent } from './output-dialog.component';
|
||||
|
||||
describe('OutputDialogComponent', () => {
|
||||
let component: OutputDialogComponent;
|
||||
let fixture: ComponentFixture<OutputDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [OutputDialogComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(OutputDialogComponent);
|
||||
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-output-dialog',
|
||||
templateUrl: './output-dialog.component.html',
|
||||
styleUrl: './output-dialog.component.css'
|
||||
})
|
||||
export class OutputDialogComponent {
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<OutputDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { input: any }
|
||||
) {}
|
||||
|
||||
close(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
|
@ -19,38 +19,54 @@
|
|||
<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"
|
||||
<input type="text" matInput [formControl]="clientControl" [matAutocomplete]="clientAuto" #commandClientInput
|
||||
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 }}
|
||||
<div style="display: flex; flex-direction: column;">
|
||||
<span>{{ client.name }}</span>
|
||||
<span style="font-size: 0.8rem; color: gray;">
|
||||
{{ client.ip }} — {{ client.mac }}
|
||||
</span>
|
||||
</div>
|
||||
</mat-option>
|
||||
|
||||
</mat-autocomplete>
|
||||
<button *ngIf="commandClientInput.value" mat-icon-button matSuffix aria-label="Clear input search"
|
||||
(click)="clearClientFilter($event, commandClientInput)">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<mat-hint>Por favor, ingrese el nombre del cliente</mat-hint>
|
||||
</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-form-field appearance="fill" class="search-select">
|
||||
<mat-label>{{ 'commandSelectStepText' | translate }}</mat-label>
|
||||
<mat-select (selectionChange)="onOptionCommandSelected($event.value)" #commandSearchInput>
|
||||
<mat-option *ngFor="let command of filteredCommands2" [value]="command">
|
||||
{{ translateCommand(command.name) }}
|
||||
</mat-option>
|
||||
</mat-autocomplete>
|
||||
</mat-select>
|
||||
<button *ngIf="commandSearchInput.value" mat-icon-button matSuffix aria-label="Clear input search"
|
||||
(click)="clearCommandFilter($event, commandSearchInput)">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</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-select (selectionChange)="onOptionStatusSelected($event.value)" placeholder="Seleccionar opción" #commandStatusInput>
|
||||
<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>
|
||||
<button *ngIf="commandStatusInput.value" mat-icon-button matSuffix aria-label="Clear input search"
|
||||
(click)="clearStatusFilter($event, commandStatusInput)">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
|
@ -82,10 +98,10 @@
|
|||
'chip-cancelled': trace.status === 'cancelled'
|
||||
}">
|
||||
{{
|
||||
trace.status === 'failed' ? 'Fallido' :
|
||||
trace.status === 'failed' ? 'Error' :
|
||||
trace.status === 'in-progress' ? 'En ejecución' :
|
||||
trace.status === 'success' ? 'Finalizado con éxito' :
|
||||
trace.status === 'pending' ? 'Pendiente de ejecutar' :
|
||||
trace.status === 'success' ? 'Completado' :
|
||||
trace.status === 'pending' ? 'Pendiente' :
|
||||
trace.status === 'cancelled' ? 'Cancelado' :
|
||||
trace.status
|
||||
}}
|
||||
|
@ -101,20 +117,59 @@
|
|||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'input'">
|
||||
<button mat-icon-button (click)="openInputModal(trace.input)">
|
||||
<mat-icon>info</mat-icon>
|
||||
</button>
|
||||
<ng-container *ngSwitchCase="'command'">
|
||||
<div style="display: flex; flex-direction: column;">
|
||||
<span>{{ translateCommand(trace.command) }}</span>
|
||||
<span style="font-size: 0.75rem; color: gray;">{{ trace.jobId }}</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'client'">
|
||||
<div style="display: flex; flex-direction: column;">
|
||||
<span>{{ trace.client?.name }}</span>
|
||||
<span style="font-size: 0.75rem; color: gray;">{{ trace.client?.ip }}</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<ng-container *ngSwitchCase="'executedAt'">
|
||||
<div style="display: flex; flex-direction: column;">
|
||||
<span style="font-size: 0.8rem;"> {{ trace.executedAt |date: 'dd/MM/yyyy hh:mm:ss'}}</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="'finishedAt'">
|
||||
<div style="display: flex; flex-direction: column;">
|
||||
<span style="font-size: 0.8rem;"> {{ trace.finishedAt |date: 'dd/MM/yyyy hh:mm:ss'}}</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchDefault>
|
||||
{{ column.cell(trace) }}
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions" joyrideStep="actionsStep" text="{{ 'actionsStepText' | translate }}">
|
||||
<th mat-header-cell *matHeaderCellDef style="text-align: center;">{{ 'columnActions' | 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>
|
||||
<span class="material-symbols-outlined">
|
||||
mode_comment
|
||||
</span>
|
||||
</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="primary" [disabled]="!trace.output" (click)="openOutputModal(trace.output)">
|
||||
<mat-icon>
|
||||
<span class="material-symbols-outlined">
|
||||
info
|
||||
</span>
|
||||
</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
|
|
|
@ -11,6 +11,9 @@ 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 { COMMAND_TYPES } from '../../shared/constants/command-types';
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-logs',
|
||||
|
@ -34,6 +37,12 @@ export class TaskLogsComponent implements OnInit {
|
|||
progress = 0;
|
||||
bufferValue = 0;
|
||||
|
||||
filteredCommands2 = Object.keys(COMMAND_TYPES).map(key => ({
|
||||
name: key,
|
||||
value: key,
|
||||
label: COMMAND_TYPES[key]
|
||||
}));
|
||||
|
||||
columns = [
|
||||
{
|
||||
columnDef: 'id',
|
||||
|
@ -47,7 +56,7 @@ export class TaskLogsComponent implements OnInit {
|
|||
},
|
||||
{
|
||||
columnDef: 'client',
|
||||
header: 'Client',
|
||||
header: 'Cliente',
|
||||
cell: (trace: any) => trace.client?.name
|
||||
},
|
||||
{
|
||||
|
@ -55,24 +64,9 @@ export class TaskLogsComponent implements OnInit {
|
|||
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',
|
||||
header: 'Ejecución',
|
||||
cell: (trace: any) => this.datePipe.transform(trace.executedAt, 'dd/MM/yyyy hh:mm:ss'),
|
||||
},
|
||||
{
|
||||
|
@ -81,7 +75,7 @@ export class TaskLogsComponent implements OnInit {
|
|||
cell: (trace: any) => this.datePipe.transform(trace.finishedAt, 'dd/MM/yyyy hh:mm:ss'),
|
||||
},
|
||||
];
|
||||
displayedColumns = [...this.columns.map(column => column.columnDef)];
|
||||
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
|
||||
|
||||
filters: { [key: string]: string } = {};
|
||||
filteredClients!: Observable<any[]>;
|
||||
|
@ -94,7 +88,8 @@ export class TaskLogsComponent implements OnInit {
|
|||
private dialog: MatDialog,
|
||||
private cdr: ChangeDetectorRef,
|
||||
private configService: ConfigService,
|
||||
private toastService: ToastrService
|
||||
private toastService: ToastrService,
|
||||
private translationService: TranslationService
|
||||
) {
|
||||
this.baseUrl = this.configService.apiUrl;
|
||||
this.mercureUrl = this.configService.mercureUrl;
|
||||
|
@ -103,7 +98,7 @@ export class TaskLogsComponent implements OnInit {
|
|||
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)),
|
||||
|
@ -147,11 +142,17 @@ export class TaskLogsComponent implements OnInit {
|
|||
}
|
||||
|
||||
|
||||
private _filterClients(name: string): any[] {
|
||||
const filterValue = name.toLowerCase();
|
||||
return this.clients.filter(client => client.name.toLowerCase().includes(filterValue));
|
||||
private _filterClients(value: string): any[] {
|
||||
const filterValue = value.toLowerCase();
|
||||
|
||||
return this.clients.filter(client =>
|
||||
client.name?.toLowerCase().includes(filterValue) ||
|
||||
client.ip?.toLowerCase().includes(filterValue) ||
|
||||
client.mac?.toLowerCase().includes(filterValue)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private _filterCommands(name: string): any[] {
|
||||
const filterValue = name.toLowerCase();
|
||||
return this.commands.filter(command => command.name.toLowerCase().includes(filterValue));
|
||||
|
@ -161,12 +162,13 @@ export class TaskLogsComponent implements OnInit {
|
|||
return client && client.name ? client.name : '';
|
||||
}
|
||||
|
||||
displayFnCommand(command: any): string {
|
||||
return command && command.name ? command.name : '';
|
||||
onOptionCommandSelected(selectedCommand: any): void {
|
||||
this.filters['command'] = selectedCommand.name;
|
||||
this.loadTraces();
|
||||
}
|
||||
|
||||
onOptionCommandSelected(selectedCommand: any): void {
|
||||
this.filters['command.id'] = selectedCommand.id;
|
||||
onOptionStatusSelected(selectedStatus: any): void {
|
||||
this.filters['status'] = selectedStatus;
|
||||
this.loadTraces();
|
||||
}
|
||||
|
||||
|
@ -177,11 +179,19 @@ export class TaskLogsComponent implements OnInit {
|
|||
|
||||
openInputModal(inputData: any): void {
|
||||
this.dialog.open(InputDialogComponent, {
|
||||
width: '700px',
|
||||
width: '70vw',
|
||||
height: '60vh',
|
||||
data: { input: inputData }
|
||||
});
|
||||
}
|
||||
|
||||
openOutputModal(outputData: any): void {
|
||||
this.dialog.open(OutputDialogComponent, {
|
||||
width: '500px',
|
||||
data: { input: outputData }
|
||||
});
|
||||
}
|
||||
|
||||
cancelTrace(trace: any): void {
|
||||
this.dialog.open(DeleteModalComponent, {
|
||||
width: '300px',
|
||||
|
@ -239,28 +249,19 @@ export class TaskLogsComponent implements OnInit {
|
|||
|
||||
loadClients() {
|
||||
this.loading = true;
|
||||
this.http.get<any>(`${this.baseUrl}/clients?&page=1&itemsPerPage=10000`).subscribe(
|
||||
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;
|
||||
}
|
||||
);
|
||||
this.clients = response['hydra:member'];
|
||||
this.loading = false;
|
||||
},
|
||||
(error: any) => {
|
||||
error => {
|
||||
console.error('Error fetching clients:', error);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
resetFilters() {
|
||||
this.loading = true;
|
||||
this.filters = {};
|
||||
|
@ -291,6 +292,31 @@ export class TaskLogsComponent implements OnInit {
|
|||
this.loadTraces();
|
||||
}
|
||||
|
||||
translateCommand(command: string): string {
|
||||
return this.translationService.getCommandTranslation(command);
|
||||
}
|
||||
|
||||
clearCommandFilter(event: Event, clientSearchCommandInput: any): void {
|
||||
event.stopPropagation();
|
||||
delete this.filters['command'];
|
||||
clientSearchCommandInput.value = null;
|
||||
this.loadTraces()
|
||||
}
|
||||
|
||||
clearStatusFilter(event: Event, clientSearchStatusInput: any): void {
|
||||
event.stopPropagation();
|
||||
delete this.filters['status'];
|
||||
clientSearchStatusInput.value = null;
|
||||
this.loadTraces()
|
||||
}
|
||||
|
||||
clearClientFilter(event: Event, clientSearchClientInput: any): void {
|
||||
event.stopPropagation();
|
||||
delete this.filters['client.id'];
|
||||
clientSearchClientInput.value = null;
|
||||
this.loadTraces()
|
||||
}
|
||||
|
||||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: [
|
||||
|
|
|
@ -2,12 +2,8 @@ mat-toolbar {
|
|||
/*height: 7vh;*/
|
||||
min-height: 65px;
|
||||
min-width: 375px;
|
||||
background-color: #3f51b5;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.trace-button .mat-icon {
|
||||
color: #ffffff;
|
||||
background-color: #e2e8f0;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.navbar-actions-row {
|
||||
|
@ -51,6 +47,10 @@ mat-toolbar {
|
|||
display: none;
|
||||
}
|
||||
|
||||
.trace-button {
|
||||
color: #3f51b5;
|
||||
}
|
||||
|
||||
@media (min-width: 1500px) {
|
||||
.hide-on-small {
|
||||
display: inline;
|
||||
|
@ -80,4 +80,4 @@ mat-toolbar {
|
|||
.smallScreenMenubutton {
|
||||
margin-right: 2vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<mat-toolbar>
|
||||
<span class="navbar-title hide-on-small" matTooltip="Consola web de administración de Opengnsys"
|
||||
matTooltipShowDelay="1000">
|
||||
Opengnsys webconsole
|
||||
</span>
|
||||
|
||||
<button mat-icon-button (click)="onToggleSidebar()" matTooltip="Abrir o cerrar la barra lateral"
|
||||
|
@ -10,8 +9,8 @@
|
|||
</button>
|
||||
|
||||
<div class="navbar-actions-row" *ngIf="!isSmallScreen">
|
||||
<button class="trace-button" routerLink="/commands-logs" mat-button>
|
||||
<mat-icon>notifications</mat-icon>
|
||||
<button routerLink="/commands-logs" mat-button>
|
||||
<mat-icon class="trace-button" >notifications</mat-icon>
|
||||
</button>
|
||||
|
||||
<div class="navbar-buttons-row">
|
||||
|
@ -73,4 +72,4 @@
|
|||
{{ 'labelEnvVars' | translate }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
</mat-toolbar>
|
||||
</mat-toolbar>
|
||||
|
|
|
@ -1,9 +1,30 @@
|
|||
/* styles.css o en el componente */
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: calc(100vh - 7vh);
|
||||
min-width: 375px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 15vw;
|
||||
min-width: 250px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.custom-sidebar {
|
||||
background-color: #1e293b;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.custom-sidebar .mat-list-item {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.mat-icon {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.mat-list-item:hover {
|
||||
background-color: #2a2a40;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<app-header (toggleSidebar)="toggleSidebar()"></app-header>
|
||||
|
||||
<mat-drawer-container class="container" autosize>
|
||||
<mat-drawer class="sidebar" [mode]="sidebarMode" [opened]="isSidebarVisible" (close)="isSidebarVisible = false">
|
||||
<mat-drawer class="sidebar custom-sidebar" [mode]="sidebarMode" [opened]="isSidebarVisible" (close)="isSidebarVisible = false">
|
||||
<app-sidebar [isVisible]="isSidebarVisible" [sidebarMode]="sidebarMode" (closeSidebar)="isSidebarVisible = false">
|
||||
</app-sidebar>
|
||||
</mat-drawer>
|
||||
|
||||
<mat-drawer-content class="content">
|
||||
<app-header (toggleSidebar)="toggleSidebar()"></app-header>
|
||||
<router-outlet></router-outlet>
|
||||
</mat-drawer-content>
|
||||
</mat-drawer-container>
|
||||
</mat-drawer-container>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mat-nav-list {
|
||||
width: auto;
|
||||
margin-right: 5px;
|
||||
overflow-x: hidden;
|
||||
width: auto;
|
||||
margin-right: 5px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
mat-list-item {
|
||||
|
@ -23,18 +23,42 @@ mat-icon {
|
|||
|
||||
.user-logged {
|
||||
align-items: center;
|
||||
height: 70px;
|
||||
gap: 2rem;
|
||||
padding: 1rem;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
.user-logged span {
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
.custom-sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background-color: #1e1e2f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.sidebar-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar-content span {
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
button {
|
||||
color: white;
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
|
||||
.admin-link {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
@ -61,5 +85,35 @@ mat-icon {
|
|||
.disabled {
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.user-info {
|
||||
justify-content: center;
|
||||
padding: 12px 0 12px;
|
||||
}
|
||||
|
||||
.user-info-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.user-logo {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
object-fit: contain;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.user-logged {
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.white-divider {
|
||||
border-top-color: rgba(255, 255, 255, 0.2) !important;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<mat-nav-list>
|
||||
<mat-list-item disabled>
|
||||
<span class="user-logged" matTooltipShowDelay="1000">
|
||||
<span>{{ 'welcomeUser' | translate:{username: username} }}</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
<mat-nav-list class="sidebar-content">
|
||||
<div disabled class="user-info">
|
||||
<div class="user-info-wrapper" matTooltipShowDelay="1000">
|
||||
<img ngSrc="assets/images/logo.png" alt="Logo" class="user-logo" height="500" width="500"/>
|
||||
<span class="user-logged">
|
||||
{{ 'welcomeUser' | translate:{username: username} }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider class="white-divider"></mat-divider>
|
||||
|
||||
<mat-list-item routerLink="/groups" (click)="onItemClick()" matTooltip="{{ 'TOOLTIP_GROUPS' | translate }}"
|
||||
matTooltipShowDelay="1000">
|
||||
|
@ -145,4 +147,4 @@
|
|||
<span>{{ 'menus' | translate }}</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
</mat-nav-list>
|
||||
</mat-nav-list>
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { COMMAND_TYPES } from '../shared/constants/command-types';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TranslationService {
|
||||
private currentLang: string = 'es';
|
||||
|
||||
constructor() {}
|
||||
|
||||
getCommandTranslation(command: string): string {
|
||||
switch(command) {
|
||||
case 'install-oglive':
|
||||
return COMMAND_TYPES['install-oglive'][this.currentLang];
|
||||
case 'create-aux-file':
|
||||
return COMMAND_TYPES['create-aux-file'][this.currentLang];
|
||||
case 'convert-image-to-virtual':
|
||||
return COMMAND_TYPES['convert-image-to-virtual'][this.currentLang];
|
||||
case 'deploy-image':
|
||||
return COMMAND_TYPES['deploy-image'][this.currentLang];
|
||||
case 'create-image':
|
||||
return COMMAND_TYPES['create-image'][this.currentLang];
|
||||
case 'reboot':
|
||||
return COMMAND_TYPES.reboot[this.currentLang];
|
||||
case 'shutdown':
|
||||
return COMMAND_TYPES.shutdown[this.currentLang];
|
||||
case 'partition-and-format':
|
||||
return COMMAND_TYPES['partition-and-format'][this.currentLang];
|
||||
case 'run-script':
|
||||
return COMMAND_TYPES['run-script'][this.currentLang];
|
||||
default:
|
||||
return command;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
export const COMMAND_TYPES: any = {
|
||||
'create-image': {
|
||||
en: 'Create Image',
|
||||
es: 'Crear Imagen'
|
||||
},
|
||||
|
||||
'deploy-image': {
|
||||
en: 'Deploy Image',
|
||||
es: 'Desplegar Imagen'
|
||||
},
|
||||
|
||||
'install-oglive': {
|
||||
en: 'Install OGLive',
|
||||
es: 'Instalar OGLive'
|
||||
},
|
||||
|
||||
'create-aux-file': {
|
||||
en: 'Create Auxiliary File',
|
||||
es: 'Crear archivos auxiliares'
|
||||
},
|
||||
|
||||
'convert-image-to-virtual': {
|
||||
en: 'Convert Image to Virtual',
|
||||
es: 'Convertir imagen a virtual'
|
||||
},
|
||||
|
||||
reboot: {
|
||||
en: 'Reboot',
|
||||
es: 'Reiniciar'
|
||||
},
|
||||
|
||||
shutdown: {
|
||||
en: 'Shutdown',
|
||||
es: 'Apagar'
|
||||
},
|
||||
|
||||
'partition-and-format': {
|
||||
en: 'Partition and Format',
|
||||
es: 'Particionar y Formatear'
|
||||
},
|
||||
|
||||
'run-script': {
|
||||
en: 'Run Script',
|
||||
es: 'Ejecutar Script'
|
||||
}
|
||||
};
|
|
@ -51,12 +51,14 @@
|
|||
"checkboxOrgMinimal": "Minimal Organizational Unit",
|
||||
"checkboxUserRole": "User",
|
||||
"groupsTitleStepText": "On this screen, you can manage the main organizational units (Faculties, Classrooms, Classroom Groups, and clients).",
|
||||
"repositoryTitleStepText": "On this screen, you can manage the repositories.",
|
||||
"tableDateRepositoryText": "Use the table to view the details of the repositories.",
|
||||
"titleStepText": "On this screen, you can manage the calendars of remote teams connected to the UDS service",
|
||||
"groupsAddStepText": "Click to add a new organizational unit or clients.",
|
||||
"adminCalendarsTitle": "Manage calendars",
|
||||
"addButtonStepText": "Click here to add a new calendar.",
|
||||
"addCalendar": "Add calendar",
|
||||
"searchStepText": "Use this search bar to filter existing calendars.",
|
||||
"searchStepText": "Use this search bar to filter existing entities.",
|
||||
"searchCalendarLabel": "Search calendar name",
|
||||
"tableStepText": "Here are the existing calendars with their characteristics and settings.",
|
||||
"actionsStepText": "Access the available actions for each calendar here.",
|
||||
|
@ -107,7 +109,7 @@
|
|||
"statusColumn": "Status",
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"adminCommandsTitle": "Command and procedure traces",
|
||||
"adminCommandsTitle": "Trace Commands",
|
||||
"resetFiltersStepText": "Click to reset the applied filters and see all traces.",
|
||||
"resetFilters": "Reset filters",
|
||||
"clientSelectStepText": "Select a client to see the associated traces.",
|
||||
|
@ -183,6 +185,7 @@
|
|||
"editUnitTooltip": "Edit this organizational unit",
|
||||
"viewUnitTooltip": "View organizational unit details",
|
||||
"viewUnitMenu": "View data",
|
||||
"tableDateStep": "Use the table to view the details",
|
||||
"addInternalUnitTooltip": "Create a new internal organizational unit",
|
||||
"addClientTooltip": "Register a client in this organizational unit",
|
||||
"deleteElementTooltip": "Delete this element",
|
||||
|
@ -359,10 +362,12 @@
|
|||
"nameColumnHeader": "Name",
|
||||
"templateColumnHeader": "Template",
|
||||
"pxeImageTitle": "Information on ogBoot server",
|
||||
"tableDatePxeTemplateText": "Use the table to view the details of the PXE templates.",
|
||||
"searchIsDefaultText": "Search for default images",
|
||||
"serverInfoDescription": "Access information and synchronization options on the OgBoot server.",
|
||||
"syncDatabaseButton": "Sync database",
|
||||
"viewInfoButton": "View Information",
|
||||
"adminImagesDescription": "From here you can manage the images configured on the OgBoot server.",
|
||||
"adminImagesDescription": "From here you can manage the ogLive images configured on the OgBoot server.",
|
||||
"actionsDescription": "Manage each image with options to view, edit, delete, and more.",
|
||||
"addClientButton": "Add client",
|
||||
"searchClientNameLabel": "Search client name",
|
||||
|
@ -427,6 +432,7 @@
|
|||
"boot": "Boot",
|
||||
"TOOLTIP_BOOT": "Configure and manage boot options",
|
||||
"ogLive": "ogLive",
|
||||
"viewInfoStepText": "View information about the OgLive server",
|
||||
"TOOLTIP_PXE_IMAGES": "View available PXE boot images",
|
||||
"pxeTemplates": "PXE Templates",
|
||||
"pxeTemplate": "Template",
|
||||
|
@ -488,6 +494,9 @@
|
|||
"processes": "Processes",
|
||||
"usedPercentageLabel": "Used",
|
||||
"errorLoadingData": "Error fetching data. Service not available",
|
||||
"repository": "Repository",
|
||||
"addRepository": "Add repository",
|
||||
"addRepositoryStepText": "Click to add a new repository.",
|
||||
"repositoryTitleStep": "On this screen you can manage image repositories.",
|
||||
"partitions": "Partitions",
|
||||
"clientsViewStepText": "Display of the selected organizational unit's clients",
|
||||
|
@ -510,5 +519,13 @@
|
|||
},
|
||||
"remoteAccess": "Remote access available",
|
||||
"noRemoteAccess": "Remote access not available",
|
||||
"capacityWarning": "The capacity cannot be negative"
|
||||
}
|
||||
"capacityWarning": "The capacity cannot be negative",
|
||||
"monolithicImageStep": "Monolithic image",
|
||||
"monolithicImageStepText": "On this screen you can manage monolithic images.",
|
||||
"monolithicImage": "Monolithic image",
|
||||
"gitImage": "Git images",
|
||||
"gitImageStep": "Git images",
|
||||
"gitImageStepText": "On this screen you can manage git images.",
|
||||
"partitions": "Particiones",
|
||||
"isDefaultLabel": "Default"
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"Administration": "Administración",
|
||||
"changePassword": "Cambiar contraseña",
|
||||
"logout": "Salir",
|
||||
"logout": "Cerrar sesión",
|
||||
"loginlabelUsername": "Introduce tu usuario",
|
||||
"loginlabelPassword": "Introduce tu contraseña",
|
||||
"buttonLogin": "Login",
|
||||
|
@ -56,7 +56,7 @@
|
|||
"adminCalendarsTitle": "Administrar calendarios",
|
||||
"addButtonStepText": "Haz clic aquí para añadir un nuevo calendario.",
|
||||
"addCalendar": "Añadir calendario",
|
||||
"searchStepText": "Utiliza esta barra de búsqueda para filtrar los calendarios existentes.",
|
||||
"searchStepText": "Utiliza esta barra de búsqueda para filtrar las entidades existentes.",
|
||||
"searchCalendarLabel": "Buscar nombre de calendario",
|
||||
"tableStepText": "Aquí se muestran los calendarios existentes con sus características y configuraciones.",
|
||||
"actionsStepText": "Accede a las acciones disponibles para cada calendario aquí.",
|
||||
|
@ -71,6 +71,7 @@
|
|||
"reasonPlaceholder": "Razón para la excepción",
|
||||
"startDate": "Fecha de inicio",
|
||||
"endDate": "Fecha de fin",
|
||||
"tableDateStep": "Esta tabla muestra los datos asociados al modulo en concreto",
|
||||
"buttonSave": "Guardar",
|
||||
"adminCommandGroupsTitle": "Administrar Grupos de Comandos",
|
||||
"addCommandGroupStepText": "Haz clic para añadir un nuevo grupo de comandos.",
|
||||
|
@ -107,13 +108,13 @@
|
|||
"statusColumn": "Estado",
|
||||
"enabled": "Habilitado",
|
||||
"disabled": "Deshabilitado",
|
||||
"adminCommandsTitle": "Trazas de comandos y procedimientos",
|
||||
"adminCommandsTitle": "Traza de ejecución",
|
||||
"CommandsTitle": "Administrar Comandos",
|
||||
"resetFiltersStepText": "Haz clic para reiniciar los filtros aplicados y ver todas las trazas.",
|
||||
"resetFilters": "Reiniciar filtros",
|
||||
"clientSelectStepText": "Selecciona un cliente para ver las trazas asociadas.",
|
||||
"filterClientPlaceholder": "Filtrar por cliente",
|
||||
"commandSelectStepText": "Selecciona un comando para ver las trazas específicas de ese comando.",
|
||||
"commandSelectStepText": "Selecciona un comando para ver las trazas.",
|
||||
"filterCommandPlaceholder": "Filtrar por comando",
|
||||
"taskDetailsTitle": "Detalles de la Tarea",
|
||||
"taskId": "ID de la Tarea",
|
||||
|
@ -263,6 +264,7 @@
|
|||
"ipLabel": "Dirección IP",
|
||||
"ipError": "Formato de dirección IP inválido. Ejemplo válido: 127.0.0.1",
|
||||
"templateLabel": "Plantilla PXE",
|
||||
"templateContent": "Contenido de la plantilla PXE",
|
||||
"digitalBoard": "Pizarra digital",
|
||||
"projectorAlt": "Proyector",
|
||||
"clientAlt": "Cliente",
|
||||
|
@ -360,10 +362,12 @@
|
|||
"nameColumnHeader": "Nombre",
|
||||
"templateColumnHeader": "Plantilla",
|
||||
"pxeImageTitle": "Información en servidor ogBoot",
|
||||
"tableDatePxeTemplateText": "Esta tabla muestra los datos asociados a las plantillas PXE existentes.",
|
||||
"searchIsDefaultText": "Filtra para mostrar solo las imágenes por defecto o no por defecto.",
|
||||
"serverInfoDescription": "Accede a información y opciones de sincronización en el servidor OgBoot.",
|
||||
"syncDatabaseButton": "Sincronizar base de datos",
|
||||
"viewInfoButton": "Ver Información",
|
||||
"adminImagesDescription": "Desde aquí puedes gestionar las imágenes configuradas en el servidor OgBoot.",
|
||||
"adminImagesDescription": "Desde aquí puedes gestionar las imágenes ogLive.",
|
||||
"actionsDescription": "Administra cada imagen con opciones para ver, editar, eliminar y más.",
|
||||
"addClientButton": "Añadir cliente",
|
||||
"searchClientNameLabel": "Buscar nombre de cliente",
|
||||
|
@ -429,6 +433,7 @@
|
|||
"boot": "Boot",
|
||||
"TOOLTIP_BOOT": "Configurar y administrar opciones de arranque",
|
||||
"ogLive": "ogLive",
|
||||
"viewInfoStepText": "Accede a información y opciones en la API de OgBoot.",
|
||||
"TOOLTIP_PXE_IMAGES": "Ver imágenes disponibles para arranque PXE",
|
||||
"pxeTemplates": "Plantillas PXE",
|
||||
"pxeTemplate": "Plantilla",
|
||||
|
@ -490,6 +495,9 @@
|
|||
"processes": "Procesos",
|
||||
"usedPercentageLabel": "Usado",
|
||||
"errorLoadingData": "Error al cargar los datos. Servicio inactivo",
|
||||
"repository": "Repositorio",
|
||||
"addRepository": "Añadir repositorio",
|
||||
"addRepositoryStepText": "Haz clic para añadir un nuevo repositorio.",
|
||||
"repositoryTitleStep": "En esta pantalla se pueden gestionar los repositorios de imágenes.",
|
||||
"partitions": "Particiones",
|
||||
"clientsViewStepText": "Visualización de los clientes de la unidad organizativa seleccionada",
|
||||
|
@ -512,5 +520,15 @@
|
|||
},
|
||||
"remoteAccess": "Disponible acceso remoto",
|
||||
"noRemoteAccess": "No disponible acceso remoto",
|
||||
"capacityWarning": "El aforo no puede ser"
|
||||
}
|
||||
"capacityWarning": "El aforo no puede ser",
|
||||
"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",
|
||||
"monolithicImageStepText": "Esta opción permite visualizar las imágenes monolíticas disponibles en el servidor.",
|
||||
"gitImageStep": "Imágenes Git",
|
||||
"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"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue