From bb9c8613015b20f42454ebf63eb4bb3195fce0f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Garc=C3=ADa?= Date: Tue, 8 Oct 2024 07:48:59 +0200 Subject: [PATCH 001/116] Metadata editor / validation report improvements (#8395) * Metadata editor / validation report improvements: - Update buttons to display success and errors to use text instead of an icon. - Add style to display the display buttons greyed when the related rules are not displayed. - Show separate messages for success and errors. - If not success or errors reported don't show the expander to show the results in the validation rules. - Group the success and error messages. * Metadata editor / validation report improvements: - Fix the display of the expander. - Improve the a bit the layout of the error / success messages. - Improve the tooltips for the buttons to hide / show the messages. --- .../partials/validationreport.html | 108 ++++++++++++++++-- .../resources/catalog/locales/en-editor.json | 4 +- .../resources/catalog/style/gn_editor.less | 6 + 3 files changed, 106 insertions(+), 12 deletions(-) diff --git a/web-ui/src/main/resources/catalog/components/edit/validationreport/partials/validationreport.html b/web-ui/src/main/resources/catalog/components/edit/validationreport/partials/validationreport.html index cd08f145494..5b144314137 100644 --- a/web-ui/src/main/resources/catalog/components/edit/validationreport/partials/validationreport.html +++ b/web-ui/src/main/resources/catalog/components/edit/validationreport/partials/validationreport.html @@ -23,26 +23,30 @@ @@ -54,7 +58,67 @@ data-ng-repeat="type in ruleTypes" data-ng-class="'schematron-result-list-' + labelImportanceClass(type)" > + +
+
+

+ +  {{(type.label || type.id) | translate}} +

+
+ +
+ + + + + + + + + + + + +
+
+ +
@@ -70,7 +134,7 @@

data-ng-if="!type.schematronVerificationError" > @@ -83,11 +147,30 @@

+ + + + {{type.success}} / {{type.total}} + + +

-
@@ -51,7 +51,9 @@

scale

resolution

diff --git a/web-ui/src/main/resources/catalog/views/default/templates/recordView/technical.html b/web-ui/src/main/resources/catalog/views/default/templates/recordView/technical.html index 5c68e76a547..3df446c6aee 100644 --- a/web-ui/src/main/resources/catalog/views/default/templates/recordView/technical.html +++ b/web-ui/src/main/resources/catalog/views/default/templates/recordView/technical.html @@ -120,11 +120,8 @@

resourceEdition

language

From 78f8bfc2ed22607ceabf6709d229138e84616e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Garc=C3=ADa?= Date: Wed, 9 Oct 2024 13:03:36 +0200 Subject: [PATCH 005/116] Metadata indexing / ISO19139 / ISO19115-3.2018 / Escape graphic overview file name for JSON (#8412) --- .../src/main/plugin/iso19115-3.2018/index-fields/index.xsl | 2 +- .../iso19139/src/main/plugin/iso19139/index-fields/index.xsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/index-fields/index.xsl b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/index-fields/index.xsl index 207439102c6..9d67f38bac0 100644 --- a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/index-fields/index.xsl +++ b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/index-fields/index.xsl @@ -434,7 +434,7 @@ { - "url": "" + "url": "" , "nameObject": diff --git a/schemas/iso19139/src/main/plugin/iso19139/index-fields/index.xsl b/schemas/iso19139/src/main/plugin/iso19139/index-fields/index.xsl index 06c47aa519b..b38d4b12a0d 100644 --- a/schemas/iso19139/src/main/plugin/iso19139/index-fields/index.xsl +++ b/schemas/iso19139/src/main/plugin/iso19139/index-fields/index.xsl @@ -385,7 +385,7 @@ { - "url": "" + "url": "" , "nameObject": From a0465e3776901135c195082947d44c57f0473333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Prunayre?= Date: Thu, 6 Jun 2024 10:06:22 +0200 Subject: [PATCH 006/116] Harvester / ISO19115-3 / Better support missing metadata date info While harvesting, `extract-date-modified.xsl` is used to retrieve last update of the record. If empty, harvester will fail with: ``` [geonetwork.harvester] - Invalid ISO date: java.lang.IllegalArgumentException: Invalid ISO date: at org.fao.geonet.domain.ISODate.parseDate(ISODate.java:426) ~[gn-domain-4.4.5-SNAPSHOT.jar:?] at org.fao.geonet.domain.ISODate.setDateAndTime(ISODate.java:239) ~[gn-domain-4.4.5-SNAPSHOT.jar:?] at org.fao.geonet.domain.ISODate.(ISODate.java:117) ~[gn-domain-4.4.5-SNAPSHOT.jar:?] at org.fao.geonet.kernel.harvest.harvester.simpleurl.Aligner.addMetadata(Aligner.java:237) ~[gn-harvesters-4.4.5-SNAPSHOT.jar:?] at org.fao.geonet.kernel.harvest.harvester.simpleurl.Aligner.lambda$insertOrUpdate$0(Aligner.java:126) ~[gn-harvesters-4.4.5-SNAPSHOT.jar:?] ``` Fallback to now. --- .../iso19115-3.2018/extract-date-modified.xsl | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/extract-date-modified.xsl b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/extract-date-modified.xsl index a6546241b0a..73d8bf5ff4b 100644 --- a/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/extract-date-modified.xsl +++ b/schemas/iso19115-3.2018/src/main/plugin/iso19115-3.2018/extract-date-modified.xsl @@ -3,27 +3,21 @@ version="2.0" xmlns:cit="http://standards.iso.org/iso/19115/-3/cit/2.0" xmlns:mdb="http://standards.iso.org/iso/19115/-3/mdb/2.0" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + - - - - - - - - - - + From 3252d14711effe7f3a8b4b553b07b9951d0cb6c1 Mon Sep 17 00:00:00 2001 From: Ian Allen Date: Sun, 8 Sep 2024 07:13:08 -0300 Subject: [PATCH 007/116] Update external management url Add {objectId} property in external management url (base64 unique identifier for the record) Change external management type url property {type} so that it is fixed values so that same value can be used in {objectId} CMIS Fixed property names used for validation fields to be consistent with other names. Jcloud Updgade from jcloud 2.3.0 to jcloud 2.5.0 Add support for external management named properties similar to cmis Fix bug with deleting all resources as it was failing to identify folders correctly for azure blob. --- .../records/attachments/AbstractStore.java | 30 ++- .../api/records/attachments/CMISStore.java | 21 +- .../geonet/resources/CMISConfiguration.java | 57 +++--- .../config-cmis-overrides.properties | 4 +- .../resources/config-store/config-cmis.xml | 6 +- .../api/records/attachments/JCloudStore.java | 190 +++++++++++++++--- .../geonet/resources/JCloudConfiguration.java | 122 +++++++++-- .../JCloudMetadataNameValidator.java | 137 +++++++++++++ .../config-jcloud-overrides.properties | 6 + .../resources/config-store/config-jcloud.xml | 7 +- pom.xml | 2 +- 11 files changed, 498 insertions(+), 84 deletions(-) create mode 100644 datastorages/jcloud/src/main/java/org/fao/geonet/resources/JCloudMetadataNameValidator.java diff --git a/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java b/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java index c5291a59bbf..168e4e2a63c 100644 --- a/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java +++ b/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java @@ -1,6 +1,6 @@ /* * ============================================================================= - * === Copyright (C) 2019 Food and Agriculture Organization of the + * === Copyright (C) 2024 Food and Agriculture Organization of the * === United Nations (FAO-UN), United Nations World Food Programme (WFP) * === and United Nations Environment Programme (UNEP) * === @@ -44,12 +44,16 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Base64; import java.util.List; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public abstract class AbstractStore implements Store { + protected static final String RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR = ":"; + protected static final String RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_ESCAPED_SEPARATOR = "\\:"; + @Override public final List getResources(final ServiceContext context, final String metadataUuid, final Sort sort, final String filter) throws Exception { @@ -279,4 +283,28 @@ public String toString() { } }; } + + private String escapeResourceManagementExternalProperties(String value) { + return value.replace(RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR, RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_ESCAPED_SEPARATOR); +} + + /** + * Create an encoded base 64 object id contains the following fields to uniquely identify the resource + * The fields are separated by a colon ":" + * @param type to identify type of storage - document/folder + * @param visibility of the resource public/private + * @param metadataId internal metadata id + * @param version identifier which can be used to directly get this version. + * @param resourceId or filename of the resource + * @return based 64 object id + */ + protected String getResourceManagementExternalPropertiesObjectId(final String type, final MetadataResourceVisibility visibility, final Integer metadataId, final String version, + final String resourceId) { + return Base64.getEncoder().encodeToString( + ((type + RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR + + escapeResourceManagementExternalProperties(visibility == null ? "" : visibility.toString().toLowerCase()) + RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR + + metadataId + RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR + + escapeResourceManagementExternalProperties(version == null ? "" : version) + RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR + + escapeResourceManagementExternalProperties(resourceId)).getBytes())); + } } diff --git a/datastorages/cmis/src/main/java/org/fao/geonet/api/records/attachments/CMISStore.java b/datastorages/cmis/src/main/java/org/fao/geonet/api/records/attachments/CMISStore.java index de258b3a711..37fe8501899 100644 --- a/datastorages/cmis/src/main/java/org/fao/geonet/api/records/attachments/CMISStore.java +++ b/datastorages/cmis/src/main/java/org/fao/geonet/api/records/attachments/CMISStore.java @@ -1,6 +1,6 @@ /* * ============================================================================= - * === Copyright (C) 2001-2016 Food and Agriculture Organization of the + * === Copyright (C) 2001-2024 Food and Agriculture Organization of the * === United Nations (FAO-UN), United Nations World Food Programme (WFP) * === and United Nations Environment Programme (UNEP) * === @@ -627,8 +627,10 @@ private GeonetworkDataDirectory getDataDirectory(ServiceContext context) { /** * get external resource management for the supplied resource. * Replace the following + * {objectId} type:visibility:metadataId:version:resourceId in base64 encoding * {id} resource id - * {type:folder:document} // If the type is folder then type "folder" will be displayed else if document then "document" will be displayed + * {type:folder:document} // Custom return type based on type. If the type is folder then type "folder" will be displayed else if document then "document" will be displayed + * {type} // If the type is folder then type "folder" will be displayed else if document then "document" will be displayed * {uuid} metadatauuid * {metadataid} metadataid * {visibility} visibility @@ -657,16 +659,27 @@ protected MetadataResourceExternalManagementProperties getMetadataResourceExtern ) { String metadataResourceExternalManagementPropertiesUrl = cmisConfiguration.getExternalResourceManagementUrl(); if (!StringUtils.isEmpty(metadataResourceExternalManagementPropertiesUrl)) { + // {objectid} objectId // It will be the type:visibility:metadataId:version:resourceId in base64 + // i.e. folder::100::100 # Folder in resource 100 + // i.e. document:public:100:v1:sample.jpg # public document 100 version v1 name sample.jpg + if (metadataResourceExternalManagementPropertiesUrl.contains("{objectid}")) { + metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("(\\{objectid\\})", + getResourceManagementExternalPropertiesObjectId((type == null ? "document" : (type instanceof Folder ? "folder" : "document")), visibility, metadataId, version, resourceId)); + } // {id} id if (metadataResourceExternalManagementPropertiesUrl.contains("{id}")) { metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("(\\{id\\})", (resourceId==null?"":resourceId)); } - // {type:folder:document} // If the type is folder then type "folder" will be displayed else if document then "document" will be displayed + // {type:folder:document} // Custom return type based on type. If the type is folder then type "folder" will be displayed else if document then "document" will be displayed if (metadataResourceExternalManagementPropertiesUrl.contains("{type:")) { metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("\\{type:([a-zA-Z0-9]*?):([a-zA-Z0-9]*?)\\}", (type==null?"":(type instanceof Folder?"$1":"$2"))); } - + // {type} // If the type is folder then type "folder" will be displayed else if document then "document" will be displayed + if (metadataResourceExternalManagementPropertiesUrl.contains("{type}")) { + metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("(\\{type\\})", + (type == null ? "document" : (type instanceof Folder ? "folder" : "document"))); + } // {uuid} metadatauuid if (metadataResourceExternalManagementPropertiesUrl.contains("{uuid}")) { metadataResourceExternalManagementPropertiesUrl = metadataResourceExternalManagementPropertiesUrl.replaceAll("(\\{uuid\\})", (metadataUuid==null?"":metadataUuid)); diff --git a/datastorages/cmis/src/main/java/org/fao/geonet/resources/CMISConfiguration.java b/datastorages/cmis/src/main/java/org/fao/geonet/resources/CMISConfiguration.java index 257ef3246d6..87b76ec0821 100644 --- a/datastorages/cmis/src/main/java/org/fao/geonet/resources/CMISConfiguration.java +++ b/datastorages/cmis/src/main/java/org/fao/geonet/resources/CMISConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2016 Food and Agriculture Organization of the + * Copyright (C) 2001-2024 Food and Agriculture Organization of the * United Nations (FAO-UN), United Nations World Food Programme (WFP) * and United Nations Environment Programme (UNEP) * @@ -59,26 +59,28 @@ public class CMISConfiguration { private Session client = null; - public final static Integer CMIS_MAX_ITEMS_PER_PAGE = 1000; - public final static String CMIS_FOLDER_DELIMITER = "/"; // Specs indicate that "/" is the folder delimiter/separator - not sure if other delimiter can be used?. - public final static String CMIS_SECONDARY_PROPERTY_SEPARATOR = "->"; - private final String CMIS_DEFAULT_WEBSERVICES_ACL_SERVICE = "/services/ACLService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_DISCOVERY_SERVICE = "/services/DiscoveryService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_MULTIFILING_SERVICE = "/services/MultiFilingService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_NAVIGATION_SERVICE = "/services/NavigationService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_OBJECT_SERVICE = "/services/ObjectService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_POLICY_SERVICE = "/services/PolicyService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_RELATIONSHIP_SERVICE = "/services/RelationshipService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_REPOSITORY_SERVICE = "/services/RepositoryService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_VERSIONING_SERVICE = "/services/VersioningService?wsdl"; - private final String CMIS_DEFAULT_WEBSERVICES_BASE_URL_SERVICE = "/cmis"; - private final String CMIS_DEFAULT_BROWSER_URL_SERVICE = "/browser"; - private final String CMIS_DEFAULT_ATOMPUB_URL_SERVICE = "/atom"; - - private final String CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_WINDOW_PARAMETERS = "toolbar=0,width=600,height=600"; - private final Boolean CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_MODAL_ENABLED = true; - private final Boolean CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_FOLDER_ENABLED = true; - private final Boolean CMIS_DEFAULT_VERSIONING_ENABLED = false; + // DFO change to 100. Due to bug with open text cmis where if max is set to 1000, it will return 100 but if it is set to 100 it will return all records. + // https://dev.azure.com/foc-poc/EDH-CDE/_workitems/edit/95878 + public static final Integer CMIS_MAX_ITEMS_PER_PAGE = 100; + public static final String CMIS_FOLDER_DELIMITER = "/"; // Specs indicate that "/" is the folder delimiter/separator - not sure if other delimiter can be used?. + public static final String CMIS_SECONDARY_PROPERTY_SEPARATOR = "->"; + private static final String CMIS_DEFAULT_WEBSERVICES_ACL_SERVICE = "/services/ACLService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_DISCOVERY_SERVICE = "/services/DiscoveryService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_MULTIFILING_SERVICE = "/services/MultiFilingService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_NAVIGATION_SERVICE = "/services/NavigationService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_OBJECT_SERVICE = "/services/ObjectService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_POLICY_SERVICE = "/services/PolicyService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_RELATIONSHIP_SERVICE = "/services/RelationshipService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_REPOSITORY_SERVICE = "/services/RepositoryService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_VERSIONING_SERVICE = "/services/VersioningService?wsdl"; + private static final String CMIS_DEFAULT_WEBSERVICES_BASE_URL_SERVICE = "/cmis"; + private static final String CMIS_DEFAULT_BROWSER_URL_SERVICE = "/browser"; + private static final String CMIS_DEFAULT_ATOMPUB_URL_SERVICE = "/atom"; + + private static final String CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_WINDOW_PARAMETERS = "toolbar=0,width=600,height=600"; + private static final Boolean CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_MODAL_ENABLED = true; + private static final Boolean CMIS_DEFAULT_EXTERNAL_RESOURCE_MANAGEMENT_FOLDER_ENABLED = true; + private static final Boolean CMIS_DEFAULT_VERSIONING_ENABLED = false; private String servicesBaseUrl; private String bindingType; @@ -111,7 +113,6 @@ public class CMISConfiguration { * Property name for validation status that is expected to be an integer with values of null, 0, 1, 2 * (See MetadataResourceExternalManagementProperties.ValidationStatus for code meaning) * Property name follows the same format as cmisMetadataUUIDPropertyName - * * If null then validation status will default to UNKNOWN. */ private String externalResourceManagementValidationStatusPropertyName; @@ -505,7 +506,6 @@ public void setExternalResourceManagementValidationStatusPropertyName(String ext String.format("Invalid format for property name %s property will not be used", externalResourceManagementValidationStatusPropertyName)); this.externalResourceManagementValidationStatusPropertyName = null; this.externalResourceManagementValidationStatusSecondaryProperty = false; - return; } else { this.externalResourceManagementValidationStatusSecondaryProperty = true; } @@ -514,7 +514,7 @@ public void setExternalResourceManagementValidationStatusPropertyName(String ext public MetadataResourceExternalManagementProperties.ValidationStatus getValidationStatusDefaultValue() { // We only need to set the default if there is a status property supplied, and it is not already set - if (this.defaultStatus == null && !org.springframework.util.StringUtils.isEmpty(getExternalResourceManagementValidationStatusPropertyName())) { + if (this.defaultStatus == null && org.springframework.util.StringUtils.hasLength(getExternalResourceManagementValidationStatusPropertyName())) { if (getExternalResourceManagementValidationStatusDefaultValue() != null) { // If a default property name does exist then use it this.defaultStatus = MetadataResourceExternalManagementProperties.ValidationStatus.valueOf(getExternalResourceManagementValidationStatusDefaultValue()); @@ -536,9 +536,8 @@ public void init() { } // default factory implementation - Map parameters = new HashMap(); + Map parameters = new HashMap<>(); - this.baseRepositoryPath = baseRepositoryPath; if (this.baseRepositoryPath == null) { this.baseRepositoryPath = ""; } @@ -609,7 +608,7 @@ public void init() { } } } else { - // Try to find the repository name for the id that we have specified.. + // Try to find the repository name for the id that we have specified. try { for (Repository repository : factory.getRepositories(parameters)) { if (repository.getId().equalsIgnoreCase(this.repositoryId)) { @@ -633,7 +632,7 @@ public void init() { repositoryUrl + "' using product '" + client.getRepositoryInfo().getProductName() + "' version '" + client.getRepositoryInfo().getProductVersion() + "'."); - // Check if we can parse the secondary parameters from human readable to secondary ids. + // Check if we can parse the secondary parameters from human-readable to secondary ids. parsedCmisMetadataUUIDPropertyName = parseSecondaryProperty(client, cmisMetadataUUIDPropertyName); parsedExternalResourceManagementValidationStatusPropertyName = parseSecondaryProperty(client, externalResourceManagementValidationStatusPropertyName); @@ -743,7 +742,7 @@ public boolean existExternalResourceManagementValidationStatusSecondaryProperty( } /** - * Generte a full url based on the supplied entered serviceurl and the default. + * Generate a full url based on the supplied entered serviceUrl and the default. * * @param baseUrl Base url * @param serviceUrl Supplied service url (This could start with / or http. If it starts with http then ignore baseUrl) diff --git a/datastorages/cmis/src/main/resources/config-store/config-cmis-overrides.properties b/datastorages/cmis/src/main/resources/config-store/config-cmis-overrides.properties index f0a62c1920a..4c154639ca5 100644 --- a/datastorages/cmis/src/main/resources/config-store/config-cmis-overrides.properties +++ b/datastorages/cmis/src/main/resources/config-store/config-cmis-overrides.properties @@ -11,8 +11,8 @@ cmis.external.resource.management.window.parameters=${CMIS_EXTERNAL_RESOURCE_MAN cmis.external.resource.management.modal.enabled=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_MODAL_ENABLED:#{null}} cmis.external.resource.management.folder.enabled=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_FOLDER_ENABLED:#{null}} cmis.external.resource.management.folder.root=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_FOLDER_ROOT:#{null}} -cmis.external.resource.status.property.name=${CMIS_EXTERNAL_RESOURCE_STATUS_PROPERTY_NAME:#{null}} -cmis.external.resource.management.status.default.value=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_STATUS_DEFAULT_VALUE:#{null}} +cmis.external.resource.management.validation.status.property.name=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_VALIDATION_STATUS_PROPERTY_NAME:#{null}} +cmis.external.resource.management.validation.status.default.value=${CMIS_EXTERNAL_RESOURCE_MANAGEMENT_VALIDATION_STATUS_DEFAULT_VALUE:#{null}} cmis.versioning.enabled=${CMIS_VERSIONING_ENABLED:#{null}} cmis.versioning.state=#{'${CMIS_VERSIONING_STATE:MAJOR}'.toUpperCase()} diff --git a/datastorages/cmis/src/main/resources/config-store/config-cmis.xml b/datastorages/cmis/src/main/resources/config-store/config-cmis.xml index 76abe73572c..1c302788b5c 100644 --- a/datastorages/cmis/src/main/resources/config-store/config-cmis.xml +++ b/datastorages/cmis/src/main/resources/config-store/config-cmis.xml @@ -1,6 +1,6 @@ -

- {{table.name}} -

- + +

+ {{table.name}} +

+ -

+

{{count | number}} / {{countTotal | number}} features + >features

- - - - +
- +
diff --git a/web/pom.xml b/web/pom.xml index feb7ee4c3cd..802d0f10586 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -30,7 +30,7 @@ org.geonetwork-opensource geonetwork - 4.4.6-0 + 4.4.7-SNAPSHOT diff --git a/web/src/main/webResources/WEB-INF/config-db/database_migration.xml b/web/src/main/webResources/WEB-INF/config-db/database_migration.xml index 38de48bb7c0..aa87fe9adcb 100644 --- a/web/src/main/webResources/WEB-INF/config-db/database_migration.xml +++ b/web/src/main/webResources/WEB-INF/config-db/database_migration.xml @@ -400,5 +400,10 @@ WEB-INF/classes/setup/sql/migrate/v446/migrate- + + + WEB-INF/classes/setup/sql/migrate/v447/migrate- + + diff --git a/web/src/main/webapp/WEB-INF/classes/setup/sql/data/data-db-default.sql b/web/src/main/webapp/WEB-INF/classes/setup/sql/data/data-db-default.sql index 8bb03368e89..3720a1cc46e 100644 --- a/web/src/main/webapp/WEB-INF/classes/setup/sql/data/data-db-default.sql +++ b/web/src/main/webapp/WEB-INF/classes/setup/sql/data/data-db-default.sql @@ -574,8 +574,8 @@ INSERT INTO Operations (id, name) VALUES (6,'featured'); INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/site/name', 'My GeoNetwork catalogue', 0, 110, 'n'); INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/site/siteId', '', 0, 120, 'n'); INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/site/organization', 'My organization', 0, 130, 'n'); -INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/platform/version', '4.4.6', 0, 150, 'n'); -INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/platform/subVersion', '0', 0, 160, 'n'); +INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/platform/version', '4.4.7', 0, 150, 'n'); +INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/platform/subVersion', 'SNAPSHOT', 0, 160, 'n'); INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/site/svnUuid', '', 0, 170, 'y'); INSERT INTO Settings (name, value, datatype, position, internal) VALUES ('system/server/host', 'localhost', 0, 210, 'n'); diff --git a/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v447/migrate-default.sql b/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v447/migrate-default.sql new file mode 100644 index 00000000000..0a97404565b --- /dev/null +++ b/web/src/main/webapp/WEB-INF/classes/setup/sql/migrate/v447/migrate-default.sql @@ -0,0 +1,2 @@ +UPDATE Settings SET value='4.4.7' WHERE name='system/platform/version'; +UPDATE Settings SET value='SNAPSHOT' WHERE name='system/platform/subVersion'; diff --git a/workers/camelPeriodicProducer/pom.xml b/workers/camelPeriodicProducer/pom.xml index 44117377b4c..80eef98c055 100644 --- a/workers/camelPeriodicProducer/pom.xml +++ b/workers/camelPeriodicProducer/pom.xml @@ -5,7 +5,7 @@ gn-workers org.geonetwork-opensource - 4.4.6-0 + 4.4.7-SNAPSHOT 4.0.0 diff --git a/workers/pom.xml b/workers/pom.xml index a08432ae2cd..83ebdb8853c 100644 --- a/workers/pom.xml +++ b/workers/pom.xml @@ -28,7 +28,7 @@ geonetwork org.geonetwork-opensource - 4.4.6-0 + 4.4.7-SNAPSHOT 4.0.0 diff --git a/workers/wfsfeature-harvester/pom.xml b/workers/wfsfeature-harvester/pom.xml index a867c6182ed..43c09a3151b 100644 --- a/workers/wfsfeature-harvester/pom.xml +++ b/workers/wfsfeature-harvester/pom.xml @@ -28,7 +28,7 @@ gn-workers org.geonetwork-opensource - 4.4.6-0 + 4.4.7-SNAPSHOT 4.0.0 diff --git a/wro4j/pom.xml b/wro4j/pom.xml index b31767f9ed9..9f7948c9ebf 100644 --- a/wro4j/pom.xml +++ b/wro4j/pom.xml @@ -7,7 +7,7 @@ org.geonetwork-opensource geonetwork - 4.4.6-0 + 4.4.7-SNAPSHOT From 43a57af1d6c4cc834a337b934603c3449845fe6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Prunayre?= Date: Tue, 22 Oct 2024 13:17:04 +0200 Subject: [PATCH 040/116] XSL utility / Add function to retrieve thesaurus URI RDF based schema plugins may need the URI of vocabularies in a number of places. This utility is used in the DCAT-AP plugin when building concept elements in thesaurus-transformation.xsl: eg. ``` public public ``` --- core/src/main/java/org/fao/geonet/util/XslUtil.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/util/XslUtil.java b/core/src/main/java/org/fao/geonet/util/XslUtil.java index 34b9ae272ee..c6e5ca26576 100644 --- a/core/src/main/java/org/fao/geonet/util/XslUtil.java +++ b/core/src/main/java/org/fao/geonet/util/XslUtil.java @@ -1440,7 +1440,7 @@ public static String getThesaurusIdByTitle(String title) { return thesaurus == null ? "" : "geonetwork.thesaurus." + thesaurus.getKey(); } - + /** * Retrieve the thesaurus title using the thesaurus key. * @@ -1455,6 +1455,15 @@ public static String getThesaurusTitleByKey(String id) { } + public static String getThesaurusUriByKey(String id) { + ApplicationContext applicationContext = ApplicationContextHolder.get(); + ThesaurusManager thesaurusManager = applicationContext.getBean(ThesaurusManager.class); + Thesaurus thesaurus = thesaurusManager.getThesaurusByName(id); + return thesaurus == null ? "" : thesaurus.getDefaultNamespace(); + } + + + /** * Utility method to retrieve the name (label) for an iso language using it's code for a specific language. *

@@ -1594,7 +1603,7 @@ private static List buildRecordLink(List hits, String type) { public static String escapeForJson(String value) { return StringEscapeUtils.escapeJson(value); } - + public static String getWebAnalyticsService() { ApplicationContext applicationContext = ApplicationContextHolder.get(); WebAnalyticsConfiguration webAnalyticsConfiguration = applicationContext.getBean(WebAnalyticsConfiguration.class); From d8a5b721346347440305aff382bcfa06a93a067a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Garc=C3=ADa?= Date: Mon, 28 Oct 2024 17:06:44 +0100 Subject: [PATCH 041/116] Metadata status changes notification mails improvements: (#8453) - Don't add saludation if the user to notify is the catalogue administrator (defined in settings), as only has the email address. - Filter out the users without mail when retrieving the users to notify. --- .../kernel/metadata/DefaultStatusActions.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/kernel/metadata/DefaultStatusActions.java b/core/src/main/java/org/fao/geonet/kernel/metadata/DefaultStatusActions.java index 58cc82a4459..8c0c0ca2b33 100644 --- a/core/src/main/java/org/fao/geonet/kernel/metadata/DefaultStatusActions.java +++ b/core/src/main/java/org/fao/geonet/kernel/metadata/DefaultStatusActions.java @@ -48,6 +48,8 @@ import org.springframework.context.ApplicationContext; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.fao.geonet.kernel.setting.Settings.SYSTEM_FEEDBACK_EMAIL; import static org.fao.geonet.util.LocalizedEmailComponent.ComponentType.*; @@ -330,22 +332,24 @@ protected void notify(List userToNotify, MetadataStatus status) throws Exc ); } - LocalizedEmail localizedEmail = new LocalizedEmail(false); - localizedEmail.addComponents(emailSubjectComponent, emailMessageComponent, emailSalutationComponent); - - String subject = localizedEmail.getParsedSubject(feedbackLocales); - for (User user : userToNotify) { + LocalizedEmail localizedEmail = new LocalizedEmail(false); + String userName = Joiner.on(" ").skipNulls().join(user.getName(), user.getSurname()); //If we have a userName add the salutation String message; if (StringUtils.isEmpty(userName)) { + localizedEmail.addComponents(emailSubjectComponent, emailMessageComponent); + message = localizedEmail.getParsedMessage(feedbackLocales); } else { + localizedEmail.addComponents(emailSubjectComponent, emailMessageComponent, emailSalutationComponent); + Map replacements = new HashMap<>(); replacements.put("{{userName}}", userName); message = localizedEmail.getParsedMessage(feedbackLocales, replacements); } + String subject = localizedEmail.getParsedSubject(feedbackLocales); sendEmail(user.getEmail(), subject, message); } } @@ -449,7 +453,9 @@ public static List getUserToNotify(StatusValueNotificationLevel notificati } } } - return users; + + // Filter out users without email + return users.stream().filter(u -> StringUtils.isNotEmpty(u.getEmail())).collect(Collectors.toList()); } public static List getGroupToNotify(StatusValueNotificationLevel notificationLevel, List groupNames) { From ea9290597fe1fc4c81d92c42ee8f22756b1799c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Garc=C3=ADa?= Date: Tue, 29 Oct 2024 09:59:29 +0100 Subject: [PATCH 042/116] Documentation / Update managing privileges page: - Remove outdated Featured privilege. - Add Editing privilege and update the related rules description. --- .../user-guide/publishing/managing-privileges.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/manual/docs/user-guide/publishing/managing-privileges.md b/docs/manual/docs/user-guide/publishing/managing-privileges.md index 7670dbff69e..2bb33525d01 100644 --- a/docs/manual/docs/user-guide/publishing/managing-privileges.md +++ b/docs/manual/docs/user-guide/publishing/managing-privileges.md @@ -16,11 +16,11 @@ Below is a brief description for each privilege to help you identify which ones **Publish**: Users in the specified group/s are able to view the metadata eg. if it matches search criteria entered by such a user. -**Download**: Users in the specified group/s are able to download the data. - **Interactive Map**: Users in the specified group/s are able to get an interactive map. The interactive map has to be created separately using a Web Map Server such as GeoServer, which is distributed with GeoNetwork. -**Featured**: When randomly selected by GeoNetwork, the metadata record can appear in the `Featured` section of the GeoNetwork home page. +**Download**: Users in the specified group/s are able to download the data. + +**Editing**: Users in the specified group/s are able to edit the metadata, if they have the *editor* profile. **Notify**: Users in the specified group receive notification if data attached to the metadata record is downloaded. @@ -57,12 +57,13 @@ Any user (logged in or not) can view the public metadata. An *administrator* can edit any metadata. -A *reviewer* can edit a metadata if: +A *reviewer* / *editor* can edit a metadata if: + +* They are the metadata owner. + +* The metadata has editing privilege in the group(s) where the user is a *reviewer* / *editor*. -- The metadata owner is member of one of the groups assigned to the reviewer. -- They are the metadata owner. -A *User Administrator* or an *Editor* can only edit metadata they created. # Setting Privileges From 750080398df027c17cf4fff826226172ce6f9d6f Mon Sep 17 00:00:00 2001 From: wangf1122 <74916635+wangf1122@users.noreply.github.com> Date: Tue, 29 Oct 2024 06:08:05 -0400 Subject: [PATCH 043/116] option to force xsd schema check for required field (#8294) * option to force xsd schema check for required field * remove xsd schema check in form builder is required logic * adjust label xml check before dtd checking --- web/src/main/webapp/xslt/ui-metadata/form-builder.xsl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/web/src/main/webapp/xslt/ui-metadata/form-builder.xsl b/web/src/main/webapp/xslt/ui-metadata/form-builder.xsl index 6426cb3de27..d7c5efd2497 100644 --- a/web/src/main/webapp/xslt/ui-metadata/form-builder.xsl +++ b/web/src/main/webapp/xslt/ui-metadata/form-builder.xsl @@ -106,6 +106,8 @@ + + + + + + + + - - - From 0de6cd4356dca862c8274f40e157ec08f341d5f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Garc=C3=ADa?= Date: Tue, 29 Oct 2024 11:11:47 +0100 Subject: [PATCH 044/116] Documentation / Metadata workflow improvements (#8473) * Documentation / Metadata workflow improvements * Update docs/manual/docs/user-guide/workflow/life-cycle.md Co-authored-by: Jody Garnett * Update docs/manual/docs/user-guide/workflow/life-cycle.md Co-authored-by: Jody Garnett --------- Co-authored-by: Jody Garnett --- .../docs/user-guide/workflow/life-cycle.md | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/manual/docs/user-guide/workflow/life-cycle.md b/docs/manual/docs/user-guide/workflow/life-cycle.md index c1bf876157f..70416aa4511 100644 --- a/docs/manual/docs/user-guide/workflow/life-cycle.md +++ b/docs/manual/docs/user-guide/workflow/life-cycle.md @@ -1,26 +1,29 @@ # Life cycle -## Record life cycle +Metadata records can have a lifecycle that typically goes through one or more states. This is an optional feature that +can be activated on demand (see [Activate the metadata workflow](#activate-workflow)). -Metadata records have a lifecycle that typically goes through one or more states. For example, when a record is: +For example, when a record is: - created and edited by an `Editor` it is in the `Draft` state. -- being reviewed by a `content reviewer`, or a review is requested brings the record to `Submitted` state. +- being reviewed by a `Content reviewer`, or a review is requested brings the record to `Submitted` state. - completed and corrected by the `Content Reviewer` it is in the `Approved` state. - superseded or replaced the state is `Retired`. -The catalog has (an extensible) set of states that a metadata record can have: +The catalog has a set of states that a metadata record can have: -- `Unknown` - this is the default state - nothing is known about the status of the metadata record. - `Draft` - the record is under construction or being edited. - `Submitted` - the record has been submitted for approval to a content review. - `Approved` - the content reviewer has reviewed and approved the metadata record. -- `Rejected` - the content reviewer has reviewed and rejected the metadata record. - `Retired` - the record has been retired. -Workflow can be enabled for the full catalogue, certain groups or on an individual record level. +When the metadata workflow is activated, the existing records are set in a special status `Unknown`. -In the last case, to enable workflow and change the status from `Unknown` to `Draft`, click the `enable workflow` button in the metadata view: +## Activate the metadata workflow {#activate-workflow} + +To enable the record life cycle, activate the metadata workflow. It can be activated for the full catalogue, certain groups, or on an individual record. + +In the case of activating for an individual record: enable workflow in a metadata, change the status from `Unknown` to `Draft`, and then click the `Enable workflow` button in the metadata view: ![](img/workflow-enable.png) @@ -28,10 +31,11 @@ In the last case, to enable workflow and change the status from `Unknown` to `Dr To use the workflow for metadata records created before enabling it, you must use the above option. +To enable workflow for the full catalogue or certain groups, check `Administration` --> `Settings` --> `Metadata Workflow`. In workflow mode, in case approved records are modified, you're working on a copy of the approved record. Changes on the record will not be visible to users outside your group until the modified record is approved again. -To enable workflow for the full catalogue or certain groups, check Administration --> Settings --> Metadata Workflow. In workflow mode, in case approved records are modified, you're working on a copy of the approved record. Changes on the record will not be visible to users outside your group until the modified record is approved again. +## Usage -When done editing you can submit a record for review by a content reviewer. The submit button is available on the `manage record` menu in the metadata view. A popup will open in which you can leave a message for the content reviewer. +When done editing you can submit a record for review by a content reviewer. The submit button is available on the `Manage record` menu in the metadata view. A popup will open in which you can leave a message for the content reviewer. ![](img/submit-for-review.png) From b62e6c27252767d084471ae66ea031280f2a7e93 Mon Sep 17 00:00:00 2001 From: tylerjmchugh <163562062+tylerjmchugh@users.noreply.github.com> Date: Tue, 29 Oct 2024 06:12:16 -0400 Subject: [PATCH 045/116] Add option to mock a dropdown for keywordPickers (#8401) * Implement attribute for mock dropdown * Implement styles for mock dropdown * Documentation * Modify directive to enable mock dropdown by default when showHintsOnFocus is enabled * retrigger checks * Implement showHintsOnFocus on multientrycombiner * Update styles so that the class is not required * Support show-hints-on-focus for language picker --- .../src/main/plugin/iso19139/layout/layout.xsl | 3 +++ .../partials/multientrycombiner.html | 1 + ...ntrycombiner_onlineresourcesdescription.html | 1 + .../components/thesaurus/ThesaurusDirective.js | 2 +- .../components/utility/UtilityDirective.js | 8 +++++++- .../views/default/less/gn_editor_default.less | 17 +++++++++++++++++ 6 files changed, 30 insertions(+), 2 deletions(-) diff --git a/schemas/iso19139/src/main/plugin/iso19139/layout/layout.xsl b/schemas/iso19139/src/main/plugin/iso19139/layout/layout.xsl index 726eeb40d78..e9955bed2d7 100644 --- a/schemas/iso19139/src/main/plugin/iso19139/layout/layout.xsl +++ b/schemas/iso19139/src/main/plugin/iso19139/layout/layout.xsl @@ -541,6 +541,9 @@ + + + diff --git a/web-ui/src/main/resources/catalog/components/edit/multientrycombiner/partials/multientrycombiner.html b/web-ui/src/main/resources/catalog/components/edit/multientrycombiner/partials/multientrycombiner.html index 6351bf308e2..76c6d3576d7 100644 --- a/web-ui/src/main/resources/catalog/components/edit/multientrycombiner/partials/multientrycombiner.html +++ b/web-ui/src/main/resources/catalog/components/edit/multientrycombiner/partials/multientrycombiner.html @@ -24,6 +24,7 @@ data-gn-keyword-picker="" data-thesaurus-key="{{c.thesaurus}}" data-number-of-suggestions="{{c.numberOfSuggestions || 20}}" + data-show-hints-on-focus="{{c.showHintsOnFocus || false}}" data-faux-multilingual="true" data-focus-to-input="false" lang="{{lang}}" diff --git a/web-ui/src/main/resources/catalog/components/edit/multientrycombiner/partials/multientrycombiner_onlineresourcesdescription.html b/web-ui/src/main/resources/catalog/components/edit/multientrycombiner/partials/multientrycombiner_onlineresourcesdescription.html index 4e85378e2e3..14dadc8d13c 100644 --- a/web-ui/src/main/resources/catalog/components/edit/multientrycombiner/partials/multientrycombiner_onlineresourcesdescription.html +++ b/web-ui/src/main/resources/catalog/components/edit/multientrycombiner/partials/multientrycombiner_onlineresourcesdescription.html @@ -19,6 +19,7 @@ data-gn-keyword-picker="" data-thesaurus-key="{{c.thesaurus}}" data-number-of-suggestions="{{c.numberOfSuggestions || 20}}" + data-show-hints-on-focus="{{c.showHintsOnFocus || false}}" data-faux-multilingual="true" data-focus-to-input="false" lang="{{lang}}" diff --git a/web-ui/src/main/resources/catalog/components/thesaurus/ThesaurusDirective.js b/web-ui/src/main/resources/catalog/components/thesaurus/ThesaurusDirective.js index 14567e0696a..3b371027283 100644 --- a/web-ui/src/main/resources/catalog/components/thesaurus/ThesaurusDirective.js +++ b/web-ui/src/main/resources/catalog/components/thesaurus/ThesaurusDirective.js @@ -662,7 +662,7 @@ scope.orderById = attrs.orderById || "false"; scope.max = gnThesaurusService.DEFAULT_NUMBER_OF_RESULTS; scope.fauxMultilingual = scope.fauxMultilingual === "true"; //default false - scope.showHintsOnFocus = attrs.showHintsOnFocus === "true"; // displays all the values on focus, default shows only the selected value + scope.showHintsOnFocus = attrs.showHintsOnFocus === "true"; // displays all the values on focus and adds a dropdown caret icon, default shows only the selected value // Configuration only required when using the directive in template fields. // diff --git a/web-ui/src/main/resources/catalog/components/utility/UtilityDirective.js b/web-ui/src/main/resources/catalog/components/utility/UtilityDirective.js index 493c85a99f6..8a765a04ff5 100644 --- a/web-ui/src/main/resources/catalog/components/utility/UtilityDirective.js +++ b/web-ui/src/main/resources/catalog/components/utility/UtilityDirective.js @@ -901,6 +901,7 @@ restrict: "A", link: function (scope, element, attrs) { scope.prefix = attrs["prefix"] || ""; + scope.showHintsOnFocus = attrs.showHintsOnFocus === "true"; // displays all the values on focus, default shows only the selected value element.attr("placeholder", "..."); element.on("focus", function () { $http @@ -945,7 +946,8 @@ $(element).typeahead( { minLength: 0, - highlight: true + highlight: true, + showHintsOnFocus: scope.showHintsOnFocus }, { name: "isoLanguages", @@ -958,6 +960,10 @@ } } ); + // Since the typeahead is initialized on focus the first focus will not trigger the hints + // So we blur then refocus to trigger the hints + $(element).blur(); + $(element).focus(); }); element.unbind("focus"); }); diff --git a/web-ui/src/main/resources/catalog/views/default/less/gn_editor_default.less b/web-ui/src/main/resources/catalog/views/default/less/gn_editor_default.less index 79345fda1af..f36b116924f 100644 --- a/web-ui/src/main/resources/catalog/views/default/less/gn_editor_default.less +++ b/web-ui/src/main/resources/catalog/views/default/less/gn_editor_default.less @@ -689,3 +689,20 @@ form.gn-editor.gn-indent-bluescale { content: ""; } } + +// Mock dropdown for typeahead +[data-show-hints-on-focus="true"]:not(.tt-hint) { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAMCAYAAABSgIzaAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDZFNDEwNjlGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDZFNDEwNkFGNzFEMTFFMkJEQ0VDRTM1N0RCMzMyMkIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NkU0MTA2N0Y3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NkU0MTA2OEY3MUQxMUUyQkRDRUNFMzU3REIzMzIyQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PuGsgwQAAAA5SURBVHjaYvz//z8DOYCJgUxAf42MQIzTk0D/M+KzkRGPoQSdykiKJrBGpOhgJFYTWNEIiEeAAAMAzNENEOH+do8AAAAASUVORK5CYII=); + background-repeat: no-repeat; + background-position: right; + padding-right: 1.5em; +} + +// Move mock dropdown caret in multilingual mode +.gn-multilingual-field { + div:not(:has(.tt-input[data-show-hints-on-focus="true"].hidden)) { + .tt-input[data-show-hints-on-focus="true"] { + background-position-y: 90%; + } + } +} From c93b5b131c9edd4da124229d414020a0cc5a2334 Mon Sep 17 00:00:00 2001 From: wangf1122 <74916635+wangf1122@users.noreply.github.com> Date: Fri, 1 Nov 2024 07:38:32 -0400 Subject: [PATCH 046/116] getResourceInternal implementation for cmis and jcloud (#8466) * getResourceInternal implementation for cmis and jcloud * Implementation in ResourceLoggerStore * User filesystemStore bean instead of resourceStore --- .../main/java/org/fao/geonet/util/XslUtil.java | 2 +- .../api/records/attachments/CMISStore.java | 15 ++++++++++++++- .../api/records/attachments/JCloudStore.java | 17 ++++++++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/util/XslUtil.java b/core/src/main/java/org/fao/geonet/util/XslUtil.java index c6e5ca26576..452ab855e75 100644 --- a/core/src/main/java/org/fao/geonet/util/XslUtil.java +++ b/core/src/main/java/org/fao/geonet/util/XslUtil.java @@ -1246,7 +1246,7 @@ public static String buildDataUrl(String url, Integer size) { Matcher m = Pattern.compile(settingManager.getNodeURL() + "api/records/(.*)/attachments/(.*)$").matcher(url); BufferedImage image; if (m.find()) { - Store store = ApplicationContextHolder.get().getBean(FilesystemStore.class); + Store store = ApplicationContextHolder.get().getBean("filesystemStore", Store.class); try (Store.ResourceHolder file = store.getResourceInternal( m.group(1), MetadataResourceVisibility.PUBLIC, diff --git a/datastorages/cmis/src/main/java/org/fao/geonet/api/records/attachments/CMISStore.java b/datastorages/cmis/src/main/java/org/fao/geonet/api/records/attachments/CMISStore.java index a158ae9a319..989dc719fc4 100644 --- a/datastorages/cmis/src/main/java/org/fao/geonet/api/records/attachments/CMISStore.java +++ b/datastorages/cmis/src/main/java/org/fao/geonet/api/records/attachments/CMISStore.java @@ -190,7 +190,20 @@ public ResourceHolder getResource(final ServiceContext context, final String met @Override public ResourceHolder getResourceInternal(String metadataUuid, MetadataResourceVisibility visibility, String resourceId, Boolean approved) throws Exception { - throw new UnsupportedOperationException("CMISStore does not support getResourceInternal."); + int metadataId = getAndCheckMetadataId(metadataUuid, approved); + checkResourceId(resourceId); + + try { + ServiceContext context = ServiceContext.get(); + final CmisObject object = cmisConfiguration.getClient().getObjectByPath(getKey(context, metadataUuid, metadataId, visibility, resourceId)); + return new ResourceHolderImpl(object, createResourceDescription(context, metadataUuid, visibility, resourceId, + (Document) object, metadataId, approved)); + } catch (CmisObjectNotFoundException e) { + throw new ResourceNotFoundException( + String.format("Metadata resource '%s' not found for metadata '%s'", resourceId, metadataUuid)) + .withMessageKey("exception.resourceNotFound.resource", new String[]{resourceId}) + .withDescriptionKey("exception.resourceNotFound.resource.description", new String[]{resourceId, metadataUuid}); + } } protected String getKey(final ServiceContext context, String metadataUuid, int metadataId, MetadataResourceVisibility visibility, String resourceId) { diff --git a/datastorages/jcloud/src/main/java/org/fao/geonet/api/records/attachments/JCloudStore.java b/datastorages/jcloud/src/main/java/org/fao/geonet/api/records/attachments/JCloudStore.java index ba300c53254..e4016a72e37 100644 --- a/datastorages/jcloud/src/main/java/org/fao/geonet/api/records/attachments/JCloudStore.java +++ b/datastorages/jcloud/src/main/java/org/fao/geonet/api/records/attachments/JCloudStore.java @@ -191,7 +191,22 @@ public ResourceHolder getResource(final ServiceContext context, final String met @Override public ResourceHolder getResourceInternal(String metadataUuid, MetadataResourceVisibility visibility, String resourceId, Boolean approved) throws Exception { - throw new UnsupportedOperationException("JCloud does not support getResourceInternal."); + int metadataId = getAndCheckMetadataId(metadataUuid, approved); + checkResourceId(resourceId); + + try { + ServiceContext context = ServiceContext.get(); + final Blob object = jCloudConfiguration.getClient().getBlobStore().getBlob( + jCloudConfiguration.getContainerName(), getKey(context, metadataUuid, metadataId, visibility, resourceId)); + return new ResourceHolderImpl(object, createResourceDescription(context, metadataUuid, visibility, resourceId, + object.getMetadata(), metadataId, approved)); + } catch (ContainerNotFoundException e) { + throw new ResourceNotFoundException( + String.format("Metadata resource '%s' not found for metadata '%s'", resourceId, metadataUuid)) + .withMessageKey("exception.resourceNotFound.resource", new String[]{resourceId}) + .withDescriptionKey("exception.resourceNotFound.resource.description", new String[]{resourceId, metadataUuid}); + } + } protected String getKey(final ServiceContext context, String metadataUuid, int metadataId, MetadataResourceVisibility visibility, String resourceId) { From cd50dedd9046ee3a676bf9e1af57c5b0767bad8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Garc=C3=ADa?= Date: Mon, 4 Nov 2024 16:22:35 +0100 Subject: [PATCH 047/116] Configuration to display an application banner (#8416) * Add configuration to display an application banner * Add configuration to display an application banner - use translations for the message * Application banner - update style --- .../resources/catalog/locales/en-admin.json | 3 +++ .../resources/catalog/style/gn_search.less | 9 +++++++++ .../templates/admin/settings/system.html | 1 - .../views/default/directives/directive.js | 19 +++++++++++++++++++ .../partials/applicationBanner.html | 3 +++ .../views/default/templates/index.html | 2 ++ .../setup/sql/data/data-db-default.sql | 3 +++ .../sql/migrate/v446/migrate-default.sql | 2 ++ 8 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 web-ui/src/main/resources/catalog/views/default/directives/partials/applicationBanner.html diff --git a/web-ui/src/main/resources/catalog/locales/en-admin.json b/web-ui/src/main/resources/catalog/locales/en-admin.json index 7f3cd11fd34..18eba6e7a79 100644 --- a/web-ui/src/main/resources/catalog/locales/en-admin.json +++ b/web-ui/src/main/resources/catalog/locales/en-admin.json @@ -850,6 +850,9 @@ "system/xlinkResolver/localXlinkEnable-help": "Local XLinks are using local:/// URL to make references to related sections instead of HTTP URL. Local XLinks are usually faster than HTTP XLinks.", "system/xlinkResolver/ignore": "Elements to ignore by XLink resolution", "system/xlinkResolver/ignore-help": "Comma separated list of elements to ignore by XLink resolution", + "system/banner": "Application banner", + "system/banner/enable": "Enable", + "system/banner/enable-help": "If set, an application banner is displayed with the message configured. To configure the message, go to Language and translations and configure a translation with the key application-banner", "metadata/workflow": "Metadata workflow", "metadata/workflow/automaticUnpublishInvalidMd": "Automatic unpublication of invalid metadata", "metadata/workflow/automaticUnpublishInvalidMd-help": " Automatically unpublishes metadata that is edited that becomes not valid according to xsd or schematron rules.", diff --git a/web-ui/src/main/resources/catalog/style/gn_search.less b/web-ui/src/main/resources/catalog/style/gn_search.less index 990fb699d59..88a286e9383 100644 --- a/web-ui/src/main/resources/catalog/style/gn_search.less +++ b/web-ui/src/main/resources/catalog/style/gn_search.less @@ -608,6 +608,15 @@ } } +.application-banner { + background-color: #fff8c5; + border: 1px solid #d4a72c66; + margin: 15px; + padding: 15px; + border-radius: 4px; + color: #000; +} + button:focus [role="tooltip"], button:hover [role="tooltip"] { clip: auto; diff --git a/web-ui/src/main/resources/catalog/templates/admin/settings/system.html b/web-ui/src/main/resources/catalog/templates/admin/settings/system.html index 6adfb7f93a1..cb22bbd21c2 100644 --- a/web-ui/src/main/resources/catalog/templates/admin/settings/system.html +++ b/web-ui/src/main/resources/catalog/templates/admin/settings/system.html @@ -397,7 +397,6 @@

{{section2.name | translate}}

> {{s.value}} -
+ +
+ + +
+ +
+
From 56a4069c99d56e8f5c1265380bb62070b6f6689d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20Gabri=C3=ABl?= Date: Fri, 8 Nov 2024 13:04:29 +0100 Subject: [PATCH 051/116] Change icon for the layer tools in the layer manager panel on the map page (#8376) * Change icon for the layer tools in the layer manager panel on the map page. The tools in the layer manager in the map are opened on hover. But the icon was misleading, it invited you to click on it. When you hovered the layer the icon disappeared leading to the thought that you couldn't click the icon and therefore couldn't open a menu and missing some extra options (that weren't there). The tools are still opened on hover, making it clickable asks for some rebuilding, but the icon has changed and the color is dimmed. * Make the layer tools menu clickable --- .../partials/layermanageritem.html | 79 ++++++++++-------- .../resources/catalog/style/gn_viewer.less | 80 +++++++++++-------- 2 files changed, 93 insertions(+), 66 deletions(-) diff --git a/web-ui/src/main/resources/catalog/components/viewer/layermanager/partials/layermanageritem.html b/web-ui/src/main/resources/catalog/components/viewer/layermanager/partials/layermanageritem.html index 5148780c18c..b40b9faa08b 100644 --- a/web-ui/src/main/resources/catalog/components/viewer/layermanager/partials/layermanageritem.html +++ b/web-ui/src/main/resources/catalog/components/viewer/layermanager/partials/layermanageritem.html @@ -29,38 +29,7 @@
- - - - - - - - - - - - - - - + +
- + +
diff --git a/web-ui/src/main/resources/catalog/style/gn_viewer.less b/web-ui/src/main/resources/catalog/style/gn_viewer.less index b9198d23921..2ca082d6b22 100644 --- a/web-ui/src/main/resources/catalog/style/gn_viewer.less +++ b/web-ui/src/main/resources/catalog/style/gn_viewer.less @@ -265,9 +265,6 @@ } li[gn-layermanager-item] { .fa-arrows-alt, - .gn-layer-ordering { - visibility: hidden; - } input[type="radio"], input[type="checkbox"] { margin-top: 6px; @@ -275,16 +272,19 @@ label { padding: 4px 20px 4px 4px; display: block; - margin-bottom: 0px; + margin-bottom: 0; } .gn-layer-radio { - padding-left: 0px; - padding-right: 0px; + padding-left: 0; + padding-right: 0; } .tab-content { background-color: white; padding: 5px; - margin: 0px; + margin: 0; + } + .text-muted { + color: @btn-default-border; } } .gn-layer-outofrange > label { @@ -307,6 +307,44 @@ } } } + .dropdown-left { + + @toggleWidth: 32px; + @toggleHeight: 32px; + + .dropdown-toggle { + width: @toggleWidth; + padding: 5px; + } + .dropdown-menu { + min-width: calc(~"(3 * @{toggleWidth}) + 6px") !important; + width: auto; + padding: 0; + margin: 0; + right: @toggleWidth; + top: 0; + box-shadow: none; + border: 0; + li { + float: left; + .btn { + width: @toggleWidth; + height: @toggleHeight; + padding: 5px; + margin-right: 2px; + border-radius: 3px !important; + &[disabled] { + color: @btn-link-disabled-color; + border-color: @input-bg-disabled; + } + } + } + + } + + + } + .gn-searchlayer-list { margin: 0; padding: 0; @@ -343,8 +381,7 @@ padding: 5px 15px; &:hover, &:focus { - .fa-arrows-alt, - .gn-layer-ordering { + .fa-arrows-alt { visibility: visible; } } @@ -353,8 +390,7 @@ margin-bottom: 0; } &:focus-within { - .fa-arrows-alt, - .gn-layer-ordering { + .fa-arrows-alt { visibility: visible; } } @@ -441,28 +477,6 @@ background-color: @gray-lighter; border-color: @list-group-border; } - .gn-layer-ordering { - margin-right: -10px; - position: absolute; - right: 15px; - .fa { - padding: 0 8px; - } - &.btn-group-xs { - .btn { - white-space: nowrap; - padding: 4px; - opacity: 1; - &[disabled] { - color: @btn-link-disabled-color; - border-color: @input-bg-disabled; - } - .caret { - margin-right: 3px; - } - } - } - } .dropdown { .dropdown-menu { min-width: 16em; From 6dbaa472536cd30d161ef5f047d11b17f185ac6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Garc=C3=ADa?= Date: Wed, 30 Oct 2024 12:46:19 +0100 Subject: [PATCH 052/116] Metadata editor / Fix display of multiple choice elements with custom label --- .../webapp/xslt/ui-metadata/form-builder.xsl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/web/src/main/webapp/xslt/ui-metadata/form-builder.xsl b/web/src/main/webapp/xslt/ui-metadata/form-builder.xsl index d7c5efd2497..007b4a9129b 100644 --- a/web/src/main/webapp/xslt/ui-metadata/form-builder.xsl +++ b/web/src/main/webapp/xslt/ui-metadata/form-builder.xsl @@ -567,7 +567,7 @@ true false
- +   @@ -934,9 +934,9 @@
-
@@ -1676,7 +1676,7 @@ data-params="{$process-params}" data-icon="{$btnClass}" data-name="{normalize-space($strings/*[name() = $process-name])}" - data-help="{normalize-space($strings/*[name() = concat($process-name, 'Help')])}"/> + data-help="{normalize-space($strings/*[name() = concat($process-name, 'Help')])}">
diff --git a/web/src/main/webapp/xslt/ui-metadata/menu-builder.xsl b/web/src/main/webapp/xslt/ui-metadata/menu-builder.xsl index 682ec672407..5fa12d2ca5c 100644 --- a/web/src/main/webapp/xslt/ui-metadata/menu-builder.xsl +++ b/web/src/main/webapp/xslt/ui-metadata/menu-builder.xsl @@ -40,7 +40,7 @@
+ data-all-depth="{if ($isFlatMode) then 'true' else 'false'}">