From 2d62b94c49f83b7d47b20f6e44d153bd045e5895 Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Sun, 27 Sep 2026 19:13:12 +0200 Subject: [PATCH 1/7] feat(profiles): add feature info field format columns Point the stack at the profile, admin, and viewer changes, and apply the same Liquibase columns on PostgreSQL, Oracle, and development. Closes #77 --- CHANGELOG.md | 18 +++ back/backend/sitmun-backend-core | 2 +- front/admin/sitmun-admin-app | 2 +- front/viewer/sitmun-viewer-app | 2 +- .../74_feature_info_field_format.yaml | 110 ++++++++++++++++++ .../development/backend/liquibase/master.xml | 1 + .../27_feature_info_field_format.yaml | 110 ++++++++++++++++++ profiles/oracle/liquibase/master.xml | 1 + .../27_feature_info_field_format.yaml | 110 ++++++++++++++++++ profiles/postgres/liquibase/master.xml | 1 + 10 files changed, 354 insertions(+), 3 deletions(-) create mode 100644 profiles/development/backend/liquibase/changelog/74_feature_info_field_format.yaml create mode 100644 profiles/oracle/liquibase/changelog/27_feature_info_field_format.yaml create mode 100644 profiles/postgres/liquibase/changelog/27_feature_info_field_format.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a3af59..778978f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Unreleased] +### Added + +#### Backend Core + +- **Profile**: Client profile layers publish ordered `featureInfoFields` for `INFO` cartography parameters. The list is omitted when empty. Labels come from `STM_TRANSLATION` on `CartographyParameter.value` ([sitmun-backend-core#268](https://github.com/sitmun/sitmun-backend-core/pull/268), [#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). + +#### Admin Application + +- **Layers**: The feature-information field grid is on the cartography form without the experimental query-layer flag. Labels translate per parameter. `N` and `P` edit fraction digits and padding. `F` chooses date or date and time. A WFS DescribeFeatureType request seeds top-level element names ([sitmun-admin-app#469](https://github.com/sitmun/sitmun-admin-app/pull/469), [#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). + +#### Viewer Application + +- **Map**: A non-empty field list replaces the full GetFeatureInfo property table, in order, with the translated label. `T`, `N`, `F`, `U`, `P`, and `I` follow the map locale. `AUTO` keeps API-SITNA detection. `feature.data` is not rewritten ([sitmun-viewer-app#179](https://github.com/sitmun/sitmun-viewer-app/pull/179), [#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). + +#### Profile-level + +- **Liquibase**: PostgreSQL and Oracle changelog 27, and development changelog 74, add `PGI_DIGITS`, `PGI_PAD`, `PGI_DATESTYLE`, and format code `AUTO` ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). + ### Fixed #### Stack-level diff --git a/back/backend/sitmun-backend-core b/back/backend/sitmun-backend-core index 6e1498f..f991b77 160000 --- a/back/backend/sitmun-backend-core +++ b/back/backend/sitmun-backend-core @@ -1 +1 @@ -Subproject commit 6e1498f3de7117cd3c75a79b99c39368149f9adf +Subproject commit f991b773d5c5718244015d43a8f2ffc4cefe7553 diff --git a/front/admin/sitmun-admin-app b/front/admin/sitmun-admin-app index 5d7dca2..9a941f4 160000 --- a/front/admin/sitmun-admin-app +++ b/front/admin/sitmun-admin-app @@ -1 +1 @@ -Subproject commit 5d7dca22360d77245a0df7858e570a96347ab1c9 +Subproject commit 9a941f4f26f19cb887e284eefc45425614aee28f diff --git a/front/viewer/sitmun-viewer-app b/front/viewer/sitmun-viewer-app index 32c7b08..ce08ba0 160000 --- a/front/viewer/sitmun-viewer-app +++ b/front/viewer/sitmun-viewer-app @@ -1 +1 @@ -Subproject commit 32c7b08591bf7613c87e64143896c5db07b2a435 +Subproject commit ce08ba00123d6f29dfc75de488e7b074f3d57ecb diff --git a/profiles/development/backend/liquibase/changelog/74_feature_info_field_format.yaml b/profiles/development/backend/liquibase/changelog/74_feature_info_field_format.yaml new file mode 100644 index 0000000..3705a6f --- /dev/null +++ b/profiles/development/backend/liquibase/changelog/74_feature_info_field_format.yaml @@ -0,0 +1,110 @@ +databaseChangeLog: + - changeSet: + id: 23-feature-info-field-columns-h2 + author: sitmun + dbms: h2 + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: INTEGER + - column: + name: PGI_PAD + type: BOOLEAN + - column: + name: PGI_DATESTYLE + type: VARCHAR(20) + - changeSet: + id: 23-feature-info-field-columns-postgresql + author: sitmun + dbms: postgresql + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: INTEGER + - column: + name: PGI_PAD + type: BOOLEAN + - column: + name: PGI_DATESTYLE + type: VARCHAR(20) + - changeSet: + id: 23-feature-info-field-columns-oracle + author: sitmun + dbms: oracle + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: NUMBER(10) + - column: + name: PGI_PAD + type: NUMBER(1) + - column: + name: PGI_DATESTYLE + type: VARCHAR2(20 CHAR) + - changeSet: + id: 23-feature-info-auto-h2 + author: sitmun + dbms: h2 + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', FALSE, FALSE, 'Automatic' + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; + - changeSet: + id: 23-feature-info-auto-postgresql + author: sitmun + dbms: postgresql + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', FALSE, FALSE, 'Automatic' + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; + - changeSet: + id: 23-feature-info-auto-oracle + author: sitmun + dbms: oracle + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', 0, 0, 'Automatic' + FROM DUAL + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; diff --git a/profiles/development/backend/liquibase/master.xml b/profiles/development/backend/liquibase/master.xml index 02af712..3246053 100644 --- a/profiles/development/backend/liquibase/master.xml +++ b/profiles/development/backend/liquibase/master.xml @@ -80,4 +80,5 @@ + diff --git a/profiles/oracle/liquibase/changelog/27_feature_info_field_format.yaml b/profiles/oracle/liquibase/changelog/27_feature_info_field_format.yaml new file mode 100644 index 0000000..3705a6f --- /dev/null +++ b/profiles/oracle/liquibase/changelog/27_feature_info_field_format.yaml @@ -0,0 +1,110 @@ +databaseChangeLog: + - changeSet: + id: 23-feature-info-field-columns-h2 + author: sitmun + dbms: h2 + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: INTEGER + - column: + name: PGI_PAD + type: BOOLEAN + - column: + name: PGI_DATESTYLE + type: VARCHAR(20) + - changeSet: + id: 23-feature-info-field-columns-postgresql + author: sitmun + dbms: postgresql + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: INTEGER + - column: + name: PGI_PAD + type: BOOLEAN + - column: + name: PGI_DATESTYLE + type: VARCHAR(20) + - changeSet: + id: 23-feature-info-field-columns-oracle + author: sitmun + dbms: oracle + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: NUMBER(10) + - column: + name: PGI_PAD + type: NUMBER(1) + - column: + name: PGI_DATESTYLE + type: VARCHAR2(20 CHAR) + - changeSet: + id: 23-feature-info-auto-h2 + author: sitmun + dbms: h2 + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', FALSE, FALSE, 'Automatic' + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; + - changeSet: + id: 23-feature-info-auto-postgresql + author: sitmun + dbms: postgresql + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', FALSE, FALSE, 'Automatic' + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; + - changeSet: + id: 23-feature-info-auto-oracle + author: sitmun + dbms: oracle + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', 0, 0, 'Automatic' + FROM DUAL + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; diff --git a/profiles/oracle/liquibase/master.xml b/profiles/oracle/liquibase/master.xml index d901d0b..8a8b5f2 100644 --- a/profiles/oracle/liquibase/master.xml +++ b/profiles/oracle/liquibase/master.xml @@ -31,4 +31,5 @@ + diff --git a/profiles/postgres/liquibase/changelog/27_feature_info_field_format.yaml b/profiles/postgres/liquibase/changelog/27_feature_info_field_format.yaml new file mode 100644 index 0000000..3705a6f --- /dev/null +++ b/profiles/postgres/liquibase/changelog/27_feature_info_field_format.yaml @@ -0,0 +1,110 @@ +databaseChangeLog: + - changeSet: + id: 23-feature-info-field-columns-h2 + author: sitmun + dbms: h2 + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: INTEGER + - column: + name: PGI_PAD + type: BOOLEAN + - column: + name: PGI_DATESTYLE + type: VARCHAR(20) + - changeSet: + id: 23-feature-info-field-columns-postgresql + author: sitmun + dbms: postgresql + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: INTEGER + - column: + name: PGI_PAD + type: BOOLEAN + - column: + name: PGI_DATESTYLE + type: VARCHAR(20) + - changeSet: + id: 23-feature-info-field-columns-oracle + author: sitmun + dbms: oracle + changes: + - addColumn: + tableName: STM_PAR_GI + columns: + - column: + name: PGI_DIGITS + type: NUMBER(10) + - column: + name: PGI_PAD + type: NUMBER(1) + - column: + name: PGI_DATESTYLE + type: VARCHAR2(20 CHAR) + - changeSet: + id: 23-feature-info-auto-h2 + author: sitmun + dbms: h2 + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', FALSE, FALSE, 'Automatic' + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; + - changeSet: + id: 23-feature-info-auto-postgresql + author: sitmun + dbms: postgresql + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', FALSE, FALSE, 'Automatic' + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; + - changeSet: + id: 23-feature-info-auto-oracle + author: sitmun + dbms: oracle + changes: + - sql: + sql: > + INSERT INTO STM_CODELIST (COD_ID, COD_LIST, COD_VALUE, COD_SYSTEM, COD_DEFAULT, COD_DESCRIPTION) + SELECT (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST), + 'cartographyParameter.format', 'AUTO', 0, 0, 'Automatic' + FROM DUAL + WHERE NOT EXISTS ( + SELECT 1 FROM STM_CODELIST + WHERE COD_LIST = 'cartographyParameter.format' AND COD_VALUE = 'AUTO' + ); + - sql: + sql: > + UPDATE STM_SEQUENCE + SET SEQ_COUNT = (SELECT COALESCE(MAX(COD_ID), 0) + 1 FROM STM_CODELIST) + WHERE SEQ_NAME = 'COD_ID'; diff --git a/profiles/postgres/liquibase/master.xml b/profiles/postgres/liquibase/master.xml index 82804b7..eeecabe 100644 --- a/profiles/postgres/liquibase/master.xml +++ b/profiles/postgres/liquibase/master.xml @@ -29,4 +29,5 @@ + From 17a9715ebb1f70366d6b4ef878c15aac791e1ce9 Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Sun, 27 Sep 2026 23:27:09 +0200 Subject: [PATCH 2/7] feat(profiles): seed Menorca GetFeatureInfo field lists A third party can identify two public layers that already return these properties, without filling the admin grid first. --- CHANGELOG.md | 1 + .../changelog/75_dev_feature_info_fields.yaml | 133 ++++++++++++++++++ .../development/backend/liquibase/master.xml | 1 + 3 files changed, 135 insertions(+) create mode 100644 profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 778978f..da17578 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), #### Profile-level - **Liquibase**: PostgreSQL and Oracle changelog 27, and development changelog 74, add `PGI_DIGITS`, `PGI_PAD`, `PGI_DATESTYLE`, and format code `AUTO` ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). +- **Liquibase**: Development changelog 75 seeds GetFeatureInfo fields on IDE genèric Menorca. Cartography 1304 (Trams del camí de cavalls) lists route, kind, max easting, and website. Cartography 4123 (Fotos de Menorca britànica) lists name, municipality, thumbnail, and photo, and is queryable. Spanish and Catalan labels are translations; English is the stored default ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). ### Fixed diff --git a/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml b/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml new file mode 100644 index 0000000..0cb5a11 --- /dev/null +++ b/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml @@ -0,0 +1,133 @@ +databaseChangeLog: + - changeSet: + id: 75-dev-feature-info-fields-postgresql + author: sitmun + context: dev + dbms: postgresql + comment: > + IDE genèric Menorca (application 12). Identify Trams del camí de cavalls + (cartography 1304, layer tu007rts_ccavalls) and Fotos de Menorca britànica + (cartography 4123, layer tu007rts_fotosbrt). English labels are PGI_VALUE; + Spanish and Catalan come from STM_TRANSLATION. + preConditions: + - onFail: MARK_RAN + sqlCheck: + expectedResult: 0 + sql: SELECT COUNT(*) FROM STM_PAR_GI WHERE PGI_ID = 9101 + - onFail: MARK_RAN + sqlCheck: + expectedResult: 1 + sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 1304 + - onFail: MARK_RAN + sqlCheck: + expectedResult: 1 + sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 4123 + changes: + - sql: + sql: | + INSERT INTO STM_PAR_GI ( + PGI_ID, PGI_NAME, PGI_VALUE, PGI_FORMAT, PGI_TYPE, PGI_GIID, PGI_ORDER, + PGI_DIGITS, PGI_PAD, PGI_DATESTYLE + ) VALUES + (9101, 'nomruta', 'Route', 'T', 'INFO', 1304, 0, NULL, NULL, NULL), + (9102, 'dstipus', 'Kind', 'AUTO', 'INFO', 1304, 1, NULL, NULL, NULL), + (9103, 'etrsxmax', 'Max easting', 'N', 'INFO', 1304, 2, 0, FALSE, NULL), + (9104, 'link', 'Website', 'U', 'INFO', 1304, 3, NULL, NULL, NULL), + (9105, 'nom', 'Name', 'T', 'INFO', 4123, 0, NULL, NULL, NULL), + (9106, 'dsmun', 'Municipality', 'T', 'INFO', 4123, 1, NULL, NULL, NULL), + (9107, 'urlthumfo', 'Thumbnail', 'I', 'INFO', 4123, 2, NULL, NULL, NULL), + (9108, 'urlfoto', 'Photo', 'U', 'INFO', 4123, 3, NULL, NULL, NULL); + INSERT INTO STM_TRANSLATION (TRA_ID, TRA_ELEID, TRA_COLUMN, TRA_LANID, TRA_NAME) VALUES + (9101001, 9101, 'CartographyParameter.value', 2, 'Ruta'), + (9101002, 9101, 'CartographyParameter.value', 3, 'Ruta'), + (9101003, 9102, 'CartographyParameter.value', 2, 'Tipo'), + (9101004, 9102, 'CartographyParameter.value', 3, 'Tipus'), + (9101005, 9103, 'CartographyParameter.value', 2, 'Este máximo'), + (9101006, 9103, 'CartographyParameter.value', 3, 'Est màxim'), + (9101007, 9104, 'CartographyParameter.value', 2, 'Enlace'), + (9101008, 9104, 'CartographyParameter.value', 3, 'Enllaç'), + (9101009, 9105, 'CartographyParameter.value', 2, 'Nombre'), + (9101010, 9105, 'CartographyParameter.value', 3, 'Nom'), + (9101011, 9106, 'CartographyParameter.value', 2, 'Municipio'), + (9101012, 9106, 'CartographyParameter.value', 3, 'Municipi'), + (9101013, 9107, 'CartographyParameter.value', 2, 'Miniatura'), + (9101014, 9107, 'CartographyParameter.value', 3, 'Miniatura'), + (9101015, 9108, 'CartographyParameter.value', 2, 'Foto'), + (9101016, 9108, 'CartographyParameter.value', 3, 'Foto'); + UPDATE STM_GEOINFO + SET GEO_QUERYABL = TRUE, GEO_QUERYACT = TRUE, GEO_QUERYLAY = 'tu007rts_fotosbrt' + WHERE GEO_ID = 4123; + UPDATE STM_TREE_NOD + SET TNO_QUERYACT = TRUE + WHERE TNO_ID IN (12084, 12633); + UPDATE STM_SEQUENCE + SET SEQ_COUNT = GREATEST(SEQ_COUNT, (SELECT COALESCE(MAX(PGI_ID), 0) + 1 FROM STM_PAR_GI)) + WHERE SEQ_NAME = 'PGI_ID'; + UPDATE STM_SEQUENCE + SET SEQ_COUNT = GREATEST(SEQ_COUNT, (SELECT COALESCE(MAX(TRA_ID), 0) + 1 FROM STM_TRANSLATION)) + WHERE SEQ_NAME = 'TRA_ID'; + - changeSet: + id: 75-dev-feature-info-fields-oracle + author: sitmun + context: dev + dbms: oracle + comment: > + IDE genèric Menorca (application 12). Identify Trams del camí de cavalls + (cartography 1304) and Fotos de Menorca britànica (cartography 4123). + preConditions: + - onFail: MARK_RAN + sqlCheck: + expectedResult: 0 + sql: SELECT COUNT(*) FROM STM_PAR_GI WHERE PGI_ID = 9101 + - onFail: MARK_RAN + sqlCheck: + expectedResult: 1 + sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 1304 + - onFail: MARK_RAN + sqlCheck: + expectedResult: 1 + sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 4123 + changes: + - sql: + sql: | + INSERT INTO STM_PAR_GI ( + PGI_ID, PGI_NAME, PGI_VALUE, PGI_FORMAT, PGI_TYPE, PGI_GIID, PGI_ORDER, + PGI_DIGITS, PGI_PAD, PGI_DATESTYLE + ) + SELECT 9101, 'nomruta', 'Route', 'T', 'INFO', 1304, 0, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL + SELECT 9102, 'dstipus', 'Kind', 'AUTO', 'INFO', 1304, 1, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL + SELECT 9103, 'etrsxmax', 'Max easting', 'N', 'INFO', 1304, 2, 0, 0, CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL + SELECT 9104, 'link', 'Website', 'U', 'INFO', 1304, 3, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL + SELECT 9105, 'nom', 'Name', 'T', 'INFO', 4123, 0, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL + SELECT 9106, 'dsmun', 'Municipality', 'T', 'INFO', 4123, 1, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL + SELECT 9107, 'urlthumfo', 'Thumbnail', 'I', 'INFO', 4123, 2, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL + SELECT 9108, 'urlfoto', 'Photo', 'U', 'INFO', 4123, 3, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL; + INSERT INTO STM_TRANSLATION (TRA_ID, TRA_ELEID, TRA_COLUMN, TRA_LANID, TRA_NAME) + SELECT 9101001, 9101, 'CartographyParameter.value', 2, 'Ruta' FROM DUAL UNION ALL + SELECT 9101002, 9101, 'CartographyParameter.value', 3, 'Ruta' FROM DUAL UNION ALL + SELECT 9101003, 9102, 'CartographyParameter.value', 2, 'Tipo' FROM DUAL UNION ALL + SELECT 9101004, 9102, 'CartographyParameter.value', 3, 'Tipus' FROM DUAL UNION ALL + SELECT 9101005, 9103, 'CartographyParameter.value', 2, 'Este máximo' FROM DUAL UNION ALL + SELECT 9101006, 9103, 'CartographyParameter.value', 3, 'Est màxim' FROM DUAL UNION ALL + SELECT 9101007, 9104, 'CartographyParameter.value', 2, 'Enlace' FROM DUAL UNION ALL + SELECT 9101008, 9104, 'CartographyParameter.value', 3, 'Enllaç' FROM DUAL UNION ALL + SELECT 9101009, 9105, 'CartographyParameter.value', 2, 'Nombre' FROM DUAL UNION ALL + SELECT 9101010, 9105, 'CartographyParameter.value', 3, 'Nom' FROM DUAL UNION ALL + SELECT 9101011, 9106, 'CartographyParameter.value', 2, 'Municipio' FROM DUAL UNION ALL + SELECT 9101012, 9106, 'CartographyParameter.value', 3, 'Municipi' FROM DUAL UNION ALL + SELECT 9101013, 9107, 'CartographyParameter.value', 2, 'Miniatura' FROM DUAL UNION ALL + SELECT 9101014, 9107, 'CartographyParameter.value', 3, 'Miniatura' FROM DUAL UNION ALL + SELECT 9101015, 9108, 'CartographyParameter.value', 2, 'Foto' FROM DUAL UNION ALL + SELECT 9101016, 9108, 'CartographyParameter.value', 3, 'Foto' FROM DUAL; + UPDATE STM_GEOINFO + SET GEO_QUERYABL = 1, GEO_QUERYACT = 1, GEO_QUERYLAY = 'tu007rts_fotosbrt' + WHERE GEO_ID = 4123; + UPDATE STM_TREE_NOD + SET TNO_QUERYACT = 1 + WHERE TNO_ID IN (12084, 12633); + UPDATE STM_SEQUENCE + SET SEQ_COUNT = GREATEST(SEQ_COUNT, (SELECT COALESCE(MAX(PGI_ID), 0) + 1 FROM STM_PAR_GI)) + WHERE SEQ_NAME = 'PGI_ID'; + UPDATE STM_SEQUENCE + SET SEQ_COUNT = GREATEST(SEQ_COUNT, (SELECT COALESCE(MAX(TRA_ID), 0) + 1 FROM STM_TRANSLATION)) + WHERE SEQ_NAME = 'TRA_ID'; diff --git a/profiles/development/backend/liquibase/master.xml b/profiles/development/backend/liquibase/master.xml index 3246053..3af0448 100644 --- a/profiles/development/backend/liquibase/master.xml +++ b/profiles/development/backend/liquibase/master.xml @@ -81,4 +81,5 @@ + From 249d0ef4c85078a2b3f0e00b5f400d44102897cc Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Sun, 27 Sep 2026 23:32:00 +0200 Subject: [PATCH 3/7] =?UTF-8?q?feat(profiles):=20seed=20GetFeatureInfo=20f?= =?UTF-8?q?ields=20on=20Cam=C3=AD=20de=20Cavalls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The development example is the public Menorca route layer, which already returns these properties. --- CHANGELOG.md | 2 +- .../changelog/75_dev_feature_info_fields.yaml | 57 ++----------------- 2 files changed, 7 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da17578..f4bbb45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), #### Profile-level - **Liquibase**: PostgreSQL and Oracle changelog 27, and development changelog 74, add `PGI_DIGITS`, `PGI_PAD`, `PGI_DATESTYLE`, and format code `AUTO` ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). -- **Liquibase**: Development changelog 75 seeds GetFeatureInfo fields on IDE genèric Menorca. Cartography 1304 (Trams del camí de cavalls) lists route, kind, max easting, and website. Cartography 4123 (Fotos de Menorca britànica) lists name, municipality, thumbnail, and photo, and is queryable. Spanish and Catalan labels are translations; English is the stored default ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). +- **Liquibase**: Development changelog 75 seeds GetFeatureInfo fields on IDE genèric Menorca cartography 1304, Trams del camí de cavalls (`tu007rts_ccavalls`): route, kind, max easting, and website. Spanish and Catalan labels are translations; English is the stored default ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). ### Fixed diff --git a/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml b/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml index 0cb5a11..4db3eda 100644 --- a/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml +++ b/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml @@ -6,8 +6,7 @@ databaseChangeLog: dbms: postgresql comment: > IDE genèric Menorca (application 12). Identify Trams del camí de cavalls - (cartography 1304, layer tu007rts_ccavalls) and Fotos de Menorca britànica - (cartography 4123, layer tu007rts_fotosbrt). English labels are PGI_VALUE; + (cartography 1304, layer tu007rts_ccavalls). English labels are PGI_VALUE; Spanish and Catalan come from STM_TRANSLATION. preConditions: - onFail: MARK_RAN @@ -18,10 +17,6 @@ databaseChangeLog: sqlCheck: expectedResult: 1 sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 1304 - - onFail: MARK_RAN - sqlCheck: - expectedResult: 1 - sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 4123 changes: - sql: sql: | @@ -32,11 +27,7 @@ databaseChangeLog: (9101, 'nomruta', 'Route', 'T', 'INFO', 1304, 0, NULL, NULL, NULL), (9102, 'dstipus', 'Kind', 'AUTO', 'INFO', 1304, 1, NULL, NULL, NULL), (9103, 'etrsxmax', 'Max easting', 'N', 'INFO', 1304, 2, 0, FALSE, NULL), - (9104, 'link', 'Website', 'U', 'INFO', 1304, 3, NULL, NULL, NULL), - (9105, 'nom', 'Name', 'T', 'INFO', 4123, 0, NULL, NULL, NULL), - (9106, 'dsmun', 'Municipality', 'T', 'INFO', 4123, 1, NULL, NULL, NULL), - (9107, 'urlthumfo', 'Thumbnail', 'I', 'INFO', 4123, 2, NULL, NULL, NULL), - (9108, 'urlfoto', 'Photo', 'U', 'INFO', 4123, 3, NULL, NULL, NULL); + (9104, 'link', 'Website', 'U', 'INFO', 1304, 3, NULL, NULL, NULL); INSERT INTO STM_TRANSLATION (TRA_ID, TRA_ELEID, TRA_COLUMN, TRA_LANID, TRA_NAME) VALUES (9101001, 9101, 'CartographyParameter.value', 2, 'Ruta'), (9101002, 9101, 'CartographyParameter.value', 3, 'Ruta'), @@ -45,21 +36,7 @@ databaseChangeLog: (9101005, 9103, 'CartographyParameter.value', 2, 'Este máximo'), (9101006, 9103, 'CartographyParameter.value', 3, 'Est màxim'), (9101007, 9104, 'CartographyParameter.value', 2, 'Enlace'), - (9101008, 9104, 'CartographyParameter.value', 3, 'Enllaç'), - (9101009, 9105, 'CartographyParameter.value', 2, 'Nombre'), - (9101010, 9105, 'CartographyParameter.value', 3, 'Nom'), - (9101011, 9106, 'CartographyParameter.value', 2, 'Municipio'), - (9101012, 9106, 'CartographyParameter.value', 3, 'Municipi'), - (9101013, 9107, 'CartographyParameter.value', 2, 'Miniatura'), - (9101014, 9107, 'CartographyParameter.value', 3, 'Miniatura'), - (9101015, 9108, 'CartographyParameter.value', 2, 'Foto'), - (9101016, 9108, 'CartographyParameter.value', 3, 'Foto'); - UPDATE STM_GEOINFO - SET GEO_QUERYABL = TRUE, GEO_QUERYACT = TRUE, GEO_QUERYLAY = 'tu007rts_fotosbrt' - WHERE GEO_ID = 4123; - UPDATE STM_TREE_NOD - SET TNO_QUERYACT = TRUE - WHERE TNO_ID IN (12084, 12633); + (9101008, 9104, 'CartographyParameter.value', 3, 'Enllaç'); UPDATE STM_SEQUENCE SET SEQ_COUNT = GREATEST(SEQ_COUNT, (SELECT COALESCE(MAX(PGI_ID), 0) + 1 FROM STM_PAR_GI)) WHERE SEQ_NAME = 'PGI_ID'; @@ -73,7 +50,7 @@ databaseChangeLog: dbms: oracle comment: > IDE genèric Menorca (application 12). Identify Trams del camí de cavalls - (cartography 1304) and Fotos de Menorca britànica (cartography 4123). + (cartography 1304, layer tu007rts_ccavalls). preConditions: - onFail: MARK_RAN sqlCheck: @@ -83,10 +60,6 @@ databaseChangeLog: sqlCheck: expectedResult: 1 sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 1304 - - onFail: MARK_RAN - sqlCheck: - expectedResult: 1 - sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 4123 changes: - sql: sql: | @@ -97,11 +70,7 @@ databaseChangeLog: SELECT 9101, 'nomruta', 'Route', 'T', 'INFO', 1304, 0, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL SELECT 9102, 'dstipus', 'Kind', 'AUTO', 'INFO', 1304, 1, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL SELECT 9103, 'etrsxmax', 'Max easting', 'N', 'INFO', 1304, 2, 0, 0, CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL - SELECT 9104, 'link', 'Website', 'U', 'INFO', 1304, 3, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL - SELECT 9105, 'nom', 'Name', 'T', 'INFO', 4123, 0, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL - SELECT 9106, 'dsmun', 'Municipality', 'T', 'INFO', 4123, 1, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL - SELECT 9107, 'urlthumfo', 'Thumbnail', 'I', 'INFO', 4123, 2, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL - SELECT 9108, 'urlfoto', 'Photo', 'U', 'INFO', 4123, 3, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL; + SELECT 9104, 'link', 'Website', 'U', 'INFO', 1304, 3, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL; INSERT INTO STM_TRANSLATION (TRA_ID, TRA_ELEID, TRA_COLUMN, TRA_LANID, TRA_NAME) SELECT 9101001, 9101, 'CartographyParameter.value', 2, 'Ruta' FROM DUAL UNION ALL SELECT 9101002, 9101, 'CartographyParameter.value', 3, 'Ruta' FROM DUAL UNION ALL @@ -110,21 +79,7 @@ databaseChangeLog: SELECT 9101005, 9103, 'CartographyParameter.value', 2, 'Este máximo' FROM DUAL UNION ALL SELECT 9101006, 9103, 'CartographyParameter.value', 3, 'Est màxim' FROM DUAL UNION ALL SELECT 9101007, 9104, 'CartographyParameter.value', 2, 'Enlace' FROM DUAL UNION ALL - SELECT 9101008, 9104, 'CartographyParameter.value', 3, 'Enllaç' FROM DUAL UNION ALL - SELECT 9101009, 9105, 'CartographyParameter.value', 2, 'Nombre' FROM DUAL UNION ALL - SELECT 9101010, 9105, 'CartographyParameter.value', 3, 'Nom' FROM DUAL UNION ALL - SELECT 9101011, 9106, 'CartographyParameter.value', 2, 'Municipio' FROM DUAL UNION ALL - SELECT 9101012, 9106, 'CartographyParameter.value', 3, 'Municipi' FROM DUAL UNION ALL - SELECT 9101013, 9107, 'CartographyParameter.value', 2, 'Miniatura' FROM DUAL UNION ALL - SELECT 9101014, 9107, 'CartographyParameter.value', 3, 'Miniatura' FROM DUAL UNION ALL - SELECT 9101015, 9108, 'CartographyParameter.value', 2, 'Foto' FROM DUAL UNION ALL - SELECT 9101016, 9108, 'CartographyParameter.value', 3, 'Foto' FROM DUAL; - UPDATE STM_GEOINFO - SET GEO_QUERYABL = 1, GEO_QUERYACT = 1, GEO_QUERYLAY = 'tu007rts_fotosbrt' - WHERE GEO_ID = 4123; - UPDATE STM_TREE_NOD - SET TNO_QUERYACT = 1 - WHERE TNO_ID IN (12084, 12633); + SELECT 9101008, 9104, 'CartographyParameter.value', 3, 'Enllaç' FROM DUAL; UPDATE STM_SEQUENCE SET SEQ_COUNT = GREATEST(SEQ_COUNT, (SELECT COALESCE(MAX(PGI_ID), 0) + 1 FROM STM_PAR_GI)) WHERE SEQ_NAME = 'PGI_ID'; From e6c6b8185efe04566d4d45002ceecc4ce1e66fac Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Sun, 27 Sep 2026 23:37:54 +0200 Subject: [PATCH 4/7] =?UTF-8?q?fix(profiles):=20load=20the=20Cam=C3=AD=20d?= =?UTF-8?q?e=20Cavalls=20field=20seed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Liquibase rejects a changeset that repeats onFail, so the development stack never reached the insert. --- .../changelog/75_dev_feature_info_fields.yaml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml b/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml index 4db3eda..7220ca4 100644 --- a/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml +++ b/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml @@ -9,14 +9,14 @@ databaseChangeLog: (cartography 1304, layer tu007rts_ccavalls). English labels are PGI_VALUE; Spanish and Catalan come from STM_TRANSLATION. preConditions: - - onFail: MARK_RAN - sqlCheck: - expectedResult: 0 - sql: SELECT COUNT(*) FROM STM_PAR_GI WHERE PGI_ID = 9101 - onFail: MARK_RAN sqlCheck: expectedResult: 1 - sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 1304 + sql: > + SELECT CASE + WHEN (SELECT COUNT(*) FROM STM_PAR_GI WHERE PGI_ID = 9101) = 0 + AND (SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 1304) = 1 + THEN 1 ELSE 0 END changes: - sql: sql: | @@ -52,14 +52,14 @@ databaseChangeLog: IDE genèric Menorca (application 12). Identify Trams del camí de cavalls (cartography 1304, layer tu007rts_ccavalls). preConditions: - - onFail: MARK_RAN - sqlCheck: - expectedResult: 0 - sql: SELECT COUNT(*) FROM STM_PAR_GI WHERE PGI_ID = 9101 - onFail: MARK_RAN sqlCheck: expectedResult: 1 - sql: SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 1304 + sql: > + SELECT CASE + WHEN (SELECT COUNT(*) FROM STM_PAR_GI WHERE PGI_ID = 9101) = 0 + AND (SELECT COUNT(*) FROM STM_GEOINFO WHERE GEO_ID = 1304) = 1 + THEN 1 ELSE 0 END changes: - sql: sql: | From af0610bcee88075d3c23df9a5311cde2ad2ddbfd Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Tue, 29 Sep 2026 02:20:55 +0200 Subject: [PATCH 5/7] feat(profiles): store feature info options in one column MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Point the profile changelogs and the Camí de Cavalls seed at PGI_OPTIONS, and cover the field list in the viewer suite. --- CHANGELOG.md | 2 +- back/backend/sitmun-backend-core | 2 +- e2e/README.md | 1 + e2e/viewer/gfi-field-list.spec.ts | 90 +++++++++++++++++++ e2e/viewer/helpers/mia.ts | 35 ++++++++ front/admin/sitmun-admin-app | 2 +- front/viewer/sitmun-viewer-app | 2 +- playwright.viewer.config.ts | 6 ++ .../74_feature_info_field_format.yaml | 36 ++------ .../changelog/75_dev_feature_info_fields.yaml | 20 ++--- .../27_feature_info_field_format.yaml | 36 ++------ .../27_feature_info_field_format.yaml | 36 ++------ 12 files changed, 173 insertions(+), 95 deletions(-) create mode 100644 e2e/viewer/gfi-field-list.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index f4bbb45..a5fd7d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), #### Profile-level -- **Liquibase**: PostgreSQL and Oracle changelog 27, and development changelog 74, add `PGI_DIGITS`, `PGI_PAD`, `PGI_DATESTYLE`, and format code `AUTO` ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). +- **Liquibase**: PostgreSQL and Oracle changelog 27, and development changelog 74, add `PGI_OPTIONS` and format code `AUTO` ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). - **Liquibase**: Development changelog 75 seeds GetFeatureInfo fields on IDE genèric Menorca cartography 1304, Trams del camí de cavalls (`tu007rts_ccavalls`): route, kind, max easting, and website. Spanish and Catalan labels are translations; English is the stored default ([#77](https://github.com/sitmun/sitmun-application-stack/issues/77)). ### Fixed diff --git a/back/backend/sitmun-backend-core b/back/backend/sitmun-backend-core index f991b77..922fb10 160000 --- a/back/backend/sitmun-backend-core +++ b/back/backend/sitmun-backend-core @@ -1 +1 @@ -Subproject commit f991b773d5c5718244015d43a8f2ffc4cefe7553 +Subproject commit 922fb1045060e4805da55c808dd2bd04ff7b3665 diff --git a/e2e/README.md b/e2e/README.md index 3ffd06b..43286d6 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -43,6 +43,7 @@ Browser E2E against backend-core on in-memory H2. No Docker Compose. - Map legend (`viewer-legend`): after loading a stubbed catalog leaf, Capas shows capabilities `LegendURL` imagery and the Legend task shows symbology when the stub denies `DescribeLayer` and fails `/wms` GetLegendGraphic (DiBa/ArcGIS-style #164); setup enables `sitna.legend` task-availability - No base map (`viewer-basemap`): basemap selector option `sitmun-no-base-map` clears raster basemap to a white viewport while a catalog leaf stays visible (#167); setup enables `sitna.basemapSelector` task-availability - Print preview (`viewer-print`): 1600×700 window; A4 landscape map becomes 1040×704 and A4 portrait 712×1034 while `tc-ctl-prnmap-printing` is set, then returns to window size ([sitmun-viewer-app#160](https://github.com/sitmun/sitmun-viewer-app/issues/160)); setup enables `sitna.printMap` and drops seed `div: "print"` / external logo +- GetFeatureInfo include list plus more-info (`viewer-gfi-fields`): profile for Toponímia (`34_TOPO_TX`, cartography 6) is given one `featureInfoFields` row (`name` → Place) and a `sitmun.moreInfo` URL task whose placeholder reads `id`. Map identify against the WMS stub shows Place and the task row, the link uses the omitted `id`, and the `id` property is not a table header (`e2e/viewer/gfi-field-list.spec.ts`). - HTML GetFeatureInfo embed (`viewer-gfi`): `e2e/viewer/gfi-html-embed.spec.ts` loads the viewer origin, then nested `iframe`s against the WMS stub. Playwright `frame.url()` is the oracle. `/embed/allow` (no `X-Frame-Options`) commits `http://127.0.0.1:18093/embed/allow`. `/embed/deny` (`X-Frame-Options: DENY`) does not. Same-origin `location.href` is not used. Chromium opaque error documents can throw `SecurityError` for both outcomes. Jest covers hide/load/probe ([sitmun-viewer-app#169](https://github.com/sitmun/sitmun-viewer-app/issues/169)). - More Info Advanced (`viewer-mia`): profile includes `sitna.moreInfoAdvanced` + type-16 parent on Toponímia (seed parent 42 includes query child 38); synthetic FeatureInfo `responseCallback` opens `.sitmun-mia-popup-overlay` and `POST /api/tasks/template/more-info-advanced/render` carries `appId`/`terId` body plus `lang` query ([sitmun-viewer-app#162](https://github.com/sitmun/sitmun-viewer-app/pull/162)); also asserts live backend render, overlay error on 500, close, multi-feature GFI re-render (`selectMiaGfiFeature`), and deferred-route races (late first identify must not overwrite a newer one; close-during-load ignores late fulfill); setup enables MIA + featureInfo task-availability. Shared helpers live in `e2e/viewer/helpers/mia.ts`. - Local Basic-auth upstream stub (plus unauthenticated `/legend` PNG for #164); capabilities advertise `GetFeatureInfo` `application/json` so SITNA sets `INFO_FORMAT`; GetFeatureInfo for layer `34_TOPO_TX` returns JSON FeatureCollection (XML fixture fallback). Production Liquibase is not modified. diff --git a/e2e/viewer/gfi-field-list.spec.ts b/e2e/viewer/gfi-field-list.spec.ts new file mode 100644 index 0000000..c823fe0 --- /dev/null +++ b/e2e/viewer/gfi-field-list.spec.ts @@ -0,0 +1,90 @@ +import { expect, test } from '@playwright/test'; +import { QUERYABLE_LEAF_CARTOGRAPHY_ID } from './fixtures'; +import { + enableCapasGfi, + identifyAtMapCenter, + loadQueryableLeafIntoCapas, + loginAndOpenMap, +} from './helpers/mia'; + +const LAYER_NAME = '34_TOPO_TX'; +const TASK_NAME = 'E2E extra field'; + +/** + * Include-list identify still grows when a sitmun.moreInfo task is present: + * listed properties stay, omitted service properties stay hidden, and the + * task appends its own row using the full payload. + */ +test.describe('GetFeatureInfo include list and more-info', () => { + test('more-info adds a row while omitted properties stay hidden', async ({ page }) => { + // The viewer service worker fetches the profile. page.route does not see that. + await page.context().route(/\/config\/client\/profile\//, async (route) => { + const response = await route.fetch(); + const body = (await response.json()) as { + layers?: Array<{ id?: string; layers?: string[]; featureInfoFields?: unknown }>; + tasks?: Array>; + }; + const layer = body.layers?.find( + (item) => Array.isArray(item.layers) && item.layers.includes(LAYER_NAME), + ); + if (!layer) { + throw new Error(`profile has no layer whose names include ${LAYER_NAME}`); + } + layer.featureInfoFields = [ + { name: 'name', label: 'Place', format: 'T', order: 0 }, + ]; + body.tasks = body.tasks ?? []; + body.tasks.push({ + id: 'e2e-more-info', + name: TASK_NAME, + 'ui-control': 'sitmun.moreInfo', + cartographyId: String(QUERYABLE_LEAF_CARTOGRAPHY_ID), + command: 'https://example.org/item/$ID$', + parameters: { + ID: { label: '$ID$', value: 'id' }, + }, + }); + await route.fulfill({ + status: response.status(), + contentType: 'application/json', + body: JSON.stringify(body), + }); + }); + + const profileSeen = page.waitForResponse( + (response) => + response.url().includes('/config/client/profile/') && response.ok(), + ); + await loginAndOpenMap(page); + const profileBody = (await (await profileSeen).json()) as { + layers?: Array<{ layers?: string[]; featureInfoFields?: Array<{ label?: string }> }>; + tasks?: Array<{ name?: string }>; + }; + const seeded = profileBody.layers?.find((item) => item.layers?.includes(LAYER_NAME)); + expect(seeded?.featureInfoFields?.some((field) => field.label === 'Place')).toBeTruthy(); + expect(profileBody.tasks?.some((task) => task.name === TASK_NAME)).toBeTruthy(); + await loadQueryableLeafIntoCapas(page); + await enableCapasGfi(page); + + const gfi = page.waitForResponse( + (response) => + /REQUEST=GetFeatureInfo/i.test(response.url()) && + /34_TOPO_TX/i.test(response.url()) && + response.ok(), + { timeout: 60_000 }, + ); + await identifyAtMapCenter(page); + await gfi; + + const table = page.locator('.tc-ctl-popup .tc-ctl-finfo-layers table').first(); + await expect(table).toBeVisible({ timeout: 30_000 }); + await expect(table.locator('th', { hasText: /^Place$/ })).toBeVisible(); + await expect(table.locator('td', { hasText: 'e2e-gfi-click' })).toBeVisible(); + await expect(table.locator('th', { hasText: TASK_NAME })).toBeVisible(); + await expect(table.locator('a.sitmun-more-info-link')).toHaveAttribute( + 'href', + 'https://example.org/item/1', + ); + await expect(table.locator('th', { hasText: /^id$/ })).toHaveCount(0); + }); +}); diff --git a/e2e/viewer/helpers/mia.ts b/e2e/viewer/helpers/mia.ts index 11df087..21ef909 100644 --- a/e2e/viewer/helpers/mia.ts +++ b/e2e/viewer/helpers/mia.ts @@ -317,6 +317,41 @@ export async function openPublicDashboard(page: Page): Promise { } /** Enable Capas GFI toggle so map clicks issue GetFeatureInfo for the loaded leaf. */ +/** Drive FeatureInfo.callback at the map center (stub GetFeatureInfo, not responseCallback). */ +export async function identifyAtMapCenter(page: Page): Promise { + await page.evaluate(async () => { + const w = window as unknown as { + TC?: { + Map?: { + get: (el: Element) => { + controls?: Array<{ callback?: (coords: number[]) => Promise }>; + getCenter?: () => number[]; + wrap?: { map?: { getView: () => { getCenter: () => number[] } } }; + }; + }; + control?: { FeatureInfo?: new () => unknown }; + }; + }; + const mapEl = document.querySelector('.tc-map'); + if (!w.TC?.Map?.get || !mapEl) { + throw new Error('TC.Map not available'); + } + const map = w.TC.Map.get(mapEl); + const FeatureInfo = w.TC.control?.FeatureInfo; + const fi = (map.controls || []).find( + (ctl) => FeatureInfo && ctl instanceof (FeatureInfo as unknown as Function), + ); + if (!fi?.callback) { + throw new Error('FeatureInfo.callback not found'); + } + const center = map.getCenter?.() || map.wrap?.map?.getView()?.getCenter() || null; + if (!center) { + throw new Error('map center unavailable'); + } + await fi.callback(center); + }); +} + export async function enableCapasGfi(page: Page): Promise { const gfi = page.locator('#tc-slot-wlm sitna-toggle.sitmun-wlm-gfi, #tc-slot-wlm .sitmun-wlm-gfi').first(); await expect(gfi).toBeVisible({ timeout: 30_000 }); diff --git a/front/admin/sitmun-admin-app b/front/admin/sitmun-admin-app index 9a941f4..6d92482 160000 --- a/front/admin/sitmun-admin-app +++ b/front/admin/sitmun-admin-app @@ -1 +1 @@ -Subproject commit 9a941f4f26f19cb887e284eefc45425614aee28f +Subproject commit 6d924820f6e307ae64704c1b82cc606518c52fa1 diff --git a/front/viewer/sitmun-viewer-app b/front/viewer/sitmun-viewer-app index ce08ba0..ab1301a 160000 --- a/front/viewer/sitmun-viewer-app +++ b/front/viewer/sitmun-viewer-app @@ -1 +1 @@ -Subproject commit ce08ba00123d6f29dfc75de488e7b074f3d57ecb +Subproject commit ab1301ae3d5ea4bd6e8a470b9861e27578ca3f8e diff --git a/playwright.viewer.config.ts b/playwright.viewer.config.ts index 86d78ac..6c481fd 100644 --- a/playwright.viewer.config.ts +++ b/playwright.viewer.config.ts @@ -104,5 +104,11 @@ export default defineConfig({ testMatch: /gfi-html-embed\.spec\.ts/, use: { ...devices['Desktop Chrome'] }, }, + { + name: 'viewer-gfi-fields', + testMatch: /gfi-field-list\.spec\.ts/, + dependencies: ['viewer-setup'], + use: { ...devices['Desktop Chrome'] }, + }, ], }); diff --git a/profiles/development/backend/liquibase/changelog/74_feature_info_field_format.yaml b/profiles/development/backend/liquibase/changelog/74_feature_info_field_format.yaml index 3705a6f..4ad5667 100644 --- a/profiles/development/backend/liquibase/changelog/74_feature_info_field_format.yaml +++ b/profiles/development/backend/liquibase/changelog/74_feature_info_field_format.yaml @@ -1,6 +1,6 @@ databaseChangeLog: - changeSet: - id: 23-feature-info-field-columns-h2 + id: 23-feature-info-options-h2 author: sitmun dbms: h2 changes: @@ -8,16 +8,10 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: INTEGER - - column: - name: PGI_PAD - type: BOOLEAN - - column: - name: PGI_DATESTYLE - type: VARCHAR(20) + name: PGI_OPTIONS + type: CLOB - changeSet: - id: 23-feature-info-field-columns-postgresql + id: 23-feature-info-options-postgresql author: sitmun dbms: postgresql changes: @@ -25,16 +19,10 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: INTEGER - - column: - name: PGI_PAD - type: BOOLEAN - - column: - name: PGI_DATESTYLE - type: VARCHAR(20) + name: PGI_OPTIONS + type: TEXT - changeSet: - id: 23-feature-info-field-columns-oracle + id: 23-feature-info-options-oracle author: sitmun dbms: oracle changes: @@ -42,14 +30,8 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: NUMBER(10) - - column: - name: PGI_PAD - type: NUMBER(1) - - column: - name: PGI_DATESTYLE - type: VARCHAR2(20 CHAR) + name: PGI_OPTIONS + type: CLOB - changeSet: id: 23-feature-info-auto-h2 author: sitmun diff --git a/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml b/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml index 7220ca4..9f4040c 100644 --- a/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml +++ b/profiles/development/backend/liquibase/changelog/75_dev_feature_info_fields.yaml @@ -22,12 +22,12 @@ databaseChangeLog: sql: | INSERT INTO STM_PAR_GI ( PGI_ID, PGI_NAME, PGI_VALUE, PGI_FORMAT, PGI_TYPE, PGI_GIID, PGI_ORDER, - PGI_DIGITS, PGI_PAD, PGI_DATESTYLE + PGI_OPTIONS ) VALUES - (9101, 'nomruta', 'Route', 'T', 'INFO', 1304, 0, NULL, NULL, NULL), - (9102, 'dstipus', 'Kind', 'AUTO', 'INFO', 1304, 1, NULL, NULL, NULL), - (9103, 'etrsxmax', 'Max easting', 'N', 'INFO', 1304, 2, 0, FALSE, NULL), - (9104, 'link', 'Website', 'U', 'INFO', 1304, 3, NULL, NULL, NULL); + (9101, 'nomruta', 'Route', 'T', 'INFO', 1304, 0, NULL), + (9102, 'dstipus', 'Kind', 'AUTO', 'INFO', 1304, 1, NULL), + (9103, 'etrsxmax', 'Max easting', 'N', 'INFO', 1304, 2, '{"fractionDigits":0}'), + (9104, 'link', 'Website', 'U', 'INFO', 1304, 3, NULL); INSERT INTO STM_TRANSLATION (TRA_ID, TRA_ELEID, TRA_COLUMN, TRA_LANID, TRA_NAME) VALUES (9101001, 9101, 'CartographyParameter.value', 2, 'Ruta'), (9101002, 9101, 'CartographyParameter.value', 3, 'Ruta'), @@ -65,12 +65,12 @@ databaseChangeLog: sql: | INSERT INTO STM_PAR_GI ( PGI_ID, PGI_NAME, PGI_VALUE, PGI_FORMAT, PGI_TYPE, PGI_GIID, PGI_ORDER, - PGI_DIGITS, PGI_PAD, PGI_DATESTYLE + PGI_OPTIONS ) - SELECT 9101, 'nomruta', 'Route', 'T', 'INFO', 1304, 0, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL - SELECT 9102, 'dstipus', 'Kind', 'AUTO', 'INFO', 1304, 1, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL - SELECT 9103, 'etrsxmax', 'Max easting', 'N', 'INFO', 1304, 2, 0, 0, CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL - SELECT 9104, 'link', 'Website', 'U', 'INFO', 1304, 3, CAST(NULL AS NUMBER), CAST(NULL AS NUMBER), CAST(NULL AS VARCHAR2(20)) FROM DUAL; + SELECT 9101, 'nomruta', 'Route', 'T', 'INFO', 1304, 0, NULL FROM DUAL UNION ALL + SELECT 9102, 'dstipus', 'Kind', 'AUTO', 'INFO', 1304, 1, NULL FROM DUAL UNION ALL + SELECT 9103, 'etrsxmax', 'Max easting', 'N', 'INFO', 1304, 2, '{"fractionDigits":0}' FROM DUAL UNION ALL + SELECT 9104, 'link', 'Website', 'U', 'INFO', 1304, 3, NULL FROM DUAL; INSERT INTO STM_TRANSLATION (TRA_ID, TRA_ELEID, TRA_COLUMN, TRA_LANID, TRA_NAME) SELECT 9101001, 9101, 'CartographyParameter.value', 2, 'Ruta' FROM DUAL UNION ALL SELECT 9101002, 9101, 'CartographyParameter.value', 3, 'Ruta' FROM DUAL UNION ALL diff --git a/profiles/oracle/liquibase/changelog/27_feature_info_field_format.yaml b/profiles/oracle/liquibase/changelog/27_feature_info_field_format.yaml index 3705a6f..4ad5667 100644 --- a/profiles/oracle/liquibase/changelog/27_feature_info_field_format.yaml +++ b/profiles/oracle/liquibase/changelog/27_feature_info_field_format.yaml @@ -1,6 +1,6 @@ databaseChangeLog: - changeSet: - id: 23-feature-info-field-columns-h2 + id: 23-feature-info-options-h2 author: sitmun dbms: h2 changes: @@ -8,16 +8,10 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: INTEGER - - column: - name: PGI_PAD - type: BOOLEAN - - column: - name: PGI_DATESTYLE - type: VARCHAR(20) + name: PGI_OPTIONS + type: CLOB - changeSet: - id: 23-feature-info-field-columns-postgresql + id: 23-feature-info-options-postgresql author: sitmun dbms: postgresql changes: @@ -25,16 +19,10 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: INTEGER - - column: - name: PGI_PAD - type: BOOLEAN - - column: - name: PGI_DATESTYLE - type: VARCHAR(20) + name: PGI_OPTIONS + type: TEXT - changeSet: - id: 23-feature-info-field-columns-oracle + id: 23-feature-info-options-oracle author: sitmun dbms: oracle changes: @@ -42,14 +30,8 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: NUMBER(10) - - column: - name: PGI_PAD - type: NUMBER(1) - - column: - name: PGI_DATESTYLE - type: VARCHAR2(20 CHAR) + name: PGI_OPTIONS + type: CLOB - changeSet: id: 23-feature-info-auto-h2 author: sitmun diff --git a/profiles/postgres/liquibase/changelog/27_feature_info_field_format.yaml b/profiles/postgres/liquibase/changelog/27_feature_info_field_format.yaml index 3705a6f..4ad5667 100644 --- a/profiles/postgres/liquibase/changelog/27_feature_info_field_format.yaml +++ b/profiles/postgres/liquibase/changelog/27_feature_info_field_format.yaml @@ -1,6 +1,6 @@ databaseChangeLog: - changeSet: - id: 23-feature-info-field-columns-h2 + id: 23-feature-info-options-h2 author: sitmun dbms: h2 changes: @@ -8,16 +8,10 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: INTEGER - - column: - name: PGI_PAD - type: BOOLEAN - - column: - name: PGI_DATESTYLE - type: VARCHAR(20) + name: PGI_OPTIONS + type: CLOB - changeSet: - id: 23-feature-info-field-columns-postgresql + id: 23-feature-info-options-postgresql author: sitmun dbms: postgresql changes: @@ -25,16 +19,10 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: INTEGER - - column: - name: PGI_PAD - type: BOOLEAN - - column: - name: PGI_DATESTYLE - type: VARCHAR(20) + name: PGI_OPTIONS + type: TEXT - changeSet: - id: 23-feature-info-field-columns-oracle + id: 23-feature-info-options-oracle author: sitmun dbms: oracle changes: @@ -42,14 +30,8 @@ databaseChangeLog: tableName: STM_PAR_GI columns: - column: - name: PGI_DIGITS - type: NUMBER(10) - - column: - name: PGI_PAD - type: NUMBER(1) - - column: - name: PGI_DATESTYLE - type: VARCHAR2(20 CHAR) + name: PGI_OPTIONS + type: CLOB - changeSet: id: 23-feature-info-auto-h2 author: sitmun From 2910f430502274e11c9ff12ca4f08d2f4ecf25dc Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Wed, 30 Sep 2026 15:43:49 +0200 Subject: [PATCH 6/7] test(e2e): cover empty and partial GetFeatureInfo field lists Identify with no fields keeps the original properties and the more-info row. Two listed fields keep a blank cell when one name is missing. --- e2e/README.md | 2 +- e2e/viewer/gfi-field-list.spec.ts | 176 ++++++++++++++++++++---------- front/viewer/sitmun-viewer-app | 2 +- 3 files changed, 120 insertions(+), 60 deletions(-) diff --git a/e2e/README.md b/e2e/README.md index 43286d6..5a9e664 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -43,7 +43,7 @@ Browser E2E against backend-core on in-memory H2. No Docker Compose. - Map legend (`viewer-legend`): after loading a stubbed catalog leaf, Capas shows capabilities `LegendURL` imagery and the Legend task shows symbology when the stub denies `DescribeLayer` and fails `/wms` GetLegendGraphic (DiBa/ArcGIS-style #164); setup enables `sitna.legend` task-availability - No base map (`viewer-basemap`): basemap selector option `sitmun-no-base-map` clears raster basemap to a white viewport while a catalog leaf stays visible (#167); setup enables `sitna.basemapSelector` task-availability - Print preview (`viewer-print`): 1600×700 window; A4 landscape map becomes 1040×704 and A4 portrait 712×1034 while `tc-ctl-prnmap-printing` is set, then returns to window size ([sitmun-viewer-app#160](https://github.com/sitmun/sitmun-viewer-app/issues/160)); setup enables `sitna.printMap` and drops seed `div: "print"` / external logo -- GetFeatureInfo include list plus more-info (`viewer-gfi-fields`): profile for Toponímia (`34_TOPO_TX`, cartography 6) is given one `featureInfoFields` row (`name` → Place) and a `sitmun.moreInfo` URL task whose placeholder reads `id`. Map identify against the WMS stub shows Place and the task row, the link uses the omitted `id`, and the `id` property is not a table header (`e2e/viewer/gfi-field-list.spec.ts`). +- GetFeatureInfo include list plus more-info (`viewer-gfi-fields`): profile for Toponímia (`34_TOPO_TX`, cartography 6) gets a `sitmun.moreInfo` URL task whose placeholder reads `id`, then three field-list cases. One listed field (`name` → Place) keeps Place and the task row, uses omitted `id` in the link, and hides the `id` header. An empty list keeps the original properties plus the more-info row. Two listed fields where one name misses the feature keep both rows (blank cell for the miss), hide unlisted headers, and still show the more-info link (`e2e/viewer/gfi-field-list.spec.ts`). - HTML GetFeatureInfo embed (`viewer-gfi`): `e2e/viewer/gfi-html-embed.spec.ts` loads the viewer origin, then nested `iframe`s against the WMS stub. Playwright `frame.url()` is the oracle. `/embed/allow` (no `X-Frame-Options`) commits `http://127.0.0.1:18093/embed/allow`. `/embed/deny` (`X-Frame-Options: DENY`) does not. Same-origin `location.href` is not used. Chromium opaque error documents can throw `SecurityError` for both outcomes. Jest covers hide/load/probe ([sitmun-viewer-app#169](https://github.com/sitmun/sitmun-viewer-app/issues/169)). - More Info Advanced (`viewer-mia`): profile includes `sitna.moreInfoAdvanced` + type-16 parent on Toponímia (seed parent 42 includes query child 38); synthetic FeatureInfo `responseCallback` opens `.sitmun-mia-popup-overlay` and `POST /api/tasks/template/more-info-advanced/render` carries `appId`/`terId` body plus `lang` query ([sitmun-viewer-app#162](https://github.com/sitmun/sitmun-viewer-app/pull/162)); also asserts live backend render, overlay error on 500, close, multi-feature GFI re-render (`selectMiaGfiFeature`), and deferred-route races (late first identify must not overwrite a newer one; close-during-load ignores late fulfill); setup enables MIA + featureInfo task-availability. Shared helpers live in `e2e/viewer/helpers/mia.ts`. - Local Basic-auth upstream stub (plus unauthenticated `/legend` PNG for #164); capabilities advertise `GetFeatureInfo` `application/json` so SITNA sets `INFO_FORMAT`; GetFeatureInfo for layer `34_TOPO_TX` returns JSON FeatureCollection (XML fixture fallback). Production Liquibase is not modified. diff --git a/e2e/viewer/gfi-field-list.spec.ts b/e2e/viewer/gfi-field-list.spec.ts index c823fe0..5d85e3d 100644 --- a/e2e/viewer/gfi-field-list.spec.ts +++ b/e2e/viewer/gfi-field-list.spec.ts @@ -1,4 +1,4 @@ -import { expect, test } from '@playwright/test'; +import { expect, test, type Page } from '@playwright/test'; import { QUERYABLE_LEAF_CARTOGRAPHY_ID } from './fixtures'; import { enableCapasGfi, @@ -10,6 +10,73 @@ import { const LAYER_NAME = '34_TOPO_TX'; const TASK_NAME = 'E2E extra field'; +type FieldSeed = { name: string; label: string; format: 'T'; order: number }; + +type ProfileBody = { + layers?: Array<{ + layers?: string[]; + featureInfoFields?: Array<{ name?: string; label?: string }>; + }>; + tasks?: Array<{ name?: string }>; +}; + +async function identifyWithFieldList(page: Page, featureInfoFields: FieldSeed[]) { + // The viewer service worker fetches the profile. page.route does not see that. + await page.context().route(/\/config\/client\/profile\//, async (route) => { + const response = await route.fetch(); + const body = (await response.json()) as { + layers?: Array<{ id?: string; layers?: string[]; featureInfoFields?: unknown }>; + tasks?: Array>; + }; + const layer = body.layers?.find( + (item) => Array.isArray(item.layers) && item.layers.includes(LAYER_NAME), + ); + if (!layer) { + throw new Error(`profile has no layer whose names include ${LAYER_NAME}`); + } + layer.featureInfoFields = featureInfoFields; + body.tasks = body.tasks ?? []; + body.tasks.push({ + id: 'e2e-more-info', + name: TASK_NAME, + 'ui-control': 'sitmun.moreInfo', + cartographyId: String(QUERYABLE_LEAF_CARTOGRAPHY_ID), + command: 'https://example.org/item/$ID$', + parameters: { + ID: { label: '$ID$', value: 'id' }, + }, + }); + await route.fulfill({ + status: response.status(), + contentType: 'application/json', + body: JSON.stringify(body), + }); + }); + + const profileSeen = page.waitForResponse( + (response) => + response.url().includes('/config/client/profile/') && response.ok(), + ); + await loginAndOpenMap(page); + const profileBody = (await (await profileSeen).json()) as ProfileBody; + await loadQueryableLeafIntoCapas(page); + await enableCapasGfi(page); + + const gfi = page.waitForResponse( + (response) => + /REQUEST=GetFeatureInfo/i.test(response.url()) && + /34_TOPO_TX/i.test(response.url()) && + response.ok(), + { timeout: 60_000 }, + ); + await identifyAtMapCenter(page); + await gfi; + + const table = page.locator('.tc-ctl-popup .tc-ctl-finfo-layers table').first(); + await expect(table).toBeVisible({ timeout: 30_000 }); + return { profileBody, table }; +} + /** * Include-list identify still grows when a sitmun.moreInfo task is present: * listed properties stay, omitted service properties stay hidden, and the @@ -17,67 +84,13 @@ const TASK_NAME = 'E2E extra field'; */ test.describe('GetFeatureInfo include list and more-info', () => { test('more-info adds a row while omitted properties stay hidden', async ({ page }) => { - // The viewer service worker fetches the profile. page.route does not see that. - await page.context().route(/\/config\/client\/profile\//, async (route) => { - const response = await route.fetch(); - const body = (await response.json()) as { - layers?: Array<{ id?: string; layers?: string[]; featureInfoFields?: unknown }>; - tasks?: Array>; - }; - const layer = body.layers?.find( - (item) => Array.isArray(item.layers) && item.layers.includes(LAYER_NAME), - ); - if (!layer) { - throw new Error(`profile has no layer whose names include ${LAYER_NAME}`); - } - layer.featureInfoFields = [ - { name: 'name', label: 'Place', format: 'T', order: 0 }, - ]; - body.tasks = body.tasks ?? []; - body.tasks.push({ - id: 'e2e-more-info', - name: TASK_NAME, - 'ui-control': 'sitmun.moreInfo', - cartographyId: String(QUERYABLE_LEAF_CARTOGRAPHY_ID), - command: 'https://example.org/item/$ID$', - parameters: { - ID: { label: '$ID$', value: 'id' }, - }, - }); - await route.fulfill({ - status: response.status(), - contentType: 'application/json', - body: JSON.stringify(body), - }); - }); - - const profileSeen = page.waitForResponse( - (response) => - response.url().includes('/config/client/profile/') && response.ok(), - ); - await loginAndOpenMap(page); - const profileBody = (await (await profileSeen).json()) as { - layers?: Array<{ layers?: string[]; featureInfoFields?: Array<{ label?: string }> }>; - tasks?: Array<{ name?: string }>; - }; + const { profileBody, table } = await identifyWithFieldList(page, [ + { name: 'name', label: 'Place', format: 'T', order: 0 }, + ]); const seeded = profileBody.layers?.find((item) => item.layers?.includes(LAYER_NAME)); expect(seeded?.featureInfoFields?.some((field) => field.label === 'Place')).toBeTruthy(); expect(profileBody.tasks?.some((task) => task.name === TASK_NAME)).toBeTruthy(); - await loadQueryableLeafIntoCapas(page); - await enableCapasGfi(page); - - const gfi = page.waitForResponse( - (response) => - /REQUEST=GetFeatureInfo/i.test(response.url()) && - /34_TOPO_TX/i.test(response.url()) && - response.ok(), - { timeout: 60_000 }, - ); - await identifyAtMapCenter(page); - await gfi; - const table = page.locator('.tc-ctl-popup .tc-ctl-finfo-layers table').first(); - await expect(table).toBeVisible({ timeout: 30_000 }); await expect(table.locator('th', { hasText: /^Place$/ })).toBeVisible(); await expect(table.locator('td', { hasText: 'e2e-gfi-click' })).toBeVisible(); await expect(table.locator('th', { hasText: TASK_NAME })).toBeVisible(); @@ -87,4 +100,51 @@ test.describe('GetFeatureInfo include list and more-info', () => { ); await expect(table.locator('th', { hasText: /^id$/ })).toHaveCount(0); }); + + test('empty field list keeps the original properties and the more-info row', async ({ + page, + }) => { + const { profileBody, table } = await identifyWithFieldList(page, []); + const seeded = profileBody.layers?.find((item) => item.layers?.includes(LAYER_NAME)); + expect(seeded?.featureInfoFields).toHaveLength(0); + expect(profileBody.tasks?.some((task) => task.name === TASK_NAME)).toBe(true); + + await expect(table.locator('th', { hasText: /^id$/ })).toBeVisible(); + await expect( + table.locator('tr', { has: page.locator('th', { hasText: /^id$/ }) }).locator('td'), + ).toHaveText('1'); + await expect(table.locator('th', { hasText: /^name$/ })).toBeVisible(); + await expect( + table.locator('tr', { has: page.locator('th', { hasText: /^name$/ }) }).locator('td'), + ).toHaveText('e2e-gfi-click'); + await expect(table.locator('th', { hasText: TASK_NAME })).toBeVisible(); + await expect(table.locator('a.sitmun-more-info-link')).toHaveAttribute( + 'href', + 'https://example.org/item/1', + ); + }); + + test('listed fields stay when one name misses the feature', async ({ page }) => { + const { profileBody, table } = await identifyWithFieldList(page, [ + { name: 'name', label: 'Place', format: 'T', order: 0 }, + { name: 'missing-attr', label: 'Missing', format: 'T', order: 1 }, + ]); + const seeded = profileBody.layers?.find((item) => item.layers?.includes(LAYER_NAME)); + const labels = seeded?.featureInfoFields?.map((field) => field.label) ?? []; + expect(labels).toEqual(expect.arrayContaining(['Place', 'Missing'])); + + await expect( + table.locator('tr', { has: page.locator('th', { hasText: /^Place$/ }) }).locator('td'), + ).toHaveText('e2e-gfi-click'); + await expect( + table.locator('tr', { has: page.locator('th', { hasText: /^Missing$/ }) }).locator('td'), + ).toHaveText(''); + await expect(table.locator('th', { hasText: /^id$/ })).toHaveCount(0); + await expect(table.locator('th', { hasText: /^name$/ })).toHaveCount(0); + await expect(table.locator('a.sitmun-more-info-link')).toHaveAttribute( + 'href', + 'https://example.org/item/1', + ); + await expect(table.locator('tr')).toHaveCount(3); + }); }); diff --git a/front/viewer/sitmun-viewer-app b/front/viewer/sitmun-viewer-app index ab1301a..3f79db3 160000 --- a/front/viewer/sitmun-viewer-app +++ b/front/viewer/sitmun-viewer-app @@ -1 +1 @@ -Subproject commit ab1301ae3d5ea4bd6e8a470b9861e27578ca3f8e +Subproject commit 3f79db37da2a7b2509840f3fe410463676366a88 From 2b7d2ec05633ca89aea4c5f34903a824fcd8bd5c Mon Sep 17 00:00:00 2001 From: Francisco J Lopez-Pellicer Date: Wed, 30 Sep 2026 15:50:23 +0200 Subject: [PATCH 7/7] ci: run Actions on Node 24 checkout, setup-java, and setup-node v4 are forced off Node 20, and setup-java v4 is deprecated. upload-artifact and setup-python move to the first majors that run on Node 24. --- .github/workflows/e2e.yml | 48 +++++++++---------- .github/workflows/liquibase-immutability.yml | 4 +- .github/workflows/liquibase-seed-identity.yml | 4 +- .github/workflows/liquibase-upgrade.yml | 14 +++--- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 6af953c..8613670 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -10,19 +10,19 @@ jobs: timeout-minutes: 45 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: recursive - name: Set up Java 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: '17' cache: gradle - name: Set up Node 20 - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '20' cache: npm @@ -47,7 +47,7 @@ jobs: - name: Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: playwright-admin-artifacts path: | @@ -60,19 +60,19 @@ jobs: timeout-minutes: 45 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: recursive - name: Set up Java 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: '17' cache: gradle - name: Set up Node 20 - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '20' cache: npm @@ -97,7 +97,7 @@ jobs: - name: Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: playwright-viewer-artifacts path: | @@ -110,19 +110,19 @@ jobs: timeout-minutes: 45 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: recursive - name: Set up Java 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: '17' cache: gradle - name: Set up Node 20 - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '20' cache: npm @@ -152,7 +152,7 @@ jobs: - name: Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: playwright-application-contact-artifacts path: | @@ -165,19 +165,19 @@ jobs: timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: recursive - name: Set up Java 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: '17' cache: gradle - name: Set up Node 20 - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '20' cache: npm @@ -207,7 +207,7 @@ jobs: - name: Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: playwright-mia-cross-artifacts path: | @@ -220,19 +220,19 @@ jobs: timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: recursive - name: Set up Java 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: '17' cache: gradle - name: Set up Node 20 - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '20' cache: npm @@ -251,7 +251,7 @@ jobs: - name: Upload Playwright artifacts if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: playwright-mobile-web-artifacts path: | @@ -264,19 +264,19 @@ jobs: timeout-minutes: 120 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: recursive - name: Set up Java 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: '17' cache: gradle - name: Set up Node 20 - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '20' cache: npm @@ -322,7 +322,7 @@ jobs: - name: Upload Android E2E artifacts if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: mobile-android-artifacts path: test-results/mobile-android/ diff --git a/.github/workflows/liquibase-immutability.yml b/.github/workflows/liquibase-immutability.yml index cd7af65..31446c1 100644 --- a/.github/workflows/liquibase-immutability.yml +++ b/.github/workflows/liquibase-immutability.yml @@ -10,13 +10,13 @@ jobs: timeout-minutes: 5 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 submodules: recursive - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.12' diff --git a/.github/workflows/liquibase-seed-identity.yml b/.github/workflows/liquibase-seed-identity.yml index 0ff60dd..5fd22d4 100644 --- a/.github/workflows/liquibase-seed-identity.yml +++ b/.github/workflows/liquibase-seed-identity.yml @@ -16,12 +16,12 @@ jobs: timeout-minutes: 5 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.12' diff --git a/.github/workflows/liquibase-upgrade.yml b/.github/workflows/liquibase-upgrade.yml index 49233bc..e62619f 100644 --- a/.github/workflows/liquibase-upgrade.yml +++ b/.github/workflows/liquibase-upgrade.yml @@ -24,7 +24,7 @@ jobs: timeout-minutes: 5 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Extracted-tree helper unit tests run: python3 tools/tests/test_prepare_extracted_liquibase.py @@ -34,7 +34,7 @@ jobs: timeout-minutes: 20 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 fetch-tags: true @@ -56,7 +56,7 @@ jobs: source: ['1.2.8'] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 fetch-tags: true @@ -72,7 +72,7 @@ jobs: timeout-minutes: 20 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 @@ -88,7 +88,7 @@ jobs: source: ['1.2.6', '1.2.7', '1.2.8'] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 fetch-tags: true @@ -107,7 +107,7 @@ jobs: timeout-minutes: 60 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 fetch-tags: true @@ -125,7 +125,7 @@ jobs: timeout-minutes: 40 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 fetch-tags: true