refs #1419 and #1420. Fix OU's path in clients' and OUs' form. Remove stepper from forms.
testing/ogGui-multibranch/pipeline/head This commit looks good Details

pull/12/head
Lucas Lara García 2025-01-31 14:09:14 +01:00
parent f092754464
commit b81db79237
11 changed files with 380 additions and 346 deletions

View File

@ -231,5 +231,15 @@ export class DataService {
); );
} }
getOrganizationalUnitPath(unit: UnidadOrganizativa, units: UnidadOrganizativa[]): string {
const path: string[] = [];
let currentUnit: UnidadOrganizativa | undefined = unit;
while (currentUnit) {
path.unshift(currentUnit.name);
currentUnit = units.find(u => u['@id'] === currentUnit?.parent?.['@id']);
}
return path.join(' / ');
}
} }

View File

@ -6,9 +6,12 @@
<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">
<mat-option *ngFor="let unit of parentUnits" [value]="unit['@id']"> <mat-select-trigger>
{{ getSelectedParentName() }}
</mat-select-trigger>
<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 class="unit-path">{{ unit.path }}</div> <div style="font-size: smaller; color: gray;">{{ unit.path }}</div>
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>

View File

@ -15,6 +15,7 @@ export class CreateClientComponent implements OnInit {
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
clientForm!: FormGroup; clientForm!: FormGroup;
parentUnits: any[] = []; parentUnits: any[] = [];
parentUnitsWithPaths: { id: string, name: string, path: string }[] = [];
hardwareProfiles: any[] = []; hardwareProfiles: any[] = [];
ogLives: any[] = []; ogLives: any[] = [];
menus: any[] = []; menus: any[] = [];
@ -80,6 +81,11 @@ export class CreateClientComponent implements OnInit {
this.http.get<any>(url).subscribe( this.http.get<any>(url).subscribe(
response => { response => {
this.parentUnits = response['hydra:member']; this.parentUnits = response['hydra:member'];
this.parentUnitsWithPaths = this.parentUnits.map(unit => ({
id: unit['@id'],
name: unit.name,
path: this.dataService.getOrganizationalUnitPath(unit, this.parentUnits)
}));
this.loading = false; this.loading = false;
}, },
error => { error => {
@ -89,6 +95,11 @@ export class CreateClientComponent implements OnInit {
); );
} }
getSelectedParentName(): string | undefined {
const parentId = this.clientForm.get('organizationalUnit')?.value;
return this.parentUnitsWithPaths.find(unit => unit.id === parentId)?.name;
}
loadHardwareProfiles(): void { loadHardwareProfiles(): void {
this.dataService.getHardwareProfiles().subscribe( this.dataService.getHardwareProfiles().subscribe(
(data: any[]) => { (data: any[]) => {

View File

@ -7,8 +7,12 @@
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>{{ 'organizationalUnitLabel' | translate }}</mat-label> <mat-label>{{ 'organizationalUnitLabel' | translate }}</mat-label>
<mat-select (selectionChange)="setOrganizationalUnit($event)" [value]="organizationalUnit"> <mat-select (selectionChange)="setOrganizationalUnit($event)" [value]="organizationalUnit">
<mat-option *ngFor="let unit of parentUnits" [value]="unit['@id']"> <mat-select-trigger>
{{ getSelectedParentName() }}
</mat-select-trigger>
<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>
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>

View File

@ -4,6 +4,7 @@ import {HttpClient} from "@angular/common/http";
import {MatSnackBar} from "@angular/material/snack-bar"; import {MatSnackBar} from "@angular/material/snack-bar";
import {ToastrService} from "ngx-toastr"; import {ToastrService} from "ngx-toastr";
import {MAT_DIALOG_DATA} from "@angular/material/dialog"; import {MAT_DIALOG_DATA} from "@angular/material/dialog";
import { DataService } from '../../../services/data.service';
@Component({ @Component({
selector: 'app-create-multiple-client', selector: 'app-create-multiple-client',
@ -13,6 +14,7 @@ import {MAT_DIALOG_DATA} from "@angular/material/dialog";
export class CreateMultipleClientComponent implements OnInit{ export class CreateMultipleClientComponent implements OnInit{
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
parentUnits: any[] = []; parentUnits: any[] = [];
parentUnitsWithPaths: { id: string, name: string, path: string }[] = [];
uploadedClients: any[] = []; uploadedClients: any[] = [];
loading: boolean = false; loading: boolean = false;
displayedColumns: string[] = ['name', 'ip', 'mac']; displayedColumns: string[] = ['name', 'ip', 'mac'];
@ -25,7 +27,8 @@ export class CreateMultipleClientComponent implements OnInit{
@Inject(MAT_DIALOG_DATA) private data: any, @Inject(MAT_DIALOG_DATA) private data: any,
private http: HttpClient, private http: HttpClient,
private snackBar: MatSnackBar, private snackBar: MatSnackBar,
private toastService: ToastrService private toastService: ToastrService,
private dataService: DataService
) {} ) {}
ngOnInit(): void { ngOnInit(): void {
@ -43,6 +46,11 @@ export class CreateMultipleClientComponent implements OnInit{
this.http.get<any>(url).subscribe( this.http.get<any>(url).subscribe(
response => { response => {
this.parentUnits = response['hydra:member']; this.parentUnits = response['hydra:member'];
this.parentUnitsWithPaths = this.parentUnits.map(unit => ({
id: unit['@id'],
name: unit.name,
path: this.dataService.getOrganizationalUnitPath(unit, this.parentUnits)
}));
this.loading = false; this.loading = false;
}, },
error => { error => {
@ -52,8 +60,12 @@ export class CreateMultipleClientComponent implements OnInit{
); );
} }
getSelectedParentName(): string | undefined {
const parentId = this.organizationalUnit;
return this.parentUnitsWithPaths.find(unit => unit.id === parentId)?.name;
}
setOrganizationalUnit(organizationalUnit: any): void { setOrganizationalUnit(organizationalUnit: any): void {
console.log('Organizational unit selected:', organizationalUnit.value);
this.organizationalUnit = organizationalUnit.value; this.organizationalUnit = organizationalUnit.value;
} }

View File

@ -6,8 +6,12 @@
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>{{ 'organizationalUnitLabel' | translate }}</mat-label> <mat-label>{{ 'organizationalUnitLabel' | translate }}</mat-label>
<mat-select formControlName="organizationalUnit"> <mat-select formControlName="organizationalUnit">
<mat-option *ngFor="let unit of parentUnits" [value]="unit['@id']"> <mat-select-trigger>
{{ unit.name }} {{ getSelectedParentName() }}
</mat-select-trigger>
<mat-option *ngFor="let unit of parentUnitsWithPaths" [value]="unit.id">
<div class="unit-name">{{ unit.name }}</div>
<div style="font-size: smaller; color: gray;">{{ unit.path }}</div>
</mat-option> </mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>

View File

@ -15,6 +15,7 @@ export class EditClientComponent {
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
clientForm!: FormGroup; clientForm!: FormGroup;
parentUnits: any[] = []; parentUnits: any[] = [];
parentUnitsWithPaths: { id: string, name: string, path: string }[] = [];
hardwareProfiles: any[] = []; hardwareProfiles: any[] = [];
repositories: any[] = []; repositories: any[] = [];
ogLives: any[] = []; ogLives: any[] = [];
@ -68,19 +69,32 @@ export class EditClientComponent {
}); });
} }
loadParentUnits() { loadParentUnits(): void {
this.loading = true;
const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=10000`; const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=10000`;
this.http.get<any>(url).subscribe( this.http.get<any>(url).subscribe(
response => { response => {
this.parentUnits = response['hydra:member']; this.parentUnits = response['hydra:member'];
this.parentUnitsWithPaths = this.parentUnits.map(unit => ({
id: unit['@id'],
name: unit.name,
path: this.dataService.getOrganizationalUnitPath(unit, this.parentUnits)
}));
this.loading = false;
}, },
error => { error => {
console.error('Error fetching parent units:', error); console.error('Error fetching parent units:', error);
this.loading = false;
} }
); );
} }
getSelectedParentName(): string | undefined {
const parentId = this.clientForm.get('organizationalUnit')?.value;
return this.parentUnitsWithPaths.find(unit => unit.id === parentId)?.name;
}
loadHardwareProfiles(): void { loadHardwareProfiles(): void {
this.dataService.getHardwareProfiles().subscribe( this.dataService.getHardwareProfiles().subscribe(
(data: any[]) => { (data: any[]) => {

View File

@ -1,180 +1,158 @@
<h1 mat-dialog-title>{{ 'addOrgUnitTitle' | translate }}</h1> <h1 mat-dialog-title>{{ 'addOrgUnitTitle' | translate }}</h1>
<div mat-dialog-content> <div mat-dialog-content>
<mat-stepper orientation="vertical" [linear]="isLinear"> <!-- Paso 1: General -->
<!-- Paso 1: General --> <form [formGroup]="generalFormGroup">
<mat-step [stepControl]="generalFormGroup"> <mat-form-field class="form-field">
<form [formGroup]="generalFormGroup"> <mat-label>{{ 'typeLabel' | translate }}</mat-label>
<ng-template matStepLabel>{{ 'generalStepLabel' | translate }}</ng-template> <mat-select formControlName="type" required>
<mat-form-field class="form-field"> <mat-option *ngFor="let type of filteredTypes" [value]="type">
<mat-label>{{ 'typeLabel' | translate }}</mat-label> {{ typeTranslations[type] }}
<mat-select formControlName="type" required> </mat-option>
<mat-option *ngFor="let type of filteredTypes" [value]="type"> </mat-select>
{{ typeTranslations[type] }} </mat-form-field>
</mat-option> <mat-form-field class="form-field">
</mat-select> <mat-label>{{ 'nameLabel' | translate }}</mat-label>
</mat-form-field> <input matInput formControlName="name" required>
<mat-form-field class="form-field"> </mat-form-field>
<mat-label>{{ 'nameLabel' | translate }}</mat-label> <mat-form-field class="form-field">
<input matInput formControlName="name" required> <mat-label>{{ 'createOrgUnitparentLabel' | translate }}</mat-label>
</mat-form-field> <mat-select formControlName="parent">
<mat-form-field class="form-field"> <mat-select-trigger>
<mat-label>{{ 'createOrgUnitparentLabel' | translate }}</mat-label> {{ getSelectedParentName() }}
<mat-select formControlName="parent"> </mat-select-trigger>
<mat-option>{{ 'noParentOption' | translate }}</mat-option> <mat-option *ngFor="let unit of parentUnitsWithPaths" [value]="unit.id">
<mat-option *ngFor="let unit of parentUnits" [value]="unit['@id']">{{ unit.name }}</mat-option> <div>{{ unit.name }}</div>
</mat-select> <div style="font-size: smaller; color: gray;">{{ unit.path }}</div>
</mat-form-field> </mat-option>
<mat-form-field class="form-field"> </mat-select>
<mat-label>{{ 'descriptionLabel' | translate }}</mat-label> </mat-form-field>
<textarea matInput formControlName="description"></textarea> <mat-form-field class="form-field">
</mat-form-field> <mat-label>{{ 'descriptionLabel' | translate }}</mat-label>
<div> <textarea matInput formControlName="description"></textarea>
<button mat-button matStepperNext>{{ 'nextButton' | translate }}</button> </mat-form-field>
</div> </form>
</form>
</mat-step>
<!-- Paso 2: Información del Aula --> <!-- Paso 2: Información del Aula -->
<mat-step *ngIf="generalFormGroup.value.type === 'classroom'" [stepControl]="classroomInfoFormGroup"> <form *ngIf="generalFormGroup.value.type === 'classroom'" [formGroup]="classroomInfoFormGroup">
<form [formGroup]="classroomInfoFormGroup"> <mat-form-field class="form-field">
<ng-template matStepLabel>{{ 'classroomInfoStepLabel' | translate }}</ng-template> <mat-label>{{ 'locationLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="location">
<mat-label>{{ 'locationLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="location"> <mat-slide-toggle formControlName="projector">{{ 'projectorToggle' | translate }}</mat-slide-toggle>
</mat-form-field> <mat-slide-toggle formControlName="board">{{ 'boardToggle' | translate }}</mat-slide-toggle>
<mat-slide-toggle formControlName="projector">{{ 'projectorToggle' | translate }}</mat-slide-toggle> <mat-form-field class="form-field">
<mat-slide-toggle formControlName="board">{{ 'boardToggle' | translate }}</mat-slide-toggle> <mat-label>{{ 'capacityLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="capacity" type="number">
<mat-label>{{ 'capacityLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="capacity" type="number"> <mat-form-field class="form-field" appearance="fill">
</mat-form-field> <mat-label>{{ 'associatedCalendarLabel' | translate }}</mat-label>
<mat-form-field class="form-field" appearance="fill"> <mat-select formControlName="remoteCalendar" (selectionChange)="onCalendarChange($event)">
<mat-label>{{ 'associatedCalendarLabel' | translate }}</mat-label> <mat-option *ngFor="let calendar of calendars" [value]="calendar['@id']">
<mat-select formControlName="remoteCalendar" (selectionChange)="onCalendarChange($event)"> {{ calendar.name }}
<mat-option *ngFor="let calendar of calendars" [value]="calendar['@id']"> </mat-option>
{{ calendar.name }} </mat-select>
</mat-option> </mat-form-field>
</mat-select> </form>
</mat-form-field>
<div> <!-- Paso 3: Información Adicional -->
<button mat-button matStepperPrevious>{{ 'backButton' | translate }}</button> <form [formGroup]="additionalInfoFormGroup">
<button mat-button matStepperNext>{{ 'nextButton' | translate }}</button> <mat-form-field class="form-field">
</div> <mat-label>{{ 'commentsLabel' | translate }}</mat-label>
</form> <textarea matInput formControlName="comments"></textarea>
</mat-step> </mat-form-field>
</form>
<!-- Paso 3: Información Adicional --> <!-- Paso 4: Configuración de Red -->
<mat-step [stepControl]="additionalInfoFormGroup"> <form *ngIf="generalFormGroup.value.type === 'classroom' || generalFormGroup.value.type === 'clients-group'" [formGroup]="networkSettingsFormGroup">
<form [formGroup]="additionalInfoFormGroup"> <mat-form-field class="form-field">
<ng-template matStepLabel>{{ 'additionalInfoStepLabel' | translate }}</ng-template> <mat-label>{{ 'ogLiveLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <mat-select formControlName="oglive" (selectionChange)="onOgLiveChange($event)">
<mat-label>{{ 'commentsLabel' | translate }}</mat-label> <mat-option *ngFor="let oglive of ogLives" [value]="oglive['@id']">
<textarea matInput formControlName="comments"></textarea> {{ oglive.filename }}
</mat-form-field> </mat-option>
<div> </mat-select>
<button mat-button matStepperPrevious>{{ 'backButton' | translate }}</button> </mat-form-field>
<button mat-button matStepperNext>{{ 'nextButton' | translate }}</button> <mat-form-field class="form-field">
</div> <mat-label>{{ 'repositoryLabel' | translate }}</mat-label>
</form> <mat-select formControlName="repository" (selectionChange)="onRepositoryChange($event)">
</mat-step> <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">
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'bootFileNameLabel' | translate }}</mat-label>
<input matInput formControlName="bootFileName">
</mat-form-field>
<!-- Paso 4: Configuración de Red --> <mat-form-field class="form-field">
<mat-step *ngIf="generalFormGroup.value.type === 'classroom'" [stepControl]="networkSettingsFormGroup"> <mat-label>{{ 'proxyUrlLabel' | translate }}</mat-label>
<form [formGroup]="networkSettingsFormGroup"> <input matInput formControlName="proxy">
<ng-template matStepLabel>{{ 'networkSettingsStepLabel' | translate }}</ng-template> </mat-form-field>
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>{{ 'ogLiveLabel' | translate }}</mat-label> <mat-label>{{ 'dnsIpLabel' | translate }}</mat-label>
<mat-select formControlName="oglive" (selectionChange)="onOgLiveChange($event)"> <input matInput formControlName="dns">
<mat-option *ngFor="let oglive of ogLives" [value]="oglive['@id']"> </mat-form-field>
{{ oglive.filename }} <mat-form-field class="form-field">
</mat-option> <mat-label>{{ 'netmaskLabel' | translate }}</mat-label>
</mat-select> <input matInput formControlName="netmask">
</mat-form-field> </mat-form-field>
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>{{ 'repositoryLabel' | translate }}</mat-label> <mat-label>{{ 'routerLabel' | translate }}</mat-label>
<mat-select formControlName="repository" (selectionChange)="onRepositoryChange($event)"> <input matInput formControlName="router">
<mat-option *ngFor="let repository of repositories" [value]="repository['@id']"> </mat-form-field>
{{ repository.name }} <mat-form-field class="form-field">
</mat-option> <mat-label>{{ 'ntpIpLabel' | translate }}</mat-label>
</mat-select> <input matInput formControlName="ntp">
</mat-form-field> </mat-form-field>
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>{{ 'nextServerLabel' | translate }}</mat-label> <mat-label>{{ 'p2pModeLabel' | translate }}</mat-label>
<input matInput formControlName="nextServer"> <mat-select formControlName="p2pMode">
</mat-form-field> <mat-option *ngFor="let option of p2pModeOptions" [value]="option.value">
<mat-form-field class="form-field"> {{ option.name }}
<mat-label>{{ 'bootFileNameLabel' | translate }}</mat-label> </mat-option>
<input matInput formControlName="bootFileName"> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field class="form-field">
<mat-form-field class="form-field"> <mat-label>{{ 'p2pTimeLabel' | translate }}</mat-label>
<mat-label>{{ 'proxyUrlLabel' | translate }}</mat-label> <input matInput formControlName="p2pTime" type="number">
<input matInput formControlName="proxy"> </mat-form-field>
</mat-form-field> <mat-form-field class="form-field">
<mat-form-field class="form-field"> <mat-label>{{ 'mcastIpLabel' | translate }}</mat-label>
<mat-label>{{ 'dnsIpLabel' | translate }}</mat-label> <input matInput formControlName="mcastIp">
<input matInput formControlName="dns"> </mat-form-field>
</mat-form-field> <mat-form-field class="form-field">
<mat-form-field class="form-field"> <mat-label>{{ 'mcastSpeedLabel' | translate }}</mat-label>
<mat-label>{{ 'netmaskLabel' | translate }}</mat-label> <input matInput formControlName="mcastSpeed" type="number">
<input matInput formControlName="netmask"> </mat-form-field>
</mat-form-field> <mat-form-field class="form-field">
<mat-form-field class="form-field"> <mat-label>{{ 'mcastPortLabel' | translate }}</mat-label>
<mat-label>{{ 'routerLabel' | translate }}</mat-label> <input matInput formControlName="mcastPort" type="number">
<input matInput formControlName="router"> </mat-form-field>
</mat-form-field> <mat-form-field class="form-field">
<mat-form-field class="form-field"> <mat-label>{{ 'mcastModeLabel' | translate }}</mat-label>
<mat-label>{{ 'ntpIpLabel' | translate }}</mat-label> <mat-select formControlName="mcastMode">
<input matInput formControlName="ntp"> <mat-option *ngFor="let option of multicastModeOptions" [value]="option.value">
</mat-form-field> {{ option.name }}
<mat-form-field class="form-field"> </mat-option>
<mat-label>{{ 'p2pModeLabel' | translate }}</mat-label> </mat-select>
<mat-select formControlName="p2pMode"> </mat-form-field>
<mat-option *ngFor="let option of p2pModeOptions" [value]="option.value"> <mat-form-field class="form-field">
{{ option.name }} <mat-label>{{ 'menuUrlLabel' | translate }}</mat-label>
</mat-option> <input matInput formControlName="menu" type="url">
</mat-select> </mat-form-field>
</mat-form-field> <mat-form-field class="form-field">
<mat-form-field class="form-field"> <mat-label>{{ 'hardwareProfileLabel' | translate }}</mat-label>
<mat-label>{{ 'p2pTimeLabel' | translate }}</mat-label> <mat-select formControlName="hardwareProfile">
<input matInput formControlName="p2pTime" type="number"> <mat-option *ngFor="let unit of hardwareProfiles" [value]="unit['@id']">{{ unit.description }}</mat-option>
</mat-form-field> </mat-select>
<mat-form-field class="form-field"> <mat-error>{{ 'urlFormatError' | translate }}</mat-error>
<mat-label>{{ 'mcastIpLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="mcastIp"> </form>
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'mcastSpeedLabel' | translate }}</mat-label>
<input matInput formControlName="mcastSpeed" type="number">
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'mcastPortLabel' | translate }}</mat-label>
<input matInput formControlName="mcastPort" type="number">
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'mcastModeLabel' | translate }}</mat-label>
<mat-select formControlName="mcastMode">
<mat-option *ngFor="let option of multicastModeOptions" [value]="option.value">
{{ option.name }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'menuUrlLabel' | translate }}</mat-label>
<input matInput formControlName="menu" type="url">
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'hardwareProfileLabel' | translate }}</mat-label>
<mat-select formControlName="hardwareProfile">
<mat-option *ngFor="let unit of hardwareProfiles" [value]="unit['@id']">{{ unit.description }}</mat-option>
</mat-select>
<mat-error>{{ 'urlFormatError' | translate }}</mat-error>
</mat-form-field>
</form>
</mat-step>
</mat-stepper>
</div> </div>
<div mat-dialog-actions align="end"> <div mat-dialog-actions align="end">
<button mat-button (click)="onNoClick()">{{ 'cancelButton' | translate }}</button> <button mat-button (click)="onNoClick()">{{ 'cancelButton' | translate }}</button>

View File

@ -39,7 +39,7 @@ export class CreateOrganizationalUnitComponent implements OnInit {
ogLives: any[] = []; ogLives: any[] = [];
repositories: any[] = []; repositories: any[] = [];
selectedCalendarUuid: string | null = null; selectedCalendarUuid: string | null = null;
parentUnitsWithPaths: { id: string, name: string, path: string }[] = [];
@Output() unitAdded = new EventEmitter<{ uuid: string; name: string }>(); @Output() unitAdded = new EventEmitter<{ uuid: string; name: string }>();
@ -104,11 +104,23 @@ export class CreateOrganizationalUnitComponent implements OnInit {
loadParentUnits() { loadParentUnits() {
const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=1000`; const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=1000`;
this.http.get<any>(url).subscribe( this.http.get<any>(url).subscribe(
response => this.parentUnits = response['hydra:member'], 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)
}));
},
error => console.error('Error fetching parent units:', error) error => console.error('Error fetching parent units:', error)
); );
} }
getSelectedParentName(): string | undefined {
const parentId = this.generalFormGroup.get('parent')?.value;
return this.parentUnitsWithPaths.find(unit => unit.id === parentId)?.name;
}
loadHardwareProfiles(): void { loadHardwareProfiles(): void {
this.dataService.getHardwareProfiles().subscribe( this.dataService.getHardwareProfiles().subscribe(
(data: any[]) => this.hardwareProfiles = data, (data: any[]) => this.hardwareProfiles = data,

View File

@ -1,168 +1,146 @@
<h1 mat-dialog-title>{{ 'editOrgUnitTitle' | translate }}</h1> <h1 mat-dialog-title>{{ 'editOrgUnitTitle' | translate }}</h1>
<div mat-dialog-content> <div mat-dialog-content>
<mat-stepper orientation="vertical" [linear]="isLinear"> <!-- Paso 1: General -->
<!-- Paso 1: General --> <form [formGroup]="generalFormGroup">
<mat-step [stepControl]="generalFormGroup"> <mat-form-field class="form-field">
<form [formGroup]="generalFormGroup"> <mat-label>{{ 'typeLabel' | translate }}</mat-label>
<ng-template matStepLabel>{{ 'generalStepLabel' | translate }}</ng-template> <mat-select formControlName="type" required>
<mat-form-field class="form-field"> <mat-option *ngFor="let type of filteredTypes" [value]="type">
<mat-label>{{ 'typeLabel' | translate }}</mat-label> {{ typeTranslations[type] }}
<mat-select formControlName="type" required> </mat-option>
<mat-option *ngFor="let type of filteredTypes" [value]="type">{{ typeTranslations[type] }}</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>{{ 'nameLabel' | translate }}</mat-label>
<mat-label>{{ 'nameLabel' | translate }}</mat-label> <input matInput formControlName="name" required>
<input matInput formControlName="name" required> </mat-form-field>
</mat-form-field> <mat-form-field class="form-field">
<mat-form-field class="form-field"> <mat-label>{{ 'editOrgUnitParentLabel' | translate }}</mat-label>
<mat-label>{{ 'editOrgUnitParentLabel' | translate }}</mat-label> <mat-select formControlName="parent">
<mat-select formControlName="parent"> <mat-select-trigger>
<mat-option *ngFor="let unit of parentUnits" [value]="unit['@id']">{{ unit.name }}</mat-option> {{ getSelectedParentName() }}
</mat-select> </mat-select-trigger>
</mat-form-field> <mat-option *ngFor="let unit of parentUnitsWithPaths" [value]="unit.id">
<mat-form-field class="form-field"> <div>{{ unit.name }}</div>
<mat-label>{{ 'descriptionLabel' | translate }}</mat-label> <div style="font-size: smaller; color: gray;">{{ unit.path }}</div>
<textarea matInput formControlName="description"></textarea> </mat-option>
</mat-form-field> </mat-select>
<div> </mat-form-field>
<button mat-button matStepperNext>{{ 'nextButton' | translate }}</button> <mat-form-field class="form-field">
</div> <mat-label>{{ 'descriptionLabel' | translate }}</mat-label>
</form> <textarea matInput formControlName="description"></textarea>
</mat-step> </mat-form-field>
</form>
<!-- Paso 2: Información del Aula --> <!-- Paso 2: Información del Aula -->
<mat-step *ngIf="generalFormGroup.value.type === 'classroom'" [stepControl]="classroomInfoFormGroup"> <form *ngIf="generalFormGroup.value.type === 'classroom'" [formGroup]="classroomInfoFormGroup">
<form [formGroup]="classroomInfoFormGroup"> <mat-form-field class="form-field">
<ng-template matStepLabel>{{ 'classroomInfoStepLabel' | translate }}</ng-template> <mat-label>{{ 'locationLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="location">
<mat-label>{{ 'locationLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="location"> <mat-slide-toggle formControlName="projector">{{ 'projectorToggle' | translate }}</mat-slide-toggle>
</mat-form-field> <mat-slide-toggle formControlName="board">{{ 'boardToggle' | translate }}</mat-slide-toggle>
<mat-slide-toggle formControlName="projector">{{ 'projectorToggle' | translate }}</mat-slide-toggle> <mat-form-field class="form-field">
<mat-slide-toggle formControlName="board">{{ 'boardToggle' | translate }}</mat-slide-toggle> <mat-label>{{ 'capacityLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="capacity" type="number">
<mat-label>{{ 'capacityLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="capacity" type="number"> <mat-form-field class="form-field" appearance="fill">
</mat-form-field> <mat-label>{{ 'associatedCalendarLabel' | translate }}</mat-label>
<mat-select formControlName="remoteCalendar" (selectionChange)="onCalendarChange($event)">
<mat-option *ngFor="let calendar of calendars" [value]="calendar['@id']">
{{ calendar.name }}
</mat-option>
</mat-select>
</mat-form-field>
</form>
<mat-form-field class="form-field" appearance="fill"> <!-- Paso 3: Información Adicional -->
<mat-label>{{ 'associatedCalendarLabel' | translate }}</mat-label> <form [formGroup]="additionalInfoFormGroup">
<mat-select formControlName="remoteCalendar" (selectionChange)="onCalendarChange($event)"> <mat-form-field class="form-field">
<mat-option *ngFor="let calendar of calendars" [value]="calendar['@id']"> <mat-label>{{ 'commentsLabel' | translate }}</mat-label>
{{ calendar.name }} <textarea matInput formControlName="comments"></textarea>
</mat-option> </mat-form-field>
</mat-select> </form>
</mat-form-field>
<div> <!-- Paso 4: Configuración de Red -->
<button mat-button matStepperPrevious>{{ 'backButton' | translate }}</button> <form *ngIf="generalFormGroup.value.type === 'classroom' || generalFormGroup.value.type === 'clients-group'" [formGroup]="networkSettingsFormGroup">
<button mat-button matStepperNext>{{ 'nextButton' | translate }}</button> <mat-form-field class="form-field">
</div> <mat-label>{{ 'ogLiveLabel' | translate }}</mat-label>
</form> <mat-select formControlName="ogLive" (selectionChange)="onOgLiveChange($event)">
</mat-step> <mat-option *ngFor="let oglive of ogLives" [value]="oglive['@id']">
{{ oglive.filename }}
<!-- Paso 3: Información Adicional --> </mat-option>
<mat-step [stepControl]="additionalInfoFormGroup"> </mat-select>
<form [formGroup]="additionalInfoFormGroup"> </mat-form-field>
<ng-template matStepLabel>{{ 'additionalInfoStepLabel' | translate }}</ng-template> <mat-form-field class="form-field">
<mat-form-field class="form-field"> <mat-label>{{ 'repositoryLabel' | translate }}</mat-label>
<mat-label>{{ 'commentsLabel' | translate }}</mat-label> <mat-select formControlName="repository" (selectionChange)="onRepositoryChange($event)">
<textarea matInput formControlName="comments"></textarea> <mat-option *ngFor="let repository of repositories" [value]="repository['@id']">
</mat-form-field> {{ repository.name }}
<div> </mat-option>
<button mat-button matStepperPrevious>{{ 'backButton' | translate }}</button> </mat-select>
<button mat-button matStepperNext>{{ 'nextButton' | translate }}</button> </mat-form-field>
</div> <mat-form-field class="form-field">
</form> <mat-label>{{ 'proxyUrlLabel' | translate }}</mat-label>
</mat-step> <input matInput formControlName="proxy">
</mat-form-field>
<!-- Paso 4: Configuración de Red --> <mat-form-field class="form-field">
<mat-step *ngIf="generalFormGroup.value.type === 'classroom' || generalFormGroup.value.type === 'clients-group'" [stepControl]="networkSettingsFormGroup"> <mat-label>{{ 'dnsIpLabel' | translate }}</mat-label>
<form [formGroup]="networkSettingsFormGroup"> <input matInput formControlName="dns">
<ng-template matStepLabel>{{ 'networkSettingsStepLabel' | translate }}</ng-template> </mat-form-field>
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>{{ 'ogLiveLabel' | translate }}</mat-label> <mat-label>{{ 'netmaskLabel' | translate }}</mat-label>
<mat-select formControlName="ogLive" (selectionChange)="onOgLiveChange($event)"> <input matInput formControlName="netmask">
<mat-option *ngFor="let oglive of ogLives" [value]="oglive['@id']"> </mat-form-field>
{{ oglive.filename }} <mat-form-field class="form-field">
</mat-option> <mat-label>{{ 'routerLabel' | translate }}</mat-label>
</mat-select> <input matInput formControlName="router">
</mat-form-field> </mat-form-field>
<mat-form-field class="form-field"> <mat-form-field class="form-field">
<mat-label>{{ 'repositoryLabel' | translate }}</mat-label> <mat-label>{{ 'ntpIpLabel' | translate }}</mat-label>
<mat-select formControlName="repository" (selectionChange)="onRepositoryChange($event)"> <input matInput formControlName="ntp">
<mat-option *ngFor="let repository of repositories" [value]="repository['@id']"> </mat-form-field>
{{ repository.name }} <mat-form-field class="form-field">
</mat-option> <mat-label>{{ 'p2pModeLabel' | translate }}</mat-label>
</mat-select> <mat-select formControlName="p2pMode">
</mat-form-field> <mat-option *ngFor="let option of p2pModeOptions" [value]="option.value">{{ option.name }}</mat-option>
<mat-form-field class="form-field"> </mat-select>
<mat-label>{{ 'proxyUrlLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="proxy"> <mat-form-field class="form-field">
</mat-form-field> <mat-label>{{ 'p2pTimeLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="p2pTime" type="number">
<mat-label>{{ 'dnsIpLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="dns"> <mat-form-field class="form-field">
</mat-form-field> <mat-label>{{ 'mcastIpLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="mcastIp">
<mat-label>{{ 'netmaskLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="netmask"> <mat-form-field class="form-field">
</mat-form-field> <mat-label>{{ 'mcastSpeedLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="mcastSpeed" type="number">
<mat-label>{{ 'routerLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="router"> <mat-form-field class="form-field">
</mat-form-field> <mat-label>{{ 'mcastPortLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="mcastPort" type="number">
<mat-label>{{ 'ntpIpLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="ntp"> <mat-form-field class="form-field">
</mat-form-field> <mat-label>{{ 'mcastModeLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <mat-select formControlName="mcastMode">
<mat-label>{{ 'p2pModeLabel' | translate }}</mat-label> <mat-option *ngFor="let option of multicastModeOptions" [value]="option.value">{{ option.name }}</mat-option>
<mat-select formControlName="p2pMode"> </mat-select>
<mat-option *ngFor="let option of p2pModeOptions" [value]="option.value">{{ option.name }}</mat-option> </mat-form-field>
</mat-select> <mat-form-field class="form-field">
</mat-form-field> <mat-label>{{ 'menuUrlLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <input matInput formControlName="menu" type="url">
<mat-label>{{ 'p2pTimeLabel' | translate }}</mat-label> </mat-form-field>
<input matInput formControlName="p2pTime" type="number"> <mat-form-field class="form-field">
</mat-form-field> <mat-label>{{ 'hardwareProfileLabel' | translate }}</mat-label>
<mat-form-field class="form-field"> <mat-select formControlName="hardwareProfile">
<mat-label>{{ 'mcastIpLabel' | translate }}</mat-label> <mat-option *ngFor="let unit of hardwareProfiles" [value]="unit['@id']">{{ unit.description }}</mat-option>
<input matInput formControlName="mcastIp"> </mat-select>
</mat-form-field> <mat-error>{{ 'urlFormatError' | translate }}</mat-error>
<mat-form-field class="form-field"> </mat-form-field>
<mat-label>{{ 'mcastSpeedLabel' | translate }}</mat-label> <mat-slide-toggle formControlName="validation">{{ 'validationToggle' | translate }}</mat-slide-toggle>
<input matInput formControlName="mcastSpeed" type="number"> </form>
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'mcastPortLabel' | translate }}</mat-label>
<input matInput formControlName="mcastPort" type="number">
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'mcastModeLabel' | translate }}</mat-label>
<mat-select formControlName="mcastMode">
<mat-option *ngFor="let option of multicastModeOptions" [value]="option.value">{{ option.name }}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'menuUrlLabel' | translate }}</mat-label>
<input matInput formControlName="menu" type="url">
</mat-form-field>
<mat-form-field class="form-field">
<mat-label>{{ 'hardwareProfileLabel' | translate }}</mat-label>
<mat-select formControlName="hardwareProfile">
<mat-option *ngFor="let unit of hardwareProfiles" [value]="unit['@id']">{{ unit.description }}</mat-option>
</mat-select>
<mat-error>{{ 'urlFormatError' | translate }}</mat-error>
</mat-form-field>
<mat-slide-toggle formControlName="validation">{{ 'validationToggle' | translate }}</mat-slide-toggle>
<div>
<button mat-button matStepperPrevious>{{ 'backButton' | translate }}</button>
</div>
</form>
</mat-step>
</mat-stepper>
</div> </div>
<div mat-dialog-actions align="end"> <div mat-dialog-actions align="end">
<button mat-button (click)="onNoClick()">{{ 'cancelButton' | translate }}</button> <button mat-button (click)="onNoClick()">{{ 'cancelButton' | translate }}</button>

View File

@ -31,6 +31,7 @@ export class EditOrganizationalUnitComponent implements OnInit {
currentCalendar: any = []; currentCalendar: any = [];
ogLives: any[] = []; ogLives: any[] = [];
repositories: any[] = []; repositories: any[] = [];
parentUnitsWithPaths: { id: string, name: string, path: string }[] = [];
protected p2pModeOptions = [ protected p2pModeOptions = [
{"name": 'Leecher', "value": "leecher"}, {"name": 'Leecher', "value": "leecher"},
{"name": 'Peer', "value": "peer"}, {"name": 'Peer', "value": "peer"},
@ -109,18 +110,25 @@ export class EditOrganizationalUnitComponent implements OnInit {
} }
loadParentUnits() { loadParentUnits() {
const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=10000`; const url = `${this.baseUrl}/organizational-units?page=1&itemsPerPage=1000`;
this.http.get<any>(url).subscribe( this.http.get<any>(url).subscribe(
response => { response => {
this.parentUnits = response['hydra:member']; this.parentUnits = response['hydra:member'];
this.parentUnitsWithPaths = this.parentUnits.map(unit => ({
id: unit['@id'],
name: unit.name,
path: this.dataService.getOrganizationalUnitPath(unit, this.parentUnits)
}));
}, },
error => { error => console.error('Error fetching parent units:', error)
console.error('Error fetching parent units:', error);
}
); );
} }
getSelectedParentName(): string | undefined {
const parentId = this.generalFormGroup.get('parent')?.value;
return this.parentUnitsWithPaths.find(unit => unit.id === parentId)?.name;
}
loadHardwareProfiles(): void { loadHardwareProfiles(): void {
this.dataService.getHardwareProfiles().subscribe( this.dataService.getHardwareProfiles().subscribe(
(data: any[]) => { (data: any[]) => {