From 5abc70512263a3b5fdc1e9a0cacaf2cb6dbbdebd Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Tue, 20 Oct 2026 09:56:31 +0200 Subject: [PATCH 1/2] fix(admin): restore AG Grid 32 editors and language default URL Register CommunityFeaturesModule so date/text cell editors mount again. Build language.default and language-default API URLs without a double slash so Spring Security 7 stops 401ing findByName. --- CHANGELOG.md | 2 ++ .../literal-translations.component.ts | 12 ++++++++++-- .../domain/translation/services/language.service.ts | 11 ++++++++--- .../src/lib/data-grid/data-grid.component.ts | 7 ++++--- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8de6afe5..5ed8e0d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- **Languages**: Set as Default no longer stays disabled after open. Default-language lookups use a single `/api/` slash so Spring Security 7 accepts `findByName`. +- **Grids**: AG Grid 32 registers `CommunityFeaturesModule` so date and text cell editors mount again (Positions Alta/Baja inline edit). - **Tests**: Jest specs match Angular 22 realities (`ng-reflect-*` opt-in, HostListener rename, `@if (; as)` syntax, jsdom Location, FileReader under Node 24) and use a 30s default timeout. - **Layers**: An Image feature-information field stores max width and max height in its options. The picture address stays unchanged. diff --git a/src/app/components/literal-translations/literal-translations/literal-translations.component.ts b/src/app/components/literal-translations/literal-translations/literal-translations.component.ts index e0ef67fa..7ad548fa 100644 --- a/src/app/components/literal-translations/literal-translations/literal-translations.component.ts +++ b/src/app/components/literal-translations/literal-translations/literal-translations.component.ts @@ -6,7 +6,15 @@ import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; import { AgGridModule } from '@ag-grid-community/angular'; -import { CellClickedEvent, ColDef, FilterChangedEvent, GridApi, GridReadyEvent, ModuleRegistry } from '@ag-grid-community/core'; +import { + CellClickedEvent, + ColDef, + CommunityFeaturesModule, + FilterChangedEvent, + GridApi, + GridReadyEvent, + ModuleRegistry, +} from '@ag-grid-community/core'; import { InfiniteRowModelModule } from '@ag-grid-community/infinite-row-model'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { debounceTime, forkJoin, tap } from 'rxjs'; @@ -35,7 +43,7 @@ import { import { filterEnabledLanguages } from '@app/services/ui-language.resolver'; import { config } from '@config'; -ModuleRegistry.registerModules([InfiniteRowModelModule]); +ModuleRegistry.registerModules([CommunityFeaturesModule, InfiniteRowModelModule]); @Component({ selector: 'app-literal-translations', diff --git a/src/app/domain/translation/services/language.service.ts b/src/app/domain/translation/services/language.service.ts index f94b9d6d..4cf2faca 100644 --- a/src/app/domain/translation/services/language.service.ts +++ b/src/app/domain/translation/services/language.service.ts @@ -89,7 +89,7 @@ export class LanguageService extends RestService { */ getCurrentDefaultLanguage(): Observable { return new Observable(observer => { - this.http.get<{ value: string }>(`${this.resourceService.getResourceUrl()}/configuration-parameters/search/findByName?name=language.default`) + this.http.get<{ value: string }>(this.apiUrl('configuration-parameters/search/findByName?name=language.default')) .subscribe({ next: (config) => { observer.next(config.value); @@ -105,7 +105,7 @@ export class LanguageService extends RestService { */ previewDefaultLanguageChange(from: string, to: string): Observable { return this.http.post( - `${this.resourceService.getResourceUrl()}/language-default/change-preview`, + this.apiUrl('language-default/change-preview'), { from, to }, {context: new HttpContext().set(SUPPRESS_HTTP_NOTIFICATION, true)} ); @@ -116,9 +116,14 @@ export class LanguageService extends RestService { */ applyDefaultLanguageChange(request: DefaultLanguageChangeRequest): Observable { return this.http.post( - `${this.resourceService.getResourceUrl()}/language-default/change`, + this.apiUrl('language-default/change'), request, {context: new HttpContext().set(SUPPRESS_HTTP_NOTIFICATION, true)} ); } + + /** Avoid `…/api//path` from getResourceUrl()'s trailing slash (401 under Spring Security 7). */ + private apiUrl(path: string): string { + return `${this.resourceService.getResourceUrl().replace(/\/$/, '')}/${path.replace(/^\//, '')}`; + } } diff --git a/src/app/frontend-gui/src/lib/data-grid/data-grid.component.ts b/src/app/frontend-gui/src/lib/data-grid/data-grid.component.ts index 02b52149..cf0b06fe 100644 --- a/src/app/frontend-gui/src/lib/data-grid/data-grid.component.ts +++ b/src/app/frontend-gui/src/lib/data-grid/data-grid.component.ts @@ -27,7 +27,7 @@ import {MatTooltipModule} from '@angular/material/tooltip'; import {AgGridModule} from '@ag-grid-community/angular'; import {ClientSideRowModelModule} from '@ag-grid-community/client-side-row-model'; -import {GridOptions, ModuleRegistry} from '@ag-grid-community/core'; +import {CommunityFeaturesModule, GridOptions, ModuleRegistry} from '@ag-grid-community/core'; import {CsvExportModule} from '@ag-grid-community/csv-export'; import {InfiniteRowModelModule} from '@ag-grid-community/infinite-row-model'; import {TranslateModule, TranslateService} from '@ngx-translate/core'; @@ -61,9 +61,10 @@ import {DialogMessageComponent} from '../dialog-message/dialog-message.component import {EditableLinkRendererComponent} from '../editable-link-renderer/editable-link-renderer.component'; import {RouterLinkRendererComponent} from '../router-link-renderer/router-link-renderer.component'; -// Removed jQuery dependency - +// AG Grid 32 moved editors/filters into CommunityFeaturesModule; without it, +// agDateStringCellEditor never mounts and Positions Alta/Baja stay read-only. ModuleRegistry.registerModules([ + CommunityFeaturesModule, ClientSideRowModelModule, InfiniteRowModelModule, CsvExportModule From 8bcd38f468995f2430c9dc875633b3799e019b9a Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Tue, 20 Oct 2026 11:09:21 +0200 Subject: [PATCH 2/2] fix(admin): use Instant-safe datePicker for AG Grid date columns agDateStringCellEditor crashes when HAL Instant ISO values make DataTypeModule infer cellDataType text. Restore datePicker and disable cellDataType inference so Positions Alta/Baja inline edit works on AG Grid 32. --- CHANGELOG.md | 2 +- .../frontend-gui/src/lib/data-grid/data-grid.component.ts | 3 ++- src/app/services/utils.service.ts | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ed8e0d9..cddb20ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - **Languages**: Set as Default no longer stays disabled after open. Default-language lookups use a single `/api/` slash so Spring Security 7 accepts `findByName`. -- **Grids**: AG Grid 32 registers `CommunityFeaturesModule` so date and text cell editors mount again (Positions Alta/Baja inline edit). +- **Grids**: AG Grid 32 registers `CommunityFeaturesModule` so text/select cell editors mount. Date columns use the Instant-safe `datePicker` editor with `cellDataType: false` so Positions Alta/Baja edit no longer throws in `DateStringCellEditor`. - **Tests**: Jest specs match Angular 22 realities (`ng-reflect-*` opt-in, HostListener rename, `@if (; as)` syntax, jsdom Location, FileReader under Node 24) and use a 30s default timeout. - **Layers**: An Image feature-information field stores max width and max height in its options. The picture address stays unchanged. diff --git a/src/app/frontend-gui/src/lib/data-grid/data-grid.component.ts b/src/app/frontend-gui/src/lib/data-grid/data-grid.component.ts index cf0b06fe..d5420298 100644 --- a/src/app/frontend-gui/src/lib/data-grid/data-grid.component.ts +++ b/src/app/frontend-gui/src/lib/data-grid/data-grid.component.ts @@ -62,7 +62,8 @@ import {EditableLinkRendererComponent} from '../editable-link-renderer/editable- import {RouterLinkRendererComponent} from '../router-link-renderer/router-link-renderer.component'; // AG Grid 32 moved editors/filters into CommunityFeaturesModule; without it, -// agDateStringCellEditor never mounts and Positions Alta/Baja stay read-only. +// inline editors never mount. Date columns still use the grid's datePicker +// component (Instant-safe); CommunityFeaturesModule covers text/select editors. ModuleRegistry.registerModules([ CommunityFeaturesModule, ClientSideRowModelModule, diff --git a/src/app/services/utils.service.ts b/src/app/services/utils.service.ts index dc0a1cf9..618f283a 100644 --- a/src/app/services/utils.service.ts +++ b/src/app/services/utils.service.ts @@ -434,6 +434,10 @@ export class UtilsService { filter: 'agDateColumnFilter', filterParams: this.getDateFilterParams(options), editable: editable ?? false, + // HAL Instant ISO strings are not AG Grid dateString (YYYY-MM-DD). Leaving + // cellDataType on lets DataTypeModule infer "text", then + // agDateStringCellEditor crashes: getDateParserFunction is not a function. + cellDataType: false, emptyValueKey: options?.emptyValueKey, headerTooltip: options?.headerTooltipKey ? this.getTranslate(options.headerTooltipKey) @@ -444,7 +448,8 @@ export class UtilsService { } return this.getDateFormated(data); }, - cellEditor: 'agDateStringCellEditor', + // Native datePicker parses Instant via Date(); agDateStringCellEditor does not. + cellEditor: 'datePicker', cellClass: (editable ?? false) ? null : 'read-only-cell' }; }