refs #1901. Fixed manage-ou component. Added spinner
testing/ogGui-multibranch/pipeline/head There was a failure building this commit Details

pull/19/head
Manuel Aranda Rosales 2025-04-11 11:14:04 +02:00
parent c365ef2a14
commit 2958e05c98
3 changed files with 205 additions and 172 deletions

View File

@ -6,6 +6,10 @@ h1 {
margin-top: 20px;
}
.create-ou-container {
position: relative;
}
.form-field {
width: 100%;
}
@ -20,6 +24,13 @@ h1 {
overflow-y: auto;
}
.loading-spinner {
display: block;
margin: 0 auto;
align-items: center;
justify-content: center;
}
.mat-dialog-actions {
display: flex;
justify-content: flex-end;
@ -55,4 +66,4 @@ h1 {
align-items: center;
grid-column: span 2;
margin-bottom: 10px;
}
}

View File

@ -1,11 +1,10 @@
<app-loading [isLoading]="loading"></app-loading>
<div *ngIf="!loading">
<div class="create-ou-container">
<h1 mat-dialog-title>{{ isEditMode ? 'Editar' : 'Crear' }} Unidad Organizativa</h1>
<div class="mat-dialog-content">
<div class="mat-dialog-content" [ngClass]="{'loading': loading}">
<!-- Paso 1: General -->
<span class="step-title">General</span>
<form [formGroup]="generalFormGroup" class="grid-form">
<mat-spinner class="loading-spinner" *ngIf="loading"></mat-spinner>
<span *ngIf="!loading" class="step-title">General</span>
<form *ngIf="generalFormGroup && !loading" [formGroup]="generalFormGroup" class="grid-form">
<mat-form-field class="form-field" appearance="fill">
<mat-label>Tipo</mat-label>
<mat-select formControlName="type" required>
@ -42,8 +41,8 @@
</form>
<!-- Paso 2: Información del Aula -->
<span *ngIf="generalFormGroup.value.type === 'classroom'" class="step-title">Información del aula</span>
<form *ngIf="generalFormGroup.value.type === 'classroom'" class="grid-form"
<span *ngIf="generalFormGroup.value.type === 'classroom' && !loading" class="step-title">Información del aula</span>
<form *ngIf="generalFormGroup.value.type === 'classroom' && !loading" class="grid-form"
[formGroup]="classroomInfoFormGroup">
<mat-form-field class="form-field">
<mat-label>Localización</mat-label>
@ -71,8 +70,8 @@
</form>
<!-- Paso 3: Configuración de Red -->
<span class="step-title">Configuración de Red</span>
<form [formGroup]="networkSettingsFormGroup" class="grid-form">
<span *ngIf="!loading" class="step-title">Configuración de Red</span>
<form *ngIf="networkSettingsFormGroup && !loading" [formGroup]="networkSettingsFormGroup" class="grid-form">
<mat-form-field class="form-field">
<mat-label>OgLive</mat-label>
<mat-select formControlName="ogLive" (selectionChange)="onOgLiveChange($event)">
@ -168,8 +167,8 @@
</form>
<!-- Paso 4: Información Adicional -->
<span class="step-title">Información Adicional</span>
<form [formGroup]="additionalInfoFormGroup">
<span *ngIf="!loading" class="step-title">Información Adicional</span>
<form *ngIf="additionalInfoFormGroup && !loading" [formGroup]="additionalInfoFormGroup">
<mat-form-field class="form-field">
<mat-label>Comentarios</mat-label>
<textarea matInput formControlName="comments"></textarea>

View File

