diff --git a/CHANGELOG.md b/CHANGELOG.md index ecb1c29c..ab179434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ All notable changes to this project will be documented in this file. The format ### Fixed +- **About**: The About window shows the installed API SITNA version and the installed OpenLayers version. Both values are read from the installed packages when the viewer is built ([#218](https://github.com/sitmun/sitmun-viewer-app/issues/218)). - **Map**: A WFS row in Loaded Layers uses the root folder as its heading, the same folder path as a WMS row, and the leaf name as its title. The toolbar overflow control shows › when the extra tools are hidden and ‹ when they are open, on every Loaded Layers row that has that control. - **Map**: A WFS entry in the legend lists the root folder and each intermediate folder above the layer, the same way a WMS legend does. The point swatch stays on the layer. - **Map**: An identify field with format Image keeps the original address and SITNA's `img.tc-img-attr`. `maxWidth` and `maxHeight` on the field set those limits. A field without them stays `width:auto;height:auto`. diff --git a/README.md b/README.md index 45d3ff5e..9560cd38 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ This frontend integrates with the [SITMUN Backend Core](https://github.com/sitmu - Internationalization (CA, ES, EN, FR) - Configurable UI components - Lazy loading and efficient rendering -- SITNA integration (api-sitna 4.8.0) +- SITNA integration (api-sitna 4.9.1, OpenLayers 10.5.0) - Service Worker for API auth token forwarding ## Quick Start @@ -453,7 +453,10 @@ The application uses the **SITNA (Sistema de Información Territorial de Navarra **Version Information:** -- **SITNA API Version**: Aligned with api-sitna 4.8.0 +- **SITNA API Version**: api-sitna 4.9.1 +- **OpenLayers**: 10.5.0, the version api-sitna 4.9.1 depends on + +The About window reads both versions from the installed packages when the viewer is built. #### **Core Mapping Features** @@ -581,7 +584,7 @@ src/ - **Modular Design**: Feature-based module organization - **Reactive Programming**: RxJS for asynchronous operations - **Material Design**: Angular Material for consistent UI -- **SITNA Integration**: Advanced mapping through SITNA library (api-sitna 4.8.0) +- **SITNA Integration**: Advanced mapping through SITNA library (api-sitna 4.9.1, OpenLayers 10.5.0) ## Contributing diff --git a/src/app/ui/components/about-dialog/about-dialog.component.html b/src/app/ui/components/about-dialog/about-dialog.component.html index bafc9f4d..d3ef76fd 100644 --- a/src/app/ui/components/about-dialog/about-dialog.component.html +++ b/src/app/ui/components/about-dialog/about-dialog.component.html @@ -40,17 +40,25 @@

{{ 'systemInfo.about' | translate }}

