Merge branch 'develop' of ssh://ognproject.evlt.uma.es:21987/opengnsys/oggui into develop
commit
3a7eaddcce
|
@ -71,12 +71,12 @@ table {
|
|||
}
|
||||
|
||||
.chip-failed {
|
||||
background-color: #f15d5d !important;
|
||||
background-color: #e87979 !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.chip-success {
|
||||
background-color: #32c532 !important;
|
||||
background-color: #46c446 !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
|
|
@ -247,9 +247,8 @@
|
|||
}
|
||||
|
||||
.charts-container {
|
||||
flex: 2;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ export class ClientMainViewComponent implements OnInit {
|
|||
partitions: any[] = [];
|
||||
commands: any[] = [];
|
||||
chartDisk: any[] = [];
|
||||
view: [number, number] = [600, 300];
|
||||
view: [number, number] = [300, 200];
|
||||
showLegend: boolean = true;
|
||||
|
||||
arrayCommands: any[] = [
|
||||
|
@ -100,15 +100,28 @@ export class ClientMainViewComponent implements OnInit {
|
|||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.clientData = history.state.clientData;
|
||||
this.loadPartitions()
|
||||
this.updateGeneralData();
|
||||
this.updateNetworkData();
|
||||
this.clientData = history.state.clientData['@id'];
|
||||
this.loadClient(this.clientData)
|
||||
this.loadCommands()
|
||||
this.calculateDiskUsage();
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
|
||||
loadClient = (uuid: string) => {
|
||||
this.http.get<any>(`${this.baseUrl}${uuid}`).subscribe({
|
||||
next: data => {
|
||||
this.clientData = data;
|
||||
this.updateGeneralData();
|
||||
this.updateNetworkData();
|
||||
this.loadPartitions()
|
||||
this.loading = false;
|
||||
},
|
||||
error: error => {
|
||||
console.error('Error al obtener el cliente:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
updateGeneralData() {
|
||||
this.generalData = [
|
||||
{ property: 'Nombre', value: this.clientData?.name || '' },
|
||||
|
@ -184,15 +197,6 @@ export class ClientMainViewComponent implements OnInit {
|
|||
dialogRef.afterClosed().subscribe();
|
||||
}
|
||||
|
||||
getStrokeOffset(partitions: any[], index: number): number {
|
||||
const totalSize = partitions.reduce((acc, part) => acc + (part.size / 1024), 0);
|
||||
|
||||
const offset = partitions.slice(0, index).reduce((acc, part) => acc + (part.size / 1024), 0);
|
||||
console.log(offset, totalSize)
|
||||
|
||||
return totalSize > 0 ? (offset / totalSize) : 0;
|
||||
}
|
||||
|
||||
loadPartitions(): void {
|
||||
this.http.get<any>(`${this.baseUrl}/partitions?client.id=${this.clientData?.id}&order[partitionNumber]=ASC`).subscribe({
|
||||
next: data => {
|
||||
|
@ -218,7 +222,6 @@ export class ClientMainViewComponent implements OnInit {
|
|||
}
|
||||
|
||||
onCommandSelect(action: any): void {
|
||||
console.log(action);
|
||||
if (action === 'partition') {
|
||||
this.openPartitionAssistant();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Seleccione método de deploy</mat-label>
|
||||
<mat-select [(ngModel)]="selectedMethod" name="selectedMethod">
|
||||
<mat-option *ngFor="let method of deployMethods" [disabled]="method !== 'unicast'" [value]="method">{{ method }}</mat-option>
|
||||
<mat-option *ngFor="let method of deployMethods" [value]="method">{{ method }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,7 @@ export class DeployImageComponent {
|
|||
images: any[] = [];
|
||||
clientName: string = '';
|
||||
selectedImage: string | null = null;
|
||||
selectedOption: string | null = null;
|
||||
selectedOption: string | null = 'deploy-image';
|
||||
selectedMethod: string | null = null;
|
||||
selectedPartition: any = null;
|
||||
mcastIp: string = '';
|
||||
|
@ -98,7 +98,7 @@ export class DeployImageComponent {
|
|||
|
||||
ngOnInit() {
|
||||
this.clientId = this.route.snapshot.paramMap.get('id');
|
||||
|
||||
this.selectedOption = 'deploy-image';
|
||||
this.loadPartitions();
|
||||
this.loadImages();
|
||||
}
|
||||
|
@ -147,6 +147,21 @@ export class DeployImageComponent {
|
|||
}
|
||||
|
||||
save(): void {
|
||||
if (!this.selectedImage) {
|
||||
this.toastService.error('Debe seleccionar una imagen');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.selectedMethod) {
|
||||
this.toastService.error('Debe seleccionar un método');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.selectedPartition) {
|
||||
this.toastService.error('Debe seleccionar una partición');
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
client: `/clients/${this.clientId}`,
|
||||
method: this.selectedMethod,
|
||||
|
@ -163,7 +178,7 @@ export class DeployImageComponent {
|
|||
.subscribe({
|
||||
next: (response) => {
|
||||
this.toastService.success('Imagen creada exitosamente');
|
||||
this.router.navigate(['/images']);
|
||||
this.router.navigate(['/commmands-logs'])
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error:', error);
|
||||
|
|
|
@ -289,7 +289,7 @@ export class PartitionAssistantComponent implements OnInit {
|
|||
this.http.post(this.apiUrl, bulkPayload).subscribe(
|
||||
(response) => {
|
||||
this.toastService.success('Particiones creadas exitosamente');
|
||||
this.router.navigate(['/traces']);
|
||||
this.router.navigate(['/commands-logs']);
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error al crear las particiones:', error);
|
||||
|
|
|
@ -219,7 +219,7 @@
|
|||
<mat-icon>sync</mat-icon>
|
||||
<span>{{ 'sync' | translate }}</span>
|
||||
</button>
|
||||
|
||||
|
||||
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
|
||||
<mat-icon>edit</mat-icon>
|
||||
<span>{{ 'edit' | translate }}</span>
|
||||
|
@ -296,7 +296,7 @@
|
|||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
<mat-menu #clientMenu="matMenu">
|
||||
|
||||
|
||||
<button mat-menu-item *ngIf="(!syncStatus || syncingClientId !== client.uuid)" (click)="getStatus(client)">
|
||||
<mat-icon>sync</mat-icon>
|
||||
<span>Sincronizar</span>
|
||||
|
@ -324,4 +324,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
|
|
|
@ -86,11 +86,45 @@ export class DataService {
|
|||
);
|
||||
}
|
||||
|
||||
getOgLives(): Observable<any[]> {
|
||||
const url = `${this.baseUrl}/og-lives`;
|
||||
return this.http.get<any>(url).pipe(
|
||||
map(response => {
|
||||
if (response['hydra:member'] && Array.isArray(response['hydra:member'])) {
|
||||
return response['hydra:member']
|
||||
} else {
|
||||
throw new Error('Unexpected response format');
|
||||
}
|
||||
}),
|
||||
catchError(error => {
|
||||
console.error('Error fetching clients', error);
|
||||
return throwError(error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getRepositories(): Observable<any[]> {
|
||||
const url = `${this.baseUrl}/image-repositories`;
|
||||
return this.http.get<any>(url).pipe(
|
||||
map(response => {
|
||||
if (response['hydra:member'] && Array.isArray(response['hydra:member'])) {
|
||||
return response['hydra:member']
|
||||
} else {
|
||||
throw new Error('Unexpected response format');
|
||||
}
|
||||
}),
|
||||
catchError(error => {
|
||||
console.error('Error fetching clients', error);
|
||||
return throwError(error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
deleteElement(uuid: string, type: string): Observable<void> {
|
||||
const url = type === 'client'
|
||||
? `${this.baseUrl}/clients/${uuid}`
|
||||
: `${this.baseUrl}/organizational-units/${uuid}`;
|
||||
|
||||
|
||||
console.log('DELETE URL:', url); // Depuración
|
||||
return this.http.delete<void>(url).pipe(
|
||||
catchError(error => {
|
||||
|
@ -99,7 +133,7 @@ export class DataService {
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
changeParent(uuid: string): Observable<void> {
|
||||
const url = `${this.baseUrl}/organizational-units/${uuid}/change-parent`;
|
||||
|
@ -186,7 +220,7 @@ export class DataService {
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
getOrganizationalUnitById(id: string): Observable<any> {
|
||||
const url = `${this.baseUrl}/organizational-units/${id}`;
|
||||
return this.http.get<any>(url).pipe(
|
||||
|
@ -196,6 +230,6 @@ export class DataService {
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -84,6 +84,22 @@
|
|||
<mat-step *ngIf="generalFormGroup.value.type === 'classroom'" [stepControl]="networkSettingsFormGroup">
|
||||
<form [formGroup]="networkSettingsFormGroup">
|
||||
<ng-template matStepLabel>{{ 'networkSettingsStepLabel' | translate }}</ng-template>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'ogLiveLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="oglive" (selectionChange)="onOgLiveChange($event)">
|
||||
<mat-option *ngFor="let oglive of ogLives" [value]="oglive['@id']">
|
||||
{{ oglive.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'repositoryLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="repository" (selectionChange)="onRepositoryChange($event)">
|
||||
<mat-option *ngFor="let repository of repositories" [value]="repository['@id']">
|
||||
{{ repository.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'nextServerLabel' | translate }}</mat-label>
|
||||
<input matInput formControlName="nextServer">
|
||||
|
|
|
@ -37,6 +37,8 @@ export class CreateOrganizationalUnitComponent implements OnInit {
|
|||
parentUnits: any[] = [];
|
||||
hardwareProfiles: any[] = [];
|
||||
calendars: any[] = [];
|
||||
ogLives: any[] = [];
|
||||
repositories: any[] = [];
|
||||
selectedCalendarUuid: string | null = null;
|
||||
|
||||
@Output() unitAdded = new EventEmitter();
|
||||
|
@ -59,6 +61,8 @@ export class CreateOrganizationalUnitComponent implements OnInit {
|
|||
comments: [''],
|
||||
});
|
||||
this.networkSettingsFormGroup = this._formBuilder.group({
|
||||
ogLive: [null],
|
||||
ogRepository: [null],
|
||||
nextServer: [''],
|
||||
bootFileName: [''],
|
||||
proxy: [''],
|
||||
|
@ -89,6 +93,8 @@ export class CreateOrganizationalUnitComponent implements OnInit {
|
|||
this.loadParentUnits();
|
||||
this.loadHardwareProfiles();
|
||||
this.loadCalendars();
|
||||
this.loadOgLives();
|
||||
this.loadRepositories();
|
||||
}
|
||||
|
||||
loadParentUnits() {
|
||||
|
@ -106,6 +112,20 @@ export class CreateOrganizationalUnitComponent implements OnInit {
|
|||
);
|
||||
}
|
||||
|
||||
loadOgLives() {
|
||||
this.dataService.getOgLives().subscribe(
|
||||
(data: any[]) => this.ogLives = data,
|
||||
error => console.error('Error fetching ogLives', error)
|
||||
);
|
||||
}
|
||||
|
||||
loadRepositories() {
|
||||
this.dataService.getRepositories().subscribe(
|
||||
(data: any[]) => this.repositories = data,
|
||||
error => console.error('Error fetching repositories', error)
|
||||
);
|
||||
}
|
||||
|
||||
loadCalendars() {
|
||||
const apiUrl = `${this.baseUrl}/remote-calendars?page=1&itemsPerPage=30`;
|
||||
this.http.get<any>(apiUrl).subscribe(
|
||||
|
@ -169,14 +189,25 @@ export class CreateOrganizationalUnitComponent implements OnInit {
|
|||
comments: additionalInfoFormValues.comments,
|
||||
networkSettings: { ...networkSettingsFormValues },
|
||||
menu: networkSettingsFormValues.menu || null,
|
||||
ogLive: networkSettingsFormValues.ogLive || null,
|
||||
ogRepository: networkSettingsFormValues.ogRepository || null,
|
||||
hardwareProfile: networkSettingsFormValues.hardwareProfile || null,
|
||||
};
|
||||
}
|
||||
|
||||
onCalendarChange(event: any) {
|
||||
this.generalFormGroup.value.remoteCalendar = event.value;
|
||||
this.selectedCalendarUuid = event.value;
|
||||
}
|
||||
|
||||
onOgLiveChange(event: any) {
|
||||
this.networkSettingsFormGroup.value.ogLive = event.value;
|
||||
}
|
||||
|
||||
onRepositoryChange(event: any) {
|
||||
this.networkSettingsFormGroup.value.ogRepository = event
|
||||
}
|
||||
|
||||
onNoClick(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
|
|
@ -81,6 +81,22 @@
|
|||
<mat-step [stepControl]="networkSettingsFormGroup">
|
||||
<form [formGroup]="networkSettingsFormGroup">
|
||||
<ng-template matStepLabel>{{ 'networkSettingsStepLabel' | translate }}</ng-template>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'ogLiveLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="ogLive" (selectionChange)="onOgLiveChange($event)">
|
||||
<mat-option *ngFor="let oglive of ogLives" [value]="oglive['@id']">
|
||||
{{ oglive.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'repositoryLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="repository" (selectionChange)="onRepositoryChange($event)">
|
||||
<mat-option *ngFor="let repository of repositories" [value]="repository['@id']">
|
||||
{{ repository.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'proxyUrlLabel' | translate }}</mat-label>
|
||||
<input matInput formControlName="proxy">
|
||||
|
@ -143,12 +159,12 @@
|
|||
<mat-slide-toggle formControlName="validation">{{ 'validationToggle' | translate }}</mat-slide-toggle>
|
||||
<div>
|
||||
<button mat-button matStepperPrevious>{{ 'backButton' | translate }}</button>
|
||||
<button mat-button (click)="onSubmit()" [disabled]="!networkSettingsFormGroup.valid">{{ 'submitButton' | translate }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</mat-step>
|
||||
</mat-stepper>
|
||||
</div>
|
||||
<div mat-dialog-actions>
|
||||
<div mat-dialog-actions align="end">
|
||||
<button mat-button (click)="onNoClick()">{{ 'cancelButton' | translate }}</button>
|
||||
<button mat-button (click)="onSubmit()" [disabled]="!networkSettingsFormGroup.valid">{{ 'submitButton' | translate }}</button>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { Component, EventEmitter, Inject, OnInit, Output } from '@angular/core';
|
||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { CreateOrganizationalUnitComponent } from '../create-organizational-unit/create-organizational-unit.component';
|
||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||
import {Component, EventEmitter, Inject, OnInit, Output} from '@angular/core';
|
||||
import {FormBuilder, FormGroup} from '@angular/forms';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||
import {CreateOrganizationalUnitComponent} from '../create-organizational-unit/create-organizational-unit.component';
|
||||
import {DataService} from "../../../services/data.service";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
|
||||
|
@ -23,6 +23,8 @@ export class EditOrganizationalUnitComponent implements OnInit {
|
|||
hardwareProfiles: any[] = [];
|
||||
isEditMode: boolean;
|
||||
currentCalendar: any = [];
|
||||
ogLives: any[] = [];
|
||||
repositories: any[] = [];
|
||||
protected p2pModeOptions = [
|
||||
{"name": 'Leecher', "value": "p2p-mode-leecher"},
|
||||
{"name": 'Peer', "value": "p2p-mode-peer"},
|
||||
|
@ -57,6 +59,8 @@ export class EditOrganizationalUnitComponent implements OnInit {
|
|||
});
|
||||
|
||||
this.networkSettingsFormGroup = this._formBuilder.group({
|
||||
ogLive: [null],
|
||||
repository: [null],
|
||||
proxy: [null],
|
||||
dns: [null],
|
||||
netmask: [null],
|
||||
|
@ -90,6 +94,8 @@ export class EditOrganizationalUnitComponent implements OnInit {
|
|||
this.loadParentUnits();
|
||||
this.loadHardwareProfiles();
|
||||
this.loadCalendars();
|
||||
this.loadOgLives();
|
||||
this.loadRepositories();
|
||||
}
|
||||
|
||||
loadParentUnits() {
|
||||
|
@ -116,6 +122,20 @@ export class EditOrganizationalUnitComponent implements OnInit {
|
|||
);
|
||||
}
|
||||
|
||||
loadOgLives() {
|
||||
this.dataService.getOgLives().subscribe(
|
||||
(data: any[]) => this.ogLives = data,
|
||||
error => console.error('Error fetching ogLives', error)
|
||||
);
|
||||
}
|
||||
|
||||
loadRepositories() {
|
||||
this.dataService.getRepositories().subscribe(
|
||||
(data: any[]) => this.repositories = data,
|
||||
error => console.error('Error fetching repositories', error)
|
||||
);
|
||||
}
|
||||
|
||||
loadCalendars() {
|
||||
const apiUrl = `${this.baseUrl}/remote-calendars?page=1&itemsPerPage=30`;
|
||||
this.http.get<any>(apiUrl).subscribe(
|
||||
|
@ -138,9 +158,15 @@ export class EditOrganizationalUnitComponent implements OnInit {
|
|||
);}
|
||||
|
||||
onCalendarChange(event: any) {
|
||||
const selectedCalendarId = event.value;
|
||||
console.log('Selected calendar ID:', selectedCalendarId);
|
||||
this.generalFormGroup.value.remoteCalendar = selectedCalendarId;
|
||||
this.generalFormGroup.value.remoteCalendar = event.value;
|
||||
}
|
||||
|
||||
onOgLiveChange(event: any) {
|
||||
this.networkSettingsFormGroup.value.ogLive = event.value;
|
||||
}
|
||||
|
||||
onRepositoryChange(event: any) {
|
||||
this.networkSettingsFormGroup.value.repository = event.value
|
||||
}
|
||||
|
||||
loadData(uuid: string) {
|
||||
|
@ -171,6 +197,8 @@ export class EditOrganizationalUnitComponent implements OnInit {
|
|||
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,
|
||||
validation: data.networkSettings.validation
|
||||
});
|
||||
this.classroomInfoFormGroup.patchValue({
|
||||
|
@ -245,5 +273,5 @@ export class EditOrganizationalUnitComponent implements OnInit {
|
|||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ export class ShowOrganizationalUnitComponent {
|
|||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
displayedColumns: string[] = ['property', 'value'];
|
||||
currentCalendar: any;
|
||||
ou: any;
|
||||
generalData: any[] = [];
|
||||
networkData = [
|
||||
];
|
||||
networkData: any[] = [];
|
||||
|
||||
constructor(
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
|
@ -22,11 +22,22 @@ export class ShowOrganizationalUnitComponent {
|
|||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.data.data.remoteCalendar) {
|
||||
this.loadCurrentCalendar(this.data.data.remoteCalendar.uuid);
|
||||
} else {
|
||||
this.initializeGeneralData();
|
||||
}
|
||||
this.loadOrganizationalUnit(this.data.data['@id']);
|
||||
}
|
||||
|
||||
loadOrganizationalUnit(uuid: string): void {
|
||||
console.log(this.data['@id'])
|
||||
const apiUrl = `${this.baseUrl}${uuid}`;
|
||||
this.http.get<any>(apiUrl).subscribe(
|
||||
response => {
|
||||
this.ou = response;
|
||||
console.log('Organizational unit', this.ou);
|
||||
this.initializeData();
|
||||
},
|
||||
error => {
|
||||
console.error('Error loading organizational unit', error);
|
||||
this.initializeData();
|
||||
});
|
||||
}
|
||||
|
||||
loadCurrentCalendar(uuid: string): void {
|
||||
|
@ -34,26 +45,39 @@ export class ShowOrganizationalUnitComponent {
|
|||
this.http.get<any>(apiUrl).subscribe(
|
||||
response => {
|
||||
this.currentCalendar = response.name;
|
||||
this.initializeGeneralData();
|
||||
this.initializeData();
|
||||
},
|
||||
error => {
|
||||
console.error('Error loading current calendar', error);
|
||||
this.initializeGeneralData();
|
||||
this.initializeData();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
initializeGeneralData(): void {
|
||||
initializeData(): void {
|
||||
this.generalData = [
|
||||
{ property: 'Nombre', value: this.data.data.name },
|
||||
{ property: 'Uuid', value: this.data.data.uuid },
|
||||
{ property: 'Descripción', value: this.data.data.description },
|
||||
{ property: 'Comentarios', value: this.data.data.comments },
|
||||
{ property: 'Tipo', value: this.data.data.type },
|
||||
{ property: 'Unidad organizativa superior', value: this.data.data.parent ? this.data.data.parent.name : '-' },
|
||||
{ property: 'Creado por', value: this.data.data.createdBy },
|
||||
{ property: 'Creado el', value: this.data.data.createdAt },
|
||||
{ property: 'Calendario asociado', value: this.data.data.remoteCalendar ? this.currentCalendar : '-' }
|
||||
{ property: 'Nombre', value: this.ou.name },
|
||||
{ property: 'Uuid', value: this.ou.uuid },
|
||||
{ property: 'Descripción', value: this.ou.description },
|
||||
{ property: 'Comentarios', value: this.ou.comments },
|
||||
{ property: 'Tipo', value: this.ou.type },
|
||||
{ property: 'Unidad organizativa superior', value: this.ou.parent ? this.ou.parent.name : '-' },
|
||||
{ property: 'Creado el', value: this.ou.createdAt },
|
||||
];
|
||||
|
||||
this.networkData = [
|
||||
{ property: 'Calendario asociado', value: this.ou.remoteCalendar ? this.currentCalendar : '-' },
|
||||
{ property: 'Aforo', value: this.ou.capacity },
|
||||
{ property: 'Localización', value: this.ou.location },
|
||||
{ property: 'Calendario', value: this.ou.calendar ? this.ou.calendar.name : '-' },
|
||||
{ property: 'Proyector', value: this.ou.projector },
|
||||
{ property: 'Pizarra', value: this.ou.board },
|
||||
{ property: 'OgLive', value: this.ou.networkSettings.ogLive ? this.ou.networkSettings.ogLive.name : '-' },
|
||||
{ property: 'Repositorio', value: this.ou.networkSettings.repository ? this.ou.networkSettings.repository.name : '-' },
|
||||
{ property: 'OgLog', value: this.ou.networkSettings.oglog },
|
||||
{ property: 'OgShare', value: this.ou.networkSettings.ogshare },
|
||||
{ property: 'Perfil de hardware', value: this.ou.networkSettings.hardwareProfile ? this.ou.networkSettings.hardwareProfile.name : '-' },
|
||||
{ property: 'Máscara de red', value: this.ou.networkSettings.netmask },
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,19 +71,23 @@ table {
|
|||
margin: 8px 8px 8px 0;
|
||||
}
|
||||
|
||||
.status-success {
|
||||
background-color: #4caf50; /* Verde */
|
||||
.chip-failed {
|
||||
background-color: #e87979 !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-failed {
|
||||
background-color: #f44336; /* Rojo */
|
||||
.chip-success {
|
||||
background-color: #46c446 !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
background-color: #ff9800; /* Naranja */
|
||||
.chip-pending {
|
||||
background-color: lightgrey !important;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.chip-in-progress {
|
||||
background-color: #f5a623 !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,7 +32,12 @@
|
|||
</mat-icon>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="column.columnDef === 'status'">
|
||||
<mat-chip >
|
||||
<mat-chip [ngClass]="{
|
||||
'chip-failed': image.status === 'failed',
|
||||
'chip-success': image.status === 'success',
|
||||
'chip-pending': image.status === 'pending',
|
||||
'chip-in-progress': image.status === 'in-progress'
|
||||
}">
|
||||
{{ getStatusLabel(image[column.columnDef]) }}
|
||||
</mat-chip>
|
||||
</ng-container>
|
||||
|
@ -54,7 +59,7 @@
|
|||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item [disabled]="!image.imageFullSum" (click)="toggleAction(image, 'get-aux')">Obtener ficheros auxiliares</button>
|
||||
<button mat-menu-item (click)="toggleAction(image, 'get-aux')">Obtener ficheros auxiliares</button>
|
||||
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'success'" (click)="toggleAction(image, 'delete-trash')">Eliminar imagen temporalmente</button>
|
||||
<button mat-menu-item [disabled]="!image.imageFullsum || image.status !== 'trash'" (click)="toggleAction(image, 'recover')">Recuperar imagen de la papelera</button>
|
||||
|
||||
|
|
|
@ -8,30 +8,14 @@
|
|||
</div>
|
||||
|
||||
<div [formGroup]="taskForm" class="search-container">
|
||||
<mat-form-field appearance="fill" class="search-boolean" joyrideStep="selectUnitStep" text="{{ 'selectUnitDescription' | translate }}">
|
||||
<mat-label>{{ 'selectUnitLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="organizationalUnit" (selectionChange)="onOrganizationalUnitChange()">
|
||||
<mat-option *ngIf="loadingUnits" disabled>{{ 'loadingUnitsOption' | translate }}</mat-option>
|
||||
<mat-option *ngFor="let unit of availableOrganizationalUnits" [value]="unit['@id']">
|
||||
{{ unit.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="taskForm.get('organizationalUnit')?.invalid">
|
||||
{{ 'requiredFieldError' | translate }}
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill" class="search-boolean" joyrideStep="selectClassStep" text="{{ 'selectClassDescription' | translate }}">
|
||||
<mat-label>{{ 'selectClassLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="selectedChild" (selectionChange)="onChildChange()">
|
||||
<mat-option *ngIf="selectedUnitChildren.length === 0" disabled>
|
||||
{{ 'noClassesOption' | translate }}
|
||||
</mat-option>
|
||||
<mat-option *ngFor="let child of selectedUnitChildren" [value]="child['@id']">
|
||||
{{ child.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<div [formGroup]="taskForm" class="search-container">
|
||||
<mat-form-field appearance="fill" class="search-boolean" joyrideStep="selectClassStep" text="{{ 'selectClassDescription' | translate }}">
|
||||
<mat-label>{{ 'selectClassLabel' | translate }}</mat-label>
|
||||
<mat-select (selectionChange)="loadChildUnits($event.value)">
|
||||
<mat-option *ngFor="let unit of units" [value]="unit.uuid">{{ unit.name }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
|
@ -49,7 +33,7 @@
|
|||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="selectedUnitChildren.length === 0"
|
||||
[disabled]="units.length === 0"
|
||||
(click)="saveOgLiveTemplates()"
|
||||
joyrideStep="saveButtonStep"
|
||||
text="{{ 'saveButtonDescription' | translate }}">
|
||||
|
@ -68,6 +52,16 @@
|
|||
<mat-cell *matCellDef="let element"> {{ element.name }} </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="ip">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'nameColumnHeader' | translate }}</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{ element.ip }} </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="mac">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'nameColumnHeader' | translate }}</mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{ element.mac }} </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="ogLive">
|
||||
<mat-header-cell *matHeaderCellDef>{{ 'templateColumnHeader' | translate }}</mat-header-cell>
|
||||
<mat-cell *matCellDef="let client">
|
||||
|
|
|
@ -19,7 +19,7 @@ export class PxeBootFilesComponent implements OnInit {
|
|||
selectedUnitChildren: any[] = [];
|
||||
dataSource: any[] = [];
|
||||
taskForm: FormGroup;
|
||||
loadingUnits: boolean = false;
|
||||
units: any[] = [];
|
||||
ogLiveOptions: any[] = [];
|
||||
globalOgLive: string | null = null;
|
||||
length: number = 0;
|
||||
|
@ -27,7 +27,7 @@ export class PxeBootFilesComponent implements OnInit {
|
|||
page: number = 0;
|
||||
pageSizeOptions: number[] = [5, 10, 20, 40, 100];
|
||||
filters: any = {};
|
||||
displayedColumns: string[] = ['id', 'name', 'ogLive'];
|
||||
displayedColumns: string[] = ['id', 'ip', 'mac', 'name', 'ogLive'];
|
||||
|
||||
|
||||
constructor(
|
||||
|
@ -43,23 +43,17 @@ export class PxeBootFilesComponent implements OnInit {
|
|||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.fetchOrganizationalUnits();
|
||||
this.fetchPxeTemplates();
|
||||
this.loadUnits()
|
||||
}
|
||||
|
||||
fetchOrganizationalUnits(): void {
|
||||
this.loadingUnits = true;
|
||||
this.http.get<any>(`${this.baseUrl}/organizational-units?page=1&itemsPerPage=30`)
|
||||
.subscribe(
|
||||
response => {
|
||||
this.availableOrganizationalUnits = response['hydra:member'].filter((item: any) => item.type === 'organizational-unit');
|
||||
this.loadingUnits = false;
|
||||
},
|
||||
error => {
|
||||
this.toastService.error('Error al cargar las unidades organizativas');
|
||||
this.loadingUnits = false;
|
||||
}
|
||||
);
|
||||
loadUnits() {
|
||||
this.http.get<any>(`${this.baseUrl}/organizational-units?type=classroom&page=1&itemsPerPage=50`).subscribe(
|
||||
response => {
|
||||
this.units = response['hydra:member'];
|
||||
},
|
||||
error => console.error('Error fetching organizational units:', error)
|
||||
);
|
||||
}
|
||||
|
||||
fetchPxeTemplates(): void {
|
||||
|
@ -75,45 +69,15 @@ export class PxeBootFilesComponent implements OnInit {
|
|||
);
|
||||
}
|
||||
|
||||
onOrganizationalUnitChange(): void {
|
||||
const selectedUnitId = this.taskForm.get('organizationalUnit')?.value;
|
||||
const selectedUnit = this.availableOrganizationalUnits.find(unit => unit['@id'] === selectedUnitId);
|
||||
|
||||
if (selectedUnit) {
|
||||
this.selectedUnitChildren = this.getAllClassrooms(selectedUnit);
|
||||
} else {
|
||||
this.selectedUnitChildren = [];
|
||||
}
|
||||
loadChildUnits(unitId: string) {
|
||||
this.http.get<any>(`${this.baseUrl}/clients?parent.id${unitId}`).subscribe(
|
||||
response => {
|
||||
this.dataSource = response['hydra:member'];
|
||||
},
|
||||
error => console.error('Error fetching child units:', error)
|
||||
);
|
||||
}
|
||||
|
||||
getAllClassrooms(unit: any): any[] {
|
||||
let classrooms: any[] = [];
|
||||
if (unit.type === 'classroom') {
|
||||
classrooms.push(unit);
|
||||
}
|
||||
if (unit.children) {
|
||||
for (const child of unit.children) {
|
||||
classrooms = classrooms.concat(this.getAllClassrooms(child));
|
||||
}
|
||||
}
|
||||
return classrooms;
|
||||
}
|
||||
|
||||
|
||||
onChildChange(): void {
|
||||
const selectedChildId = this.taskForm.get('selectedChild')?.value;
|
||||
const selectedChild = this.selectedUnitChildren.find(child => child['@id'] === selectedChildId);
|
||||
if (selectedChild && selectedChild.clients) {
|
||||
this.dataSource = selectedChild.clients.map((client: { template: { [x: string]: any; }; }) => ({
|
||||
...client,
|
||||
ogLive: client.template ? client.template['@id'] : null
|
||||
}));
|
||||
} else {
|
||||
this.dataSource = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
applyToAll(): void {
|
||||
this.dataSource = this.dataSource.map(client => ({
|
||||
...client,
|
||||
|
@ -152,12 +116,6 @@ export class PxeBootFilesComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
onPageChange(event: PageEvent): void {
|
||||
this.page = event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
this.fetchPxeTemplates();
|
||||
}
|
||||
|
||||
iniciarTour(): void {
|
||||
this.joyrideService.startTour({
|
||||
steps: [
|
||||
|
@ -173,5 +131,5 @@ export class PxeBootFilesComponent implements OnInit {
|
|||
themeColor: '#3f51b5'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
<mat-label>Boot File Name</mat-label>
|
||||
<input matInput [(ngModel)]="bootFileName" placeholder="Boot File Name">
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Router</mat-label>
|
||||
<input matInput [(ngModel)]="router" placeholder="Router">
|
||||
</mat-form-field>
|
||||
</mat-expansion-panel>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
@ -60,5 +64,5 @@
|
|||
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button (click)="onNoClick()">Cancelar</button>
|
||||
<button mat-button (click)="addNetworkConfig()" cdkFocusInitial>Guardar</button>
|
||||
<button mat-button (click)="save()" cdkFocusInitial>Guardar</button>
|
||||
</mat-dialog-actions>
|
||||
|
|
|
@ -17,6 +17,7 @@ export class CreateSubnetComponent implements OnInit {
|
|||
ipAddress: string = '';
|
||||
nextServer: string = '';
|
||||
bootFileName: string = '';
|
||||
router: string = '';
|
||||
syncronized: boolean = false;
|
||||
serverId: number = 0;
|
||||
clients: any[] = [];
|
||||
|
@ -44,6 +45,7 @@ export class CreateSubnetComponent implements OnInit {
|
|||
this.ipAddress = this.data.ipAddress;
|
||||
this.nextServer = this.data.nextServer;
|
||||
this.bootFileName = this.data.bootFileName;
|
||||
this.router = this.data.router;
|
||||
this.syncronized = this.data.syncronized;
|
||||
this.serverId = this.data.serverId;
|
||||
this.clients = this.data.clients
|
||||
|
@ -53,13 +55,14 @@ export class CreateSubnetComponent implements OnInit {
|
|||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
addNetworkConfig(): void {
|
||||
save(): void {
|
||||
const payload = {
|
||||
name: this.name,
|
||||
netmask: this.netmask,
|
||||
ipAddress: this.ipAddress,
|
||||
nextServer: this.nextServer || null,
|
||||
bootFileName: this.bootFileName || null
|
||||
router: this.router || null,
|
||||
nextServer: this.nextServer || null,
|
||||
bootFileName: this.bootFileName || null
|
||||
};
|
||||
|
||||
if (!this.data){
|
||||
|
|
|
@ -18,6 +18,7 @@ export interface Subnet {
|
|||
netmask: string;
|
||||
ipAddress: string;
|
||||
nextServer: string;
|
||||
router: string;
|
||||
bootFileName: string;
|
||||
synchronized: boolean;
|
||||
serverId: number;
|
||||
|
|
|
@ -232,6 +232,7 @@
|
|||
"editClientDialogTitle": "Edit Client",
|
||||
"organizationalUnitLabel": "Parent",
|
||||
"ogLiveLabel": "OgLive",
|
||||
"repositoryLabel": "Repository",
|
||||
"serialNumberLabel": "Serial Number",
|
||||
"netifaceLabel": "Network interface",
|
||||
"netDriverLabel": "Network driver",
|
||||
|
|
|
@ -233,6 +233,7 @@
|
|||
"editClientDialogTitle": "Editar Cliente",
|
||||
"organizationalUnitLabel": "Padre",
|
||||
"ogLiveLabel": "OgLive",
|
||||
"repositoryLabel": "Repositorio",
|
||||
"serialNumberLabel": "Número de Serie",
|
||||
"netifaceLabel": "Interfaz de red",
|
||||
"netDriverLabel": "Controlador de red",
|
||||
|
|
Loading…
Reference in New Issue