diff --git a/CHANGELOG.md b/CHANGELOG.md index 957d75f..519a19f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [1.14.3] - 2026-10-09 + +### Fixed +- **UI/UX (Componentes Genéricos)**: Solucionado un problema de regresión introducido en la versión 1.14.2 donde múltiples componentes de creación y edición (Crear/Editar Tarea, Usuarios, Aula, Cliente, Crear Múltiples Clientes y Mover Clientes) enviaban un identificador numérico en el payload en lugar del identificador URI (`@id`) esperado por el backend para las relaciones de `organizationalUnit`, provocando errores al intentar guardar. Ahora, estos componentes detectan automáticamente el identificador devuelto por el selector genérico y construyen la URI correcta antes de realizar la petición HTTP. + ## [1.14.2] - 2026-10-06 ### Fixed diff --git a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts index 9312390..61ee1e9 100644 --- a/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts +++ b/ogWebconsole/src/app/components/admin/users/users/add-user-modal/add-user-modal.component.ts @@ -122,9 +122,17 @@ export class AddUserModalComponent implements OnInit { onSubmit(): void { if (this.userForm.valid) { + const mappedOUs = (this.userForm.value.organizationalUnits || []).map((ou: any) => { + if (typeof ou === 'number' || (typeof ou === 'string' && !ou.includes('/'))) { + const selectedUnit = this.organizationalUnits.find((u: any) => u.id === Number(ou)); + return selectedUnit ? (selectedUnit['@id'] || `/organizational-units/${selectedUnit.uuid}`) : ou; + } + return ou; + }); + const payload: any = { username: this.userForm.value.username, - allowedOrganizationalUnits: this.userForm.value.organizationalUnits, + allowedOrganizationalUnits: mappedOUs, enabled: true, userGroups: [this.userForm.value.role], groupsView: this.userForm.value.groupsView, diff --git a/ogWebconsole/src/app/components/commands/commands-task/create-task/create-task.component.ts b/ogWebconsole/src/app/components/commands/commands-task/create-task/create-task.component.ts index 5602349..4a5350e 100644 --- a/ogWebconsole/src/app/components/commands/commands-task/create-task/create-task.component.ts +++ b/ogWebconsole/src/app/components/commands/commands-task/create-task/create-task.component.ts @@ -281,7 +281,12 @@ export class CreateTaskComponent implements OnInit { payload.clients = this.selectedClients.map(client => client['@id'] ? client['@id'] : client.uuid); payload.organizationalUnit = null; } else { - payload.organizationalUnit = formData.organizationalUnit; + let ou = formData.organizationalUnit; + if (typeof ou === 'number' || (typeof ou === 'string' && !ou.includes('/'))) { + const selectedUnit = this.availableOrganizationalUnits.find((u: any) => u.id === Number(ou)); + ou = selectedUnit ? (selectedUnit['@id'] || `/organizational-units/${selectedUnit.uuid}`) : ou; + } + payload.organizationalUnit = ou; } if (this.editing) { diff --git a/ogWebconsole/src/app/components/groups/shared/change-parent/change-parent.component.ts b/ogWebconsole/src/app/components/groups/shared/change-parent/change-parent.component.ts index 10a1fbf..338a3ad 100644 --- a/ogWebconsole/src/app/components/groups/shared/change-parent/change-parent.component.ts +++ b/ogWebconsole/src/app/components/groups/shared/change-parent/change-parent.component.ts @@ -52,8 +52,11 @@ export class ChangeParentComponent implements OnInit { } save() { - const selectedUnit = this.units.find(u => u.id === this.newOU || u['@id'] === this.newOU); - const unitIri = selectedUnit ? selectedUnit['@id'] : (typeof this.newOU === 'number' ? `/api/organizational_units/${this.newOU}` : this.newOU); + let unitIri = this.newOU; + if (typeof this.newOU === 'number' || (typeof this.newOU === 'string' && !this.newOU.includes('/'))) { + const selectedUnit = this.units.find(u => u.id === Number(this.newOU)); + unitIri = selectedUnit ? (selectedUnit['@id'] || `/organizational-units/${selectedUnit.uuid}`) : this.newOU; + } this.http.post(`${this.baseUrl}/clients/change-organizational-unit`, { clients: this.data.clients.map((client: any) => client['@id']), diff --git a/ogWebconsole/src/app/components/groups/shared/clients/create-multiple-client/create-multiple-client.component.ts b/ogWebconsole/src/app/components/groups/shared/clients/create-multiple-client/create-multiple-client.component.ts index af0a3da..a503a1e 100644 --- a/ogWebconsole/src/app/components/groups/shared/clients/create-multiple-client/create-multiple-client.component.ts +++ b/ogWebconsole/src/app/components/groups/shared/clients/create-multiple-client/create-multiple-client.component.ts @@ -130,9 +130,15 @@ export class CreateMultipleClientComponent implements OnInit { let successCount = 0; let errorMessages: string[] = []; + let ou = this.organizationalUnit; + if (typeof ou === 'number' || (typeof ou === 'string' && !ou.includes('/'))) { + const selectedUnit = this.parentUnits.find((u: any) => u.id === Number(ou)); + ou = selectedUnit ? (selectedUnit['@id'] || `/organizational-units/${selectedUnit.uuid}`) : ou; + } + this.uploadedClients.forEach(client => { const formData = { - organizationalUnit: this.organizationalUnit, + organizationalUnit: ou, name: client.name || null, mac: client.mac || null, ip: client.ip || null, diff --git a/ogWebconsole/src/app/components/groups/shared/clients/manage-client/manage-client.component.ts b/ogWebconsole/src/app/components/groups/shared/clients/manage-client/manage-client.component.ts index 5398c0b..f2f2206 100644 --- a/ogWebconsole/src/app/components/groups/shared/clients/manage-client/manage-client.component.ts +++ b/ogWebconsole/src/app/components/groups/shared/clients/manage-client/manage-client.component.ts @@ -345,7 +345,14 @@ export class ManageClientComponent implements OnInit { onSubmit(): void { if (this.clientForm.valid) { - const formData = this.clientForm.value; + const formData = { ...this.clientForm.value }; + + let ou = formData.organizationalUnit; + if (typeof ou === 'number' || (typeof ou === 'string' && !ou.includes('/'))) { + const selectedUnit = this.parentUnits.find((u: any) => u.id === Number(ou)); + ou = selectedUnit ? (selectedUnit['@id'] || `/organizational-units/${selectedUnit.uuid}`) : ou; + } + formData.organizationalUnit = ou; if (this.isEditMode) { const putUrl = `${this.baseUrl}/clients/${this.data.uuid}`; diff --git a/ogWebconsole/src/app/components/groups/shared/organizational-units/manage-organizational-unit/manage-organizational-unit.component.ts b/ogWebconsole/src/app/components/groups/shared/organizational-units/manage-organizational-unit/manage-organizational-unit.component.ts index c3ae2d6..a65eb91 100644 --- a/ogWebconsole/src/app/components/groups/shared/organizational-units/manage-organizational-unit/manage-organizational-unit.component.ts +++ b/ogWebconsole/src/app/components/groups/shared/organizational-units/manage-organizational-unit/manage-organizational-unit.component.ts @@ -341,7 +341,11 @@ export class ManageOrganizationalUnitComponent implements OnInit { } private submitForm(propagate: boolean) { - const parentValue = this.generalFormGroup.value.parent; + let parentValue = this.generalFormGroup.value.parent; + if (typeof parentValue === 'number' || (typeof parentValue === 'string' && !parentValue.includes('/'))) { + const selectedUnit = this.parentUnits.find(u => u.id === Number(parentValue)); + parentValue = selectedUnit ? (selectedUnit['@id'] || `/organizational-units/${selectedUnit.uuid}`) : parentValue; + } const networkSettings = { ...this.networkSettingsFormGroup.value }; diff --git a/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.ts b/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.ts index 1a635a3..88d7271 100644 --- a/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.ts +++ b/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.ts @@ -133,7 +133,14 @@ export class PxeBootFilesComponent implements OnInit { } loadChildUnits(event: any) { - this.selectedUnit = event.value; + let unitId = event.value; + if (typeof event.value === 'object' && event.value !== null) { + unitId = event.value.id; + } else if (typeof event.value === 'string' && event.value.includes('/')) { + unitId = event.value.split('/').pop(); + } + + this.selectedUnit = this.units.find(u => u.id == unitId || u['@id'] === event.value) || event.value; this.refreshClientList(); } diff --git a/ogWebconsole/src/app/components/ogdhcp/add-clients-to-subnet/add-clients-to-subnet.component.ts b/ogWebconsole/src/app/components/ogdhcp/add-clients-to-subnet/add-clients-to-subnet.component.ts index 8824e39..b59278a 100644 --- a/ogWebconsole/src/app/components/ogdhcp/add-clients-to-subnet/add-clients-to-subnet.component.ts +++ b/ogWebconsole/src/app/components/ogdhcp/add-clients-to-subnet/add-clients-to-subnet.component.ts @@ -65,7 +65,13 @@ export class AddClientsToSubnetComponent implements OnInit { loadChildUnits(event: any) { - const unitId = typeof event.value === 'string' && event.value.includes('/') ? event.value.split('/').pop() : event.value; + let unitId = event.value; + if (typeof event.value === 'object' && event.value !== null) { + unitId = event.value.id; + } else if (typeof event.value === 'string' && event.value.includes('/')) { + unitId = event.value.split('/').pop(); + } + this.http.get(`${this.baseUrl}/clients?organizationalUnit.id=${unitId}&exists[subnet]=false`).subscribe( response => { this.clients = response['hydra:member']; diff --git a/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.ts b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.ts index 4d5a8ec..b878a9a 100644 --- a/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.ts +++ b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.ts @@ -69,9 +69,10 @@ export class OuSelectComponent implements ControlValueAccessor { getSelectedName(): string { if (this.multiple) { if (!this.value || !Array.isArray(this.value)) return ''; - return this.units.filter(u => this.value.includes(u['@id'] || u.id)).map(u => u.name).join(', '); + return this.units.filter(u => this.value.includes(u['@id'] || u.id)).map(u => u.path || u.name).join(', '); } else { - return this.units.find(u => (u['@id'] || u.id) === this.value)?.name || ''; + const selectedUnit = this.units.find(u => (u['@id'] || u.id) === this.value); + return selectedUnit ? (selectedUnit.path || selectedUnit.name) : ''; } } }