- @if (data.sitnaVersion) { -
- map -
- - {{ 'systemInfo.sitnaVersion' | translate }}: - - {{ data.sitnaVersion }} -
+
+ map +
+ + {{ 'systemInfo.sitnaVersion' | translate }}: + + {{ data.sitnaVersion }}
- } +
+ +
+ layers +
+ + {{ 'systemInfo.openLayersVersion' | translate }}: + + {{ data.openLayersVersion }} +
+
@if (data.buildTimestamp) {
diff --git a/src/app/ui/components/about-dialog/about-dialog.component.ts b/src/app/ui/components/about-dialog/about-dialog.component.ts index 7781f38c..4cc3b751 100644 --- a/src/app/ui/components/about-dialog/about-dialog.component.ts +++ b/src/app/ui/components/about-dialog/about-dialog.component.ts @@ -7,13 +7,10 @@ export interface AboutDialogData { environmentName: string; angularVersion: string; buildTimestamp?: string; - sitnaVersion?: string; + sitnaVersion: string; + openLayersVersion: string; } -/** - * Component for displaying application information dialog. - * TODO: Add unit tests (about-dialog.component.spec.ts) - */ @Component({ standalone: false, selector: 'app-about-dialog', diff --git a/src/app/ui/components/about-dialog/library-versions.ts b/src/app/ui/components/about-dialog/library-versions.ts new file mode 100644 index 00000000..fe2a9f4e --- /dev/null +++ b/src/app/ui/components/about-dialog/library-versions.ts @@ -0,0 +1,5 @@ +import sitnaPackage from 'api-sitna/package.json'; +import olPackage from 'ol/package.json'; + +export const sitnaVersion: string = sitnaPackage.version; +export const openLayersVersion: string = olPackage.version; diff --git a/src/app/ui/components/menu/menu.component.spec.ts b/src/app/ui/components/menu/menu.component.spec.ts index 096d008d..4467ebd1 100644 --- a/src/app/ui/components/menu/menu.component.spec.ts +++ b/src/app/ui/components/menu/menu.component.spec.ts @@ -1,3 +1,6 @@ +import { readFileSync } from 'fs'; +import { join } from 'path'; + import { NgOptimizedImage } from '@angular/common'; import { provideHttpClient } from '@angular/common/http'; import { provideHttpClientTesting } from '@angular/common/http/testing'; @@ -17,6 +20,17 @@ import { AuthenticationService } from '@auth/services/authentication.service'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { MenuComponent } from './menu.component'; +import { AboutDialogComponent } from '../about-dialog/about-dialog.component'; + +function installedPackageVersion(name: string): string { + const manifest = JSON.parse( + readFileSync( + join(process.cwd(), 'node_modules', name, 'package.json'), + 'utf8' + ) + ) as { version: string }; + return manifest.version; +} describe('MenuComponent', () => { let component: MenuComponent; @@ -24,7 +38,7 @@ describe('MenuComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [MenuComponent], + declarations: [MenuComponent, AboutDialogComponent], imports: [ BrowserAnimationsModule, NgOptimizedImage, @@ -92,4 +106,31 @@ describe('MenuComponent', () => { it('should initialize with default language', () => { expect(component.currentLang).toBe('en'); }); + + it('shows the installed SITNA and OpenLayers versions in About', () => { + const translate = TestBed.inject(TranslateService); + translate.setTranslation('en', { + 'systemInfo.about': 'About', + 'systemInfo.application': 'Application', + 'systemInfo.applicationName': 'Visualizador SITMUN', + 'systemInfo.version': 'Version', + 'systemInfo.environment': 'Environment', + 'systemInfo.angularVersion': 'Angular Version', + 'systemInfo.sitnaVersion': 'API SITNA Version', + 'systemInfo.openLayersVersion': 'OpenLayers Version', + 'common.button.close': 'Close' + }); + translate.use('en'); + + component.openAboutDialog(); + fixture.detectChanges(); + + const text = (document.body.textContent ?? '').replace(/\s+/g, ' '); + expect(text).toContain( + `API SITNA Version: ${installedPackageVersion('api-sitna')}` + ); + expect(text).toContain( + `OpenLayers Version: ${installedPackageVersion('ol')}` + ); + }); }); diff --git a/src/app/ui/components/menu/menu.component.ts b/src/app/ui/components/menu/menu.component.ts index 3a4c32d8..74d449b0 100644 --- a/src/app/ui/components/menu/menu.component.ts +++ b/src/app/ui/components/menu/menu.component.ts @@ -29,6 +29,10 @@ import { AboutDialogComponent, AboutDialogData } from '../about-dialog/about-dialog.component'; +import { + openLayersVersion, + sitnaVersion +} from '../about-dialog/library-versions'; @Component({ standalone: false, @@ -182,7 +186,8 @@ export class MenuComponent implements OnInit, OnDestroy { environmentName: this.environment.environmentName || 'N/A', angularVersion: this.angularVersion, buildTimestamp: (this.environment as any).buildTimestamp, - sitnaVersion: this.environment.sitnaVersion + sitnaVersion, + openLayersVersion }; this.dialog.open(AboutDialogComponent, { diff --git a/src/assets/i18n/ca.json b/src/assets/i18n/ca.json index 5636e263..6f9f194a 100644 --- a/src/assets/i18n/ca.json +++ b/src/assets/i18n/ca.json @@ -278,6 +278,7 @@ "systemInfo.errorType.logger": "Error d'aplicació", "systemInfo.errorType.uncaught": "Excepció no capturada", "systemInfo.noErrors": "No hi ha errors registrats", + "systemInfo.openLayersVersion": "Versió d'OpenLayers", "systemInfo.recentErrors": "Errors recents", "systemInfo.sitnaVersion": "Versió API SITNA", "systemInfo.version": "Versió", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 6cd23abf..777afe3c 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -278,6 +278,7 @@ "systemInfo.errorType.logger": "Application Error", "systemInfo.errorType.uncaught": "Uncaught Exception", "systemInfo.noErrors": "No errors recorded", + "systemInfo.openLayersVersion": "OpenLayers Version", "systemInfo.recentErrors": "Recent Errors", "systemInfo.sitnaVersion": "API SITNA Version", "systemInfo.version": "Version", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index 01cee2e3..b8c06b9e 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -278,6 +278,7 @@ "systemInfo.errorType.logger": "Error de Aplicación", "systemInfo.errorType.uncaught": "Excepción No Capturada", "systemInfo.noErrors": "No hay errores registrados", + "systemInfo.openLayersVersion": "Versión de OpenLayers", "systemInfo.recentErrors": "Errores Recientes", "systemInfo.sitnaVersion": "Versión API SITNA", "systemInfo.version": "Versión", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 16a076cc..3d0fbe2c 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -278,6 +278,7 @@ "systemInfo.errorType.logger": "Erreur d'application", "systemInfo.errorType.uncaught": "Exception non interceptée", "systemInfo.noErrors": "Aucune erreur enregistrée", + "systemInfo.openLayersVersion": "Version d'OpenLayers", "systemInfo.recentErrors": "Erreurs récentes", "systemInfo.sitnaVersion": "Version API SITNA", "systemInfo.version": "Version", diff --git a/src/assets/i18n/oc-aranes.json b/src/assets/i18n/oc-aranes.json index 7e3b2fb4..926535d5 100644 --- a/src/assets/i18n/oc-aranes.json +++ b/src/assets/i18n/oc-aranes.json @@ -278,6 +278,7 @@ "systemInfo.errorType.logger": "Error d'aplicacion", "systemInfo.errorType.uncaught": "Excepcion no capturada", "systemInfo.noErrors": "Non i a errors registrats", + "systemInfo.openLayersVersion": "Versió OpenLayers", "systemInfo.recentErrors": "Errors recents", "systemInfo.sitnaVersion": "Versió API SITNA", "systemInfo.version": "Versió", diff --git a/src/environments/environment.e2e.ts b/src/environments/environment.e2e.ts index 61bfbc87..54d76257 100644 --- a/src/environments/environment.e2e.ts +++ b/src/environments/environment.e2e.ts @@ -8,7 +8,6 @@ export const environment = { apiUrl: '/backend', version: '1.2.9', environmentName: 'E2E', - sitnaVersion: '4.8.0', buildTimestamp: new Date().toISOString(), loginBackgroundImageUrl: '', proxyTokenRefreshIntervalMs: 10 * 60 * 1000, diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index dffa2dca..04564562 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -9,7 +9,6 @@ export const environment = { apiUrl: '/backend', // Change this when there is a real production environment version: '1.2.9', environmentName: 'Production', - sitnaVersion: '4.8.0', buildTimestamp: new Date().toISOString(), loginBackgroundImageUrl: 'assets/logos/barcelona_background.jpg', proxyTokenRefreshIntervalMs: 2 * 60 * 1000, diff --git a/src/environments/environment.ts b/src/environments/environment.ts index b0250eec..aacffb1e 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -9,7 +9,6 @@ export const environment = { apiUrl: 'http://localhost:9000/backend', version: '1.2.9', environmentName: 'Development', - sitnaVersion: '4.8.0', buildTimestamp: new Date().toISOString(), loginBackgroundImageUrl: 'assets/logos/barcelona_background.jpg', proxyTokenRefreshIntervalMs: 2 * 60 * 1000, diff --git a/tsconfig.json b/tsconfig.json index c984541e..3cbbdc4a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,7 @@ "moduleResolution": "bundler", "importHelpers": true, "esModuleInterop": true, + "resolveJsonModule": true, "target": "ES2022", "module": "es2020", "types": ["node"],