refs #1523. Hierarchy networkSettings. Resolve conflicts
testing/ogGui-multibranch/pipeline/head There was a failure building this commit Details
testing/ogGui-multibranch/pipeline/tag There was a failure building this commit Details

pull/16/head opengnsys_devel-0.1.0
Manuel Aranda Rosales 2025-02-17 14:42:49 +01:00
parent 024914d993
commit b0ede36d3b
9 changed files with 86 additions and 33 deletions

View File

@ -64,7 +64,7 @@
<ng-container [ngSwitch]="column.columnDef"> <ng-container [ngSwitch]="column.columnDef">
<!-- Caso para "status" --> <!-- Caso para "status" -->
<ng-container *ngSwitchCase="'status'"> <ng-container *ngSwitchCase="'status'">
<ng-container *ngIf="trace.status === 'in-progress'; else statusChip"> <ng-container *ngIf="trace.status === 'in-progress' && trace.progress; else statusChip">
<div class="progress-container"> <div class="progress-container">
<mat-progress-bar class="example-margin" [mode]="mode" [value]="progress" [bufferValue]="bufferValue"> <mat-progress-bar class="example-margin" [mode]="mode" [value]="progress" [bufferValue]="bufferValue">
</mat-progress-bar> </mat-progress-bar>
@ -80,6 +80,7 @@
}"> }">
{{ {{
trace.status === 'failed' ? 'Fallido' : trace.status === 'failed' ? 'Fallido' :
trace.status === 'in-progress' ? 'En ejecución' :
trace.status === 'success' ? 'Finalizado con éxito' : trace.status === 'success' ? 'Finalizado con éxito' :
trace.status === 'pending' ? 'Pendiente de ejecutar' : trace.status === 'pending' ? 'Pendiente de ejecutar' :
trace.status trace.status
@ -114,4 +115,4 @@
<mat-paginator [length]="length" [pageSize]="itemsPerPage" [pageIndex]="page" [pageSizeOptions]="pageSizeOptions" <mat-paginator [length]="length" [pageSize]="itemsPerPage" [pageIndex]="page" [pageSizeOptions]="pageSizeOptions"
(page)="onPageChange($event)"> (page)="onPageChange($event)">
</mat-paginator> </mat-paginator>
</div> </div>

View File

@ -265,14 +265,14 @@ export class PartitionAssistantComponent {
if (totalPartitionSize > this.selectedDisk.totalDiskSize) { if (totalPartitionSize > this.selectedDisk.totalDiskSize) {
this.errorMessage = 'El tamaño total de las particiones en el disco seleccionado excede el tamaño total del disco.'; this.errorMessage = 'El tamaño total de las particiones en el disco seleccionado excede el tamaño total del disco.';
this.loading = false;
return; return;
} else {
this.errorMessage = '';
} }
const modifiedPartitions = this.selectedDisk.partitions.filter((partition: { removed: any; format: any; }) => !partition.removed || partition.format); const modifiedPartitions = this.selectedDisk.partitions.filter((partition: { removed: any; format: any; }) => !partition.removed || partition.format);
if (modifiedPartitions.length === 0) { if (modifiedPartitions.length === 0) {
this.loading = false;
this.errorMessage = 'No hay cambios para guardar en el disco seleccionado.'; this.errorMessage = 'No hay cambios para guardar en el disco seleccionado.';
return; return;
} }

View File

@ -5,11 +5,11 @@
<form [formGroup]="clientForm" class="client-form grid-form" *ngIf="!loading"> <form [formGroup]="clientForm" class="client-form grid-form" *ngIf="!loading">
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label i18n="@@organizational-unit-label">Padre</mat-label> <mat-label i18n="@@organizational-unit-label">Padre</mat-label>
<mat-select formControlName="organizationalUnit"> <mat-select formControlName="organizationalUnit" (selectionChange)="onParentChange($event)">
<mat-select-trigger> <mat-select-trigger>
{{ getSelectedParentName() }} {{ getSelectedParentName() }}
</mat-select-trigger> </mat-select-trigger>
<mat-option *ngFor="let unit of parentUnitsWithPaths" [value]="unit.id"> <mat-option *ngFor="let unit of parentUnitsWithPaths" [value]="unit.id" >
<div class="unit-name">{{ unit.name }}</div> <div class="unit-name">{{ unit.name }}</div>
<div style="font-size: smaller; color: gray;">{{ unit.path }}</div> <div style="font-size: smaller; color: gray;">{{ unit.path }}</div>
</mat-option> </mat-option>

View File

@ -43,13 +43,13 @@ export class CreateClientComponent implements OnInit {
) {} ) {}
ngOnInit(): void { ngOnInit(): void {
this.initForm();
this.loadParentUnits(); this.loadParentUnits();
this.loadHardwareProfiles(); this.loadHardwareProfiles();
this.loadOgLives(); this.loadOgLives();
this.loadPxeTemplates(); this.loadPxeTemplates();
this.loadRepositories(); this.loadRepositories();
this.loadMenus() this.loadMenus()
this.initForm();
} }
initForm(): void { initForm(): void {
@ -65,9 +65,7 @@ export class CreateClientComponent implements OnInit {
mac: ['', Validators.required], mac: ['', Validators.required],
ip: ['', Validators.required], ip: ['', Validators.required],
template: [null], template: [null],
hardwareProfile: [ hardwareProfile: [null],
this.data.organizationalUnit?.networkSettings?.hardwareProfile?.['@id'] || null
],
ogLive: [null], ogLive: [null],
repository: [null], repository: [null],
menu: [null] menu: [null]
@ -84,8 +82,19 @@ export class CreateClientComponent implements OnInit {
this.parentUnitsWithPaths = this.parentUnits.map(unit => ({ this.parentUnitsWithPaths = this.parentUnits.map(unit => ({
id: unit['@id'], id: unit['@id'],
name: unit.name, name: unit.name,
path: this.dataService.getOrganizationalUnitPath(unit, this.parentUnits) path: this.dataService.getOrganizationalUnitPath(unit, this.parentUnits),
repository: unit.networkSettings?.repository?.['@id'],
hardwareProfile: unit.networkSettings?.hardwareProfile?.['@id'],
ogLive: unit.networkSettings?.ogLive?.['@id'],
menu: unit.networkSettings?.menu?.['@id']
})); }));
// 🚀 Ahora que los datos están listos, aplicamos la configuración inicial
const initialUnitId = this.clientForm.get('organizationalUnit')?.value;
if (initialUnitId) {
this.setOrganizationalUnitDefaults(initialUnitId);
}
this.loading = false; this.loading = false;
}, },
error => { error => {
@ -165,6 +174,22 @@ export class CreateClientComponent implements OnInit {
); );
} }
onParentChange(event: any): void {
this.setOrganizationalUnitDefaults(event.value);
}
setOrganizationalUnitDefaults(unitId: string): void {
const selectedUnit: any = this.parentUnitsWithPaths.find(unit => unit.id === unitId);
if (selectedUnit) {
this.clientForm.patchValue({
repository: selectedUnit.repository || null,
hardwareProfile: selectedUnit.hardwareProfile || null,
ogLive: selectedUnit.ogLive || null,
menu: selectedUnit.menu || null
});
}
}
onSubmit(): void { onSubmit(): void {
if (this.clientForm.valid) { if (this.clientForm.valid) {
const formData = this.clientForm.value; const formData = this.clientForm.value;

View File

@ -27,10 +27,15 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field class="form-field description-form-field" appearance="fill"> <mat-form-field class="form-field description-form-field" appearance="fill">
<mat-label>Descripción</mat-label> <mat-label>Descripción</mat-label>
<textarea matInput formControlName="description"></textarea> <textarea matInput formControlName="description"></textarea>
</mat-form-field> </mat-form-field>
<mat-checkbox formControlName="excludeParentChanges">
{{ 'excludeParentChanges' | translate }}
</mat-checkbox>
</form> </form>
<!-- Paso 2: Información del Aula --> <!-- Paso 2: Información del Aula -->
@ -132,10 +137,14 @@
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>Menú</mat-label> <mat-label>Menu</mat-label>
<input matInput formControlName="menu" type="url"> <mat-select formControlName="menu">
</mat-form-field> <mat-option *ngFor="let menu of menus" [value]="menu['@id']">
{{ menu.name }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>Perfil de Hardware</mat-label> <mat-label>Perfil de Hardware</mat-label>
<mat-select formControlName="hardwareProfile"> <mat-select formControlName="hardwareProfile">
@ -144,9 +153,6 @@
</mat-select> </mat-select>
<mat-error>Formato de URL incorrecto</mat-error> <mat-error>Formato de URL incorrecto</mat-error>
</mat-form-field> </mat-form-field>
<div class="validation-field">
<mat-slide-toggle formControlName="validation">Validación</mat-slide-toggle>
</div>
</form> </form>
<!-- Paso 4: Información Adicional --> <!-- Paso 4: Información Adicional -->
@ -163,4 +169,4 @@
<button mat-button (click)="onSubmit()" <button mat-button (click)="onSubmit()"
[disabled]="!generalFormGroup.valid || !additionalInfoFormGroup.valid || !networkSettingsFormGroup.valid">{{ [disabled]="!generalFormGroup.valid || !additionalInfoFormGroup.valid || !networkSettingsFormGroup.valid">{{
isEditMode ? 'Editar' : 'Crear' }}</button> isEditMode ? 'Editar' : 'Crear' }}</button>
</div> </div>

View File

@ -2,13 +2,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ManageOrganizationalUnitComponent } from './manage-organizational-unit.component'; import { ManageOrganizationalUnitComponent } from './manage-organizational-unit.component';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { HttpClientTestingModule } from '@angular/common/http/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ReactiveFormsModule } from '@angular/forms'; import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import { ToastrModule } from 'ngx-toastr'; import { ToastrModule } from 'ngx-toastr';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle'; import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {TranslateModule} from "@ngx-translate/core";
describe('ManageOrganizationalUnitComponent', () => { describe('ManageOrganizationalUnitComponent', () => {
let component: ManageOrganizationalUnitComponent; let component: ManageOrganizationalUnitComponent;
@ -25,6 +26,7 @@ describe('ManageOrganizationalUnitComponent', () => {
MatInputModule, MatInputModule,
MatSelectModule, MatSelectModule,
MatSlideToggleModule, MatSlideToggleModule,
TranslateModule.forRoot(),
BrowserAnimationsModule BrowserAnimationsModule
], ],
providers: [ providers: [
@ -42,4 +44,4 @@ describe('ManageOrganizationalUnitComponent', () => {
it('should create', () => { it('should create', () => {
expect(component).toBeTruthy(); expect(component).toBeTruthy();
}); });
}); });

View File

@ -29,6 +29,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
isEditMode: boolean; isEditMode: boolean;
currentCalendar: any = []; currentCalendar: any = [];
ogLives: any[] = []; ogLives: any[] = [];
menus: any[] = [];
repositories: any[] = []; repositories: any[] = [];
parentUnitsWithPaths: { id: string, name: string, path: string }[] = []; parentUnitsWithPaths: { id: string, name: string, path: string }[] = [];
protected p2pModeOptions = [ protected p2pModeOptions = [
@ -57,7 +58,8 @@ export class ManageOrganizationalUnitComponent implements OnInit {
name: [null, Validators.required], name: [null, Validators.required],
parent: [data?.parent ? data.parent['@id'] : null], parent: [data?.parent ? data.parent['@id'] : null],
description: [null], description: [null],
type: [null, Validators.required] type: [null, Validators.required],
excludeParentChanges: [false],
}); });
this.additionalInfoFormGroup = this._formBuilder.group({ this.additionalInfoFormGroup = this._formBuilder.group({
@ -79,8 +81,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
mcastPort: [null], mcastPort: [null],
mcastMode: [null], mcastMode: [null],
menu: [null], menu: [null],
hardwareProfile: [null], hardwareProfile: [null]
validation: [false]
}); });
this.classroomInfoFormGroup = this._formBuilder.group({ this.classroomInfoFormGroup = this._formBuilder.group({
@ -102,6 +103,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
this.loadCalendars(); this.loadCalendars();
this.loadOgLives(); this.loadOgLives();
this.loadRepositories(); this.loadRepositories();
this.loadMenus()
} }
get filteredTypes(): string[] { get filteredTypes(): string[] {
@ -139,6 +141,20 @@ export class ManageOrganizationalUnitComponent implements OnInit {
); );
} }
loadMenus(): void {
const url = `${this.baseUrl}/menus?page=1&itemsPerPage=10000`;
this.http.get<any>(url).subscribe(
response => {
this.menus = response['hydra:member'];
},
error => {
console.error('Error fetching menus:', error);
}
);
}
loadOgLives() { loadOgLives() {
this.dataService.getOgLives().subscribe( this.dataService.getOgLives().subscribe(
(data: any[]) => { (data: any[]) => {
@ -191,14 +207,15 @@ export class ManageOrganizationalUnitComponent implements OnInit {
loadData(uuid: string) { loadData(uuid: string) {
const url = `${this.baseUrl}/organizational-units/${uuid}`; const url = `${this.baseUrl}/organizational-units/${uuid}`;
this.http.get<any>(url).subscribe( this.http.get<any>(url).subscribe(
data => { data => {
this.generalFormGroup.patchValue({ this.generalFormGroup.patchValue({
name: data.name, name: data.name,
parent: data.parent ? data.parent['@id'] : '', parent: data.parent ? data.parent['@id'] : '',
description: data.description, description: data.description,
type: data.type type: data.type,
excludeParentChanges: data.excludeParentChanges
}); });
this.additionalInfoFormGroup.patchValue({ this.additionalInfoFormGroup.patchValue({
comments: data.comments comments: data.comments
@ -218,8 +235,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
menu: data.networkSettings.menu ? data.networkSettings.menu['@id'] : null, menu: data.networkSettings.menu ? data.networkSettings.menu['@id'] : null,
hardwareProfile: data.networkSettings.hardwareProfile ? data.networkSettings.hardwareProfile['@id'] : null, hardwareProfile: data.networkSettings.hardwareProfile ? data.networkSettings.hardwareProfile['@id'] : null,
ogLive: data.networkSettings.ogLive ? data.networkSettings.ogLive['@id'] : null, ogLive: data.networkSettings.ogLive ? data.networkSettings.ogLive['@id'] : null,
repository: data.networkSettings.repository ? data.networkSettings.repository['@id'] : null, repository: data.networkSettings.repository ? data.networkSettings.repository['@id'] : null
validation: data.networkSettings.validation
}); });
this.classroomInfoFormGroup.patchValue({ this.classroomInfoFormGroup.patchValue({
location: data.location, location: data.location,
@ -229,7 +245,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
remoteCalendar: data.remoteCalendar ? data.remoteCalendar['@id'] : null remoteCalendar: data.remoteCalendar ? data.remoteCalendar['@id'] : null
}); });
}, },
error => { error => {
console.error('Error fetching data for edit:', error); console.error('Error fetching data for edit:', error);
this.toastService.error('Error fetching data'); this.toastService.error('Error fetching data');
@ -243,6 +259,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
const parentValue = this.generalFormGroup.value.parent; const parentValue = this.generalFormGroup.value.parent;
const formData = { const formData = {
name: this.generalFormGroup.value.name, name: this.generalFormGroup.value.name,
excludeParentChanges: this.generalFormGroup.value.excludeParentChanges,
parent: parentValue || null, parent: parentValue || null,
description: this.generalFormGroup.value.description, description: this.generalFormGroup.value.description,
comments: this.additionalInfoFormGroup.value.comments, comments: this.additionalInfoFormGroup.value.comments,
@ -254,11 +271,11 @@ export class ManageOrganizationalUnitComponent implements OnInit {
board: this.classroomInfoFormGroup.value.board, board: this.classroomInfoFormGroup.value.board,
capacity: this.classroomInfoFormGroup.value.capacity, capacity: this.classroomInfoFormGroup.value.capacity,
}; };
if (this.isEditMode) { if (this.isEditMode) {
const putUrl = `${this.baseUrl}/organizational-units/${this.data.uuid}`; const putUrl = `${this.baseUrl}/organizational-units/${this.data.uuid}`;
const headers = new HttpHeaders({ 'Content-Type': 'application/json' }); const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
this.http.put<any>(putUrl, formData, { headers }).subscribe( this.http.put<any>(putUrl, formData, { headers }).subscribe(
response => { response => {
this.unitAdded.emit(); this.unitAdded.emit();
@ -273,7 +290,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
} else { } else {
const postUrl = `${this.baseUrl}/organizational-units`; const postUrl = `${this.baseUrl}/organizational-units`;
const headers = new HttpHeaders({ 'Content-Type': 'application/json' }); const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
this.http.post<any>(postUrl, formData, { headers }).subscribe( this.http.post<any>(postUrl, formData, { headers }).subscribe(
response => { response => {
this.unitAdded.emit(response); this.unitAdded.emit(response);
@ -292,4 +309,4 @@ export class ManageOrganizationalUnitComponent implements OnInit {
onNoClick(): void { onNoClick(): void {
this.dialogRef.close(); this.dialogRef.close();
} }
} }

View File

@ -182,6 +182,7 @@
"toggleNodeAriaLabel": "Toggle node", "toggleNodeAriaLabel": "Toggle node",
"closeButton": "Close", "closeButton": "Close",
"inputDetails": "Input details", "inputDetails": "Input details",
"excludeParentChanges": "Exclude parent changes",
"orgUnitPropertiesTitle": "Organizational unit properties", "orgUnitPropertiesTitle": "Organizational unit properties",
"generalDataTab": "General data", "generalDataTab": "General data",
"propertyHeader": "Property", "propertyHeader": "Property",

View File

@ -266,6 +266,7 @@
"roomMapOption": "Plano de aula", "roomMapOption": "Plano de aula",
"clientDetailsTitle": "Datos de cliente", "clientDetailsTitle": "Datos de cliente",
"commandsButton": "Comandos", "commandsButton": "Comandos",
"excludeParentChanges": "Excluir cambios de las unidades organizativas superiores",
"networkPropertiesTab": "Propiedades de red", "networkPropertiesTab": "Propiedades de red",
"disksPartitionsTitle": "Discos/Particiones", "disksPartitionsTitle": "Discos/Particiones",
"diskTitle": "Disco", "diskTitle": "Disco",