Añadido campo resolución en los ajustes de red de aulas y grupos para propagarlo a los equipos. Rediseño de la vista de propiedades de una OU #73
|
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## [1.5.2] - 2026-04-24
|
||||
### Added
|
||||
- Añadido campo resolución en los ajustes de red de aulas y grupos para propagarlo a los equipos.
|
||||
- Rediseño del menú de configuracion de una Unidad Organizativa
|
||||
|
||||
## [1.5.1] - 2026-04-23
|
||||
### Improved
|
||||
- Creadas claves de traducción para idiomas, añadido menu para cambiar de idioma en la barra superior
|
||||
|
|
|
|||
|
|
@ -108,23 +108,23 @@ export class ClientDetailsComponent {
|
|||
|
||||
updateGeneralData() {
|
||||
this.generalData = [
|
||||
{ property: 'Nombre', value: this.clientData?.name || '' },
|
||||
{ property: 'IP', value: this.clientData?.ip || '' },
|
||||
{ property: 'MAC', value: this.clientData?.mac || '' },
|
||||
{ property: 'Nº de serie', value: this.clientData?.serialNumber || '' },
|
||||
{ property: 'Netiface', value: this.clientData?.netiface || this.clientData?.organizationalUnit?.networkSettings?.netiface || '' },
|
||||
{ property: 'Perfil hardware', value: this.clientData?.hardwareProfile?.description || '' },
|
||||
{ property: this.translate.instant('labelName'), value: this.clientData?.name || '' },
|
||||
{ property: this.translate.instant('labelIp'), value: this.clientData?.ip || '' },
|
||||
{ property: this.translate.instant('labelMac'), value: this.clientData?.mac || '' },
|
||||
{ property: this.translate.instant('labelSerialNumber'), value: this.clientData?.serialNumber || '' },
|
||||
{ property: this.translate.instant('labelNetiface'), value: this.clientData?.netiface || this.clientData?.organizationalUnit?.networkSettings?.netiface || '' },
|
||||
{ property: this.translate.instant('labelHardwareProfile'), value: this.clientData?.hardwareProfile?.description || '' },
|
||||
];
|
||||
}
|
||||
|
||||
updateNetworkData() {
|
||||
this.networkData = [
|
||||
{ property: 'Padre', value: this.clientData?.organizationalUnit?.name || '' },
|
||||
{ property: 'Pxe', value: this.clientData?.pxeTemplate?.name || '' },
|
||||
{ property: 'Remote Pc', value: this.clientData.remotePc || '' },
|
||||
{ property: 'Subred', value: this.clientData?.subnet || '' },
|
||||
{ property: 'OGlive', value: this.clientData?.ogLive?.name || '' },
|
||||
{ property: 'Repositorio', value: this.clientData?.repository?.name || '' },
|
||||
{ property: this.translate.instant('labelParent'), value: this.clientData?.organizationalUnit?.name || '' },
|
||||
{ property: this.translate.instant('labelTemplate'), value: this.clientData?.pxeTemplate?.name || '' },
|
||||
{ property: this.translate.instant('remotePc'), value: this.clientData.remotePc || '' },
|
||||
{ property: this.translate.instant('labelSubnet'), value: this.clientData?.subnet || '' },
|
||||
{ property: this.translate.instant('labelOgLive'), value: this.clientData?.ogLive?.name || '' },
|
||||
{ property: this.translate.instant('labelRepository'), value: this.clientData?.repository?.name || '' },
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -154,14 +154,14 @@ export class ClientDetailsComponent {
|
|||
|
||||
this.chartDisk = Array.from(diskUsageMap.entries()).map(([diskNumber, { total, used, partitions }]) => {
|
||||
const partitionData = partitions.map(partition => ({
|
||||
name: `Partición ${partition.partitionNumber}`,
|
||||
name: `${this.translate.instant('labelPartition')} ${partition.partitionNumber}`,
|
||||
value: Number((partition.size / 1024).toFixed(2))
|
||||
}));
|
||||
|
||||
const freeSpace = total - used;
|
||||
if (freeSpace > 0) {
|
||||
partitionData.push({
|
||||
name: 'Espacio libre',
|
||||
name: this.translate.instant('labelFreeSpace'),
|
||||
value: Number(freeSpace.toFixed(2))
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ mat-option .unit-path {
|
|||
padding: 1.5em;
|
||||
}
|
||||
|
||||
/* Boot grouping */
|
||||
.boot-group {
|
||||
/* Generic fieldset grouping */
|
||||
.fieldset-group {
|
||||
grid-column: 1 / -1;
|
||||
border: 1px solid #c5c5c5;
|
||||
border-radius: 6px;
|
||||
|
|
@ -64,7 +64,7 @@ mat-option .unit-path {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.boot-group-legend {
|
||||
.fieldset-legend {
|
||||
font-size: 0.78rem;
|
||||
color: #3f51b5;
|
||||
font-weight: 600;
|
||||
|
|
@ -73,7 +73,13 @@ mat-option .unit-path {
|
|||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.boot-group-grid {
|
||||
.fieldset-grid-2 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
column-gap: 20px;
|
||||
}
|
||||
|
||||
.fieldset-grid-3 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
column-gap: 20px;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelRoleName' | translate }}</mat-label>
|
||||
<mat-label>{{ 'labelName' | translate }}</mat-label>
|
||||
<input matInput formControlName="name" required>
|
||||
</mat-form-field>
|
||||
|
||||
|
|
@ -59,43 +59,49 @@
|
|||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMenu' | translate }}</mat-label>
|
||||
<mat-select formControlName="menu">
|
||||
@for (menu of menus; track menu['@id']) {
|
||||
<mat-option [value]="menu['@id']">{{ menu.name }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>{{ 'menuError' | translate }}</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelResolution' | translate }}</mat-label>
|
||||
<mat-select formControlName="resolution" required>
|
||||
<mat-option value="769">{{ 'resolution640x480x8' | translate }}</mat-option>
|
||||
<mat-option value="771">{{ 'resolution800x600x8' | translate }}</mat-option>
|
||||
<mat-option value="773">{{ 'resolution1024x768x8' | translate }}</mat-option>
|
||||
<mat-option value="775">{{ 'resolution1280x1024x8' | translate }}</mat-option>
|
||||
<mat-option value="784">{{ 'resolution640x480x16' | translate }}</mat-option>
|
||||
<mat-option value="787">{{ 'resolution800x600x16' | translate }}</mat-option>
|
||||
<mat-option value="791">{{ 'resolution1024x768x16' | translate }}</mat-option>
|
||||
<mat-option value="794">{{ 'resolution1280x1024x16' | translate }}</mat-option>
|
||||
<mat-option value="785">{{ 'resolution640x480x24' | translate }}</mat-option>
|
||||
<mat-option value="788">{{ 'resolution800x600x24' | translate }}</mat-option>
|
||||
<mat-option value="792">{{ 'resolution1024x768x24' | translate }}</mat-option>
|
||||
<mat-option value="795">{{ 'resolution1280x1024x24' | translate }}</mat-option>
|
||||
</mat-select>
|
||||
<mat-error>{{ 'resolutionError' | translate }}</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-checkbox formControlName="maintenance">
|
||||
{{ 'maintenance' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<!-- ===== Agrupación: Configuración del menú ===== -->
|
||||
<fieldset class="fieldset-group">
|
||||
<legend class="fieldset-legend">{{ 'menuConfiguration' | translate }}</legend>
|
||||
<div class="fieldset-grid-2">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMenu' | translate }}</mat-label>
|
||||
<mat-select formControlName="menu">
|
||||
@for (menu of menus; track menu['@id']) {
|
||||
<mat-option [value]="menu['@id']">{{ menu.name }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
<mat-error>{{ 'menuError' | translate }}</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelResolution' | translate }}</mat-label>
|
||||
<mat-select formControlName="resolution" required>
|
||||
<mat-option value="769">{{ 'resolution640x480x8' | translate }}</mat-option>
|
||||
<mat-option value="771">{{ 'resolution800x600x8' | translate }}</mat-option>
|
||||
<mat-option value="773">{{ 'resolution1024x768x8' | translate }}</mat-option>
|
||||
<mat-option value="775">{{ 'resolution1280x1024x8' | translate }}</mat-option>
|
||||
<mat-option value="784">{{ 'resolution640x480x16' | translate }}</mat-option>
|
||||
<mat-option value="787">{{ 'resolution800x600x16' | translate }}</mat-option>
|
||||
<mat-option value="791">{{ 'resolution1024x768x16' | translate }}</mat-option>
|
||||
<mat-option value="794">{{ 'resolution1280x1024x16' | translate }}</mat-option>
|
||||
<mat-option value="785">{{ 'resolution640x480x24' | translate }}</mat-option>
|
||||
<mat-option value="788">{{ 'resolution800x600x24' | translate }}</mat-option>
|
||||
<mat-option value="792">{{ 'resolution1024x768x24' | translate }}</mat-option>
|
||||
<mat-option value="795">{{ 'resolution1280x1024x24' | translate }}</mat-option>
|
||||
</mat-select>
|
||||
<mat-error>{{ 'resolutionError' | translate }}</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- ===== Agrupación: Configuración de arranque ===== -->
|
||||
<fieldset class="boot-group">
|
||||
<legend class="boot-group-legend">{{ 'bootConfiguration' | translate }}</legend>
|
||||
<div class="boot-group-grid">
|
||||
<fieldset class="fieldset-group">
|
||||
<legend class="fieldset-legend">{{ 'bootConfiguration' | translate }}</legend>
|
||||
<div class="fieldset-grid-3">
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'bootServer' | translate }}</mat-label>
|
||||
|
|
|
|||
|
|
@ -66,16 +66,16 @@ h1 {
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Boot grouping */
|
||||
.boot-group {
|
||||
/* Generic fieldset grouping */
|
||||
.fieldset-group {
|
||||
grid-column: 1 / -1;
|
||||
border: 1px solid #c5c5c5;
|
||||
border-radius: 6px;
|
||||
padding: 12px 16px 4px 16px;
|
||||
margin: 0;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.boot-group-legend {
|
||||
.fieldset-legend {
|
||||
font-size: 0.78rem;
|
||||
color: #3f51b5;
|
||||
font-weight: 600;
|
||||
|
|
@ -84,7 +84,13 @@ h1 {
|
|||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.boot-group-grid {
|
||||
.fieldset-grid-2 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
column-gap: 20px;
|
||||
}
|
||||
|
||||
.fieldset-grid-3 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
column-gap: 20px;
|
||||
|
|
|
|||
|
|
@ -42,10 +42,9 @@
|
|||
</form>
|
||||
|
||||
<!-- Paso 2: Información del Aula -->
|
||||
<span *ngIf="generalFormGroup.value.type === 'classroom' && !loading"
|
||||
class="step-title">{{ 'labelClassroomInfoStep' | translate }}</span>
|
||||
<form *ngIf="generalFormGroup.value.type === 'classroom' && !loading" class="grid-form"
|
||||
[formGroup]="classroomInfoFormGroup">
|
||||
@if (generalFormGroup.value.type === 'classroom' && !loading) {
|
||||
<span class="step-title">{{ 'labelClassroomInfoStep' | translate }}</span>
|
||||
<form class="grid-form" [formGroup]="classroomInfoFormGroup">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelLocation' | translate }}</mat-label>
|
||||
<input matInput formControlName="location">
|
||||
|
|
@ -70,20 +69,22 @@
|
|||
<mat-slide-toggle formControlName="board">{{ 'boardToggle' | translate }}</mat-slide-toggle>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
|
||||
<!-- Paso 3: Configuración de Red -->
|
||||
<span *ngIf="!loading" class="step-title">{{ 'labelNetworkSettingsStep' | translate }}</span>
|
||||
<form *ngIf="networkSettingsFormGroup && !loading" [formGroup]="networkSettingsFormGroup" class="grid-form">
|
||||
|
||||
<!-- ===== Agrupación: Configuración de arranque ===== -->
|
||||
<fieldset class="boot-group">
|
||||
<legend class="boot-group-legend">{{ 'bootConfiguration' | translate }}</legend>
|
||||
<div class="boot-group-grid">
|
||||
<fieldset class="fieldset-group">
|
||||
<legend class="fieldset-legend">{{ 'bootConfiguration' | translate }}</legend>
|
||||
<div class="fieldset-grid-3">
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'bootServer' | translate }}</mat-label>
|
||||
<mat-select formControlName="bootServer" (selectionChange)="onBootServerChange($event)">
|
||||
@for (server of bootServers; track server['@id']) {
|
||||
<mat-option [value]="server['@id']">{{ server.name }}</mat-option>
|
||||
<mat-option [value]="server['@id']">{{ server.name }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
|
@ -92,10 +93,10 @@
|
|||
<mat-label>{{ 'ogLive' | translate }}</mat-label>
|
||||
<mat-select formControlName="ogLive" (selectionChange)="onOgLiveChange($event)">
|
||||
@for (oglive of ogLives; track oglive['@id']) {
|
||||
<mat-option [value]="oglive['@id']">{{ oglive.name }}</mat-option>
|
||||
<mat-option [value]="oglive['@id']">{{ oglive.name }}</mat-option>
|
||||
}
|
||||
@if (ogLives.length === 0 && networkSettingsFormGroup.get('bootServer')?.value) {
|
||||
<mat-option disabled>{{ 'noOgLivesInServer' | translate }}</mat-option>
|
||||
<mat-option disabled>{{ 'noOgLivesInServer' | translate }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
|
@ -104,16 +105,17 @@
|
|||
<mat-label>{{ 'labelTemplate' | translate }}</mat-label>
|
||||
<mat-select formControlName="pxeTemplate" (selectionChange)="onPxeTemplateChange($event)">
|
||||
@for (template of pxeTemplates; track template['@id']) {
|
||||
<mat-option [value]="template['@id']">{{ template.name }}</mat-option>
|
||||
<mat-option [value]="template['@id']">{{ template.name }}</mat-option>
|
||||
}
|
||||
@if (pxeTemplates.length === 0 && networkSettingsFormGroup.get('bootServer')?.value) {
|
||||
<mat-option disabled>{{ 'noTemplatesInServer' | translate }}</mat-option>
|
||||
<mat-option disabled>{{ 'noTemplatesInServer' | translate }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelRepository' | translate }}</mat-label>
|
||||
<mat-select formControlName="repository" (selectionChange)="onRepositoryChange($event)">
|
||||
|
|
@ -150,60 +152,97 @@
|
|||
<mat-label>{{ 'labelNtp' | translate }}</mat-label>
|
||||
<input matInput formControlName="ntp">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelP2pMode' | translate }}</mat-label>
|
||||
<mat-select formControlName="p2pMode">
|
||||
<mat-option *ngFor="let option of p2pModeOptions" [value]="option.value">
|
||||
{{ option.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field" *ngIf="networkSettingsFormGroup.get('p2pMode')?.value === 'seeder'">
|
||||
<mat-label>{{ 'labelP2pTime' | translate }} (minutos)</mat-label>
|
||||
<input matInput formControlName="p2pTime" type="number">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMcastIp' | translate }}</mat-label>
|
||||
<input matInput formControlName="mcastIp">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMcastSpeed' | translate }}</mat-label>
|
||||
<input matInput formControlName="mcastSpeed" type="number">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMcastPort' | translate }}</mat-label>
|
||||
<input matInput formControlName="mcastPort" type="number">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMcastMode' | 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>{{ 'labelMenu' | translate }}</mat-label>
|
||||
<mat-select formControlName="menu">
|
||||
<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-label>{{ 'labelHardwareProfile' | 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>
|
||||
<!-- ===== Agrupación: Configuración de multicast ===== -->
|
||||
<fieldset class="fieldset-group">
|
||||
<legend class="fieldset-legend">{{ 'multicastConfiguration' | translate }}</legend>
|
||||
<div class="fieldset-grid-2">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMcastIp' | translate }}</mat-label>
|
||||
<input matInput formControlName="mcastIp">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMcastSpeed' | translate }}</mat-label>
|
||||
<input matInput formControlName="mcastSpeed" type="number">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMcastPort' | translate }}</mat-label>
|
||||
<input matInput formControlName="mcastPort" type="number">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMcastMode' | 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>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- ===== Agrupación: Configuración de p2p ===== -->
|
||||
<fieldset class="fieldset-group">
|
||||
<legend class="fieldset-legend">{{ 'p2pConfiguration' | translate }}</legend>
|
||||
<div class="fieldset-grid-2">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelP2pMode' | translate }}</mat-label>
|
||||
<mat-select formControlName="p2pMode">
|
||||
<mat-option *ngFor="let option of p2pModeOptions" [value]="option.value">
|
||||
{{ option.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="form-field" *ngIf="networkSettingsFormGroup.get('p2pMode')?.value === 'seeder'">
|
||||
<mat-label>{{ 'labelP2pTime' | translate }} (minutos)</mat-label>
|
||||
<input matInput formControlName="p2pTime" type="number">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<!-- ===== Agrupación: Configuración del menú ===== -->
|
||||
<fieldset class="fieldset-group">
|
||||
<legend class="fieldset-legend">{{ 'menuConfiguration' | translate }}</legend>
|
||||
<div class="fieldset-grid-2">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-label>{{ 'labelMenu' | translate }}</mat-label>
|
||||
<mat-select formControlName="menu" (selectionChange)="onMenuChange($event)">
|
||||
<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-label>{{ 'labelResolution' | translate }}</mat-label>
|
||||
<mat-select formControlName="resolution">
|
||||
<mat-option value="769">{{ 'resolution640x480x8' | translate }}</mat-option>
|
||||
<mat-option value="771">{{ 'resolution800x600x8' | translate }}</mat-option>
|
||||
<mat-option value="773">{{ 'resolution1024x768x8' | translate }}</mat-option>
|
||||
<mat-option value="775">{{ 'resolution1280x1024x8' | translate }}</mat-option>
|
||||
<mat-option value="784">{{ 'resolution640x480x16' | translate }}</mat-option>
|
||||
<mat-option value="787">{{ 'resolution800x600x16' | translate }}</mat-option>
|
||||
<mat-option value="791">{{ 'resolution1024x768x16' | translate }}</mat-option>
|
||||
<mat-option value="794">{{ 'resolution1280x1024x16' | translate }}</mat-option>
|
||||
<mat-option value="785">{{ 'resolution640x480x24' | translate }}</mat-option>
|
||||
<mat-option value="788">{{ 'resolution800x600x24' | translate }}</mat-option>
|
||||
<mat-option value="792">{{ 'resolution1024x768x24' | translate }}</mat-option>
|
||||
<mat-option value="795">{{ 'resolution1280x1024x24' | translate }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<!-- Paso 4: Información Adicional -->
|
||||
<span *ngIf="!loading" class="step-title">{{ 'labelAdditionalInfoStep' | translate }}</span>
|
||||
<form *ngIf="additionalInfoFormGroup && !loading" [formGroup]="additionalInfoFormGroup">
|
||||
<mat-form-field class="form-field">
|
||||
<mat-form-field class="form-field description-form-field">
|
||||
<mat-label>{{ 'labelComments' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="comments"></textarea>
|
||||
</mat-form-field>
|
||||
|
|
@ -214,5 +253,5 @@
|
|||
<button class="ordinary-button" (click)="onNoClick()">{{ 'buttonCancel' | translate }}</button>
|
||||
<button class="submit-button" (click)="onSubmit()"
|
||||
[disabled]="!generalFormGroup.valid || !additionalInfoFormGroup.valid || !networkSettingsFormGroup.valid">{{
|
||||
isEditMode ? ('edit' | translate) : ('createButton' | translate) }}</button>
|
||||
isEditMode ? ('buttonEdit' | translate) : ('createButton' | translate) }}</button>
|
||||
</mat-dialog-actions>
|
||||
|
|
@ -78,7 +78,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
});
|
||||
|
||||
this.additionalInfoFormGroup = this._formBuilder.group({
|
||||
comments: [null],
|
||||
comments: [null]
|
||||
});
|
||||
|
||||
this.networkSettingsFormGroup = this._formBuilder.group({
|
||||
|
|
@ -99,6 +99,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
mcastPort: [null],
|
||||
mcastMode: [null],
|
||||
menu: [null],
|
||||
resolution: [null],
|
||||
hardwareProfile: [null]
|
||||
});
|
||||
|
||||
|
|
@ -125,9 +126,11 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
Promise.all(observables).then(() => {
|
||||
if (this.isEditMode) {
|
||||
this.loadData(this.data.uuid).then(() => {
|
||||
this.setMenuResolutionIfEmpty();
|
||||
this.loading = false;
|
||||
});
|
||||
} else {
|
||||
this.setMenuResolutionIfEmpty();
|
||||
this.loading = false;
|
||||
}
|
||||
}).catch(error => {
|
||||
|
|
@ -156,6 +159,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
ogLive: unit.networkSettings?.ogLive?.['@id'],
|
||||
pxeTemplate: unit.networkSettings?.pxeTemplate?.['@id'],
|
||||
menu: unit.networkSettings?.menu?.['@id'],
|
||||
resolution: unit.networkSettings?.resolution || null,
|
||||
mcastIp: unit.networkSettings?.mcastIp,
|
||||
mcastSpeed: unit.networkSettings?.mcastSpeed,
|
||||
mcastPort: unit.networkSettings?.mcastPort,
|
||||
|
|
@ -192,14 +196,12 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
setOrganizationalUnitDefaults(unitId: string): void {
|
||||
const selectedUnit: any = this.parentUnitsWithPaths.find(unit => unit.id === unitId);
|
||||
const exclude = this.generalFormGroup.get('excludeParentChanges')?.value;
|
||||
if (selectedUnit && !exclude) {
|
||||
if (selectedUnit && !exclude) {
|
||||
this.networkSettingsFormGroup.patchValue({
|
||||
repository: selectedUnit.repository || null,
|
||||
bootServer: selectedUnit.bootServer || null,
|
||||
hardwareProfile: selectedUnit.hardwareProfile || null,
|
||||
ogLive: selectedUnit.ogLive || null,
|
||||
pxeTemplate: selectedUnit.pxeTemplate || null,
|
||||
menu: selectedUnit.menu || null,
|
||||
mcastIp: selectedUnit.mcastIp || null,
|
||||
mcastSpeed: selectedUnit.mcastSpeed || null,
|
||||
mcastPort: selectedUnit.mcastPort || null,
|
||||
|
|
@ -210,7 +212,10 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
dns: selectedUnit.dns || null,
|
||||
netmask: selectedUnit.netmask || null,
|
||||
router: selectedUnit.router || null,
|
||||
ntp: selectedUnit.ntp || null
|
||||
ntp: selectedUnit.ntp || null,
|
||||
menu: selectedUnit.menu || null,
|
||||
resolution: selectedUnit.resolution || null,
|
||||
hardwareProfile: selectedUnit.hardwareProfile || null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -239,11 +244,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
excludeParentChanges: data.excludeParentChanges
|
||||
});
|
||||
|
||||
this.additionalInfoFormGroup.patchValue({
|
||||
comments: data.comments
|
||||
});
|
||||
|
||||
// Patch all network fields except ogLive and pxeTemplate
|
||||
// Patch all network fields except ogLive and pxeTemplate
|
||||
this.networkSettingsFormGroup.patchValue({
|
||||
proxy: data.networkSettings?.proxy,
|
||||
dns: data.networkSettings?.dns,
|
||||
|
|
@ -257,10 +258,15 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
mcastSpeed: data.networkSettings?.mcastSpeed,
|
||||
mcastPort: data.networkSettings?.mcastPort,
|
||||
mcastMode: data.networkSettings?.mcastMode,
|
||||
menu: data.networkSettings?.menu ? data.networkSettings.menu['@id'] : null,
|
||||
bootServer: bootServerIri,
|
||||
repository: data.networkSettings?.repository ? data.networkSettings.repository['@id'] : null,
|
||||
menu: data.networkSettings?.menu ? data.networkSettings.menu['@id'] : null,
|
||||
resolution: data.networkSettings?.resolution ? String(data.networkSettings.resolution) : null,
|
||||
hardwareProfile: data.networkSettings?.hardwareProfile ? data.networkSettings.hardwareProfile['@id'] : null,
|
||||
repository: data.networkSettings?.repository ? data.networkSettings.repository['@id'] : null
|
||||
});
|
||||
|
||||
this.additionalInfoFormGroup.patchValue({
|
||||
comments: data.comments
|
||||
});
|
||||
|
||||
this.classroomInfoFormGroup.patchValue({
|
||||
|
|
@ -304,8 +310,8 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
const confirmRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '400px',
|
||||
data: {
|
||||
title : this.translate.instant('propagateParameters'),
|
||||
message : this.translate.instant('youWantToPropagateTheParametersOf'),
|
||||
title: this.translate.instant('propagateParameters'),
|
||||
message: this.translate.instant('youWantToPropagateTheParametersOf'),
|
||||
confirmText: 'Sí, propagar',
|
||||
cancelText: 'No, solo guardar',
|
||||
}
|
||||
|
|
@ -323,7 +329,8 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
private submitForm(propagate: boolean) {
|
||||
const parentValue = this.generalFormGroup.value.parent;
|
||||
|
||||
const networkSettings = { ...this.networkSettingsFormGroup.value };
|
||||
const networkSettings = { ...this.networkSettingsFormGroup.value };
|
||||
|
||||
if (networkSettings.p2pMode !== 'seeder') {
|
||||
networkSettings.p2pTime = null;
|
||||
}
|
||||
|
|
@ -334,7 +341,7 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
parent: parentValue || null,
|
||||
description: this.generalFormGroup.value.description,
|
||||
comments: this.additionalInfoFormGroup.value.comments,
|
||||
remoteCalendar: this.generalFormGroup.value.remoteCalendar,
|
||||
remoteCalendar: this.classroomInfoFormGroup.value.remoteCalendar,
|
||||
type: this.generalFormGroup.value.type,
|
||||
networkSettings: networkSettings,
|
||||
location: this.classroomInfoFormGroup.value.location,
|
||||
|
|
@ -491,8 +498,6 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
// loadPxeTemplates and loadOgLives removed: resources are now loaded on-demand per BootServer
|
||||
|
||||
loadMenus(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `${this.baseUrl}/menus?page=1&itemsPerPage=10000`;
|
||||
|
|
@ -544,20 +549,47 @@ export class ManageOrganizationalUnitComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
setMenuResolutionIfEmpty(): void {
|
||||
const selectedMenuId = this.networkSettingsFormGroup.get('menu')?.value;
|
||||
const currentResolution = this.networkSettingsFormGroup.get('resolution')?.value;
|
||||
|
||||
if (selectedMenuId && !currentResolution) {
|
||||
const selectedMenu = this.menus.find(menu => menu['@id'] === selectedMenuId);
|
||||
if (selectedMenu && selectedMenu.resolution) {
|
||||
this.networkSettingsFormGroup.patchValue({
|
||||
resolution: String(selectedMenu.resolution)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMenuChange(event: any): void {
|
||||
// Only pre-fill if resolution is empty
|
||||
const currentResolution = this.networkSettingsFormGroup.get('resolution')?.value;
|
||||
if (!currentResolution) {
|
||||
const selectedMenu = this.menus.find(menu => menu['@id'] === event.value);
|
||||
if (selectedMenu && selectedMenu.resolution) {
|
||||
this.networkSettingsFormGroup.patchValue({
|
||||
resolution: String(selectedMenu.resolution)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onCalendarChange(event: any) {
|
||||
this.generalFormGroup.value.remoteCalendar = event.value;
|
||||
this.classroomInfoFormGroup.patchValue({ remoteCalendar: event.value });
|
||||
}
|
||||
|
||||
onOgLiveChange(event: any) {
|
||||
this.networkSettingsFormGroup.value.ogLive = event.value;
|
||||
this.networkSettingsFormGroup.patchValue({ ogLive: event.value });
|
||||
}
|
||||
|
||||
onRepositoryChange(event: any) {
|
||||
this.networkSettingsFormGroup.value.repository = event.value;
|
||||
this.networkSettingsFormGroup.patchValue({ repository: event.value });
|
||||
}
|
||||
|
||||
onPxeTemplateChange(event: any) {
|
||||
this.networkSettingsFormGroup.value.pxeTemplate = event.value;
|
||||
this.networkSettingsFormGroup.patchValue({ pxeTemplate: event.value });
|
||||
}
|
||||
|
||||
onNoClick(): void {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,118 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Directorios base: buscará en todo ./src y modificará los JSON de ./src/locale
|
||||
const srcDir = __dirname+"/src";
|
||||
const localeDir = path.join(srcDir, 'locale');
|
||||
|
||||
// Expresiones regulares para capturar las claves de traducción
|
||||
const regexes = [
|
||||
// Captura: 'mi.clave' | translate O "mi.clave" | translate
|
||||
/['"]([^'"]+)['"]\s*\|\s*translate/g,
|
||||
// Captura: translate="mi.clave" O translate='mi.clave'
|
||||
/translate\s*=\s*['"]([^'"]+)['"]/g,
|
||||
// Captura: translate.instant('mi.clave') O translate.instant("mi.clave")
|
||||
/translate\.instant\(\s*['"]([^'"]+)['"]/g,
|
||||
// Captura: [translate]="'mi.clave'"
|
||||
/\[translate\]\s*=\s*['"]'([^']+)'['"]/g,
|
||||
// Captura: [translate]='"mi.clave"'
|
||||
/\[translate\]\s*=\s*['"]"([^"]+)"['"]/g
|
||||
];
|
||||
|
||||
/**
|
||||
* Función recursiva para obtener todos los archivos con las extensiones deseadas
|
||||
*/
|
||||
function getFiles(dir, exts, fileList = []) {
|
||||
const files = fs.readdirSync(dir);
|
||||
for (const file of files) {
|
||||
const filePath = path.join(dir, file);
|
||||
if (fs.statSync(filePath).isDirectory()) {
|
||||
getFiles(filePath, exts, fileList);
|
||||
} else {
|
||||
if (exts.includes(path.extname(filePath))) {
|
||||
fileList.push(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrae todas las claves únicas usando las expresiones regulares
|
||||
*/
|
||||
function extractKeys() {
|
||||
const files = getFiles(srcDir, ['.ts', '.html']);
|
||||
const keys = new Set();
|
||||
|
||||
files.forEach(file => {
|
||||
const content = fs.readFileSync(file, 'utf8');
|
||||
regexes.forEach(regex => {
|
||||
let match;
|
||||
while ((match = regex.exec(content)) !== null) {
|
||||
const key = match[1];
|
||||
if (key && key.trim() !== '') {
|
||||
keys.add(key.trim());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return Array.from(keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza y ordena los archivos de idiomas
|
||||
*/
|
||||
function updateLocales(extractedKeys) {
|
||||
if (!fs.existsSync(localeDir)) {
|
||||
console.error('No se pudo encontrar el directorio de traducciones:', localeDir);
|
||||
return;
|
||||
}
|
||||
|
||||
const localeFiles = fs.readdirSync(localeDir).filter(f => f.endsWith('.json'));
|
||||
|
||||
localeFiles.forEach(file => {
|
||||
const filePath = path.join(localeDir, file);
|
||||
let localeData = {};
|
||||
|
||||
try {
|
||||
localeData = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
} catch (e) {
|
||||
console.error(`Error al procesar el JSON en ${file}:`, e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
let addedCount = 0;
|
||||
|
||||
// Añadir claves faltantes
|
||||
extractedKeys.forEach(key => {
|
||||
if (!localeData.hasOwnProperty(key)) {
|
||||
localeData[key] = key; // Usa la propia clave como valor
|
||||
addedCount++;
|
||||
}
|
||||
});
|
||||
|
||||
// Ordenar alfabéticamente todas las claves
|
||||
const sortedData = {};
|
||||
Object.keys(localeData)
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
.forEach(k => {
|
||||
sortedData[k] = localeData[k];
|
||||
});
|
||||
|
||||
// Guardar el fichero de nuevo
|
||||
fs.writeFileSync(filePath, JSON.stringify(sortedData, null, 4) + '\n', 'utf8');
|
||||
console.log(`[${file}] Actualizado. Agregadas ${addedCount} claves nuevas. Fichero ordenado alfabéticamente.`);
|
||||
});
|
||||
}
|
||||
|
||||
function run() {
|
||||
console.log('Buscando claves de traducción en archivos .ts y .html...');
|
||||
const keys = extractKeys();
|
||||
console.log(`Se encontraron ${keys.length} claves únicas en el código.`);
|
||||
console.log('Actualizando diccionarios...');
|
||||
updateLocales(keys);
|
||||
console.log('¡Proceso completado exitosamente!');
|
||||
}
|
||||
|
||||
run();
|
||||
Loading…
Reference in New Issue