@ -100,63 +100,76 @@ export class ManageOrganizationalUnitComponent implements OnInit {
capacity: [null, [Validators.required, Validators.min(0)]],
remoteCalendar: [null]
});
if (this.isEditMode) {
this.loadData(data.uuid);
}
}
ngOnInit() {
this.loadParentUnits();
this.loadHardwareProfiles();
this.loadCalendars();
this.loadOgLives();
this.loadRepositories();
this.loadMenus()
ngOnInit(): void {
this.loading = true;
const observables = [
this.loadParentUnits(),
this.loadHardwareProfiles(),
this.loadCalendars(),
this.loadOgLives(),
this.loadRepositories(),
this.loadMenus(),
];
Promise.all(observables).then(() => {
if (this.isEditMode) {
this.loadData(this.data.uuid).then(() => {
this.loading = false;
});
} else {
this.loading = false;
}
}).catch(error => {
console.error('Error loading data:', error);
this.loading = false;
});
}
get filteredTypes(): string[] {
return this.generalFormGroup.get('parent')?.value ? this.types.filter(type => type !== 'organizational-unit') : this.types;
}
loadParentUnits() {
this.loading = true;
const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=1000`;
this.http.get<any>(url).subscribe(
response => {
this.parentUnits = response['hydra:member'];
this.parentUnitsWithPaths = this.parentUnits.map(unit => ({
id: unit['@id'],
name: unit.name,
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'],
mcastIp: unit.networkSettings?.mcastIp,
mcastSpeed: unit.networkSettings?.mcastSpeed,
mcastPort: unit.networkSettings?.mcastPort,
mcastMode: unit.networkSettings?.mcastMode,
netiface: unit.networkSettings?.netiface,
p2pMode: unit.networkSettings?.p2pMode,
p2pTime: unit.networkSettings?.p2pTime,
dns: unit.networkSettings?.dns,
netmask: unit.networkSettings?.netmask,
router: unit.networkSettings?.router,
ntp: unit.networkSettings?.ntp
}));
loadParentUnits(): Promise<void> {
return new Promise((resolve, reject) => {
const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=1000`;
this.http.get<any>(url).subscribe(
response => {
this.parentUnits = response['hydra:member'];
this.parentUnitsWithPaths = this.parentUnits.map(unit => ({
id: unit['@id'],
name: unit.name,
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'],
mcastIp: unit.networkSettings?.mcastIp,
mcastSpeed: unit.networkSettings?.mcastSpeed,
mcastPort: unit.networkSettings?.mcastPort,
mcastMode: unit.networkSettings?.mcastMode,
netiface: unit.networkSettings?.netiface,
p2pMode: unit.networkSettings?.p2pMode,
p2pTime: unit.networkSettings?.p2pTime,
dns: unit.networkSettings?.dns,
netmask: unit.networkSettings?.netmask,
router: unit.networkSettings?.router,
ntp: unit.networkSettings?.ntp
}));
const initialUnitId = this.generalFormGroup.get('parent')?.value;
if (initialUnitId) {
this.setOrganizationalUnitDefaults(initialUnitId);
const initialUnitId = this.generalFormGroup.get('parent')?.value;
if (initialUnitId) {
this.setOrganizationalUnitDefaults(initialUnitId);
}
resolve();
},
error => {
console.error('Error fetching parent units:', error);
reject(error);
}
this.loading = false;
},
error => {
console.error('Error fetching parent units:', error);
this.loading = false;
}
);
);
});
}
onParentChange(event: any): void {
@ -191,78 +204,87 @@ export class ManageOrganizationalUnitComponent implements OnInit {
return this.parentUnitsWithPaths.find(unit => unit.id === parentId)?.name;
}
loadHardwareProfiles(): void {
this.loading = true;
this.dataService.getHardwareProfiles().subscribe(
(data: any[]) => {
this.hardwareProfiles = data;
this.loading = false;
},
(error: any) => {
console.error('Error fetching hardware profiles', error);
this.loading = false;
}
);
loadHardwareProfiles(): Promise<void> {
return new Promise((resolve, reject) => {
this.dataService.getHardwareProfiles().subscribe(
(data: any[]) => {
this.hardwareProfiles = data;
resolve();
},
error => {
console.error('Error fetching hardware profiles:', error);
reject(error);
}
);
});
}
loadMenus(): void {
this.loading = true;
const url = `${this.baseUrl}/menus?page=1&itemsPerPage=10000`;
loadOgLives(): Promise<void> {
return new Promise((resolve, reject) => {
const url = `${this.baseUrl}/og-lives?page=1&itemsPerPage=30`;
this.http.get<any>(url).subscribe(
response => {
this.menus = response['hydra:member'];
this.loading = false;
},
error => {
console.error('Error fetching menus:', error);
this.loading = false;
}
);
this.http.get<any>(url).subscribe(
response => {
this.ogLives = response['hydra:member'];
resolve();
},
error => {
console.error('Error fetching ogLives:', error);
reject(error);
}
);
});
}
loadOgLives() {
this.loading = true;
this.dataService.getOgLives().subscribe(
(data: any[]) => {
this.ogLives = data;
this.loading = false;
},
error => {
console.error('Error fetching ogLives', error);
this.loading = false;
}
);
loadMenus(): Promise<void> {
return new Promise((resolve, reject) => {
const url = `${this.baseUrl}/menus?page=1&itemsPerPage=10000`;
this.http.get<any>(url).subscribe(
response => {
this.menus = response['hydra:member'];
resolve();
},
error => {
console.error('Error fetching menus:', error);
reject(error);
}
);
});
}
loadRepositories() {
this.loading = true;
this.dataService.getRepositories().subscribe(
(data: any[]) => {
this.repositories = data;
this.loading = false;
},
error => {
console.error('Error fetching repositories', error);
this.loading = false;
}
);
loadRepositories(): Promise<void> {
return new Promise((resolve, reject) => {
const url = `${this.baseUrl}/image-repositories?page=1&itemsPerPage=10000`;
this.http.get<any>(url).subscribe(
response => {
this.repositories = response['hydra:member'];
resolve();
},
error => {
console.error('Error fetching ogLives:', error);
reject(error);
}
);
});
}
loadCalendars() {
this.loading = true;
const apiUrl = `${this.baseUrl}/remote-calendars?page=1&itemsPerPage=30`;
this.http.get<any>(apiUrl).subscribe(
response => {
this.calendars = response['hydra:member'];
this.loading = false;
},
error => {
console.error('Error loading calendars', error);
this.toastService.error('Error loading current calendar');
this.loading = false;
}
);
loadCalendars(): Promise<void> {
return new Promise((resolve, reject) => {
const apiUrl = `${this.baseUrl}/remote-calendars?page=1&itemsPerPage=30`;
this.http.get<any>(apiUrl).subscribe(
response => {
this.calendars = response['hydra:member'];
resolve();
},
error => {
console.error('Error loading calendars', error);
this.toastService.error('Error loading current calendar');
reject(error);
}
);
});
}
loadCurrentCalendar(uuid: string): void {
@ -293,57 +315,58 @@ export class ManageOrganizationalUnitComponent implements OnInit {
this.networkSettingsFormGroup.value.repository = event.value;
}
loadData(uuid: string) {
this.loading = true;
const url = `${this.baseUrl}/organizational-units/${uuid}`;
loadData(uuid: string): Promise<void> {
return new Promise((resolve, reject) => {
const url = `${this.baseUrl}/organizational-units/${uuid}`;
this.http.get<any>(url).subscribe(
data => {
this.generalFormGroup.patchValue({
name: data.name,
parent: data.parent ? data.parent['@id'] : '',
description: data.description,
type: data.type,
excludeParentChanges: data.excludeParentChanges
});
this.additionalInfoFormGroup.patchValue({
comments: data.comments
});
this.networkSettingsFormGroup.patchValue({
proxy: data.networkSettings.proxy,
dns: data.networkSettings.dns,
netmask: data.networkSettings.netmask,
router: data.networkSettings.router,
ntp: data.networkSettings.ntp,
netiface: data.networkSettings.netiface,
p2pMode: data.networkSettings.p2pMode,
p2pTime: data.networkSettings.p2pTime,
mcastIp: data.networkSettings.mcastIp,
mcastSpeed: data.networkSettings.mcastSpeed,
mcastPort: data.networkSettings.mcastPort,
mcastMode: data.networkSettings.mcastMode,
menu: data.networkSettings.menu ? data.networkSettings.menu['@id'] : null,
hardwareProfile: data.networkSettings.hardwareProfile ? data.networkSettings.hardwareProfile['@id'] : null,
ogLive: data.networkSettings.ogLive ? data.networkSettings.ogLive['@id'] : null,
repository: data.networkSettings.repository ? data.networkSettings.repository['@id'] : null
});
this.classroomInfoFormGroup.patchValue({
location: data.location,
projector: data.projector,
board: data.board,
capacity: data.capacity,
remoteCalendar: data.remoteCalendar ? data.remoteCalendar['@id'] : null
});
this.loading = false;
},
this.http.get<any>(url).subscribe(
data => {
this.generalFormGroup.patchValue({
name: data.name,
parent: data.parent ? data.parent['@id'] : '',
description: data.description,
type: data.type,
excludeParentChanges: data.excludeParentChanges
});
this.additionalInfoFormGroup.patchValue({
comments: data.comments
});
this.networkSettingsFormGroup.patchValue({
proxy: data.networkSettings?.proxy,
dns: data.networkSettings?.dns,
netmask: data.networkSettings?.netmask,
router: data.networkSettings?.router,
ntp: data.networkSettings?.ntp,
netiface: data.networkSettings?.netiface,
p2pMode: data.networkSettings?.p2pMode,
p2pTime: data.networkSettings?.p2pTime,
mcastIp: data.networkSettings?.mcastIp,
mcastSpeed: data.networkSettings?.mcastSpeed,
mcastPort: data.networkSettings?.mcastPort,
mcastMode: data.networkSettings?.mcastMode,
menu: data.networkSettings?.menu ? data.networkSettings.menu['@id'] : null,
hardwareProfile: data.networkSettings?.hardwareProfile ? data.networkSettings.hardwareProfile['@id'] : null,
ogLive: data.networkSettings?.ogLive ? data.networkSettings.ogLive['@id'] : null,
repository: data.networkSettings?.repository ? data.networkSettings.repository['@id'] : null
});
this.classroomInfoFormGroup.patchValue({
location: data.location,
projector: data.projector,
board: data.board,
capacity: data.capacity,
remoteCalendar: data.remoteCalendar ? data.remoteCalendar['@id'] : null
});
resolve();
},
error => {
console.error('Error fetching data for edit:', error);
this.toastService.error('Error fetching data');
this.loading = false;
this.onNoClick();
}
);
error => {
console.error('Error fetching data for edit:', error);
this.toastService.error('Error fetching data');
reject(error);
this.onNoClick();
}
);
});
}
onSubmit() {