Added router in subnet. Advanced bootfile changes, and partition assistant updates
testing/ogGui-multibranch/pipeline/head This commit is unstable Details

pull/10/head
Manuel Aranda Rosales 2024-12-05 12:50:15 +01:00
parent aecc16c332
commit e3cf6a85d0
22 changed files with 296 additions and 159 deletions

View File

@ -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;
}

View File

@ -247,9 +247,8 @@
}
.charts-container {
flex: 2;
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}

View File

@ -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();
}

View File

@ -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>

View File

@ -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);

View File

@ -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);

View File

@ -218,7 +218,7 @@
<mat-icon>sync</mat-icon>
<span>Sincronizar</span>
</button>
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
<mat-icon>edit</mat-icon>
<span>Edit</span>
@ -289,7 +289,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>
@ -317,4 +317,4 @@
</div>
</div>
</div>
</ng-template>
</ng-template>

View File

@ -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 {
})
);
}
}

View File

@ -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">

View File

@ -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();
}

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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 },
]
}
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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">

View File

@ -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'
});
}
}

View File

@ -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>

View File

@ -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){

View File

@ -18,6 +18,7 @@ export interface Subnet {
netmask: string;
ipAddress: string;
nextServer: string;
router: string;
bootFileName: string;
synchronized: boolean;
serverId: number;

View File

@ -232,6 +232,7 @@
"editClientDialogTitle": "Edit Client",
"organizationalUnitLabel": "Parent",
"ogLiveLabel": "OgLive",
"repositoryLabel": "Repository",
"serialNumberLabel": "Serial Number",
"netifaceLabel": "Network interface",
"netDriverLabel": "Network driver",

View File

@ -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",