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 @@
-
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"],