diff --git a/api/api-iam/iam-internal/src/main/resources/dev/customer-init.yml b/api/api-iam/iam-internal/src/main/resources/dev/customer-init.yml index df76f583127..c18fd1028cb 100644 --- a/api/api-iam/iam-internal/src/main/resources/dev/customer-init.yml +++ b/api/api-iam/iam-internal/src/main/resources/dev/customer-init.yml @@ -224,6 +224,7 @@ customer-init: - ROLE_TRANSFER_REQUEST - ROLE_GET_RULES - ROLE_TRANSFER_ACKNOWLEDGMENT + - ROLE_GET_SCHEMAS - name: Consultation description: Profil pour la recherche et consultation des archives dans Vitam sans mises à jour des règles, sans export DIP et sans élimination @@ -236,17 +237,17 @@ customer-init: - ROLE_SEARCH_WITH_RULES - ROLE_GET_ACCESS_CONTRACTS - ROLE_GET_RULES + - ROLE_GET_SCHEMAS - name: Profil pour la gestion des pua/pa de pastis description: Gestion de Pastis dans Vitam app-name: PASTIS_APP level: roles: - - ROLE_GET_PASTIS - - ROLE_CREATE_PASTIS - - ROLE_UPDATE_PASTIS - - ROLE_DELETE_PASTIS - + - ROLE_GET_PASTIS + - ROLE_CREATE_PASTIS + - ROLE_UPDATE_PASTIS + - ROLE_DELETE_PASTIS - name: Archiviste description: Profil pour la recherche et consultation des archives dans Vitam sans mises à jour des règles de gestion, avec export DIP et sans élimination @@ -261,6 +262,7 @@ customer-init: - ROLE_GET_ACCESS_CONTRACTS - ROLE_UPDATE_UNIT_DESC_METADATA - ROLE_GET_RULES + - ROLE_GET_SCHEMAS - name: Collecte description: Collecte de données, Application de préparation de versements @@ -300,7 +302,6 @@ customer-init: - ROLE_IMPORT_ARCHIVE_PROFILES - ROLE_DELETE_ARCHIVE_PROFILES - #- name: profileName # description: desc # level: 1 diff --git a/api/api-iam/iam-security/src/main/java/fr/gouv/vitamui/iam/security/service/InternalSecurityService.java b/api/api-iam/iam-security/src/main/java/fr/gouv/vitamui/iam/security/service/InternalSecurityService.java index 660fe63da57..9ee2e45a57a 100644 --- a/api/api-iam/iam-security/src/main/java/fr/gouv/vitamui/iam/security/service/InternalSecurityService.java +++ b/api/api-iam/iam-security/src/main/java/fr/gouv/vitamui/iam/security/service/InternalSecurityService.java @@ -187,6 +187,10 @@ public TenantDto getCurrentTenantDto() { return getTenant(getTenantIdentifier()); } + public VitamContext getVitamContext() { + return buildVitamContext(getTenantIdentifier()); + } + /** * Build Vitam Context using tenantIdentifier. * @param tenantId diff --git a/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/ExtendedOntologyCreateDto.java b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/ExtendedOntologyCreateDto.java new file mode 100644 index 00000000000..3e1dfb90375 --- /dev/null +++ b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/ExtendedOntologyCreateDto.java @@ -0,0 +1,62 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.common.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import fr.gouv.vitam.common.model.administration.OntologyOrigin; +import fr.gouv.vitam.common.model.administration.SchemaType; +import fr.gouv.vitamui.referential.common.model.Cardinality; +import fr.gouv.vitamui.referential.common.model.Collection; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +@Data +@Accessors(chain = true) +public class ExtendedOntologyCreateDto { + @JsonProperty("Tenant") private Integer tenant; + @JsonProperty("Version") private Integer version; + @JsonProperty("Depth") private Integer depth; // TODO: Useless, easy to compute + @JsonProperty("path") private String path; + @JsonProperty("DataType") private String dataType; + @JsonProperty("DataSize") private String dataSize; // TODO: Useless, don't know how to use this + @JsonProperty("Cardinality") private Cardinality cardinality; + @JsonProperty("Identifier") private String identifier; + @JsonProperty("ShortName") private String shortName; + @JsonProperty("Description") private String description; + @JsonProperty("CreationDate") private String creationDate; + @JsonProperty("LastUpdate") private String lastUpdate; + @JsonProperty("SedaField") private String sedaField; + @JsonProperty("ApiField") private String apiField; + @JsonProperty("Type") private SchemaType type; + @JsonProperty("Origin") private OntologyOrigin origin; + @JsonProperty("Collections") private List collections; + @JsonProperty("SedaVersions") private List sedaVersions; + @JsonProperty("RootPaths") private List rootPaths; +} diff --git a/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/ExtendedOntologyDto.java b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/ExtendedOntologyDto.java new file mode 100644 index 00000000000..bc3e9bf875d --- /dev/null +++ b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/ExtendedOntologyDto.java @@ -0,0 +1,40 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.common.dto; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + + +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class ExtendedOntologyDto extends ExtendedOntologyCreateDto { + private String id; +} diff --git a/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/SchemaDto.java b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/SchemaDto.java new file mode 100644 index 00000000000..33ba69ccacc --- /dev/null +++ b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/dto/SchemaDto.java @@ -0,0 +1,33 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.common.dto; + +import java.util.ArrayList; + +public class SchemaDto extends ArrayList { +} diff --git a/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/exception/NoCollectionException.java b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/exception/NoCollectionException.java new file mode 100644 index 00000000000..607d9cb9e20 --- /dev/null +++ b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/exception/NoCollectionException.java @@ -0,0 +1,39 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.common.exception; + +import org.springframework.web.bind.annotation.ResponseStatus; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +@ResponseStatus(value = BAD_REQUEST) +public class NoCollectionException extends Exception { + public NoCollectionException() { + super("No collection provided"); + } +} diff --git a/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/model/Cardinality.java b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/model/Cardinality.java new file mode 100644 index 00000000000..000a4da9285 --- /dev/null +++ b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/model/Cardinality.java @@ -0,0 +1,61 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.common.model; + +import java.util.Arrays; +import java.util.Objects; + +public enum Cardinality { + ZERO_OR_ONE("0-1"), + ZERO_OR_MORE("0-N"), + ONE_OR_ONE("1-1"), + ONE_OR_MORE("1-N"); + + private final String cardinality; + + Cardinality(final String cardinality) { + this.cardinality = cardinality; + } + + public String getValue() { + return cardinality; + } + + public boolean isMandatory() { + return this.cardinality.contains("1"); + } + + public boolean isMultiple() { + return this.cardinality.contains("N"); + } + + public static Cardinality of(final String cardinality) { + return Arrays.stream(Cardinality.values()).filter(c -> Objects.equals(c.getValue(), cardinality)).findFirst() + .orElseThrow(); + } +} diff --git a/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/model/Collection.java b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/model/Collection.java new file mode 100644 index 00000000000..8cfb4e570cd --- /dev/null +++ b/api/api-referential/referential-commons/src/main/java/fr/gouv/vitamui/referential/common/model/Collection.java @@ -0,0 +1,51 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.common.model; + +import java.util.Arrays; +import java.util.Objects; + +public enum Collection { + ARCHIVE_UNIT("archive-unit"), + OBJECT_GROUP("object-group"); + + private final String type; + + Collection(final String type) { + this.type = type; + } + + public String getValue() { + return type; + } + + public static Collection of(final String collection) { + return Arrays.stream(Collection.values()).filter(c -> Objects.equals(c.getValue(), collection)).findFirst() + .orElseThrow(); + } +} diff --git a/api/api-referential/referential-external-client/src/main/java/fr/gouv/vitamui/referential/external/client/ReferentialExternalRestClientFactory.java b/api/api-referential/referential-external-client/src/main/java/fr/gouv/vitamui/referential/external/client/ReferentialExternalRestClientFactory.java index 58e554669e9..79ddb3bef76 100644 --- a/api/api-referential/referential-external-client/src/main/java/fr/gouv/vitamui/referential/external/client/ReferentialExternalRestClientFactory.java +++ b/api/api-referential/referential-external-client/src/main/java/fr/gouv/vitamui/referential/external/client/ReferentialExternalRestClientFactory.java @@ -123,4 +123,8 @@ public RuleExternalRestClient getRuleExternalRestClient() { public LogbookManagementOperationExternalRestClient getLogbookManagementOperationExternalRestClient() { return new LogbookManagementOperationExternalRestClient(getRestTemplate(), getBaseUrl()); } + + public SchemaClient getSchemaClient() { + return new SchemaClient(getRestTemplate(), getBaseUrl()); + } } diff --git a/api/api-referential/referential-external-client/src/main/java/fr/gouv/vitamui/referential/external/client/SchemaClient.java b/api/api-referential/referential-external-client/src/main/java/fr/gouv/vitamui/referential/external/client/SchemaClient.java new file mode 100644 index 00000000000..4373e3e4a5c --- /dev/null +++ b/api/api-referential/referential-external-client/src/main/java/fr/gouv/vitamui/referential/external/client/SchemaClient.java @@ -0,0 +1,75 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.external.client; + +import fr.gouv.vitamui.commons.api.CommonConstants; +import fr.gouv.vitamui.commons.rest.client.AbstractHttpContext; +import fr.gouv.vitamui.commons.rest.client.BaseRestClient; +import fr.gouv.vitamui.commons.rest.client.ExternalHttpContext; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.model.Collection; +import org.apache.http.client.utils.URIBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.springframework.http.HttpMethod.GET; + +public class SchemaClient extends BaseRestClient { + public SchemaClient(RestTemplate restTemplate, String baseUrl) { + super(restTemplate, baseUrl); + } + + @Override + public String getPathUrl() { + return CommonConstants.SCHEMAS; + } + + public List getSchemas(final ExternalHttpContext externalHttpContext, final Set collections) + throws URISyntaxException { + final URI uri = new URIBuilder(getUrl()).addParameter("collections", + collections.stream().map(Collection::name).collect( + Collectors.joining(","))).build(); + final ResponseEntity responseEntity = + restTemplate.exchange(uri, GET, generateHeaders(externalHttpContext), SchemaDto[].class); + + return Arrays.asList(Objects.requireNonNull(responseEntity.getBody())); + } + + private HttpEntity generateHeaders(final AbstractHttpContext abstractHttpContext) { + return new HttpEntity<>(buildHeaders(abstractHttpContext)); + } +} diff --git a/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/config/ApiReferentialServerConfig.java b/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/config/ApiReferentialServerConfig.java index 952ed4fca9f..c4bce42f0e8 100644 --- a/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/config/ApiReferentialServerConfig.java +++ b/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/config/ApiReferentialServerConfig.java @@ -242,4 +242,9 @@ public RuleInternalWebClient ruleInternalWebClient(final ReferentialInternalWebC public AccessionRegisterDetailInternalRestClient accessionRegisterDetailInternalRestClient(final ReferentialInternalRestClientFactory referentialInternalRestClientFactory) { return referentialInternalRestClientFactory.getAccessionRegisterDetailInternalRestClient(); } + + @Bean + public SchemaClient schemaClient(final ReferentialInternalRestClientFactory referentialInternalRestClientFactory) { + return referentialInternalRestClientFactory.getSchemaClient(); + } } diff --git a/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/rest/SchemaController.java b/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/rest/SchemaController.java new file mode 100644 index 00000000000..43cfffd2806 --- /dev/null +++ b/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/rest/SchemaController.java @@ -0,0 +1,79 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.external.server.rest; + +import fr.gouv.vitamui.commons.api.CommonConstants; +import fr.gouv.vitamui.commons.rest.client.InternalHttpContext; +import fr.gouv.vitamui.iam.security.service.ExternalSecurityService; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.exception.NoCollectionException; +import fr.gouv.vitamui.referential.common.model.Collection; +import fr.gouv.vitamui.referential.external.server.service.SchemaService; +import org.bouncycastle.util.Arrays; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.annotation.Secured; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.ws.rs.Produces; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Set; + +import static fr.gouv.vitamui.commons.api.domain.ServicesData.ROLE_GET_SCHEMAS; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +@RestController +@RequestMapping(CommonConstants.SCHEMAS) +public class SchemaController { + private final SchemaService schemaService; + private final ExternalSecurityService externalSecurityService; + + @Autowired + public SchemaController(final SchemaService schemaService, final ExternalSecurityService externalSecurityService) { + this.schemaService = schemaService; + this.externalSecurityService = externalSecurityService; + } + + @GetMapping + @Produces(APPLICATION_JSON) + @Secured(ROLE_GET_SCHEMAS) + public ResponseEntity> getSchemas(@RequestParam final Set collections) + throws NoCollectionException, URISyntaxException { + if (CollectionUtils.isEmpty(collections)) { + throw new NoCollectionException(); + } + + return ResponseEntity.ok(schemaService.getSchemas( + InternalHttpContext.buildFromExternalHttpContext(externalSecurityService.getHttpContext()), collections)); + } +} diff --git a/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/service/SchemaService.java b/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/service/SchemaService.java new file mode 100644 index 00000000000..407165f87b1 --- /dev/null +++ b/api/api-referential/referential-external/src/main/java/fr/gouv/vitamui/referential/external/server/service/SchemaService.java @@ -0,0 +1,50 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.external.server.service; + +import fr.gouv.vitamui.commons.rest.client.InternalHttpContext; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.model.Collection; +import fr.gouv.vitamui.referential.internal.client.SchemaClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.net.URISyntaxException; +import java.util.List; +import java.util.Set; + +@Service +public class SchemaService { + @Autowired + private SchemaClient client; + + public List getSchemas(final InternalHttpContext internalHttpContext, final Set collections) + throws URISyntaxException { + return client.getSchemas(internalHttpContext, collections); + } +} diff --git a/api/api-referential/referential-internal-client/src/main/java/fr/gouv/vitamui/referential/internal/client/ReferentialInternalRestClientFactory.java b/api/api-referential/referential-internal-client/src/main/java/fr/gouv/vitamui/referential/internal/client/ReferentialInternalRestClientFactory.java index 25d641c2c03..0f36e640b11 100644 --- a/api/api-referential/referential-internal-client/src/main/java/fr/gouv/vitamui/referential/internal/client/ReferentialInternalRestClientFactory.java +++ b/api/api-referential/referential-internal-client/src/main/java/fr/gouv/vitamui/referential/internal/client/ReferentialInternalRestClientFactory.java @@ -121,4 +121,8 @@ public LogbookManagementOperationInternalRestClient getLogbookManagementOperatio public AccessionRegisterDetailInternalRestClient getAccessionRegisterDetailInternalRestClient() { return new AccessionRegisterDetailInternalRestClient(getRestTemplate(), getBaseUrl()); } + + public SchemaClient getSchemaClient() { + return new SchemaClient(getRestTemplate(), getBaseUrl()); + } } diff --git a/api/api-referential/referential-internal-client/src/main/java/fr/gouv/vitamui/referential/internal/client/SchemaClient.java b/api/api-referential/referential-internal-client/src/main/java/fr/gouv/vitamui/referential/internal/client/SchemaClient.java new file mode 100644 index 00000000000..0f03b01d5ec --- /dev/null +++ b/api/api-referential/referential-internal-client/src/main/java/fr/gouv/vitamui/referential/internal/client/SchemaClient.java @@ -0,0 +1,75 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.internal.client; + +import fr.gouv.vitamui.commons.api.CommonConstants; +import fr.gouv.vitamui.commons.rest.client.AbstractHttpContext; +import fr.gouv.vitamui.commons.rest.client.BaseRestClient; +import fr.gouv.vitamui.commons.rest.client.InternalHttpContext; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.model.Collection; +import org.apache.http.client.utils.URIBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.springframework.http.HttpMethod.GET; + +public class SchemaClient extends BaseRestClient { + public SchemaClient(RestTemplate restTemplate, String baseUrl) { + super(restTemplate, baseUrl); + } + + @Override + public String getPathUrl() { + return CommonConstants.SCHEMAS; + } + + public List getSchemas(final InternalHttpContext internalHttpContext, final Set collections) + throws URISyntaxException { + final URI uri = new URIBuilder(getUrl()).addParameter("collections", + collections.stream().map(Collection::name).collect( + Collectors.joining(","))).build(); + final ResponseEntity responseEntity = + restTemplate.exchange(uri, GET, generateHeaders(internalHttpContext), SchemaDto[].class); + + return Arrays.asList(Objects.requireNonNull(responseEntity.getBody())); + } + + private HttpEntity generateHeaders(final AbstractHttpContext abstractHttpContext) { + return new HttpEntity<>(buildHeaders(abstractHttpContext)); + } +} diff --git a/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaController.java b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaController.java new file mode 100644 index 00000000000..e59c811a2b6 --- /dev/null +++ b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaController.java @@ -0,0 +1,68 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.internal.server.schema; + +import fr.gouv.vitamui.commons.api.CommonConstants; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.exception.NoCollectionException; +import fr.gouv.vitamui.referential.common.model.Collection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.ws.rs.Produces; +import java.util.List; +import java.util.Set; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + +@RestController +@RequestMapping(CommonConstants.SCHEMAS) +public class SchemaController { + private final SchemaService schemaService; + + @Autowired + public SchemaController(final SchemaService schemaService) { + this.schemaService = schemaService; + } + + @GetMapping + @Produces(APPLICATION_JSON) + public ResponseEntity> getSchemas(@RequestParam final Set collections) + throws NoCollectionException { + if (CollectionUtils.isEmpty(collections)) { + throw new NoCollectionException(); + } + + return ResponseEntity.ok(schemaService.getSchemas(collections)); + } +} diff --git a/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaLoadingException.java b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaLoadingException.java new file mode 100644 index 00000000000..fe3387c751a --- /dev/null +++ b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaLoadingException.java @@ -0,0 +1,39 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.internal.server.schema; + +import org.springframework.web.bind.annotation.ResponseStatus; + +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; + +@ResponseStatus(code = INTERNAL_SERVER_ERROR, reason = "Error during schema loading") +public class SchemaLoadingException extends RuntimeException { + public SchemaLoadingException(Throwable cause) { + super(cause); + } +} diff --git a/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaModelToExtendedOntologyDtoConverter.java b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaModelToExtendedOntologyDtoConverter.java new file mode 100644 index 00000000000..6a3778d54e7 --- /dev/null +++ b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaModelToExtendedOntologyDtoConverter.java @@ -0,0 +1,80 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.internal.server.schema; + +import com.fasterxml.jackson.databind.util.StdConverter; +import fr.gouv.vitam.common.model.administration.OntologyStringTypeSize; +import fr.gouv.vitam.common.model.administration.OntologyType; +import fr.gouv.vitam.common.model.administration.SchemaModel; +import fr.gouv.vitamui.referential.common.dto.ExtendedOntologyDto; +import fr.gouv.vitamui.referential.common.model.Cardinality; +import fr.gouv.vitamui.referential.common.model.Collection; + +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.stream.Collectors; + +public class SchemaModelToExtendedOntologyDtoConverter extends StdConverter { + @Override + public ExtendedOntologyDto convert(SchemaModel schemaModel) { + final OntologyStringTypeSize stringTypeSize = schemaModel.getStringSize(); + final String stringSize = stringTypeSize != null ? stringTypeSize.value().toLowerCase(Locale.ROOT) : null; + + return (ExtendedOntologyDto) new ExtendedOntologyDto() + // setId(schemaModel.getId()) // No mapping + // setTenant(schemaModel.getTenant()) // No mapping + // setVersion(schemaModel.getVersion()) // Don't know if still used + // setDepth(schemaModel.getDepth()) // Not precomputed + .setPath(schemaModel.getPath()) + // setDataType(schemaModel.getDataType()) // Mapped by Type + .setDataSize(stringSize) + .setCardinality(Cardinality.of(schemaModel.getCardinality().value())) + .setIdentifier(schemaModel.getIdentifier()) + .setShortName(schemaModel.getShortName()) + .setDescription(schemaModel.getDescription()) + // setCreationDate(schemaModel.getCreationDate()) // No mapping + // setLastUpdate(schemaModel.getLastUpdate()) // No mapping + .setSedaField(schemaModel.getSedaField()) + .setApiField(schemaModel.getApiField()) + .setType(schemaModel.getType()) + .setOrigin(schemaModel.getOrigin()) + .setCollections(mapCollections(schemaModel)) + .setSedaVersions(schemaModel.getSedaVersions()) + .setRootPaths(null); + } + + private List mapCollections(final SchemaModel schemaModel) { + return schemaModel.getCollections().stream().map(collection -> { + if (Objects.equals(collection, "Unit")) { + return Collection.ARCHIVE_UNIT; + } + return Collection.of(collection); + }).collect(Collectors.toList()); + } +} diff --git a/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaParsingException.java b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaParsingException.java new file mode 100644 index 00000000000..06df65d7149 --- /dev/null +++ b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaParsingException.java @@ -0,0 +1,39 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.internal.server.schema; + +import org.springframework.web.bind.annotation.ResponseStatus; + +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; + +@ResponseStatus(code = INTERNAL_SERVER_ERROR, reason = "Error during schema parsing") +public class SchemaParsingException extends RuntimeException { + public SchemaParsingException(Throwable cause) { + super(cause); + } +} diff --git a/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaService.java b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaService.java new file mode 100644 index 00000000000..d1704ddceff --- /dev/null +++ b/api/api-referential/referential-internal/src/main/java/fr/gouv/vitamui/referential/internal/server/schema/SchemaService.java @@ -0,0 +1,96 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.referential.internal.server.schema; + +import fr.gouv.vitam.access.external.client.AdminExternalClient; +import fr.gouv.vitam.common.client.VitamContext; +import fr.gouv.vitam.common.exception.VitamClientException; +import fr.gouv.vitam.common.model.RequestResponse; +import fr.gouv.vitam.common.model.RequestResponseOK; +import fr.gouv.vitam.common.model.administration.SchemaModel; +import fr.gouv.vitamui.commons.api.logger.VitamUILogger; +import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory; +import fr.gouv.vitamui.iam.security.service.InternalSecurityService; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.model.Collection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +public class SchemaService { + private static final VitamUILogger log = VitamUILoggerFactory.getInstance(SchemaService.class); + private final InternalSecurityService internalSecurityService; + private final AdminExternalClient adminExternalClient; + + @Autowired + public SchemaService(final InternalSecurityService internalSecurityService, + final AdminExternalClient adminExternalClient) { + this.internalSecurityService = internalSecurityService; + this.adminExternalClient = adminExternalClient; + } + + public Optional getSchema(final Collection collection) { + try { + final RequestResponse payload = getSchemaModels(collection).orElseThrow(); + final List schemaModels = ((RequestResponseOK) payload).getResults(); + final SchemaModelToExtendedOntologyDtoConverter converter = new SchemaModelToExtendedOntologyDtoConverter(); + final SchemaDto schemaDto = new SchemaDto(); + schemaDto.addAll(schemaModels.stream() + .map(converter::convert) + .collect(Collectors.toList())); + return Optional.of(schemaDto); + } catch (VitamClientException e) { + throw new SchemaLoadingException(e); + } + } + + public List getSchemas(final Set collections) { + return collections.stream() + .map(this::getSchema) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); + } + + private Optional> getSchemaModels(Collection collection) throws VitamClientException { + final VitamContext vitamContext = internalSecurityService.getVitamContext(); + if (Objects.equals(collection, Collection.ARCHIVE_UNIT)) { + return Optional.of(adminExternalClient.getUnitSchema(vitamContext)); + } + if (Objects.equals(collection, Collection.OBJECT_GROUP)) { + return Optional.of(adminExternalClient.getObjectGroupSchema(vitamContext)); + } + return Optional.empty(); + } +} diff --git a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/CommonConstants.java b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/CommonConstants.java index d2f27a80692..7725e091454 100644 --- a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/CommonConstants.java +++ b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/CommonConstants.java @@ -357,4 +357,5 @@ public class CommonConstants { public static final String HISTORY = "history"; public static final String EXTERNAL_ONTOLOGIES_LIST = "/external-ontologies"; public static final String INTERNAL_ONTOLOGY_LIST = "/internal-ontologies"; + public static final String SCHEMAS = "/schemas"; } diff --git a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/ServicesData.java b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/ServicesData.java index c044872e420..45d98fd6245 100644 --- a/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/ServicesData.java +++ b/commons/commons-api/src/main/java/fr/gouv/vitamui/commons/api/domain/ServicesData.java @@ -346,14 +346,20 @@ public class ServicesData { public static final String SERVICE_ONTOLOGIES = "ONTOLOGIES"; - public static final String ROLE_GET_ONTOLOGIES = CREATE_ROLE_PREFIX + SERVICE_ONTOLOGIES; + public static final String ROLE_GET_ONTOLOGIES = GET_ROLE_PREFIX + SERVICE_ONTOLOGIES; - public static final String ROLE_CREATE_ONTOLOGIES = GET_ROLE_PREFIX + SERVICE_ONTOLOGIES; + public static final String ROLE_CREATE_ONTOLOGIES = CREATE_ROLE_PREFIX + SERVICE_ONTOLOGIES; public static final String ROLE_DELETE_ONTOLOGIES = DELETE_ROLE_PREFIX + SERVICE_ONTOLOGIES; public static final String ROLE_IMPORT_ONTOLOGIES = IMPORT_ROLE_PREFIX + SERVICE_ONTOLOGIES; + //------------------------------------ ONTOLOGIES ----------------------------------------- + + public static final String SERVICE_SCHEMAS = "SCHEMAS"; + + public static final String ROLE_GET_SCHEMAS = GET_ROLE_PREFIX + SERVICE_SCHEMAS; + //------------------------------------- OPERATIONS -------------------------------------------- public static final String SERVICE_OPERATIONS = "OPERATIONS"; diff --git a/deployment/roles/vitamui/files/customer-init.yml b/deployment/roles/vitamui/files/customer-init.yml index 970753c6a90..07d801a4ac6 100644 --- a/deployment/roles/vitamui/files/customer-init.yml +++ b/deployment/roles/vitamui/files/customer-init.yml @@ -213,6 +213,7 @@ customer-init: - ROLE_TRANSFER_REQUEST - ROLE_TRANSFER_ACKNOWLEDGMENT - ROLE_GET_RULES + - ROLE_GET_SCHEMAS - name: Consultation description: Profil pour la recherche et consultation des archives dans Vitam sans mises à jour des règles, sans export DIP et sans élimination @@ -225,6 +226,7 @@ customer-init: - ROLE_SEARCH_WITH_RULES - ROLE_GET_ACCESS_CONTRACTS - ROLE_GET_RULES + - ROLE_GET_SCHEMAS - name: Archiviste description: Profil pour la recherche et consultation des archives dans Vitam sans mises à jour des règles de gestion, avec export DIP et sans élimination @@ -238,6 +240,7 @@ customer-init: - ROLE_SEARCH_WITH_RULES - ROLE_GET_ACCESS_CONTRACTS - ROLE_GET_RULES + - ROLE_GET_SCHEMAS - name: Registre des fonds description: Visualisation de l'ensemble des données du registre des fonds diff --git a/deployment/scripts/mongod/v7.1/01_update_archive_search_profiles_with_schemas_roles.js.j2 b/deployment/scripts/mongod/v7.1/01_update_archive_search_profiles_with_schemas_roles.js.j2 new file mode 100644 index 00000000000..98665f91ba3 --- /dev/null +++ b/deployment/scripts/mongod/v7.1/01_update_archive_search_profiles_with_schemas_roles.js.j2 @@ -0,0 +1,14 @@ +db = db.getSiblingDB('iam') + +print("Start - 01_update_archive_search_profiles_with_schemas_roles"); + +db.profiles.updateMany({ + applicationName: "ARCHIVE_SEARCH_MANAGEMENT_APP" +}, { + $addToSet: { + roles: + { name: "ROLE_GET_SCHEMAS" } + } +}); + +print("End - 01_update_archive_search_profiles_with_schemas_roles"); diff --git a/deployment/scripts/mongod/v7.1/02_add_roles_for_archive_search_management_app.js.j2 b/deployment/scripts/mongod/v7.1/02_add_roles_for_archive_search_management_app.js.j2 new file mode 100644 index 00000000000..f0988d26886 --- /dev/null +++ b/deployment/scripts/mongod/v7.1/02_add_roles_for_archive_search_management_app.js.j2 @@ -0,0 +1,19 @@ +db = db.getSiblingDB('security') + +print("Start - 02_add_roles_for_archive_search_management_app.js"); + +// -------- ADD MANAGEMENT CONTRACT APPLICATION ROLES TO UI REFERENTIAL CONTEXT ----- + +db.contexts.updateOne({ + "_id": "ui_archive_search_context" +}, { + $addToSet: { + "roleNames": { + $each: [ + "ROLE_GET_SCHEMAS" + ] + } + } +}); + +print("End - 02_add_roles_for_archive_search_management_app.js"); diff --git a/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/AutoConfigurationRestController.java b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/AutoConfigurationRestController.java index 1f05ac5f46e..2bb271ebc2b 100644 --- a/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/AutoConfigurationRestController.java +++ b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/AutoConfigurationRestController.java @@ -44,6 +44,7 @@ import fr.gouv.vitamui.ui.commons.rest.LogbookController; import fr.gouv.vitamui.ui.commons.rest.OntologyCommonController; import fr.gouv.vitamui.ui.commons.rest.RuleController; +import fr.gouv.vitamui.ui.commons.rest.SchemaController; import fr.gouv.vitamui.ui.commons.rest.SecurityController; import fr.gouv.vitamui.ui.commons.rest.SubrogationController; import fr.gouv.vitamui.ui.commons.rest.UnitController; @@ -57,6 +58,7 @@ import fr.gouv.vitamui.ui.commons.service.LogbookService; import fr.gouv.vitamui.ui.commons.service.OntologyCommonService; import fr.gouv.vitamui.ui.commons.service.RuleService; +import fr.gouv.vitamui.ui.commons.service.SchemaService; import fr.gouv.vitamui.ui.commons.service.SubrogationService; import fr.gouv.vitamui.ui.commons.service.UnitService; import fr.gouv.vitamui.ui.commons.service.UserInfoService; @@ -156,4 +158,11 @@ public UnitController unitController(final UnitService unitService) { public OntologyCommonController ontologyCommonController(final OntologyCommonService ontologyCommonService) { return new OntologyCommonController(ontologyCommonService); } + + @Bean("schemaController") + @DependsOn("schemaService") + @ConditionalOnMissingBean + public SchemaController schemaController(final SchemaService schemaService) { + return new SchemaController(schemaService); + } } diff --git a/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/AutoConfigurationService.java b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/AutoConfigurationService.java index 045df43db11..e8a8f0e2985 100644 --- a/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/AutoConfigurationService.java +++ b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/AutoConfigurationService.java @@ -42,6 +42,7 @@ import fr.gouv.vitamui.referential.external.client.OntologyExternalRestClient; import fr.gouv.vitamui.referential.external.client.ReferentialExternalRestClientFactory; import fr.gouv.vitamui.referential.external.client.ReferentialExternalWebClientFactory; +import fr.gouv.vitamui.referential.external.client.SchemaClient; import fr.gouv.vitamui.referential.external.client.UnitExternalRestClient; import fr.gouv.vitamui.ui.commons.property.UIProperties; import fr.gouv.vitamui.ui.commons.service.AccessContractService; @@ -53,6 +54,7 @@ import fr.gouv.vitamui.ui.commons.service.LogbookService; import fr.gouv.vitamui.ui.commons.service.OntologyCommonService; import fr.gouv.vitamui.ui.commons.service.RuleService; +import fr.gouv.vitamui.ui.commons.service.SchemaService; import fr.gouv.vitamui.ui.commons.service.SubrogationService; import fr.gouv.vitamui.ui.commons.service.UnitService; import fr.gouv.vitamui.ui.commons.service.UserInfoService; @@ -166,4 +168,11 @@ public UnitService unitService(final UnitExternalRestClient unitRestClient) { public OntologyCommonService ontologyCommonService( final OntologyExternalRestClient ontologyExternalRestClient) { return new OntologyCommonService(ontologyExternalRestClient); } + + @Bean("schemaService") + @DependsOn(value = {"schemaClient"}) + @ConditionalOnMissingBean + public SchemaService schemaService(final SchemaClient schemaClient) { + return new SchemaService(schemaClient); + } } diff --git a/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/UICommonsAutoConfiguration.java b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/UICommonsAutoConfiguration.java index 52b27ab81f8..39c4bd9814a 100644 --- a/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/UICommonsAutoConfiguration.java +++ b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/config/UICommonsAutoConfiguration.java @@ -43,6 +43,7 @@ import fr.gouv.vitamui.referential.external.client.OntologyExternalRestClient; import fr.gouv.vitamui.referential.external.client.ReferentialExternalRestClientFactory; import fr.gouv.vitamui.referential.external.client.ReferentialExternalWebClientFactory; +import fr.gouv.vitamui.referential.external.client.SchemaClient; import fr.gouv.vitamui.referential.external.client.UnitExternalRestClient; import fr.gouv.vitamui.ui.commons.property.UIProperties; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -114,4 +115,11 @@ public OntologyExternalRestClient ontologyExternalRestClient( final ReferentialExternalRestClientFactory referentialRestClientFactory) { return referentialRestClientFactory.getOntologyRestClient(); } + + @Bean + @ConditionalOnMissingBean + @DependsOn("uiProperties") + public SchemaClient schemaClient(final ReferentialExternalRestClientFactory referentialRestClientFactory) { + return referentialRestClientFactory.getSchemaClient(); + } } diff --git a/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/rest/SchemaController.java b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/rest/SchemaController.java new file mode 100644 index 00000000000..4fea5e69621 --- /dev/null +++ b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/rest/SchemaController.java @@ -0,0 +1,79 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.ui.commons.rest; + +import fr.gouv.vitam.common.exception.InvalidParseOperationException; +import fr.gouv.vitamui.commons.rest.AbstractUiRestController; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.exception.NoCollectionException; +import fr.gouv.vitamui.referential.common.model.Collection; +import fr.gouv.vitamui.ui.commons.service.SchemaService; +import io.swagger.annotations.Api; +import org.bouncycastle.util.Arrays; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Set; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.springframework.http.HttpStatus.OK; + +@Api(tags = "schemas") +@RestController +@RequestMapping("${ui-prefix}/schemas") +@Consumes(APPLICATION_JSON) +@Produces(APPLICATION_JSON) +public class SchemaController extends AbstractUiRestController { + private final SchemaService schemaService; + + @Autowired + public SchemaController(final SchemaService schemaService) { + this.schemaService = schemaService; + } + + @GetMapping + @ResponseStatus(OK) + public ResponseEntity> getSchemas(@RequestParam final Set collections) + throws NoCollectionException, URISyntaxException, InvalidParseOperationException { + if (CollectionUtils.isEmpty(collections)) { + throw new NoCollectionException(); + } + + return ResponseEntity.ok(schemaService.getSchemas(buildUiHttpContext(), collections)); + } +} diff --git a/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/service/SchemaService.java b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/service/SchemaService.java new file mode 100644 index 00000000000..912f8f4e238 --- /dev/null +++ b/ui/ui-commons/src/main/java/fr/gouv/vitamui/ui/commons/service/SchemaService.java @@ -0,0 +1,55 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.ui.commons.service; + +import fr.gouv.vitamui.commons.rest.client.ExternalHttpContext; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.model.Collection; +import fr.gouv.vitamui.referential.external.client.SchemaClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.net.URISyntaxException; +import java.util.List; +import java.util.Set; + +@Service +public class SchemaService { + + private final SchemaClient client; + + @Autowired + public SchemaService(final SchemaClient client) { + this.client = client; + } + + public List getSchemas(final ExternalHttpContext externalHttpContext, final Set collections) + throws URISyntaxException { + return client.getSchemas(externalHttpContext, collections); + } +} diff --git a/ui/ui-commons/src/test/java/fr/gouv/vitamui/ui/commons/rest/SchemaControllerTest.java b/ui/ui-commons/src/test/java/fr/gouv/vitamui/ui/commons/rest/SchemaControllerTest.java new file mode 100644 index 00000000000..98078aef95a --- /dev/null +++ b/ui/ui-commons/src/test/java/fr/gouv/vitamui/ui/commons/rest/SchemaControllerTest.java @@ -0,0 +1,130 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + */ + +package fr.gouv.vitamui.ui.commons.rest; + +import fr.gouv.vitamui.commons.api.domain.IdDto; +import fr.gouv.vitamui.commons.api.identity.ServerIdentityConfiguration; +import fr.gouv.vitamui.commons.api.logger.VitamUILogger; +import fr.gouv.vitamui.commons.rest.client.configuration.RestClientConfiguration; +import fr.gouv.vitamui.referential.common.dto.SchemaDto; +import fr.gouv.vitamui.referential.common.model.Collection; +import fr.gouv.vitamui.ui.commons.config.UICommonsAutoConfiguration; +import fr.gouv.vitamui.ui.commons.config.UICommonsAutoSpringMockConfiguration; +import fr.gouv.vitamui.ui.commons.config.UIPropertiesImpl; +import fr.gouv.vitamui.ui.commons.property.UIProperties; +import fr.gouv.vitamui.ui.commons.security.SecurityConfig; +import fr.gouv.vitamui.ui.commons.service.SchemaService; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static fr.gouv.vitamui.referential.common.model.Collection.ARCHIVE_UNIT; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebMvcTest(controllers = SchemaController.class) +@ImportAutoConfiguration(classes = { UICommonsAutoConfiguration.class, UICommonsAutoSpringMockConfiguration.class }) +@Import(value = { SecurityConfig.class, ServerIdentityConfiguration.class }) +public class SchemaControllerTest extends UIControllerTest { + @Value("${ui-prefix}") + protected String moduleName; + @MockBean private SchemaService schemaService; + + @TestConfiguration + static class UserConfiguration { + + @Bean + public UIProperties uiProperties() { + final UIPropertiesImpl properties = new UIPropertiesImpl(); + properties.setIamExternalClient(new RestClientConfiguration()); + properties.setReferentialExternalClient(new RestClientConfiguration()); + return properties; + } + } + + @Test + public void shouldListSchemas() throws Exception { + final Set collections = Set.of(ARCHIVE_UNIT); + final List schemas = List.of(); + + Mockito.when(schemaService.getSchemas(any(), eq(collections))).thenReturn(schemas); + + final Map params = new HashMap<>(); + + params.put("collections", ARCHIVE_UNIT); + + super.performGet("", params) + .andDo(print()).andExpect(status().isOk()).andExpect(content().string(Matchers.containsString("[]"))); + + Mockito.verify(schemaService, Mockito.times(1)).getSchemas(any(), eq(collections)); + } + + @Override + protected Class getDtoClass() { + return null; + } + + @Override + protected IdDto buildDto() { + return null; + } + + @Override + protected VitamUILogger getLog() { + return null; + } + + @Override + protected void preparedServices() { + + } + + @Override + protected String getRessourcePrefix() { + return "/" + moduleName + "/schemas"; + } +} \ No newline at end of file diff --git a/ui/ui-frontend-common/package.json b/ui/ui-frontend-common/package.json index 20cc97ff967..121cace4e02 100644 --- a/ui/ui-frontend-common/package.json +++ b/ui/ui-frontend-common/package.json @@ -99,7 +99,7 @@ "@types/jasmine": "~3.3.0", "@types/jasminewd2": "^2.0.8", "@types/lodash-es": "^4.17.3", - "@types/lodash": "4.14.186", + "@types/lodash": "4.14.191", "@types/node": "^12.11.1", "angular-oauth2-oidc": "^10.0.3", "bootstrap": "^4.5.0", @@ -139,8 +139,7 @@ "utf-8-validate": "^5.0.2", "web-animations-js": "^2.3.2", "webpack-bundle-analyzer": "^3.8.0", - "zone.js": "~0.10.2", - "@types/lodash": "4.14.191" + "zone.js": "~0.10.2" }, "resolutions": { "moment": "2.26.0" diff --git a/ui/ui-frontend-common/src/app/modules/archive/archive.module.ts b/ui/ui-frontend-common/src/app/modules/archive/archive.module.ts index 83dfa3f5e2d..3ca4c4455c0 100644 --- a/ui/ui-frontend-common/src/app/modules/archive/archive.module.ts +++ b/ui/ui-frontend-common/src/app/modules/archive/archive.module.ts @@ -39,13 +39,15 @@ import { NgModule } from '@angular/core'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; +import { ObjectViewerModule } from '../object-viewer/object-viewer.module'; import { PipesModule } from '../pipes/pipes.module'; import { ArchiveUnitCountComponent } from './components/archive-unit-count/archive-unit-count.component'; +import { ArchiveUnitViewerComponent } from './components/archive-unit-viewer/archive-unit-viewer.component'; import { PhysicalArchiveViewerComponent } from './components/physical-archive-viewer/physical-archive-viewer.component'; @NgModule({ - imports: [CommonModule, TranslateModule, PipesModule, MatTooltipModule, MatProgressSpinnerModule], - declarations: [PhysicalArchiveViewerComponent, ArchiveUnitCountComponent], - exports: [PhysicalArchiveViewerComponent, ArchiveUnitCountComponent], + imports: [CommonModule, ObjectViewerModule, TranslateModule, PipesModule, MatTooltipModule, MatProgressSpinnerModule], + declarations: [PhysicalArchiveViewerComponent, ArchiveUnitCountComponent, ArchiveUnitViewerComponent], + exports: [PhysicalArchiveViewerComponent, ArchiveUnitCountComponent, ArchiveUnitViewerComponent], }) export class ArchiveModule {} diff --git a/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-count/archive-unit-count.component.spec.ts b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-count/archive-unit-count.component.spec.ts index 2d19d86ff03..6c94d18b8c2 100644 --- a/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-count/archive-unit-count.component.spec.ts +++ b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-count/archive-unit-count.component.spec.ts @@ -65,6 +65,7 @@ describe('ArchiveUnitCountComponent', () => { PipesModule, MatTooltipModule, MatProgressSpinnerModule, + LoggerModule.forRoot(), ], }).compileComponents(); }); diff --git a/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-schema-service.ts b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-schema-service.ts new file mode 100644 index 00000000000..b4ee5aa9134 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-schema-service.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ExtendedOntology } from '../../../object-viewer/models'; +import { Collection, SchemaService } from '../../../schema'; + +@Injectable() +export class ArchiveUnitSchemaService { + constructor(private schemaService: SchemaService) {} + + getInternalOntologyFieldsList(): Observable { + return this.schemaService.getSchema(Collection.ARCHIVE_UNIT); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.html b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.html new file mode 100644 index 00000000000..f2216c3ffb9 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.html @@ -0,0 +1 @@ + diff --git a/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.scss b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.spec.ts b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.spec.ts new file mode 100644 index 00000000000..c002cd6f233 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.spec.ts @@ -0,0 +1,109 @@ +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { BASE_URL } from '../../../injection-tokens'; +import { LoggerModule } from '../../../logger'; +import { ObjectViewerModule } from '../../../object-viewer/object-viewer.module'; +import { MockExtendedOntologyService } from '../../../object-viewer/services/mock-extended-ontology.service'; +import { OntologyService } from '../../../ontology'; +import { Collection, Schema, SchemaService } from '../../../schema'; +import { SchemaApiService } from '../../../schema/schema-api.service'; +import { ArchiveUnitViewerComponent } from './archive-unit-viewer.component'; + +describe('ArchiveUnitViewerComponent', () => { + let component: ArchiveUnitViewerComponent; + let fixture: ComponentFixture; + const archiveUnit = { + '#id': 'aeaqaaaaaeecehmeabneoamjofozk4iaaaea', + Title: 'Gambetta par producteur1', + DescriptionLevel: 'RecordGrp', + Description: 'Station Gambetta ligne 3 Paris', + OriginatingAgencyArchiveUnitIdentifier: [], + '#tenant': 1, + '#unitups': [], + '#min': 1, + '#max': 1, + '#allunitups': [], + '#unitType': 'INGEST', + '#operations': ['aeeaaaaaagecehmeaa5rwamjofoy5haaaaaq'], + '#opi': 'aeeaaaaaagecehmeaa5rwamjofoy5haaaaaq', + '#originating_agency': 'producteur1', + '#originating_agencies': ['producteur1'], + '#management': { + AppraisalRule: null, + HoldRule: null, + StorageRule: null, + ReuseRule: null, + ClassificationRule: null, + DisseminationRule: null, + AccessRule: null, + UpdateOperation: null, + }, + StartDate: '2016-06-03T15:28:00', + EndDate: '2016-06-03T15:28:00', + Xtag: [], + Vtag: [], + '#storage': { + strategyId: 'default', + }, + '#qualifiers': [], + OriginatingSystemId: [], + PhysicalAgency: [], + PhysicalStatus: [], + PhysicalType: [], + Keyword: [], + '#approximate_creation_date': '2023-07-20T03:35:07.967', + '#approximate_update_date': '2023-07-20T03:35:07.967', + originating_agencyName: 'Service producteur1', + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ArchiveUnitViewerComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [HttpClientTestingModule, ObjectViewerModule, LoggerModule.forRoot(), TranslateModule.forRoot()], + providers: [ + SchemaService, + { provide: BASE_URL, useValue: '/fake-api' }, + { provide: OntologyService, useClass: MockExtendedOntologyService }, + { + provide: SchemaApiService, + use: () => ({ + getSchemas: (collections: Collection[]): Observable => { + return new MockExtendedOntologyService().getInternalOntologyFieldsList().pipe(map((schema) => [schema])); + }, + getSchema: (collection: Collection): Observable => { + return new MockExtendedOntologyService().getInternalOntologyFieldsList(); + }, + }), + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ArchiveUnitViewerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should create with archive unit', () => { + component.data = archiveUnit; + + component.ngOnChanges({ + data: new SimpleChange(null, archiveUnit, true), + }); + + fixture.detectChanges(); + + expect(component.data).toBeTruthy(); + expect(component.template).toBeTruthy(); + }); +}); diff --git a/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.ts b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.ts new file mode 100644 index 00000000000..37e44e8d152 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/archive/components/archive-unit-viewer/archive-unit-viewer.component.ts @@ -0,0 +1,457 @@ +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { DisplayObjectService, DisplayRule } from '../../../object-viewer/models'; +import { OntologyStrategyDisplayObjectService } from '../../../object-viewer/services/ontology-strategy-display-object.service'; +import { OntologyService } from '../../../ontology'; +import { ArchiveUnitSchemaService } from './archive-unit-schema-service'; + +@Component({ + selector: 'vitamui-common-archive-unit-viewer', + templateUrl: './archive-unit-viewer.component.html', + styleUrls: ['./archive-unit-viewer.component.scss'], + providers: [ + { provide: DisplayObjectService, useClass: OntologyStrategyDisplayObjectService }, + { provide: OntologyService, useClass: ArchiveUnitSchemaService }, + ], +}) +export class ArchiveUnitViewerComponent implements OnInit, OnChanges { + @Input() data!: any; + @Input() template: DisplayRule[] = [ + { + path: '', + ui: { + path: '', + component: 'group', + open: true, + display: true, + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: '#originating_agency', + ui: { + path: '#originating_agency', + component: 'textfield', + open: true, + display: true, + layout: { + columns: 2, + size: 'small', + }, + }, + }, + { + path: '#originating_agencies', + ui: { + path: '#originating_agencies', + component: 'textfield', + open: true, + display: true, + layout: { + columns: 2, + size: 'small', + }, + }, + }, + { + path: null, + ui: { + path: 'Generalities', + component: 'group', + open: true, + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: 'DescriptionLevel', + ui: { + path: 'Generalities.DescriptionLevel', + component: 'select', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'Title', + ui: { + path: 'Generalities.Title', + component: 'textfield', + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: 'Title_', + ui: { + path: 'Generalities.Title_', + component: 'select+textfield', + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: 'Description', + ui: { + path: 'Generalities.Description', + component: 'textarea', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + { + path: 'Description_.*', + ui: { + path: 'Generalities.Description_.*', + component: 'select+textarea', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + { + path: 'Tag', + ui: { + path: 'Generalities.Tag', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: null, + ui: { + path: 'Generalities.Dates', + component: 'group', + open: false, + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: 'StartDate', + ui: { + path: 'Generalities.Dates.StartDate', + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'EndDate', + ui: { + path: 'Generalities.Dates.EndDate', + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'CreatedDate', + ui: { + path: 'Generalities.Dates.CreatedDate', + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'TransactedDate', + ui: { + path: 'Generalities.Dates.TransactedDate', + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'SentDate', + ui: { + path: 'Generalities.Dates.SentDate', + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'ReceivedDate', + ui: { + path: 'Generalities.Dates.ReceivedDate', + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'RegisteredDate', + ui: { + path: 'Generalities.Dates.RegisteredDate', + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'AcquiredDate', + ui: { + path: 'Generalities.Dates.AcquiredDate', + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'DateLitteral', + ui: { + path: 'Generalities.Dates.DateLitteral', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: null, + ui: { + path: 'Generalities.Identifiers', + component: 'group', + open: false, + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: 'SystemId', + ui: { + path: 'Generalities.Identifiers.SystemId', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'OriginatingSystemId', + ui: { + path: 'Generalities.Identifiers.OriginatingSystemId', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'OriginatingAgencyArchiveUnitIdentifier', + ui: { + path: 'Generalities.Identifiers.OriginatingAgencyArchiveUnitIdentifier', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'TransferringAgencyArchiveUnitIdentifier', + ui: { + path: 'Generalities.Identifiers.TransferringAgencyArchiveUnitIdentifier', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'ArchivalAgencyArchiveUnitIdentifier', + ui: { + path: 'Generalities.Identifiers.ArchivalAgencyArchiveUnitIdentifier', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'FilePlanPosition', + ui: { + path: 'Generalities.Identifiers.FilePlanPosition', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: null, + ui: { + path: 'Generalities.Characteristics', + component: 'group', + open: false, + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: 'Type', + ui: { + path: 'Generalities.Characteristics.Type', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'DocumentType', + ui: { + path: 'Generalities.Characteristics.DocumentType', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'Language', + ui: { + path: 'Generalities.Characteristics.Language', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'DescriptionLanguage', + ui: { + path: 'Generalities.Characteristics.DescriptionLanguage', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'Status', + ui: { + path: 'Generalities.Characteristics.Status', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'Source', + ui: { + path: 'Generalities.Characteristics.Source', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'Version', + ui: { + path: 'Generalities.Characteristics.Version', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'OriginatingSystemIdReplyTo', + ui: { + path: 'Generalities.Characteristics.OriginatingSystemIdReplyTo', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + { + path: 'TextContent', + ui: { + path: 'Generalities.Characteristics.TextContent', + component: 'textfield', + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + ]; + mode = 'default'; + + constructor(private displayObjectService: DisplayObjectService) {} + + ngOnInit(): void { + this.displayObjectService.setMode(this.mode); + this.displayObjectService.setTemplate(this.template); + this.displayObjectService.setData(this.data); + } + + ngOnChanges(changes: SimpleChanges): void { + const { data, template } = changes; + + if (data) { + this.displayObjectService.setData(data.currentValue); + } + if (template) { + this.displayObjectService.setTemplate(template.currentValue); + } + } +} diff --git a/ui/ui-frontend-common/src/app/modules/index.ts b/ui/ui-frontend-common/src/app/modules/index.ts index 1ce8086d72f..44f3ababc43 100644 --- a/ui/ui-frontend-common/src/app/modules/index.ts +++ b/ui/ui-frontend-common/src/app/modules/index.ts @@ -137,6 +137,7 @@ export * from './ontology/index'; export * from './paginated-api.interface'; export * from './pipes/index'; export * from './rule/index'; +export * from './schema/index'; export * from './security/security.service'; export * from './services/index'; export * from './sidenav-page.class'; diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.html b/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.html new file mode 100644 index 00000000000..3dfc7dc5b37 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.html @@ -0,0 +1,33 @@ +
+
+
+
+
+ + {{ displayObject.path | translate }} +
+
+ {{ favoritePath | translate }}: {{ favoriteEntry[1] | empty }} +
+
+
+
+
+
+
+
+ + + + + +
+
+
{{ displayObject.value | empty }}
+
diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.scss b/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.scss new file mode 100644 index 00000000000..594345d4c80 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.scss @@ -0,0 +1,101 @@ +:host { + width: 100%; +} + +.v-col { + display: flex; + flex: 1; +} + +.v-col:not(:last-child) { + margin-right: 10px; +} + +.v-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + width: 100%; +} + +.align-items-center { + align-items: center; +} + +.display-none { + display: none; +} + +.content { + background-color: transparent; + padding: 20px 30px; + + .header { + // Le header du deuxième niveau a une hauteur de 40px + .content & { + min-height: 40px; + border-radius: unset; + font-size: 16px; + line-height: 24px; + font-weight: 700; + padding-left: 16px; + padding-right: 16px; + + &.opened { + border-left: 2px solid var(--vitamui-primary); + color: var(--vitamui-primary); + } + + .favorite-entry { + font-size: 14px; + line-height: 22px; + font-weight: 700; + } + + // Le header du troisième niveau a une hauteur de 30px + .content & { + min-height: 30px; + + // Le header du quatrième niveau a une hauteur de 20px + .content & { + min-height: 20px; + } + } + } + } + + .content { + background-color: white; + } +} + +.header { + min-height: 50px; + margin-top: 10px; + margin-bottom: 10px; + padding-left: 16px; + border-radius: 5px; + display: flex; + background-color: white; + flex-direction: row; + font-size: 20px; + line-height: 28px; + font-weight: 700; + cursor: pointer; + + &.opened { + border-left: 2px solid var(--vitamui-primary); + color: var(--vitamui-primary); + } +} + +.favorite-entry { + font-size: 16px; + line-height: 24px; + font-weight: 700; +} + +.icon { + font-size: 24px; + padding-right: 0.3rem; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.ts new file mode 100644 index 00000000000..bd39ef79cc6 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/group/group.component.ts @@ -0,0 +1,73 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { DisplayObject } from '../../models'; +import { FavoriteEntryService } from '../../services/favorite-entry.service'; +import { LayoutService } from '../../services/layout.service'; +import { DisplayObjectType } from '../../types'; + +@Component({ + selector: 'vitamui-common-group', + templateUrl: './group.component.html', + styleUrls: ['./group.component.scss'], +}) +export class GroupComponent implements OnChanges { + @Input() displayObject: DisplayObject; + + entries: [key: string, value: any][] = []; + favoriteEntry: [key: string, value: any]; + favoritePath: string; + rows: DisplayObject[][] = [[]]; + + readonly DisplayObjectType = DisplayObjectType; + + constructor(private layoutService: LayoutService, private favoriteEntryService: FavoriteEntryService) {} + + ngOnChanges(changes: SimpleChanges): void { + const { displayObject } = changes; + + if (displayObject) { + this.favoriteEntry = this.favoriteEntryService.favoriteEntry(this.displayObject); + this.favoritePath = this.favoriteEntryService.favoritePath(this.displayObject); + this.rows = this.layoutService.compute(this.displayObject); + } + } + + toggle(): void { + this.displayObject.open = !this.displayObject.open; + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.html b/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.html new file mode 100644 index 00000000000..b3786a303c6 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.html @@ -0,0 +1,37 @@ + +
+
+
+
+
+ + {{ displayObject.path | translate }} +
+
+
+
{{ favoritePath | translate }}: {{ favoriteEntry[1] | empty }}
+
+
+
+ + + + + +
+
+ + + +
+ +
    +
  • {{ item.value }}
  • +
+
diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.scss b/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.scss new file mode 100644 index 00000000000..0a3515e4872 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.scss @@ -0,0 +1,113 @@ +:host { + width: 100%; +} + +.v-col { + display: flex; + flex: 1; +} + +.v-col:not(:last-child) { + margin-right: 10px; +} + +.v-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + width: 100%; +} + +.align-items-center { + align-items: center; +} + +.display-none { + display: none; +} + +.content { + background-color: transparent; + padding: 20px 30px; + + .header { + // Le header du deuxième niveau a une hauteur de 40px + .content & { + min-height: 40px; + border-radius: unset; + font-size: 16px; + line-height: 24px; + font-weight: 700; + padding-left: 16px; + padding-right: 16px; + + &.opened { + border-left: 2px solid var(--vitamui-primary); + color: var(--vitamui-primary); + } + + .favorite-entry { + font-size: 14px; + line-height: 22px; + font-weight: 700; + } + + // Le header du troisième niveau a une hauteur de 30px + .content & { + min-height: 30px; + + // Le header du quatrième niveau a une hauteur de 20px + .content & { + min-height: 20px; + } + } + } + } + + .content { + background-color: white; + } +} + +.header { + min-height: 50px; + margin-top: 10px; + margin-bottom: 10px; + padding-left: 16px; + border-radius: 5px; + display: flex; + background-color: white; + flex-direction: row; + font-size: 20px; + line-height: 28px; + font-weight: 700; + cursor: pointer; + + &.opened { + border-left: 2px solid var(--vitamui-primary); + color: var(--vitamui-primary); + } +} + +.icon { + font-size: 24px; + margin-left: 5px; + margin-right: 5px; +} + +.field { + font-weight: 400; + + label { + display: inline-block; + font-size: 12px; + font-weight: 700; + color: var(--vitamui-primary); + padding-bottom: 5px; + overflow-wrap: anywhere; + } +} + +li { + overflow-wrap: anywhere; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.ts new file mode 100644 index 00000000000..c11ad5ecb88 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/list/list.component.ts @@ -0,0 +1,71 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { DisplayObject } from '../../models'; +import { FavoriteEntryService } from '../../services/favorite-entry.service'; +import { TypeService } from '../../services/type.service'; +import { DisplayObjectType } from '../../types'; + +@Component({ + selector: 'vitamui-common-list', + templateUrl: './list.component.html', + styleUrls: ['./list.component.scss'], +}) +export class ListComponent implements OnChanges { + @Input() displayObject: DisplayObject; + + favoriteEntry: [key: string, value: any]; + favoritePath: string; + isPrimitiveList: boolean; + + readonly DisplayObjectType = DisplayObjectType; + + constructor(private typeService: TypeService, private favoriteEntryService: FavoriteEntryService) {} + + ngOnChanges(changes: SimpleChanges): void { + const { displayObject } = changes; + + if (displayObject) { + this.favoriteEntryService.favoriteEntry(this.displayObject); + this.isPrimitiveList = this.typeService.isPrimitiveList(this.displayObject.value); + } + } + + toggle(): void { + this.displayObject.open = !this.displayObject.open; + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.html b/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.html new file mode 100644 index 00000000000..790691ce934 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.html @@ -0,0 +1,14 @@ +
+ +
+ + {{ displayObject.value | date : 'medium' | empty }} + + + {{ displayObject.value | date : 'medium' | empty }} + + + {{ displayObject.value | empty }} + +
+
diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.scss b/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.scss new file mode 100644 index 00000000000..307c1ddca08 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.scss @@ -0,0 +1,20 @@ +:host { + padding-bottom: 10px; +} + +.field { + font-weight: 400; + + label { + display: inline-block; + font-size: 12px; + font-weight: 700; + color: var(--vitamui-primary); + padding-bottom: 5px; + overflow-wrap: anywhere; + } + + div { + overflow-wrap: anywhere; + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.ts new file mode 100644 index 00000000000..3ff715d4625 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/components/primitive/primitive.component.ts @@ -0,0 +1,59 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Component, Input, OnInit } from '@angular/core'; +import { DisplayObject } from '../../models'; +import { DateDisplayService } from '../../services/date-display.service'; +import { ComponentType, UiComponentDateFormatMapName } from '../../types'; + +@Component({ + selector: 'vitamui-common-primitive', + templateUrl: './primitive.component.html', + styleUrls: ['./primitive.component.scss'], +}) +export class PrimitiveComponent implements OnInit { + @Input() displayObject: DisplayObject; + + uiComponent: ComponentType; + dateFormat: string; + + constructor(private dateDisplayService: DateDisplayService) {} + + ngOnInit(): void { + this.uiComponent = this.displayObject.displayRule?.ui?.component; + this.dateFormat = this.dateDisplayService.getFormat(this.uiComponent); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/configuration.model.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/configuration.model.ts new file mode 100644 index 00000000000..9dce552c2b6 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/configuration.model.ts @@ -0,0 +1,43 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { DisplayRule } from './display-rule.model'; +import { ExtendedOntology } from './extended-ontology.model'; + +export interface Configuration { + readonly ontology: ExtendedOntology; + readonly displayRule: DisplayRule; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-object-service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-object-service.ts new file mode 100644 index 00000000000..a25701ffb2c --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-object-service.ts @@ -0,0 +1,48 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { DisplayRule } from './display-rule.model'; + +@Injectable() +export abstract class DisplayObjectService { + displayObject$: Observable; + + public abstract setData(data: any): void; + public abstract setTemplate(template: DisplayRule[]): void; + public abstract setMode(mode: string): void; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-object.model.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-object.model.ts new file mode 100644 index 00000000000..ada5b09166a --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-object.model.ts @@ -0,0 +1,52 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { DisplayRule } from './display-rule.model'; + +import { ComponentType, DisplayObjectType } from '../types'; + +export interface DisplayObject { + readonly children?: DisplayObject[]; + readonly component: ComponentType; + readonly favoriteKeys?: string[]; + readonly key: string; + readonly path: string; + readonly type?: DisplayObjectType; + readonly value: any; + open?: boolean; + visible?: boolean; + displayRule?: DisplayRule; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-rule.model.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-rule.model.ts new file mode 100644 index 00000000000..214196e8275 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/display-rule.model.ts @@ -0,0 +1,42 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Ui } from './ui.model'; +import { WithPath } from './with-path.model'; + +export interface DisplayRule extends WithPath { + readonly ui: Ui; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/extended-ontology.model.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/extended-ontology.model.ts new file mode 100644 index 00000000000..c8d59d17c5b --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/extended-ontology.model.ts @@ -0,0 +1,64 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Ontology } from '../../models'; +import { Cardinality, SedaVersion } from '../types'; +import { WithPath } from './with-path.model'; + +export interface ExtendedOntology extends WithPath, Ontology { + readonly DataType: + | 'object' + | 'array' + | 'string' + | 'number' + | 'enum' + | 'date' + | 'complex Type' + | 'NonEmptyTokenType' + | 'nonEmptyToken' + | 'token' + | 'entier' + | 'IDREF' + | 'language' + | 'objet' + | 'S.O' + | string; + readonly DataSize: 'short' | 'medium' | 'large'; + readonly Cardinality: Cardinality; + readonly SedaVersions: SedaVersion[]; + readonly Depth: number; + readonly Collections: string[]; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/index.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/index.ts new file mode 100644 index 00000000000..7e7c9de40e1 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/index.ts @@ -0,0 +1,45 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +export * from './configuration.model'; +export * from './display-object-service'; +export * from './display-object.model'; +export * from './display-rule.model'; +export * from './extended-ontology.model'; +export * from './layout.model'; +export * from './ui-component-date-format-map.model'; +export * from './ui.model'; +export * from './with-path.model'; diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/layout.model.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/layout.model.ts new file mode 100644 index 00000000000..3cc9f5c9edd --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/layout.model.ts @@ -0,0 +1,42 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { LayoutSize } from '../types'; + +export interface Layout { + readonly columns: number; + readonly size: LayoutSize; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/ui-component-date-format-map.model.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/ui-component-date-format-map.model.ts new file mode 100644 index 00000000000..b82fc3382ac --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/ui-component-date-format-map.model.ts @@ -0,0 +1,40 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +export interface UiComponentDateFormatMap { + readonly datepicker?: string; + readonly datetime?: string; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/ui.model.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/ui.model.ts new file mode 100644 index 00000000000..2b3eaa2db4a --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/ui.model.ts @@ -0,0 +1,47 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { ComponentType } from '../types'; +import { Layout } from './layout.model'; +import { WithPath } from './with-path.model'; + +export interface Ui extends WithPath { + readonly component: ComponentType; + readonly layout?: Layout; + readonly favoriteKeys?: string[]; + readonly open?: boolean; + readonly display?: boolean; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/models/with-path.model.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/models/with-path.model.ts new file mode 100644 index 00000000000..b2fc8cfbb2e --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/models/with-path.model.ts @@ -0,0 +1,39 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +export interface WithPath { + readonly path: string; +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.html b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.html new file mode 100644 index 00000000000..fef041044ce --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.html @@ -0,0 +1,5 @@ + + + + + diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.scss b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.spec.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.spec.ts new file mode 100644 index 00000000000..eedd24d6137 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.spec.ts @@ -0,0 +1,480 @@ +import { HttpBackend } from '@angular/common/http'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ChangeDetectionStrategy, CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MissingTranslationHandler, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { Observable, of } from 'rxjs'; +import { BASE_URL } from '../injection-tokens'; +import { LoggerModule } from '../logger/logger.module'; +import { VitamuiMissingTranslationHandler } from '../missing-translation-handler'; +import { PipesModule } from '../pipes/pipes.module'; +import { GroupComponent } from './components/group/group.component'; +import { ListComponent } from './components/list/list.component'; +import { PrimitiveComponent } from './components/primitive/primitive.component'; +import { DisplayObjectService, DisplayRule } from './models'; +import { ObjectViewerComponent } from './object-viewer.component'; +import { DataStructureService } from './services/data-structure.service'; +import { DateDisplayService } from './services/date-display.service'; +import { DisplayObjectHelperService } from './services/display-object-helper.service'; +import { DisplayRuleHelperService } from './services/display-rule-helper.service'; +import { FavoriteEntryService } from './services/favorite-entry.service'; +import { LayoutService } from './services/layout.service'; +import { OntologyToDisplayRuleMapper } from './services/ontology-to-display-rule.mapper'; +import { PathStrategyDisplayObjectService } from './services/path-strategy-display-object.service'; +import { TypeService } from './services/type.service'; + +class FakeTranslateLoader implements TranslateLoader { + getTranslation(lang: string): Observable { + if (lang === 'fr') { + return of({ + ARCHIVE_SEARCH: { + RESULTS: 'résultats', + ONE_SELECTED: 'séléctionné', + MORE_THAN: '+ de', + }, + }); + } + + return of({ + ARCHIVE_SEARCH: { + RESULTS: 'results', + ONE_SELECTED: 'selected', + MORE_THAN: '+ than', + }, + }); + } +} + +describe('ObjectViewerComponent', () => { + let component: ObjectViewerComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ObjectViewerComponent, GroupComponent, ListComponent, PrimitiveComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + providers: [ + DataStructureService, + TypeService, + DisplayObjectHelperService, + DisplayRuleHelperService, + OntologyToDisplayRuleMapper, + DateDisplayService, + LayoutService, + FavoriteEntryService, + { provide: BASE_URL, useValue: '/fake-api' }, + // { provide: OntologyService, useClass: MockExtendedOntologyService }, + { provide: DisplayObjectService, useClass: PathStrategyDisplayObjectService }, + ], + imports: [ + HttpClientTestingModule, + TranslateModule.forRoot({ + missingTranslationHandler: { provide: MissingTranslationHandler, useClass: VitamuiMissingTranslationHandler }, + defaultLanguage: 'fr', + loader: { + provide: TranslateLoader, + useClass: FakeTranslateLoader, + deps: [HttpBackend], + }, + }), + PipesModule, + LoggerModule.forRoot(), + ], + }) + .overrideComponent(ObjectViewerComponent, { + set: { changeDetection: ChangeDetectionStrategy.Default }, + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ObjectViewerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should create with any', () => { + component.data = data; + component.template = template; + + component.ngOnChanges({ + data: new SimpleChange(null, data, true), + template: new SimpleChange(null, template, true), + }); + + fixture.detectChanges(); + + expect(component.data).toBeTruthy(); + expect(component.template).toBeTruthy(); + }); +}); + +const template: DisplayRule[] = [ + { + path: '_sps', + ui: { + path: '_sps', + component: 'textfield', + layout: { columns: 2, size: 'medium' }, + }, + }, + { + path: '', + ui: { + path: 'Generalities', + component: 'group', + layout: { columns: 2, size: 'medium' }, + }, + }, + { + path: 'DescriptionLevel', + ui: { + path: 'Generalities.DescriptionLevel', + component: 'select', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'Title', + ui: { + path: 'Generalities.Title', + component: 'textfield', + layout: { columns: 2, size: 'medium' }, + }, + }, + { + path: 'Title_.*', + ui: { + path: 'Generalities.Title_.*', + component: 'select+textfield', + layout: { columns: 2, size: 'medium' }, + }, + }, + { + path: 'Description', + ui: { + path: 'Generalities.Description', + component: null, + layout: { columns: 2, size: 'large' }, + }, + }, + { + path: 'Description_.*', + ui: { + path: 'Generalities.Description_.*', + component: 'select+textarea', + layout: { columns: 2, size: 'large' }, + }, + }, + { + path: 'Tag', + ui: { + path: 'Generalities.Tag', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: '', + ui: { + path: 'Generalities.Dates', + component: 'group', + layout: { columns: 2, size: 'medium' }, + }, + }, + { + path: 'StartDate', + ui: { + path: 'Generalities.Dates.StartDate', + component: 'datepicker', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'EndDate', + ui: { + path: 'Generalities.Dates.EndDate', + component: 'datepicker', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'CreatedDate', + ui: { + path: 'Generalities.Dates.CreatedDate', + component: 'datepicker', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'TransactedDate', + ui: { + path: 'Generalities.Dates.TransactedDate', + component: 'datepicker', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'SentDate', + ui: { + path: 'Generalities.Dates.SentDate', + component: 'datepicker', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'ReceivedDate', + ui: { + path: 'Generalities.Dates.ReceivedDate', + component: 'datepicker', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'RegisteredDate', + ui: { + path: 'Generalities.Dates.RegisteredDate', + component: 'datepicker', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'AcquiredDate', + ui: { + path: 'Generalities.Dates.AcquiredDate', + component: 'datepicker', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'DateLitteral', + ui: { + path: 'Generalities.Dates.DateLitteral', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: '', + ui: { + path: 'Generalities.Identifiers', + component: 'group', + layout: { columns: 2, size: 'medium' }, + }, + }, + { + path: 'SystemId', + ui: { + path: 'Generalities.Identifiers.SystemId', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'OriginatingSystemId', + ui: { + path: 'Generalities.Identifiers.OriginatingSystemId', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'OriginatingAgencyArchiveUnitIdentifier', + ui: { + path: 'Generalities.Identifiers.OriginatingAgencyArchiveUnitIdentifier', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'TransferringAgencyArchiveUnitIdentifier', + ui: { + path: 'Generalities.Identifiers.TransferringAgencyArchiveUnitIdentifier', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'ArchivalAgencyArchiveUnitIdentifier', + ui: { + path: 'Generalities.Identifiers.ArchivalAgencyArchiveUnitIdentifier', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'FilePlanPosition', + ui: { + path: 'Generalities.Identifiers.FilePlanPosition', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'PersistentIdentifier', + ui: { + path: 'Generalities.PersistentIdentifier', + component: 'group', + layout: { columns: 2, size: 'medium' }, + }, + }, + { + path: 'PersistentIdentifier.PersistentIdentifierType', + ui: { + path: 'Generalities.PersistentIdentifier.PersistentIdentifierType', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'PersistentIdentifier.PersistentIdentifierOrigin', + ui: { + path: 'Generalities.PersistentIdentifier.PersistentIdentifierOrigin', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'PersistentIdentifier.PersistentIdentifierReference', + ui: { + path: 'Generalities.PersistentIdentifier.PersistentIdentifierReference', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'PersistentIdentifier.PersistentIdentifierContent', + ui: { + path: 'Generalities.PersistentIdentifier.PersistentIdentifierContent', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: '', + ui: { + path: 'Generalities.Characteristics', + component: 'group', + layout: { columns: 2, size: 'medium' }, + }, + }, + { + path: 'Type', + ui: { + path: 'Generalities.Characteristics.Type', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'DocumentType', + ui: { + path: 'Generalities.Characteristics.DocumentType', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'Language', + ui: { + path: 'Generalities.Characteristics.Language', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'DescriptionLanguage', + ui: { + path: 'Generalities.Characteristics.DescriptionLanguage', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'Status', + ui: { + path: 'Generalities.Characteristics.Status', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'Source', + ui: { + path: 'Generalities.Characteristics.Source', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'Version', + ui: { + path: 'Generalities.Characteristics.Version', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'OriginatingSystemIdReplyTo', + ui: { + path: 'Generalities.Characteristics.OriginatingSystemIdReplyTo', + component: 'textfield', + layout: { columns: 1, size: 'small' }, + }, + }, + { + path: 'TextContent', + ui: { + path: 'Generalities.Characteristics.TextContent', + component: 'textfield', + layout: { columns: 2, size: 'medium' }, + }, + }, +]; +const data = { + '#id': 'aeaqaaaaaeecehmeabneoamjofozk4iaaaea', + Title: 'Gambetta par producteur1', + DescriptionLevel: 'RecordGrp', + Description: 'Station Gambetta ligne 3 Paris', + OriginatingAgencyArchiveUnitIdentifier: [], + '#tenant': 1, + '#unitups': [], + '#min': 1, + '#max': 1, + '#allunitups': [], + '#unitType': 'INGEST', + '#operations': ['aeeaaaaaagecehmeaa5rwamjofoy5haaaaaq'], + '#opi': 'aeeaaaaaagecehmeaa5rwamjofoy5haaaaaq', + '#originating_agency': 'producteur1', + '#originating_agencies': ['producteur1'], + '#management': { + AppraisalRule: null, + HoldRule: null, + StorageRule: null, + ReuseRule: null, + ClassificationRule: null, + DisseminationRule: null, + AccessRule: null, + UpdateOperation: null, + }, + StartDate: '2016-06-03T15:28:00', + EndDate: '2016-06-03T15:28:00', + Xtag: [], + Vtag: [], + '#storage': { + strategyId: 'default', + }, + '#qualifiers': [], + OriginatingSystemId: [], + PhysicalAgency: [], + PhysicalStatus: [], + PhysicalType: [], + Keyword: [], + '#approximate_creation_date': '2023-07-20T03:35:07.967', + '#approximate_update_date': '2023-07-20T03:35:07.967', + originating_agencyName: 'Service producteur1', +}; diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.ts new file mode 100644 index 00000000000..30b826a9369 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.component.ts @@ -0,0 +1,76 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { Logger } from '../logger/logger'; +import { DisplayObjectService, DisplayRule } from './models'; + +@Component({ + selector: 'vitamui-common-object-viewer', + templateUrl: './object-viewer.component.html', + styleUrls: ['./object-viewer.component.scss'], +}) +export class ObjectViewerComponent implements OnInit, OnChanges { + @Input() data!: any; + @Input() template!: DisplayRule[]; + @Input() mode = 'template-driven'; + + constructor(private logger: Logger, public displayObjectService: DisplayObjectService) {} + + ngOnInit(): void { + this.displayObjectService.setMode(this.mode); + if (!this.data) { + this.logger.warn(this, 'No data provided at init'); + } + if (!this.template) { + this.logger.warn(this, 'No template provided at init'); + } + } + + ngOnChanges(changes: SimpleChanges): void { + const { data, template, mode } = changes; + + if (mode) { + this.displayObjectService.setMode(mode.currentValue); + } + if (data) { + this.displayObjectService.setData(data.currentValue); + } + if (template) { + this.displayObjectService.setTemplate(template.currentValue); + } + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.module.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.module.ts new file mode 100644 index 00000000000..3feefa6667e --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/object-viewer.module.ts @@ -0,0 +1,74 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { TranslateModule } from '@ngx-translate/core'; +import { PipesModule } from '../pipes/pipes.module'; +import { GroupComponent } from './components/group/group.component'; +import { ListComponent } from './components/list/list.component'; +import { PrimitiveComponent } from './components/primitive/primitive.component'; +import { DisplayObjectService } from './models'; +import { ObjectViewerComponent } from './object-viewer.component'; +import { DataStructureService } from './services/data-structure.service'; +import { DateDisplayService } from './services/date-display.service'; +import { DisplayObjectHelperService } from './services/display-object-helper.service'; +import { DisplayRuleHelperService } from './services/display-rule-helper.service'; +import { FavoriteEntryService } from './services/favorite-entry.service'; +import { LayoutService } from './services/layout.service'; +import { OntologyToDisplayRuleMapper } from './services/ontology-to-display-rule.mapper'; +import { PathStrategyDisplayObjectService } from './services/path-strategy-display-object.service'; +import { TypeService } from './services/type.service'; + +@NgModule({ + imports: [CommonModule, TranslateModule, PipesModule, MatTooltipModule, MatProgressSpinnerModule], + declarations: [ObjectViewerComponent, GroupComponent, ListComponent, PrimitiveComponent], + providers: [ + DateDisplayService, + DataStructureService, + TypeService, + DisplayObjectHelperService, + DisplayRuleHelperService, + OntologyToDisplayRuleMapper, + LayoutService, + FavoriteEntryService, + { provide: DisplayObjectService, useClass: PathStrategyDisplayObjectService }, + ], + exports: [ObjectViewerComponent, GroupComponent, ListComponent, PrimitiveComponent], +}) +export class ObjectViewerModule {} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/data-structure.service.spec.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/data-structure.service.spec.ts new file mode 100644 index 00000000000..3d11e647236 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/data-structure.service.spec.ts @@ -0,0 +1,296 @@ +import { TestBed } from '@angular/core/testing'; +import { ObjectViewerModule } from '../object-viewer.module'; +import { DataStructureService } from './data-structure.service'; + +describe('DataStructureService', () => { + let service: DataStructureService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ObjectViewerModule], + }); + service = TestBed.inject(DataStructureService); + }); + + it('should create', () => { + expect(service).toBeTruthy(); + }); + + it('should flatten data', () => { + const computer = { + name: 'asus', + cpus: [ + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + ], + description: 'description', + nested: { + information: 'information', + }, + }; + const expected = { + name: 'asus', + 'cpus[0].name': 'xeon', + 'cpus[0].cores': 4, + 'cpus[1].name': 'xeon', + 'cpus[1].cores': 4, + 'cpus[2].name': 'xeon', + 'cpus[2].cores': 4, + 'cpus[3].name': 'xeon', + 'cpus[3].cores': 4, + description: 'description', + 'nested.information': 'information', + }; + + expect(service.flatten(computer)).toEqual(expected); + }); + + it('should unflatten data', () => { + const flattened = { + name: 'asus', + 'cpus[0].name': 'xeon', + 'cpus[0].cores': 4, + 'cpus[1].name': 'xeon', + 'cpus[1].cores': 4, + 'cpus[2].name': 'xeon', + 'cpus[2].cores': 4, + 'cpus[3].name': 'xeon', + 'cpus[3].cores': 4, + description: 'description', + 'nested.information': 'information', + }; + const expected = { + name: 'asus', + cpus: [ + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + ], + description: 'description', + nested: { + information: 'information', + }, + }; + console.log(service.unflatten(flattened)); + expect(service.unflatten(flattened)).toEqual(expected); + }); + + it('should flatten complexe data', () => { + const data = { + name: 'Complex Data Example', + age: 30, + address: { + street: '123 Main St', + city: 'Big City', + country: 'Country', + }, + friends: [ + { + name: 'John Doe', + age: 28, + }, + { + name: 'Jane Smith', + age: 32, + address: { + street: '456 Elm St', + city: 'Small Town', + country: 'Country', + }, + hobbies: ['Reading', 'Painting'], + }, + ], + projects: [ + { + name: 'Project A', + status: 'In Progress', + team: ['John Doe', 'Jane Smith'], + }, + { + name: 'Project B', + status: 'Completed', + team: ['Alice', 'Bob', 'Eve'], + }, + ], + nestedLevel1: { + nestedLevel2: { + nestedLevel3: { + nestedLevel4: { + nestedLevel5: { + nestedLevel6: { + nestedLevel7: { + nestedLevel8: { + nestedLevel9: { + nestedLevel10: 'Final Nested Level!', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }; + const flattened = { + name: 'Complex Data Example', + age: 30, + 'address.street': '123 Main St', + 'address.city': 'Big City', + 'address.country': 'Country', + 'friends[0].name': 'John Doe', + 'friends[0].age': 28, + 'friends[1].name': 'Jane Smith', + 'friends[1].age': 32, + 'friends[1].address.street': '456 Elm St', + 'friends[1].address.city': 'Small Town', + 'friends[1].address.country': 'Country', + 'friends[1].hobbies[0]': 'Reading', + 'friends[1].hobbies[1]': 'Painting', + 'projects[0].name': 'Project A', + 'projects[0].status': 'In Progress', + 'projects[0].team[0]': 'John Doe', + 'projects[0].team[1]': 'Jane Smith', + 'projects[1].name': 'Project B', + 'projects[1].status': 'Completed', + 'projects[1].team[0]': 'Alice', + 'projects[1].team[1]': 'Bob', + 'projects[1].team[2]': 'Eve', + 'nestedLevel1.nestedLevel2.nestedLevel3.nestedLevel4.nestedLevel5.nestedLevel6.nestedLevel7.nestedLevel8.nestedLevel9.nestedLevel10': + 'Final Nested Level!', + }; + + expect(service.flatten(data)).toEqual(flattened); + }); + + it('should unflatten complexe data', () => { + const unflattened = { + name: 'Complex Data Example', + age: 30, + address: { + street: '123 Main St', + city: 'Big City', + country: 'Country', + }, + friends: [ + { + name: 'John Doe', + age: 28, + }, + { + name: 'Jane Smith', + age: 32, + address: { + street: '456 Elm St', + city: 'Small Town', + country: 'Country', + }, + hobbies: ['Reading', 'Painting'], + }, + ], + projects: [ + { + name: 'Project A', + status: 'In Progress', + team: ['John Doe', 'Jane Smith'], + }, + { + name: 'Project B', + status: 'Completed', + team: ['Alice', 'Bob', 'Eve'], + }, + ], + nestedLevel1: { + nestedLevel2: { + nestedLevel3: { + nestedLevel4: { + nestedLevel5: { + nestedLevel6: { + nestedLevel7: { + nestedLevel8: { + nestedLevel9: { + nestedLevel10: 'Final Nested Level!', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }; + const flattened = { + name: 'Complex Data Example', + age: 30, + 'address.street': '123 Main St', + 'address.city': 'Big City', + 'address.country': 'Country', + 'friends[0].name': 'John Doe', + 'friends[0].age': 28, + 'friends[1].name': 'Jane Smith', + 'friends[1].age': 32, + 'friends[1].address.street': '456 Elm St', + 'friends[1].address.city': 'Small Town', + 'friends[1].address.country': 'Country', + 'friends[1].hobbies[0]': 'Reading', + 'friends[1].hobbies[1]': 'Painting', + 'projects[0].name': 'Project A', + 'projects[0].status': 'In Progress', + 'projects[0].team[0]': 'John Doe', + 'projects[0].team[1]': 'Jane Smith', + 'projects[1].name': 'Project B', + 'projects[1].status': 'Completed', + 'projects[1].team[0]': 'Alice', + 'projects[1].team[1]': 'Bob', + 'projects[1].team[2]': 'Eve', + 'nestedLevel1.nestedLevel2.nestedLevel3.nestedLevel4.nestedLevel5.nestedLevel6.nestedLevel7.nestedLevel8.nestedLevel9.nestedLevel10': + 'Final Nested Level!', + }; + + expect(service.unflatten(flattened)).toEqual(unflattened); + }); + + it('should restore original after flat/unflat data', () => { + const data = { + name: 'asus', + cpus: [ + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + ], + description: 'description', + nested: { + information: 'information', + }, + }; + const flattened = service.flatten(data); + const unflattened = service.unflatten(flattened); + + expect(unflattened).toEqual(data); + }); + + it('should find deep value', () => { + const unflattened = { + name: 'asus', + cpus: [ + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + { name: 'xeon', cores: 4 }, + ], + description: 'description', + nested: { + information: 'information', + }, + }; + + expect(service.deepValue(unflattened, 'name')).toEqual('asus'); + expect(service.deepValue(unflattened, 'nested.information')).toEqual('information'); + expect(service.deepValue(unflattened, 'cpus[0].cores')).toEqual(4); + }); +}); diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/data-structure.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/data-structure.service.ts new file mode 100644 index 00000000000..83fb2a6d9d3 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/data-structure.service.ts @@ -0,0 +1,179 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Injectable } from '@angular/core'; + +@Injectable() +export class DataStructureService { + /** + * Transforms a nested object into a flat object. + * + * @param data Nested object. + * @returns Flat object. + */ + public flatten(data: any) { + const result = {}; + function recurse(cur: any, prop: any) { + if (Object(cur) !== cur) { + result[prop] = cur; + } else if (Array.isArray(cur)) { + for (let i = 0, l = cur.length; i < l; i++) { + recurse(cur[i], prop + '[' + i + ']'); + } + if (cur.length === 0) { + result[prop] = []; + } + } else { + let isEmpty = true; + for (const p in cur) { + isEmpty = false; + recurse(cur[p], prop ? prop + '.' + p : p); + } + if (isEmpty && prop) { + result[prop] = {}; + } + } + } + recurse(data, ''); + return result; + } + + /** + * Transforms flat a object into nested object. + * + * @param data Flat object. + * @returns Nested object. + */ + public unflatten(data: any) { + if (Object(data) !== data || Array.isArray(data)) { + return data; + } + + const regex = /\.?([^.\[\]]+)|\[(\d+)\]/g; + const resultholder = {}; + + for (const p in data) { + let cur = resultholder; + let prop = ''; + let m: RegExpExecArray; + + while ((m = regex.exec(p))) { + cur = cur[prop] || (cur[prop] = m[2] ? [] : {}); + prop = m[2] || m[1]; + } + cur[prop] = data[p]; + } + + return resultholder[''] || resultholder; + } + + /** + * Finds a value inside an object by providing its path. + * + * @param obj Root object for the research. + * @param path Path of value inside the root object. + * @returns Found value. + */ + public deepValue(obj: any, path: any): any { + path = path.replace(/\[(\w+)\]/g, '.$1'); // Convertit tous les [index] en .index + path = path.replace(/^\./, ''); // Supprime le point au début s'il y en a un + + const keys = path.split('.'); + + for (let i = 0, len = keys.length; i < len; i++) { + if (obj && typeof obj === 'object') { + obj = obj[keys[i]]; + } else { + return undefined; + } + } + + return obj; + } + + /** + * Folds an array into sereval rows. + * + * @param array Initial array. + * @param columnCount Max columns by row. + * @returns A n+1 dimentional array. + */ + public fold(array: any[], columnCount: number): any[][] { + const rowCount = Math.ceil(array.length / columnCount); + const rows = []; + + for (let row = 0; row < rowCount; row++) { + const columns: any[] = []; + + for (let column = 0; column < columnCount; column++) { + const index = row * columnCount + column; + + if (index < array.length) { + columns.push(array[index]); + } + } + + rows.push(columns); + } + + return rows; + } + + /** + * Deep merge two objects. + * + * @param target Target object. + * @param source Source object. + * @returns A merged object. + */ + public deepMerge(target: any, source: any) { + // Iterate through all properties in the source object + for (const key in source) { + if (source.hasOwnProperty(key)) { + // Check if the current property is an object and needs merging + if (source[key] instanceof Object && key in target && target[key] instanceof Object) { + // Recursively merge the nested objects + this.deepMerge(target[key], source[key]); + } else { + // Perform a regular assignment if the property doesn't need merging + target[key] = source[key]; + } + } + } + + return target; + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/date-display.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/date-display.service.ts new file mode 100644 index 00000000000..9ff2677d6f7 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/date-display.service.ts @@ -0,0 +1,50 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Injectable } from '@angular/core'; +import { ComponentType } from '../types'; + +@Injectable() +export class DateDisplayService { + private dateFormat = { + wanted: { datepicker: 'dd/MM/yyyy', datetime: 'dd/MM/yyyy hh:mm:ss' }, + default: { datepicker: 'medium', datetime: 'medium' }, + }; + + public getFormat(component: ComponentType, formatSet = 'default') { + return this.dateFormat[formatSet][component] || 'short'; + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-object-helper.service.spec.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-object-helper.service.spec.ts new file mode 100644 index 00000000000..4d5d83733e7 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-object-helper.service.spec.ts @@ -0,0 +1,434 @@ +import { TestBed } from '@angular/core/testing'; +import { LoggerModule } from '../../logger'; +import { DisplayObject, DisplayRule } from '../models'; +import { DisplayObjectType } from '../types'; +import { DataStructureService } from './data-structure.service'; +import { DisplayObjectHelperService } from './display-object-helper.service'; +import { DisplayRuleHelperService } from './display-rule-helper.service'; +import { TypeService } from './type.service'; + +describe('DisplayObjectHelperService', () => { + let service: DisplayObjectHelperService; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [DisplayObjectHelperService, DisplayRuleHelperService, TypeService, DataStructureService], + imports: [LoggerModule.forRoot()], + }); + service = TestBed.inject(DisplayObjectHelperService); + }); + + describe('toDisplayObject', () => { + it('should map to display object', () => { + const inputs: { data: any; template: DisplayRule[]; expected: DisplayObject }[] = [ + { + data: 'bonjour', + template: [], + expected: { + type: DisplayObjectType.PRIMITIVE, + path: '', + key: '', + value: 'bonjour', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + }, + { + data: ['A', 'B', 'C'], + template: [], + expected: { + type: DisplayObjectType.LIST, + path: '', + key: '', + value: ['A', 'B', 'C'], + component: 'textfield', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: '[0]', + key: '[0]', + value: 'A', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: '[0]', + ui: { + path: '[0]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: '[1]', + key: '[1]', + value: 'B', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: '[1]', + ui: { + path: '[1]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: '[2]', + key: '[2]', + value: 'C', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: '[2]', + ui: { + path: '[2]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + }, + { + data: { id: '1', name: 'core' }, + template: [], + expected: { + type: DisplayObjectType.GROUP, + path: '', + key: '', + value: { id: '1', name: 'core' }, + component: 'group', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: 'id', + key: 'id', + value: '1', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'id', + ui: { + path: 'id', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'name', + key: 'name', + value: 'core', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'name', + ui: { + path: 'name', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + }, + { + data: { id: '1', name: 'core', tags: ['low', 'medium', 'high'] }, + template: [ + { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['name'], + }, + }, + { + path: '', + ui: { + path: 'Generalities', + component: 'group', + favoriteKeys: ['name'], + }, + }, + { + path: 'name', + ui: { + path: 'Generalities.name', + component: 'group', + }, + }, + ], + expected: { + type: DisplayObjectType.GROUP, + path: '', + key: '', + value: { id: '1', name: 'core', tags: ['low', 'medium', 'high'] }, + component: 'group', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: 'id', + key: 'id', + value: '1', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'id', + ui: { + path: 'id', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'name', + key: 'name', + value: 'core', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'name', + ui: { + path: 'name', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.LIST, + path: 'tags', + key: 'tags', + value: ['low', 'medium', 'high'], + component: 'textfield', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[0]', + key: 'tags[0]', + value: 'low', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[0]', + ui: { + path: 'tags[0]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[1]', + key: 'tags[1]', + value: 'medium', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[1]', + ui: { + path: 'tags[1]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[2]', + key: 'tags[2]', + value: 'high', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[2]', + ui: { + path: 'tags[2]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags', + ui: { + path: 'tags', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: ['name'], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['name'], + open: true, + display: true, + }, + }, + }, + }, + ]; + + expect(service).toBeTruthy(); + inputs.forEach((input, i) => { + const { data, template, expected }: { data: any; template: DisplayRule[]; expected: DisplayObject } = input; + + expect(data).toBeTruthy(); + expect(template).toBeTruthy(); + expect(expected).toBeTruthy(); + + const displayObject = service.toDisplayObject(data, template); + + expect(displayObject).withContext(`failed on index ${i}`).toEqual(expected, `failed on index ${i}`); + }); + }); + }); +}); diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-object-helper.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-object-helper.service.ts new file mode 100644 index 00000000000..cb96dccebae --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-object-helper.service.ts @@ -0,0 +1,160 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Injectable } from '@angular/core'; +import { Logger } from '../../logger/logger'; +import { DisplayObject, DisplayRule } from '../models'; +import { ComponentType, DisplayObjectType } from '../types'; +import { DataStructureService } from './data-structure.service'; +import { DisplayRuleHelperService } from './display-rule-helper.service'; +import { TypeService } from './type.service'; + +@Injectable() +export class DisplayObjectHelperService { + constructor( + private logger: Logger, + private typeService: TypeService, + private dataStructureService: DataStructureService, + private displayRuleHelperService: DisplayRuleHelperService + ) {} + + public getComponentType(data: any, template: DisplayRule[] = [], path: string = ''): ComponentType { + const type: DisplayObjectType = this.typeService.dataType(data); + const componentFromTemplate = template.find((displayRule) => displayRule?.ui?.path === path)?.ui?.component; + const componentFromType = ((displayObjectType: DisplayObjectType): ComponentType => + displayObjectType === DisplayObjectType.GROUP ? 'group' : 'textfield')(type); + + return componentFromTemplate || componentFromType; + } + + public getFavoriteKeys(path: string, template: DisplayRule[] = []): string[] { + const displayRule = template.find((rule) => rule?.ui?.path === path); + + return displayRule?.ui?.favoriteKeys || []; + } + + public toDisplayObject( + data: any, + template: DisplayRule[] = [], + path: string = '', + configuration = { displayEmptyValues: true } + ): DisplayObject { + const defaultDisplayRule = this.displayRuleHelperService.toDisplayRule(data, path, configuration); + const templateDisplayRule = template.find((rule) => rule?.ui?.path === path); + const displayRule: DisplayRule = this.dataStructureService.deepMerge(defaultDisplayRule, templateDisplayRule); + + let children = []; + + if (data && this.typeService.isList(data)) { + children = data.map((value: any, index: number) => this.toDisplayObject(value, template, `${path}[${index}]`, configuration)); + } + + if (data && this.typeService.isGroup(data)) { + children = Object.entries(data).map(([key, value]) => + this.toDisplayObject(value, template, `${path ? path + '.' + key : key}`, configuration) + ); + } + + return { + children, + component: this.getComponentType(data, template, path), + displayRule, + favoriteKeys: this.getFavoriteKeys(path, template), + key: path.split('.').pop(), + open: displayRule.ui.open, + path, + type: this.typeService.dataType(data), + value: data, + }; + } + + public dataDrivenDisplayObject(data: any, configuration = { displayEmptyValues: true }): DisplayObject { + return this.toDisplayObject(data, [], '', configuration); + } + + public templateDrivenDisplayObject(data: any, template: DisplayRule[], configuration = { displayEmptyValues: true }): DisplayObject { + if (!template) { + return null; + } + + const mappings = template.map((displayRule) => this.mapValueToUiPath(data, displayRule)); + const consistentMappings = mappings.filter((value) => configuration.displayEmptyValues || this.typeService.hasDefined(value)); + const flatTemplatedData = consistentMappings.reduce(this.dataStructureService.deepMerge, {}); + const nestedTemplatedData = this.dataStructureService.unflatten(flatTemplatedData); + const templatedDisplayObject = this.toDisplayObject(nestedTemplatedData, template, '', configuration); + + return templatedDisplayObject; + } + + public mixedDrivenDisplayObject(data: any, template: DisplayRule[], configuration = { displayEmptyValues: true }): DisplayObject { + const dataDisplayObject = this.dataDrivenDisplayObject(data, configuration); + const templateDisplayObject = this.templateDrivenDisplayObject(data, template, configuration); + const dataDisplayObjectValue = dataDisplayObject?.value || {}; + const templateDisplayObjectValue = templateDisplayObject?.value || {}; + const mixedValue = this.dataStructureService.deepMerge( + this.dataStructureService.deepMerge({}, templateDisplayObjectValue), + dataDisplayObjectValue + ); + + return this.toDisplayObject(mixedValue, template, '', configuration); + } + + public extractDisplayRules(displayObject: DisplayObject): DisplayRule[] { + const template: DisplayRule[] = []; + const stack: DisplayObject[] = [displayObject]; + + while (stack.length > 0) { + const current = stack.pop(); + + template.push(current.displayRule); + + if (current.children && current.children.length > 0) { + for (let i = current.children.length - 1; i >= 0; i--) { + stack.push(current.children[i]); + } + } + } + + return template; + } + + private mapValueToUiPath(data: any, displayRule: DisplayRule) { + const key = displayRule.ui.path; + const value = displayRule.path ? this.dataStructureService.deepValue(data, displayRule.path) : undefined; + + return { [key]: value }; + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-rule-helper.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-rule-helper.service.ts new file mode 100644 index 00000000000..bba4ee54837 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/display-rule-helper.service.ts @@ -0,0 +1,110 @@ +import { Injectable } from '@angular/core'; +import { DisplayRule, Ui } from '../models'; +import { DisplayObjectType } from '../types'; +import { DataStructureService } from './data-structure.service'; +import { TypeService } from './type.service'; + +@Injectable() +export class DisplayRuleHelperService { + constructor(private typeService: TypeService, private dataStructureService: DataStructureService) {} + + private isUndefinedOrNull(path: any): boolean { + return path === undefined || path === null; + } + + private arePathsEqual(path1: any, path2: any): boolean { + return path1 === path2; + } + + private shouldDisplay(data: any, configuration = { displayEmptyValues: true }): boolean { + return configuration.displayEmptyValues || this.typeService.isConsistent(data); + } + + public toDisplayRule(data: any, path = null, configuration = { displayEmptyValues: true }): DisplayRule { + const type = this.typeService.dataType(data); + const isPrimitive = type === DisplayObjectType.PRIMITIVE; + + return { + path, + ui: { + path, + component: isPrimitive ? 'textfield' : 'group', + layout: { + columns: isPrimitive ? 1 : 2, + size: isPrimitive ? 'small' : 'medium', + }, + open: true, + display: this.shouldDisplay(data, configuration), + }, + }; + } + + public getCommonDisplayRules(sourceRules: DisplayRule[], targetRules: DisplayRule[]): DisplayRule[] { + return sourceRules.filter((sourceRule) => + targetRules.some((targetRule) => !this.isUndefinedOrNull(targetRule.path) && this.arePathsEqual(targetRule.path, sourceRule.path)) + ); + } + + public getUniqueDisplayRules(sourceRules: DisplayRule[], targetRules: DisplayRule[]): DisplayRule[] { + return sourceRules.filter((sourceRule) => targetRules.every((targetRule) => !this.arePathsEqual(targetRule.path, sourceRule.path))); + } + + public mergeDisplayRulesByPath(sourceRules: DisplayRule[], targetRules: DisplayRule[]): DisplayRule[] { + return targetRules.map((targetRule) => { + const sourceRule = sourceRules.find((rule) => rule.path === targetRule.path); + + if (sourceRule) { + this.dataStructureService.deepMerge(sourceRule, targetRule); + } + + return targetRule; + }); + } + + public prioritizeAndMergeDisplayRules(sourceRules: DisplayRule[], targetRules: DisplayRule[]): DisplayRule[] { + const sourceUiPathMap = new Map(); + + // Indexe les règles d'affichage de source par chemin + sourceRules.forEach((rule) => { + sourceUiPathMap.set(rule.ui.path, rule); + }); + + const displayRules: DisplayRule[] = []; + + // Parcourt les règles de target et traite chaque règle + targetRules.forEach((targetRule) => { + const sourceRule = sourceUiPathMap.get(targetRule.ui.path); + + // Si une règle correspondante existe dans source, fusionne les valeurs + if (sourceRule) { + // Fusionne les valeurs de sourceRule et targetRule (utilisez votre propre logique de fusion) + const mergedRule = this.mergeDisplayRules(sourceRule, targetRule); + displayRules.push(mergedRule); + } else { + // Si aucune règle correspondante n'existe dans source, ajoute simplement la règle de target + displayRules.push(targetRule); + } + }); + + return displayRules; + } + + private mergeDisplayRules(sourceRule: DisplayRule, targetRule: DisplayRule): DisplayRule { + if (sourceRule.ui.path !== targetRule.ui.path) { + throw new Error('Les règles n\'ont pas le même chemin et ne peuvent pas être fusionnées.'); + } + + const mergedUI: Ui = { + ...sourceRule.ui, + component: targetRule.ui.component, + layout: targetRule.ui.layout, + favoriteKeys: targetRule.ui.favoriteKeys, + open: targetRule.ui.open, + display: targetRule.ui.display, + }; + + const mergedRule: DisplayRule = { ...sourceRule, ui: mergedUI }; + + return mergedRule; + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/favorite-entry.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/favorite-entry.service.ts new file mode 100644 index 00000000000..29f6902c2ae --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/favorite-entry.service.ts @@ -0,0 +1,26 @@ +import { DisplayObject } from '../models'; + +export class FavoriteEntryService { + public favoriteEntry(displayObject: DisplayObject): [key: string, value: unknown] | null { + const favoriteEntry: [key: string, value: any] = displayObject.favoriteKeys.reduce((entry, key) => { + const value = displayObject.value[key]; + + return value ? [key, value] : entry; + }, null as [key: string, value: any]); + + return favoriteEntry; + } + + public favoritePath(displayObject: DisplayObject): string | null { + const favoriteEntry = this.favoriteEntry(displayObject); + + if (favoriteEntry && displayObject.path) { + return `${displayObject.path}.${favoriteEntry[0]}`; + } + if (favoriteEntry) { + return `${favoriteEntry[0]}`; + } + + return null; + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/layout.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/layout.service.ts new file mode 100644 index 00000000000..3752a86de92 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/layout.service.ts @@ -0,0 +1,66 @@ +import { Injectable } from '@angular/core'; +import { Logger } from '../../logger/logger'; +import { DisplayObject, Layout } from '../models'; +import { LayoutSize } from '../types'; + +@Injectable() +export class LayoutService { + MAX_COMLUMS = 2; + DEFAULT_COLUMNS = this.MAX_COMLUMS; + DEFAULT_SIZE: LayoutSize = 'medium'; + + constructor(private logger: Logger) {} + + private keepNodeWithDisplayRuleFilter(displayObject: DisplayObject): boolean { + const hasDisplayRule = Boolean(displayObject.displayRule); + + if (!hasDisplayRule) { + this.logger.warn(this, 'No display rule found for the node, the node will be skipped', { displayObject }); + } + + return hasDisplayRule; + } + + private keepDisplayedNodeFilter(displayObject: DisplayObject): boolean { + return Boolean(displayObject?.displayRule?.ui?.display); + } + + private getLastRowIndex = (rows: any[]) => rows.length - 1; + + private getLastRow = (rows: any[]) => rows[this.getLastRowIndex(rows)]; + + private getLayout(displayObject: DisplayObject): Layout { + const { columns, size } = displayObject.displayRule?.ui?.layout; + + if (columns === undefined) { + this.logger.info(this, `No columns found in display rule, default one (${this.DEFAULT_COLUMNS}) will be applied`); + } + if (size === undefined) { + this.logger.info(this, `No size found in display rule, default one (${this.DEFAULT_SIZE}) will be applied`); + } + + return { + columns: columns || this.DEFAULT_COLUMNS, + size: size || this.DEFAULT_SIZE, + }; + } + + public compute(displayObject: DisplayObject): DisplayObject[][] { + return displayObject.children + .filter(this.keepNodeWithDisplayRuleFilter) + .filter(this.keepDisplayedNodeFilter) + .reduce((rows, child: DisplayObject) => { + if (!this.getLastRow(rows)) { + rows.push([]); + } + + const lastRow = this.getLastRow(rows); + const consumedColumns = lastRow.reduce((acc: number, cell: DisplayObject) => acc + cell.displayRule.ui.layout.columns, 0); + const canInsertInLastRow = consumedColumns + this.getLayout(child).columns <= this.MAX_COMLUMS; + + canInsertInLastRow ? lastRow.push(child) : rows.push([child]); + + return rows; + }, []); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/mock-extended-ontology.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/mock-extended-ontology.service.ts new file mode 100644 index 00000000000..4977a98fda6 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/mock-extended-ontology.service.ts @@ -0,0 +1,7366 @@ +import { Injectable } from '@angular/core'; +import { Observable, of } from 'rxjs'; +import { ExtendedOntology } from '../models'; + +@Injectable() +export class MockExtendedOntologyService { + private ontologies: ExtendedOntology[] = [ + { + id: '0', + path: '_sp', + DataType: 'string', + DataSize: 'medium', + Cardinality: '1-1', + SedaVersions: ['INTERNE'], + Collections: ['Unit'], + Depth: 0, + Identifier: '_sp', + ApiField: '#originating_agency', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: '_sp', + Origin: 'Internal', + SedaField: '_sp', + Description: null, + CreationDate: '1692880151935', + LastUpdate: '1692880151935', + }, + { + id: '1', + path: '_sps', + DataType: 'string', + DataSize: 'medium', + Cardinality: '1-N', + SedaVersions: ['INTERNE'], + Collections: ['Unit'], + Depth: 0, + Identifier: '_sps', + ApiField: '#originating_agencies', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: '_sps', + Origin: 'Internal', + SedaField: '_sps', + Description: null, + CreationDate: '1692880151935', + LastUpdate: '1692880151935', + }, + { + id: '3', + path: 'DescriptionLevel', + DataType: 'token', + DataSize: 'short', + Cardinality: '1-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'DescriptionLevel', + ApiField: 'DescriptionLevel', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DescriptionLevel', + Origin: 'Internal', + SedaField: 'DescriptionLevel', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '4', + path: 'Title', + DataType: 'string', + DataSize: 'medium', + Cardinality: '1-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Title', + ApiField: 'Title', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Title', + Origin: 'Internal', + SedaField: 'Title', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '5', + path: 'Title_.*', + DataType: 'string', + DataSize: 'medium', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: '*', + ApiField: '*', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: '*', + Origin: 'Internal', + SedaField: '*', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '6', + path: 'Description', + DataType: 'string', + DataSize: 'large', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Description', + ApiField: 'Description', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Description', + Origin: 'Internal', + SedaField: 'Description', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '7', + path: 'Description_.*', + DataType: 'string', + DataSize: 'large', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: '*', + ApiField: '*', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: '*', + Origin: 'Internal', + SedaField: '*', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '8', + path: 'Tag', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Tag', + ApiField: 'Tag', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Tag', + Origin: 'Internal', + SedaField: 'Tag', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '10', + path: 'StartDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'StartDate', + ApiField: 'StartDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'StartDate', + Origin: 'Internal', + SedaField: 'StartDate', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '11', + path: 'EndDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'EndDate', + ApiField: 'EndDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'EndDate', + Origin: 'Internal', + SedaField: 'EndDate', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '12', + path: 'CreatedDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'CreatedDate', + ApiField: 'CreatedDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'CreatedDate', + Origin: 'Internal', + SedaField: 'CreatedDate', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '13', + path: 'TransactedDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'TransactedDate', + ApiField: 'TransactedDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'TransactedDate', + Origin: 'Internal', + SedaField: 'TransactedDate', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '14', + path: 'SentDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'SentDate', + ApiField: 'SentDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'SentDate', + Origin: 'Internal', + SedaField: 'SentDate', + Description: null, + CreationDate: '1692880151936', + LastUpdate: '1692880151936', + }, + { + id: '15', + path: 'ReceivedDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'ReceivedDate', + ApiField: 'ReceivedDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'ReceivedDate', + Origin: 'Internal', + SedaField: 'ReceivedDate', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '16', + path: 'RegisteredDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'RegisteredDate', + ApiField: 'RegisteredDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'RegisteredDate', + Origin: 'Internal', + SedaField: 'RegisteredDate', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '17', + path: 'AcquiredDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'AcquiredDate', + ApiField: 'AcquiredDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'AcquiredDate', + Origin: 'Internal', + SedaField: 'AcquiredDate', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '18', + path: 'DateLitteral', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.2'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'DateLitteral', + ApiField: 'DateLitteral', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'DateLitteral', + Origin: 'Internal', + SedaField: 'DateLitteral', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '20', + path: 'SystemId', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'SystemId', + ApiField: 'SystemId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'SystemId', + Origin: 'Internal', + SedaField: 'SystemId', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '21', + path: 'OriginatingSystemId', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'OriginatingSystemId', + ApiField: 'OriginatingSystemId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'OriginatingSystemId', + Origin: 'Internal', + SedaField: 'OriginatingSystemId', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '22', + path: 'OriginatingAgencyArchiveUnitIdentifier', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'OriginatingAgencyArchiveUnitIdentifier', + ApiField: 'OriginatingAgencyArchiveUnitIdentifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'OriginatingAgencyArchiveUnitIdentifier', + Origin: 'Internal', + SedaField: 'OriginatingAgencyArchiveUnitIdentifier', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '23', + path: 'TransferringAgencyArchiveUnitIdentifier', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'TransferringAgencyArchiveUnitIdentifier', + ApiField: 'TransferringAgencyArchiveUnitIdentifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'TransferringAgencyArchiveUnitIdentifier', + Origin: 'Internal', + SedaField: 'TransferringAgencyArchiveUnitIdentifier', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '24', + path: 'ArchivalAgencyArchiveUnitIdentifier', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'ArchivalAgencyArchiveUnitIdentifier', + ApiField: 'ArchivalAgencyArchiveUnitIdentifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ArchivalAgencyArchiveUnitIdentifier', + Origin: 'Internal', + SedaField: 'ArchivalAgencyArchiveUnitIdentifier', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '25', + path: 'FilePlanPosition', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'FilePlanPosition', + ApiField: 'FilePlanPosition', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'FilePlanPosition', + Origin: 'Internal', + SedaField: 'FilePlanPosition', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '32', + path: 'Type', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Type', + ApiField: 'Type', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Type', + Origin: 'Internal', + SedaField: 'Type', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '33', + path: 'DocumentType', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'DocumentType', + ApiField: 'DocumentType', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'DocumentType', + Origin: 'Internal', + SedaField: 'DocumentType', + Description: null, + CreationDate: '1692880151937', + LastUpdate: '1692880151937', + }, + { + id: '34', + path: 'Language', + DataType: 'language', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Language', + ApiField: 'Language', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Language', + Origin: 'Internal', + SedaField: 'Language', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '35', + path: 'DescriptionLanguage', + DataType: 'language', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'DescriptionLanguage', + ApiField: 'DescriptionLanguage', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DescriptionLanguage', + Origin: 'Internal', + SedaField: 'DescriptionLanguage', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '36', + path: 'Status', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Status', + ApiField: 'Status', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Status', + Origin: 'Internal', + SedaField: 'Status', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '37', + path: 'Source', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Source', + ApiField: 'Source', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Source', + Origin: 'Internal', + SedaField: 'Source', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '38', + path: 'Version', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Version', + ApiField: 'Version', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Version', + Origin: 'Internal', + SedaField: 'Version', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '39', + path: 'OriginatingSystemIdReplyTo', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.2'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'OriginatingSystemIdReplyTo', + ApiField: 'OriginatingSystemIdReplyTo', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'OriginatingSystemIdReplyTo', + Origin: 'Internal', + SedaField: 'OriginatingSystemIdReplyTo', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '40', + path: 'TextContent', + DataType: 'nonEmptyToken', + DataSize: 'medium', + Cardinality: '0-N', + SedaVersions: ['2.2'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'TextContent', + ApiField: 'TextContent', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'TextContent', + Origin: 'Internal', + SedaField: 'TextContent', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '41', + path: 'CustodialHistory', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'CustodialHistory', + ApiField: 'CustodialHistory', + Type: 'CustodialHistory', + ShortName: 'CustodialHistory', + Origin: 'Internal', + SedaField: 'CustodialHistory', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '42', + path: 'CustodialHistory.CustodialHistoryItem', + DataType: 'string', + DataSize: 'large', + Cardinality: '1-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'CustodialHistoryItem', + ApiField: 'CustodialHistoryItem', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'CustodialHistoryItem', + Origin: 'Internal', + SedaField: 'CustodialHistoryItem', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '43', + path: 'CustodialHistory.CustodialHistoryFile', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'CustodialHistoryFile', + ApiField: 'CustodialHistoryFile', + Type: 'CustodialHistoryFile', + ShortName: 'CustodialHistoryFile', + Origin: 'Internal', + SedaField: 'CustodialHistoryFile', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '44', + path: 'CustodialHistory.CustodialHistoryFile.DataObjectGroupReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '1-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DataObjectGroupReferenceId', + ApiField: 'DataObjectGroupReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectGroupReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectGroupReferenceId', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '45', + path: 'CustodialHistory.CustodialHistoryFile.DataObjectReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '1-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DataObjectReferenceId', + ApiField: 'DataObjectReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectReferenceId', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '46', + path: 'AuthorizedAgent', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'AuthorizedAgent', + ApiField: 'AuthorizedAgent', + Type: 'AuthorizedAgent', + ShortName: 'AuthorizedAgent', + Origin: 'Internal', + SedaField: 'AuthorizedAgent', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '47', + path: 'AuthorizedAgent.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '48', + path: 'AuthorizedAgent.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '49', + path: 'AuthorizedAgent.FullName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FullName', + ApiField: 'FullName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FullName', + Origin: 'Internal', + SedaField: 'FullName', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '50', + path: 'AuthorizedAgent.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '51', + path: 'AuthorizedAgent.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '52', + path: 'AuthorizedAgent.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151938', + LastUpdate: '1692880151938', + }, + { + id: '53', + path: 'AuthorizedAgent.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '54', + path: 'AuthorizedAgent.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '55', + path: 'AuthorizedAgent.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '56', + path: 'AuthorizedAgent.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '57', + path: 'AuthorizedAgent.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '58', + path: 'AuthorizedAgent.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '59', + path: 'AuthorizedAgent.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '60', + path: 'AuthorizedAgent.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '61', + path: 'AuthorizedAgent.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '62', + path: 'AuthorizedAgent.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '63', + path: 'AuthorizedAgent.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '64', + path: 'AuthorizedAgent.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '65', + path: 'AuthorizedAgent.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '66', + path: 'AuthorizedAgent.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '67', + path: 'AuthorizedAgent.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '68', + path: 'AuthorizedAgent.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '69', + path: 'AuthorizedAgent.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '70', + path: 'AuthorizedAgent.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '71', + path: 'AuthorizedAgent.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151939', + LastUpdate: '1692880151939', + }, + { + id: '72', + path: 'AuthorizedAgent.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '73', + path: 'AuthorizedAgent.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '74', + path: 'AuthorizedAgent.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '75', + path: 'AuthorizedAgent.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '76', + path: 'Agent', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Agent', + ApiField: 'Agent', + Type: 'Agent', + ShortName: 'Agent', + Origin: 'Internal', + SedaField: 'Agent', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '77', + path: 'Agent.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '78', + path: 'Agent.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '79', + path: 'Agent.FullName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FullName', + ApiField: 'FullName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FullName', + Origin: 'Internal', + SedaField: 'FullName', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '80', + path: 'Agent.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '81', + path: 'Agent.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '82', + path: 'Agent.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '83', + path: 'Agent.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '84', + path: 'Agent.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '85', + path: 'Agent.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '86', + path: 'Agent.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '87', + path: 'Agent.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '88', + path: 'Agent.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '89', + path: 'Agent.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151940', + }, + { + id: '90', + path: 'Agent.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151940', + LastUpdate: '1692880151941', + }, + { + id: '91', + path: 'Agent.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '92', + path: 'Agent.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '93', + path: 'Agent.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '94', + path: 'Agent.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '95', + path: 'Agent.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '96', + path: 'Agent.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '97', + path: 'Agent.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '98', + path: 'Agent.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '99', + path: 'Agent.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '100', + path: 'Agent.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '101', + path: 'Agent.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '102', + path: 'Agent.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '103', + path: 'Agent.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '104', + path: 'Agent.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '105', + path: 'Agent.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '106', + path: 'Writer', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Writer', + ApiField: 'Writer', + Type: 'Writer', + ShortName: 'Writer', + Origin: 'Internal', + SedaField: 'Writer', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '107', + path: 'Writer.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '108', + path: 'Writer.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '109', + path: 'Writer.FullName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FullName', + ApiField: 'FullName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FullName', + Origin: 'Internal', + SedaField: 'FullName', + Description: null, + CreationDate: '1692880151941', + LastUpdate: '1692880151941', + }, + { + id: '110', + path: 'Writer.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '111', + path: 'Writer.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '112', + path: 'Writer.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '113', + path: 'Writer.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '114', + path: 'Writer.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '115', + path: 'Writer.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '116', + path: 'Writer.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '117', + path: 'Writer.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '118', + path: 'Writer.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '119', + path: 'Writer.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '120', + path: 'Writer.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '121', + path: 'Writer.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '122', + path: 'Writer.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '123', + path: 'Writer.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '124', + path: 'Writer.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '125', + path: 'Writer.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '126', + path: 'Writer.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '127', + path: 'Writer.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '128', + path: 'Writer.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '129', + path: 'Writer.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151942', + LastUpdate: '1692880151942', + }, + { + id: '130', + path: 'Writer.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151943', + LastUpdate: '1692880151943', + }, + { + id: '131', + path: 'Writer.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151943', + LastUpdate: '1692880151943', + }, + { + id: '132', + path: 'Writer.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151943', + LastUpdate: '1692880151943', + }, + { + id: '133', + path: 'Writer.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151943', + LastUpdate: '1692880151943', + }, + { + id: '134', + path: 'Writer.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '135', + path: 'Writer.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '136', + path: 'Addressee', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Addressee', + ApiField: 'Addressee', + Type: 'Addressee', + ShortName: 'Addressee', + Origin: 'Internal', + SedaField: 'Addressee', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '137', + path: 'Addressee.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '138', + path: 'Addressee.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '139', + path: 'Addressee.Fullpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Fullpname', + ApiField: 'Fullpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Fullpname', + Origin: 'Internal', + SedaField: 'Fullpname', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '140', + path: 'Addressee.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '141', + path: 'Addressee.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '142', + path: 'Addressee.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151944', + LastUpdate: '1692880151944', + }, + { + id: '143', + path: 'Addressee.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '144', + path: 'Addressee.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '145', + path: 'Addressee.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '146', + path: 'Addressee.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '147', + path: 'Addressee.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '148', + path: 'Addressee.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '149', + path: 'Addressee.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '150', + path: 'Addressee.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '151', + path: 'Addressee.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '152', + path: 'Addressee.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '153', + path: 'Addressee.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '154', + path: 'Addressee.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151945', + LastUpdate: '1692880151945', + }, + { + id: '155', + path: 'Addressee.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '156', + path: 'Addressee.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '157', + path: 'Addressee.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '158', + path: 'Addressee.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '159', + path: 'Addressee.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '160', + path: 'Addressee.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '161', + path: 'Addressee.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '162', + path: 'Addressee.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '163', + path: 'Addressee.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '164', + path: 'Addressee.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '165', + path: 'Addressee.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '166', + path: 'Recipient', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Recipient', + ApiField: 'Recipient', + Type: 'Recipient', + ShortName: 'Recipient', + Origin: 'Internal', + SedaField: 'Recipient', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '167', + path: 'Recipient.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '168', + path: 'Recipient.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151946', + LastUpdate: '1692880151946', + }, + { + id: '169', + path: 'Recipient.FullName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FullName', + ApiField: 'FullName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FullName', + Origin: 'Internal', + SedaField: 'FullName', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '170', + path: 'Recipient.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '171', + path: 'Recipient.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '172', + path: 'Recipient.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '173', + path: 'Recipient.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '174', + path: 'Recipient.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '175', + path: 'Recipient.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '176', + path: 'Recipient.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '177', + path: 'Recipient.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '178', + path: 'Recipient.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '179', + path: 'Recipient.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '180', + path: 'Recipient.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '181', + path: 'Recipient.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '182', + path: 'Recipient.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '183', + path: 'Recipient.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '184', + path: 'Recipient.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151947', + }, + { + id: '185', + path: 'Recipient.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151947', + LastUpdate: '1692880151948', + }, + { + id: '186', + path: 'Recipient.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '187', + path: 'Recipient.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '188', + path: 'Recipient.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '189', + path: 'Recipient.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '190', + path: 'Recipient.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '191', + path: 'Recipient.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '192', + path: 'Recipient.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '193', + path: 'Recipient.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '194', + path: 'Recipient.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '195', + path: 'Recipient.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '196', + path: 'Transmitter', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Transmitter', + ApiField: 'Transmitter', + Type: 'Transmitter', + ShortName: 'Transmitter', + Origin: 'Internal', + SedaField: 'Transmitter', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '197', + path: 'Transmitter.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '198', + path: 'Transmitter.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '199', + path: 'Transmitter.FullName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FullName', + ApiField: 'FullName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FullName', + Origin: 'Internal', + SedaField: 'FullName', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '200', + path: 'Transmitter.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '201', + path: 'Transmitter.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '202', + path: 'Transmitter.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '203', + path: 'Transmitter.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151948', + }, + { + id: '204', + path: 'Transmitter.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151948', + LastUpdate: '1692880151949', + }, + { + id: '205', + path: 'Transmitter.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '206', + path: 'Transmitter.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '207', + path: 'Transmitter.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '208', + path: 'Transmitter.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '209', + path: 'Transmitter.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '210', + path: 'Transmitter.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '211', + path: 'Transmitter.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '212', + path: 'Transmitter.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '213', + path: 'Transmitter.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '214', + path: 'Transmitter.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '215', + path: 'Transmitter.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '216', + path: 'Transmitter.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '217', + path: 'Transmitter.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '218', + path: 'Transmitter.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '219', + path: 'Transmitter.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '220', + path: 'Transmitter.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '221', + path: 'Transmitter.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '222', + path: 'Transmitter.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151949', + LastUpdate: '1692880151949', + }, + { + id: '223', + path: 'Transmitter.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '224', + path: 'Transmitter.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '225', + path: 'Transmitter.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '226', + path: 'Sender', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Sender', + ApiField: 'Sender', + Type: 'Sender', + ShortName: 'Sender', + Origin: 'Internal', + SedaField: 'Sender', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '227', + path: 'Sender.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '228', + path: 'Sender.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '229', + path: 'Sender.FullName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'FullName', + ApiField: 'FullName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FullName', + Origin: 'Internal', + SedaField: 'FullName', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '230', + path: 'Sender.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '231', + path: 'Sender.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '232', + path: 'Sender.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151950', + LastUpdate: '1692880151950', + }, + { + id: '233', + path: 'Sender.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151951', + LastUpdate: '1692880151951', + }, + { + id: '234', + path: 'Sender.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151951', + LastUpdate: '1692880151951', + }, + { + id: '235', + path: 'Sender.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151951', + LastUpdate: '1692880151951', + }, + { + id: '236', + path: 'Sender.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151951', + LastUpdate: '1692880151951', + }, + { + id: '237', + path: 'Sender.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151951', + LastUpdate: '1692880151951', + }, + { + id: '238', + path: 'Sender.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151951', + LastUpdate: '1692880151951', + }, + { + id: '239', + path: 'Sender.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151951', + LastUpdate: '1692880151951', + }, + { + id: '240', + path: 'Sender.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151951', + LastUpdate: '1692880151951', + }, + { + id: '241', + path: 'Sender.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '242', + path: 'Sender.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '243', + path: 'Sender.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '244', + path: 'Sender.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '245', + path: 'Sender.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '246', + path: 'Sender.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '247', + path: 'Sender.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '248', + path: 'Sender.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '249', + path: 'Sender.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '250', + path: 'Sender.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '251', + path: 'Sender.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '252', + path: 'Sender.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151952', + LastUpdate: '1692880151952', + }, + { + id: '253', + path: 'Sender.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '254', + path: 'Sender.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '255', + path: 'Sender.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '256', + path: 'Signature', + DataType: 'objet', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Signature', + ApiField: 'Signature', + Type: 'Signature', + ShortName: 'Signature', + Origin: 'Internal', + SedaField: 'Signature', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '258', + path: 'Signature.ReferencedObject', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '1-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'ReferencedObject', + ApiField: 'ReferencedObject', + Type: 'ReferencedObject', + ShortName: 'ReferencedObject', + Origin: 'Internal', + SedaField: 'ReferencedObject', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '261', + path: 'Signature.Signer', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '1-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Signer', + ApiField: 'Signer', + Type: 'Signer', + ShortName: 'Signer', + Origin: 'Internal', + SedaField: 'Signer', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '262', + path: 'Signature.Signer.SigningTime', + DataType: 'date', + DataSize: 'short', + Cardinality: '1-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'SigningTime', + ApiField: 'SigningTime', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'SigningTime', + Origin: 'Internal', + SedaField: 'SigningTime', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '263', + path: 'Signature.Signer.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '264', + path: 'Signature.Signer.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '265', + path: 'Signature.Signer.Fullpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Fullpname', + ApiField: 'Fullpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Fullpname', + Origin: 'Internal', + SedaField: 'Fullpname', + Description: null, + CreationDate: '1692880151953', + LastUpdate: '1692880151953', + }, + { + id: '266', + path: 'Signature.Signer.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '267', + path: 'Signature.Signer.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '268', + path: 'Signature.Signer.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '269', + path: 'Signature.Signer.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '270', + path: 'Signature.Signer.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '271', + path: 'Signature.Signer.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '272', + path: 'Signature.Signer.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '273', + path: 'Signature.Signer.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '274', + path: 'Signature.Signer.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '275', + path: 'Signature.Signer.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '276', + path: 'Signature.Signer.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '277', + path: 'Signature.Signer.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '278', + path: 'Signature.Signer.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '279', + path: 'Signature.Signer.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '280', + path: 'Signature.Signer.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '281', + path: 'Signature.Signer.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151955', + LastUpdate: '1692880151955', + }, + { + id: '282', + path: 'Signature.Signer.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '283', + path: 'Signature.Signer.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '284', + path: 'Signature.Signer.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '285', + path: 'Signature.Signer.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '286', + path: 'Signature.Signer.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '287', + path: 'Signature.Signer.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '288', + path: 'Signature.Signer.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '289', + path: 'Signature.Signer.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '290', + path: 'Signature.Signer.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '291', + path: 'Signature.Signer.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '292', + path: 'Signature.Validator', + DataType: 'objet', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Validator', + ApiField: 'Validator', + Type: 'Validator', + ShortName: 'Validator', + Origin: 'Internal', + SedaField: 'Validator', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '293', + path: 'Signature.Validator.ValidationTime', + DataType: 'date', + DataSize: 'short', + Cardinality: '1-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ValidationTime', + ApiField: 'ValidationTime', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'ValidationTime', + Origin: 'Internal', + SedaField: 'ValidationTime', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '294', + path: 'Signature.Validator.FirstName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'FirstName', + ApiField: 'FirstName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'FirstName', + Origin: 'Internal', + SedaField: 'FirstName', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '295', + path: 'Signature.Validator.BirthName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'BirthName', + ApiField: 'BirthName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'BirthName', + Origin: 'Internal', + SedaField: 'BirthName', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '296', + path: 'Signature.Validator.Fullpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Fullpname', + ApiField: 'Fullpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Fullpname', + Origin: 'Internal', + SedaField: 'Fullpname', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '297', + path: 'Signature.Validator.GivenName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'GivenName', + ApiField: 'GivenName', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'GivenName', + Origin: 'Internal', + SedaField: 'GivenName', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '298', + path: 'Signature.Validator.Gender', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Gender', + ApiField: 'Gender', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Gender', + Origin: 'Internal', + SedaField: 'Gender', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '299', + path: 'Signature.Validator.BirthDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'BirthDate', + ApiField: 'BirthDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'BirthDate', + Origin: 'Internal', + SedaField: 'BirthDate', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '300', + path: 'Signature.Validator.DeathDate', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DeathDate', + ApiField: 'DeathDate', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'DeathDate', + Origin: 'Internal', + SedaField: 'DeathDate', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '301', + path: 'Signature.Validator.BirthPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'BirthPlace', + ApiField: 'BirthPlace', + Type: 'BirthPlace', + ShortName: 'BirthPlace', + Origin: 'Internal', + SedaField: 'BirthPlace', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '302', + path: 'Signature.Validator.BirthPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '303', + path: 'Signature.Validator.BirthPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '304', + path: 'Signature.Validator.BirthPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151956', + LastUpdate: '1692880151956', + }, + { + id: '305', + path: 'Signature.Validator.BirthPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '306', + path: 'Signature.Validator.BirthPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '307', + path: 'Signature.Validator.BirthPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '308', + path: 'Signature.Validator.DeathPlace', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DeathPlace', + ApiField: 'DeathPlace', + Type: 'DeathPlace', + ShortName: 'DeathPlace', + Origin: 'Internal', + SedaField: 'DeathPlace', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '309', + path: 'Signature.Validator.DeathPlace.Geogname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Geogname', + ApiField: 'Geogname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Geogname', + Origin: 'Internal', + SedaField: 'Geogname', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '310', + path: 'Signature.Validator.DeathPlace.Address', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Address', + ApiField: 'Address', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Address', + Origin: 'Internal', + SedaField: 'Address', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '311', + path: 'Signature.Validator.DeathPlace.PostalCode', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'PostalCode', + ApiField: 'PostalCode', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'PostalCode', + Origin: 'Internal', + SedaField: 'PostalCode', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '312', + path: 'Signature.Validator.DeathPlace.City', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'City', + ApiField: 'City', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'City', + Origin: 'Internal', + SedaField: 'City', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '313', + path: 'Signature.Validator.DeathPlace.Region', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Region', + ApiField: 'Region', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Region', + Origin: 'Internal', + SedaField: 'Region', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '314', + path: 'Signature.Validator.DeathPlace.Country', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'Country', + ApiField: 'Country', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Country', + Origin: 'Internal', + SedaField: 'Country', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '315', + path: 'Signature.Validator.Nationality', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Nationality', + ApiField: 'Nationality', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Nationality', + Origin: 'Internal', + SedaField: 'Nationality', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '316', + path: 'Signature.Validator.Corpname', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Corpname', + ApiField: 'Corpname', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Corpname', + Origin: 'Internal', + SedaField: 'Corpname', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '317', + path: 'Signature.Validator.Identifier', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '318', + path: 'Signature.Validator.Function', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Function', + ApiField: 'Function', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Function', + Origin: 'Internal', + SedaField: 'Function', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '319', + path: 'Signature.Validator.Activity', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Activity', + ApiField: 'Activity', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Activity', + Origin: 'Internal', + SedaField: 'Activity', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '320', + path: 'Signature.Validator.Position', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Position', + ApiField: 'Position', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Position', + Origin: 'Internal', + SedaField: 'Position', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '321', + path: 'Signature.Validator.Role', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Role', + ApiField: 'Role', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Role', + Origin: 'Internal', + SedaField: 'Role', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '322', + path: 'Signature.Validator.Mandate', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'Mandate', + ApiField: 'Mandate', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Mandate', + Origin: 'Internal', + SedaField: 'Mandate', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '323', + path: 'Event', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Event', + ApiField: 'Event', + Type: 'Event', + ShortName: 'Event', + Origin: 'Internal', + SedaField: 'Event', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '325', + path: 'Event.evTypeProc', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'evTypeProc', + ApiField: 'evTypeProc', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'evTypeProc', + Origin: 'Internal', + SedaField: 'evTypeProc', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '326', + path: 'Event.evType', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'evType', + ApiField: 'evType', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'evType', + Origin: 'Internal', + SedaField: 'evType', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '327', + path: 'Event.evDateTime', + DataType: 'date', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'evDateTime', + ApiField: 'evDateTime', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'evDateTime', + Origin: 'Internal', + SedaField: 'evDateTime', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '328', + path: 'Event.evTypeDetail', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'evTypeDetail', + ApiField: 'evTypeDetail', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'evTypeDetail', + Origin: 'Internal', + SedaField: 'evTypeDetail', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '329', + path: 'Event.outcome', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'outcome', + ApiField: 'outcome', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'outcome', + Origin: 'Internal', + SedaField: 'outcome', + Description: null, + CreationDate: '1692880151957', + LastUpdate: '1692880151957', + }, + { + id: '330', + path: 'Event.outDetail', + DataType: 'nonEmptyToken', + DataSize: 'medium', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'outDetail', + ApiField: 'outDetail', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'outDetail', + Origin: 'Internal', + SedaField: 'outDetail', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '331', + path: 'Event.outMessg', + DataType: 'nonEmptyToken', + DataSize: 'medium', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'outMessg', + ApiField: 'outMessg', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'outMessg', + Origin: 'Internal', + SedaField: 'outMessg', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '332', + path: 'Event.evDetData', + DataType: 'nonEmptyToken', + DataSize: 'medium', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'evDetData', + ApiField: 'evDetData', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'evDetData', + Origin: 'Internal', + SedaField: 'evDetData', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '333', + path: 'Event.LinkingAgentIdentifier', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.2'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'LinkingAgentIdentifier', + ApiField: 'LinkingAgentIdentifier', + Type: 'LinkingAgentIdentifier', + ShortName: 'LinkingAgentIdentifier', + Origin: 'Internal', + SedaField: 'LinkingAgentIdentifier', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '334', + path: 'Event.LinkingAgentIdentifier.LinkingAgentIdentifierType', + DataType: 'NonEmptyTokenType', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.2'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'LinkingAgentIdentifierType', + ApiField: 'LinkingAgentIdentifierType', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'LinkingAgentIdentifierType', + Origin: 'Internal', + SedaField: 'LinkingAgentIdentifierType', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '335', + path: 'Event.LinkingAgentIdentifier.LinkingAgentIdentifierValue', + DataType: 'NonEmptyTokenType', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.2'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'LinkingAgentIdentifierValue', + ApiField: 'LinkingAgentIdentifierValue', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'LinkingAgentIdentifierValue', + Origin: 'Internal', + SedaField: 'LinkingAgentIdentifierValue', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '336', + path: 'Event.LinkingAgentIdentifier.LinkingAgentRole', + DataType: 'NonEmptyTokenType', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.2'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'LinkingAgentRole', + ApiField: 'LinkingAgentRole', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'LinkingAgentRole', + Origin: 'Internal', + SedaField: 'LinkingAgentRole', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '337', + path: 'RelatedObjectReference', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'RelatedObjectReference', + ApiField: 'RelatedObjectReference', + Type: 'RelatedObjectReference', + ShortName: 'RelatedObjectReference', + Origin: 'Internal', + SedaField: 'RelatedObjectReference', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '338', + path: 'RelatedObjectReference.IsVersionOf', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'IsVersionOf', + ApiField: 'IsVersionOf', + Type: 'IsVersionOf', + ShortName: 'IsVersionOf', + Origin: 'Internal', + SedaField: 'IsVersionOf', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '339', + path: 'RelatedObjectReference.IsVersionOf.ArchiveUnitRefId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ArchiveUnitRefId', + ApiField: 'ArchiveUnitRefId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ArchiveUnitRefId', + Origin: 'Internal', + SedaField: 'ArchiveUnitRefId', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '340', + path: 'RelatedObjectReference.IsVersionOf.DataObjectReference', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DataObjectReference', + ApiField: 'DataObjectReference', + Type: 'DataObjectReference', + ShortName: 'DataObjectReference', + Origin: 'Internal', + SedaField: 'DataObjectReference', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '341', + path: 'RelatedObjectReference.IsVersionOf.DataObjectReference.DataObjectGroupReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'DataObjectGroupReferenceId', + ApiField: 'DataObjectGroupReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectGroupReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectGroupReferenceId', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '342', + path: 'RelatedObjectReference.IsVersionOf.DataObjectReference.DataObjectReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'DataObjectReferenceId', + ApiField: 'DataObjectReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectReferenceId', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '343', + path: 'RelatedObjectReference.IsVersionOf.RepositoryArchiveUnitPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'RepositoryArchiveUnitPID', + ApiField: 'RepositoryArchiveUnitPID', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'RepositoryArchiveUnitPID', + Origin: 'Internal', + SedaField: 'RepositoryArchiveUnitPID', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '344', + path: 'RelatedObjectReference.IsVersionOf.RepositoryObjectPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'RepositoryObjectPID', + ApiField: 'RepositoryObjectPID', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'RepositoryObjectPID', + Origin: 'Internal', + SedaField: 'RepositoryObjectPID', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '345', + path: 'RelatedObjectReference.IsVersionOf.ExternalReference', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ExternalReference', + ApiField: 'ExternalReference', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'ExternalReference', + Origin: 'Internal', + SedaField: 'ExternalReference', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '346', + path: 'RelatedObjectReference.Replaces', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Replaces', + ApiField: 'Replaces', + Type: 'Replaces', + ShortName: 'Replaces', + Origin: 'Internal', + SedaField: 'Replaces', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '347', + path: 'RelatedObjectReference.Replaces.ArchiveUnitRefId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ArchiveUnitRefId', + ApiField: 'ArchiveUnitRefId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ArchiveUnitRefId', + Origin: 'Internal', + SedaField: 'ArchiveUnitRefId', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '348', + path: 'RelatedObjectReference.Replaces.DataObjectReference', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DataObjectReference', + ApiField: 'DataObjectReference', + Type: 'DataObjectReference', + ShortName: 'DataObjectReference', + Origin: 'Internal', + SedaField: 'DataObjectReference', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '349', + path: 'RelatedObjectReference.Replaces.DataObjectReference.DataObjectGroupReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'DataObjectGroupReferenceId', + ApiField: 'DataObjectGroupReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectGroupReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectGroupReferenceId', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '350', + path: 'RelatedObjectReference.Replaces.DataObjectReference.DataObjectReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'DataObjectReferenceId', + ApiField: 'DataObjectReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectReferenceId', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '351', + path: 'RelatedObjectReference.Replaces.ExternalReference', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ExternalReference', + ApiField: 'ExternalReference', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ExternalReference', + Origin: 'Internal', + SedaField: 'ExternalReference', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '352', + path: 'RelatedObjectReference.Replaces.RepositoryArchiveUnitPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'RepositoryArchiveUnitPID', + ApiField: 'RepositoryArchiveUnitPID', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'RepositoryArchiveUnitPID', + Origin: 'Internal', + SedaField: 'RepositoryArchiveUnitPID', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '353', + path: 'RelatedObjectReference.Replaces.RepositoryObjectPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'RepositoryObjectPID', + ApiField: 'RepositoryObjectPID', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'RepositoryObjectPID', + Origin: 'Internal', + SedaField: 'RepositoryObjectPID', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '354', + path: 'RelatedObjectReference.Requires', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Requires', + ApiField: 'Requires', + Type: 'Requires', + ShortName: 'Requires', + Origin: 'Internal', + SedaField: 'Requires', + Description: null, + CreationDate: '1692880151958', + LastUpdate: '1692880151958', + }, + { + id: '355', + path: 'RelatedObjectReference.Requires.ArchiveUnitRefId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ArchiveUnitRefId', + ApiField: 'ArchiveUnitRefId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ArchiveUnitRefId', + Origin: 'Internal', + SedaField: 'ArchiveUnitRefId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '356', + path: 'RelatedObjectReference.Requires.DataObjectReference', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DataObjectReference', + ApiField: 'DataObjectReference', + Type: 'DataObjectReference', + ShortName: 'DataObjectReference', + Origin: 'Internal', + SedaField: 'DataObjectReference', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '357', + path: 'RelatedObjectReference.Requires.DataObjectReference.DataObjectGroupReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'DataObjectGroupReferenceId', + ApiField: 'DataObjectGroupReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectGroupReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectGroupReferenceId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '358', + path: 'RelatedObjectReference.Requires.DataObjectReference.DataObjectReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'DataObjectReferenceId', + ApiField: 'DataObjectReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectReferenceId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '359', + path: 'RelatedObjectReference.Requires.ExternalReference', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ExternalReference', + ApiField: 'ExternalReference', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ExternalReference', + Origin: 'Internal', + SedaField: 'ExternalReference', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '360', + path: 'RelatedObjectReference.Requires.RepositoryArchiveUnitPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'RepositoryArchiveUnitPID', + ApiField: 'RepositoryArchiveUnitPID', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'RepositoryArchiveUnitPID', + Origin: 'Internal', + SedaField: 'RepositoryArchiveUnitPID', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '361', + path: 'RelatedObjectReference.Requires.RepositoryObjectPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'RepositoryObjectPID', + ApiField: 'RepositoryObjectPID', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'RepositoryObjectPID', + Origin: 'Internal', + SedaField: 'RepositoryObjectPID', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '362', + path: 'RelatedObjectReference.IsPartOf', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'IsPartOf', + ApiField: 'IsPartOf', + Type: 'IsPartOf', + ShortName: 'IsPartOf', + Origin: 'Internal', + SedaField: 'IsPartOf', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '363', + path: 'RelatedObjectReference.IsPartOf.ArchiveUnitRefId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ArchiveUnitRefId', + ApiField: 'ArchiveUnitRefId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ArchiveUnitRefId', + Origin: 'Internal', + SedaField: 'ArchiveUnitRefId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '364', + path: 'RelatedObjectReference.IsPartOf.DataObjectReference', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DataObjectReference', + ApiField: 'DataObjectReference', + Type: 'DataObjectReference', + ShortName: 'DataObjectReference', + Origin: 'Internal', + SedaField: 'DataObjectReference', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '365', + path: 'RelatedObjectReference.IsPartOf.DataObjectReference.DataObjectGroupReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'DataObjectGroupReferenceId', + ApiField: 'DataObjectGroupReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectGroupReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectGroupReferenceId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '366', + path: 'RelatedObjectReference.IsPartOf.DataObjectReference.DataObjectReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 3, + Identifier: 'DataObjectReferenceId', + ApiField: 'DataObjectReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectReferenceId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '367', + path: 'RelatedObjectReference.IsPartOf.ExternalReference', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'ExternalReference', + ApiField: 'ExternalReference', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ExternalReference', + Origin: 'Internal', + SedaField: 'ExternalReference', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '368', + path: 'RelatedObjectReference.IsPartOf.RepositoryArchiveUnitPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'RepositoryArchiveUnitPID', + ApiField: 'RepositoryArchiveUnitPID', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'RepositoryArchiveUnitPID', + Origin: 'Internal', + SedaField: 'RepositoryArchiveUnitPID', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '369', + path: 'RelatedObjectReference.IsPartOf.RepositoryObjectPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'RepositoryObjectPID', + ApiField: 'RepositoryObjectPID', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'RepositoryObjectPID', + Origin: 'Internal', + SedaField: 'RepositoryObjectPID', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '370', + path: 'References', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'References', + ApiField: 'References', + Type: 'References', + ShortName: 'References', + Origin: 'Internal', + SedaField: 'References', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '371', + path: 'References.ArchiveUnitRefId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'ArchiveUnitRefId', + ApiField: 'ArchiveUnitRefId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'ArchiveUnitRefId', + Origin: 'Internal', + SedaField: 'ArchiveUnitRefId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '372', + path: 'References.DataObjectReference', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'DataObjectReference', + ApiField: 'DataObjectReference', + Type: 'DataObjectReference', + ShortName: 'DataObjectReference', + Origin: 'Internal', + SedaField: 'DataObjectReference', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '373', + path: 'References.DataObjectReference.DataObjectReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DataObjectReferenceId', + ApiField: 'DataObjectReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectReferenceId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '374', + path: 'References.DataObjectReference.DataObjectGroupReferenceId', + DataType: 'IDREF', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 2, + Identifier: 'DataObjectGroupReferenceId', + ApiField: 'DataObjectGroupReferenceId', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'DataObjectGroupReferenceId', + Origin: 'Internal', + SedaField: 'DataObjectGroupReferenceId', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '375', + path: 'References.RepositoryArchiveUnitPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'RepositoryArchiveUnitPID', + ApiField: 'RepositoryArchiveUnitPID', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'RepositoryArchiveUnitPID', + Origin: 'Internal', + SedaField: 'RepositoryArchiveUnitPID', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '376', + path: 'References.RepositoryObjectPID', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'RepositoryObjectPID', + ApiField: 'RepositoryObjectPID', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'RepositoryObjectPID', + Origin: 'Internal', + SedaField: 'RepositoryObjectPID', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '377', + path: 'References.ExternalReference', + DataType: 'nonEmptyToken', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'ExternalReference', + ApiField: 'ExternalReference', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'ExternalReference', + Origin: 'Internal', + SedaField: 'ExternalReference', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '378', + path: 'OriginatingAgency', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'OriginatingAgency', + ApiField: 'OriginatingAgency', + Type: 'OriginatingAgency', + ShortName: 'OriginatingAgency', + Origin: 'Internal', + SedaField: 'OriginatingAgency', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '379', + path: 'OriginatingAgency.Identifier', + DataType: 'token', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151959', + LastUpdate: '1692880151959', + }, + { + id: '381', + path: 'SubmissionAgency', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'SubmissionAgency', + ApiField: 'SubmissionAgency', + Type: 'SubmissionAgency', + ShortName: 'SubmissionAgency', + Origin: 'Internal', + SedaField: 'SubmissionAgency', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '382', + path: 'SubmissionAgency.Identifier', + DataType: 'token', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Identifier', + ApiField: 'Identifier', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'Identifier', + Origin: 'Internal', + SedaField: 'Identifier', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '384', + path: 'Keyword', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Keyword', + ApiField: 'Keyword', + Type: 'Keyword', + ShortName: 'Keyword', + Origin: 'Internal', + SedaField: 'Keyword', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '385', + path: 'Keyword.KeywordContent', + DataType: 'string', + DataSize: 'short', + Cardinality: '1-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'KeywordContent', + ApiField: 'KeywordContent', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'KeywordContent', + Origin: 'Internal', + SedaField: 'KeywordContent', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '386', + path: 'Keyword.KeywordReference', + DataType: 'token', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'KeywordReference', + ApiField: 'KeywordReference', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'KeywordReference', + Origin: 'Internal', + SedaField: 'KeywordReference', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '387', + path: 'Keyword.KeywordType', + DataType: 'token', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'KeywordType', + ApiField: 'KeywordType', + Type: 'keyword (saisie exacte OU sélecteur selon champ)', + ShortName: 'KeywordType', + Origin: 'Internal', + SedaField: 'KeywordType', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '388', + path: 'Coverage', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Coverage', + ApiField: 'Coverage', + Type: 'Coverage', + ShortName: 'Coverage', + Origin: 'Internal', + SedaField: 'Coverage', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '389', + path: 'Coverage.Spatial', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Spatial', + ApiField: 'Spatial', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Spatial', + Origin: 'Internal', + SedaField: 'Spatial', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '390', + path: 'Coverage.Temporal', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Temporal', + ApiField: 'Temporal', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Temporal', + Origin: 'Internal', + SedaField: 'Temporal', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '391', + path: 'Coverage.Juridictional', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-N', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'Juridictional', + ApiField: 'Juridictional', + Type: 'text (texte libre petit ou multi-lignes)', + ShortName: 'Juridictional', + Origin: 'Internal', + SedaField: 'Juridictional', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '392', + path: 'Gps', + DataType: 'complex Type', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 0, + Identifier: 'Gps', + ApiField: 'Gps', + Type: 'Gps', + ShortName: 'Gps', + Origin: 'Internal', + SedaField: 'Gps', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '393', + path: 'Gps.GpsAltitude', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GpsAltitude', + ApiField: 'GpsAltitude', + Type: 'number (nombre saisie libre)', + ShortName: 'GpsAltitude', + Origin: 'Internal', + SedaField: 'GpsAltitude', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '394', + path: 'Gps.GpsAltitudeRef', + DataType: 'entier', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GpsAltitudeRef', + ApiField: 'GpsAltitudeRef', + Type: 'number (nombre saisie libre)', + ShortName: 'GpsAltitudeRef', + Origin: 'Internal', + SedaField: 'GpsAltitudeRef', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '395', + path: 'Gps.GpsDateStamp', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GpsDateStamp', + ApiField: 'GpsDateStamp', + Type: 'number (nombre saisie libre)', + ShortName: 'GpsDateStamp', + Origin: 'Internal', + SedaField: 'GpsDateStamp', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '396', + path: 'Gps.GpsLatitude', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GpsLatitude', + ApiField: 'GpsLatitude', + Type: 'number (nombre saisie libre)', + ShortName: 'GpsLatitude', + Origin: 'Internal', + SedaField: 'GpsLatitude', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '397', + path: 'Gps.GpsLatitudeRef', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GpsLatitudeRef', + ApiField: 'GpsLatitudeRef', + Type: 'number (nombre saisie libre)', + ShortName: 'GpsLatitudeRef', + Origin: 'Internal', + SedaField: 'GpsLatitudeRef', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '398', + path: 'Gps.GpsLongitude', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GpsLongitude', + ApiField: 'GpsLongitude', + Type: 'number (nombre saisie libre)', + ShortName: 'GpsLongitude', + Origin: 'Internal', + SedaField: 'GpsLongitude', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '399', + path: 'Gps.GpsLongitudeRef', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GpsLongitudeRef', + ApiField: 'GpsLongitudeRef', + Type: 'number (nombre saisie libre)', + ShortName: 'GpsLongitudeRef', + Origin: 'Internal', + SedaField: 'GpsLongitudeRef', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '400', + path: 'Gps.GpsVersionID', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'GpsVersionID', + ApiField: 'GpsVersionID', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'GpsVersionID', + Origin: 'Internal', + SedaField: 'GpsVersionID', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + { + id: '401', + path: 'originating_agencyName', + DataType: 'string', + DataSize: 'short', + Cardinality: '0-1', + SedaVersions: ['2.1'], + Collections: ['Unit'], + Depth: 1, + Identifier: 'originating_agencyName', + ApiField: 'originating_agencyName', + Type: 'datetime (date et/ou heure selon champ)', + ShortName: 'originating_agencyName', + Origin: 'External', + SedaField: 'originating_agencyName', + Description: null, + CreationDate: '1692880151960', + LastUpdate: '1692880151960', + }, + ]; + + getInternalOntologyFieldsList(): Observable { + return of(this.ontologies); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-strategy-display-object.service.spec.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-strategy-display-object.service.spec.ts new file mode 100644 index 00000000000..df10823f352 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-strategy-display-object.service.spec.ts @@ -0,0 +1,571 @@ +import { HttpClient } from '@angular/common/http'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { BASE_URL } from '../../injection-tokens'; +import { LoggerModule } from '../../logger/logger.module'; +import { OntologyService } from '../../ontology'; +import { DisplayObject, DisplayRule } from '../models'; +import { DisplayObjectType } from '../types'; +import { DataStructureService } from './data-structure.service'; +import { DisplayObjectHelperService } from './display-object-helper.service'; +import { DisplayRuleHelperService } from './display-rule-helper.service'; +import { MockExtendedOntologyService } from './mock-extended-ontology.service'; +import { OntologyStrategyDisplayObjectService } from './ontology-strategy-display-object.service'; +import { OntologyToDisplayRuleMapper } from './ontology-to-display-rule.mapper'; +import { TypeService } from './type.service'; + +describe('OntologyStrategyDisplayObjectService', () => { + let httpClient: HttpClient; + let httpTestingController: HttpTestingController; + let service: OntologyStrategyDisplayObjectService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule, LoggerModule.forRoot()], + providers: [ + OntologyStrategyDisplayObjectService, + TypeService, + DataStructureService, + DisplayObjectHelperService, + DisplayRuleHelperService, + OntologyToDisplayRuleMapper, + { provide: BASE_URL, useValue: '/fake-api' }, + { provide: OntologyService, useClass: MockExtendedOntologyService }, + ], + }); + httpClient = TestBed.inject(HttpClient); + httpTestingController = TestBed.inject(HttpTestingController); + service = TestBed.inject(OntologyStrategyDisplayObjectService); + }); + + describe('Observable initialization', () => { + it('should initialize displayObject with null', () => { + service.displayObject$.subscribe((displayObject: DisplayObject) => { + expect(displayObject).toBeNull(); + }); + }); + }); + + describe('Default mode', () => { + it('should update data and compute display object when data is an ontology', (done) => { + const data = { Title: 'La ville de Paris' }; + + service.setData(data); + + service.displayObject$.subscribe((displayObject: DisplayObject) => { + console.log('displayObject', displayObject); + + expect(displayObject).toBeTruthy(); + expect(displayObject.children).toBeTruthy(); + expect(displayObject.children.length).toEqual(1); + if (displayObject.children.length) { + expect(displayObject.children[0].path).toEqual('Title'); + expect(displayObject.children[0].value).toEqual('La ville de Paris'); + } + + done(); + }); + }); + + it('should update data and compute display object when data is not an ontology', (done) => { + const data = { notOntologicKey: 'La ville de Paris' }; + + service.setData(data); + + service.displayObject$.subscribe((displayObject: DisplayObject) => { + console.log('displayObject', displayObject); + + expect(displayObject).toBeTruthy(); + expect(displayObject.children).toBeTruthy(); + expect(displayObject.children.length).toEqual(1); + if (displayObject.children.length) { + expect(displayObject.children[0].path).toEqual('notOntologicKey'); + expect(displayObject.children[0].value).toEqual('La ville de Paris'); + } + + done(); + }); + }); + + it('should display ontology nodes and not others', (done) => { + const inputs: { data: any; template: DisplayRule[]; expected: DisplayObject }[] = [ + { + data: { id: '1', Title: 'core', tags: ['low', 'medium', 'high'] }, + template: [ + { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['Title'], + }, + }, + ], + expected: { + type: DisplayObjectType.GROUP, + component: 'group', + path: '', + key: '', + value: { + Title: 'core', + }, + children: [ + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'id', + key: 'id', + value: '1', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'id', + ui: { + path: 'id', + component: 'textfield', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'Title', + key: 'Title', + value: 'core', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'Title', + ui: { + path: 'Title', + component: 'textfield', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.LIST, + component: 'group', + path: 'tags', + key: 'tags', + value: '1', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'tags[0]', + key: 'tags[0]', + value: 'low', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[0]', + ui: { + path: 'tags[0]', + component: 'textfield', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'tags[1]', + key: 'tags[1]', + value: 'medium', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[0]', + ui: { + path: 'tags[0]', + component: 'textfield', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'tags[2]', + key: 'tags[2]', + value: 'high', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[0]', + ui: { + path: 'tags[0]', + component: 'textfield', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags', + ui: { + path: 'tags', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: ['Title'], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['Title'], + open: true, + display: true, + }, + }, + }, + }, + ]; + + expect(service).toBeTruthy(); + + service.setMode('default'); + + const { data, template, expected }: { data: any; template: DisplayRule[]; expected: DisplayObject } = inputs[0]; + + expect(data).toBeTruthy(); + expect(template).toBeTruthy(); + expect(expected).toBeTruthy(); + + service.setTemplate(template); + service.setData(data); + service.displayObject$.subscribe(async (displayObject) => { + await expect(displayObject).toBeTruthy(); + await expect(displayObject.children).toBeTruthy(); + await expect(displayObject.children.length).toEqual(3); + await expect(displayObject.children[0]).toBeTruthy(); + await expect(displayObject.children[0].path).toEqual('id'); + await expect(displayObject.children[0].displayRule.ui.display).toEqual(false); + await expect(displayObject.children[1]).toBeTruthy(); + await expect(displayObject.children[1].path).toEqual('Title'); + await expect(displayObject.children[1].displayRule.ui.display).toEqual(true); + await expect(displayObject.children[2]).toBeTruthy(); + await expect(displayObject.children[2].path).toEqual('tags'); + await expect(displayObject.children[2].displayRule.ui.display).toEqual(false); + await expect(displayObject.children[2].children).toBeTruthy(); + await expect(displayObject.children[2].children.length).toEqual(3); + await expect(displayObject.children[2].children[0].path).toEqual('tags[0]'); + await expect(displayObject.children[2].children[0].value).toEqual('low'); + await expect(displayObject.children[2].children[0].displayRule.ui.display).toEqual(false); + await expect(displayObject.children[2].children[1].path).toEqual('tags[1]'); + await expect(displayObject.children[2].children[1].value).toEqual('medium'); + await expect(displayObject.children[2].children[1].displayRule.ui.display).toEqual(false); + await expect(displayObject.children[2].children[2].path).toEqual('tags[2]'); + await expect(displayObject.children[2].children[2].value).toEqual('high'); + await expect(displayObject.children[2].children[2].displayRule.ui.display).toEqual(false); + + done(); + }); + }); + + it('should only map data known as ontology or custom template to display object', (done) => { + const inputs: { data: any; template: DisplayRule[]; expected: DisplayObject }[] = [ + { + data: { id: '1', Title: 'core', Tag: ['low', 'medium', 'high'] }, + template: [ + { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['Title'], + }, + }, + { + path: null, + ui: { + path: 'Generalities', + component: 'group', + favoriteKeys: [], + }, + }, + { + path: 'Title', + ui: { + path: 'Generalities.Title', + component: 'textfield', + }, + }, + ], + expected: { + type: DisplayObjectType.GROUP, + component: 'group', + path: '', + key: '', + value: { + Generalities: { + Title: 'core', + }, + Tag: ['low', 'medium', 'high'], + }, + children: [ + { + type: DisplayObjectType.GROUP, + component: 'group', + path: 'Generalities', + key: 'Generalities', + value: { + Title: 'core', + }, + children: [ + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'Generalities.Title', + key: 'Title', + value: 'core', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'Title', + ui: { + path: 'Generalities.Title', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: null, + ui: { + path: 'Generalities', + component: 'group', + favoriteKeys: [], + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.LIST, + component: 'textfield', + path: 'Tag', + key: 'Tag', + value: ['low', 'medium', 'high'], + children: [ + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'Tag[0]', + key: 'Tag[0]', + value: 'low', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'Tag[0]', + ui: { + path: 'Tag[0]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'Tag[1]', + key: 'Tag[1]', + value: 'medium', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'Tag[1]', + ui: { + path: 'Tag[1]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + component: 'textfield', + path: 'Tag[2]', + key: 'Tag[2]', + value: 'high', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'Tag[2]', + ui: { + path: 'Tag[2]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: 'Tag', + ui: { + path: 'Tag', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: ['Title'], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['Title'], + open: true, + display: true, + }, + }, + }, + }, + ]; + + expect(service).toBeTruthy(); + + service.setMode('default'); + + const { data, template, expected }: { data: any; template: DisplayRule[]; expected: DisplayObject } = inputs[0]; + + expect(data).toBeTruthy(); + expect(template).toBeTruthy(); + expect(expected).toBeTruthy(); + + service.setTemplate(template); + service.setData(data); + service.displayObject$.subscribe(async (displayObject) => { + console.log({ displayObject }); + await expect(displayObject).toBeTruthy(); + await expect(displayObject.favoriteKeys).toBeTruthy(); + await expect(displayObject.favoriteKeys.length).toEqual(1); + await expect(displayObject.children).toBeTruthy(); + await expect(displayObject.children.length).toEqual(3); + // await expect(displayObject.children[0]).toBeTruthy(); + // await expect(displayObject.children[0].path).toEqual('id'); + // await expect(displayObject.children[0].displayRule.ui.display).toEqual(false); + // await expect(displayObject.children[1]).toBeTruthy(); + // await expect(displayObject.children[1].path).toEqual('Title'); + // await expect(displayObject.children[1].displayRule.ui.display).toEqual(true); + // await expect(displayObject.children[2]).toBeTruthy(); + // await expect(displayObject.children[2].path).toEqual('tags'); + // await expect(displayObject.children[2].displayRule.ui.display).toEqual(false); + // await expect(displayObject.children[2].children).toBeTruthy(); + // await expect(displayObject.children[2].children.length).toEqual(3); + // await expect(displayObject.children[2].children[0].path).toEqual('tags[0]'); + // await expect(displayObject.children[2].children[0].value).toEqual('low'); + // await expect(displayObject.children[2].children[0].displayRule.ui.display).toEqual(false); + // await expect(displayObject.children[2].children[1].path).toEqual('tags[1]'); + // await expect(displayObject.children[2].children[1].value).toEqual('medium'); + // await expect(displayObject.children[2].children[1].displayRule.ui.display).toEqual(false); + // await expect(displayObject.children[2].children[2].path).toEqual('tags[2]'); + // await expect(displayObject.children[2].children[2].value).toEqual('high'); + // await expect(displayObject.children[2].children[2].displayRule.ui.display).toEqual(false); + + done(); + }); + }); + }); +}); diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-strategy-display-object.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-strategy-display-object.service.ts new file mode 100644 index 00000000000..af81fa904e1 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-strategy-display-object.service.ts @@ -0,0 +1,274 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; +import { Logger } from '../../logger/logger'; +import { OntologyService } from '../../ontology'; +import { DisplayObject, DisplayObjectService, DisplayRule, ExtendedOntology } from '../models'; +import { DisplayObjectHelperService } from './display-object-helper.service'; +import { DisplayRuleHelperService } from './display-rule-helper.service'; +import { OntologyToDisplayRuleMapper } from './ontology-to-display-rule.mapper'; +import { TypeService } from './type.service'; + +enum Mode { + DEFAULT = 'default', +} + +@Injectable() +export class OntologyStrategyDisplayObjectService implements DisplayObjectService { + private readonly configuration = { + displayEmptyValues: false, + }; + private displayObject = new BehaviorSubject(null); + private data = new BehaviorSubject(null); + private template = new BehaviorSubject([]); + private mode = new BehaviorSubject(Mode.DEFAULT); + + displayObject$: Observable = this.displayObject.asObservable(); + + private readonly OriginInternal = 'internal'; + private readonly OriginExternal = 'external'; + private readonly PathOtherMetadata = 'OtherMetadata'; + + constructor( + private logger: Logger, + private ontologyService: OntologyService, + private displayObjectHelper: DisplayObjectHelperService, + private displayRuleHelper: DisplayRuleHelperService, + private componentMapperService: OntologyToDisplayRuleMapper, + private typeService: TypeService + ) { + combineLatest([ + this.ontologyService.getInternalOntologyFieldsList() as Observable, + this.data, + this.template, + ]).subscribe( + ([ontologies, data, template]) => { + if (data === null) { + this.displayObject.next(null); + + return; + } + + const ontologiesByOrigin = this.groupOntologiesByOrigin(ontologies); + const internalOntologies = ontologiesByOrigin[this.OriginInternal] || []; + const externalOntologies = ontologiesByOrigin[this.OriginExternal] || []; + const defaultTemplate = this.getDefaultTemplate(data); + const internalOntologyTemplate = this.componentMapperService.mapOntologiesToDisplayRules(internalOntologies); + const externalOntologyTemplate = this.componentMapperService.mapOntologiesToDisplayRules(externalOntologies); + const customTemplate = template; + const otherMetadataTemplate = this.getOtherMetadataTemplate(externalOntologies); + const kwargs = { + ontologies, + ontologiesByOrigin, + defaultTemplate, + internalOntologyTemplate, + externalOntologyTemplate, + customTemplate, + otherMetadataTemplate, + }; + + this.displayObject.next(this.computeDisplayObject(kwargs)); + }, + (error) => { + this.logger.error(this, 'Error in observable', error); + } + ); + } + + private groupOntologiesByOrigin(ontologies: ExtendedOntology[]): Record { + const groupedByOrigin: Record = {}; + + ontologies + .filter((ontology) => { + if (!ontology.Origin) { + this.logger.warn(this, `Path ${ontology.path} have not origin, it will be skipped...`, { ontology }); + + return false; + } + + return true; + }) + .forEach((ontology) => { + const originToLocaleLowerCase = ontology.Origin.toLocaleLowerCase(); + + if (!groupedByOrigin[originToLocaleLowerCase]) { + groupedByOrigin[originToLocaleLowerCase] = []; + } + + groupedByOrigin[originToLocaleLowerCase].push(ontology); + }); + + return groupedByOrigin; + } + + public setData(data: any): void { + this.data.next(data); + } + + public setTemplate(template: DisplayRule[]): void { + if (template) { + this.template.next(template); + } + } + + public setMode(mode: string): void { + if (mode) { + this.mode.next(mode as Mode); + } + } + + private computeDisplayObject({ + ontologies, + defaultTemplate, + internalOntologyTemplate, + externalOntologyTemplate, + customTemplate, + otherMetadataTemplate, + }: { + ontologies: ExtendedOntology[]; + defaultTemplate: DisplayRule[]; + internalOntologyTemplate: DisplayRule[]; + externalOntologyTemplate: DisplayRule[]; + customTemplate: DisplayRule[]; + otherMetadataTemplate: DisplayRule[]; + }): DisplayObject { + if (this.mode.value !== Mode.DEFAULT) { + throw new Error(`Mode ${this.mode.value} is not supported`); + } + + const ontologyTemplate = internalOntologyTemplate.concat(externalOntologyTemplate); + const finalOntologyTemplate = this.displayRuleHelper.mergeDisplayRulesByPath(ontologyTemplate, defaultTemplate); + const finalCustomTemplate = this.displayRuleHelper.prioritizeAndMergeDisplayRules(finalOntologyTemplate, customTemplate); + const finalOtherMetadataTemplate = this.displayRuleHelper.prioritizeAndMergeDisplayRules(finalOntologyTemplate, otherMetadataTemplate); + const finalNotConsumedRulesByCustomTemplate = this.displayRuleHelper.getUniqueDisplayRules(finalOntologyTemplate, finalCustomTemplate); + const finalNotConsumedRulesByOtherMetadataTemplate = this.displayRuleHelper.getUniqueDisplayRules( + finalOntologyTemplate, + finalOtherMetadataTemplate + ); + const finalNotConsumedTemplate = this.displayRuleHelper.getCommonDisplayRules( + finalNotConsumedRulesByCustomTemplate, + finalNotConsumedRulesByOtherMetadataTemplate + ); + + const template = finalCustomTemplate.concat(finalNotConsumedTemplate).concat(finalOtherMetadataTemplate); + + this.logger.log( + this, + 'computeDisplayObject', + { internalOntologyTemplate, externalOntologyTemplate }, + { + ontologyTemplate, + finalOntologyTemplate, + finalCustomTemplate, + finalOtherMetadataTemplate, + finalNotConsumedRulesByCustomTemplate, + finalNotConsumedRulesByOtherMetadataTemplate, + finalNotConsumedTemplate, + } + ); + + const displayObject = this.displayObjectHelper.templateDrivenDisplayObject(this.data.value, template, this.configuration); + + this.logger.log(this, 'computeDisplayObject', { + displayObject, + }); + + this.hideUnconcernedNodes(ontologies, displayObject); + + return displayObject; + } + + private ontologyByPathFilter = + (path: string) => + (ontology: ExtendedOntology): boolean => { + const backendPath = ontology.path; + const frontendPath = this.componentMapperService.getOntologyFrontendModelPath(ontology); + + return [backendPath, frontendPath].includes(path); + }; + + private hideUnconcernedNodes(ontologies: ExtendedOntology[], displayObject: DisplayObject): void { + const { displayRule, value } = displayObject; + const { path, ui } = displayRule; + const ontology = ontologies.find(this.ontologyByPathFilter(path)); + const belongsToOntologies = Boolean(ontology); + const isConsistent = this.typeService.isConsistent(value); + const isVirtual = displayRule.path === null; + const belongsToTemplate = this.template.value.some((rule) => rule.ui.path === path); + const shouldDisplay = isConsistent && (belongsToOntologies || isVirtual || belongsToTemplate); + + displayObject.displayRule = { ...displayRule, ui: { ...ui, display: shouldDisplay } }; + + if (displayObject.children) { + displayObject.children.forEach((child) => this.hideUnconcernedNodes(ontologies, child)); + } + } + + private getDefaultTemplate(data: any): DisplayRule[] { + const defaultDisplayObject: DisplayObject = this.displayObjectHelper.dataDrivenDisplayObject(data, this.configuration); + + return this.displayObjectHelper.extractDisplayRules(defaultDisplayObject); + } + + private getOtherMetadataTemplate(ontologies: ExtendedOntology[], origin = this.OriginExternal): DisplayRule[] { + const otherMetadataDisplayRule: DisplayRule = { + path: null, + ui: { + path: this.PathOtherMetadata, + component: 'group', + open: false, + display: true, + layout: { + columns: 2, + size: 'medium', + }, + }, + }; + const externalOntologyMovedInOtherMetadataTemplate = this.componentMapperService + .mapOntologiesToDisplayRules(ontologies) + .map((displayRule) => ({ + ...displayRule, + ui: { + ...displayRule.ui, + path: `${this.PathOtherMetadata}.${displayRule.ui.path}`, + }, + })); + + return [otherMetadataDisplayRule].concat(externalOntologyMovedInOtherMetadataTemplate); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-to-display-rule.mapper.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-to-display-rule.mapper.ts new file mode 100644 index 00000000000..5d846a29d14 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/ontology-to-display-rule.mapper.ts @@ -0,0 +1,357 @@ +import { Injectable } from '@angular/core'; +import { DisplayRule, ExtendedOntology } from '../models'; + +type ComponentName = + | 'balise-n1' + | 'balise-n2' + | 'balise-n3' + | 'balise-n4' + | 'textfield-short-mono' + | 'textfield-short-multi' + | 'textfield-medium-mono' + | 'textfield-medium-multi' + | 'textfield-large-mono' + | 'textfield-large-multi' + | 'attribut-short-mono' + | 'attribut-short-multi' + | 'attribut-mono' + | 'attribut-multi' + | 'select-mono' + | 'select-multi' + | 'datepicker-date' + | 'datepicker-datetime'; + +@Injectable() +export class OntologyToDisplayRuleMapper { + private ontologyComponentTypeToDisplayRule: Record = { + 'attribut-mono': { + path: null, + ui: { + path: null, + component: 'select+textfield', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + 'attribut-multi': { + path: null, + ui: { + path: null, + component: 'select+textarea', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + 'attribut-short-mono': { + path: null, + ui: { + path: null, + component: 'select+textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + 'attribut-short-multi': { + path: null, + ui: { + path: null, + component: 'select+textarea', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + 'balise-n1': { + path: null, + ui: { + path: null, + component: 'group', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + 'balise-n2': { + path: null, + ui: { + path: null, + component: 'group', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + 'balise-n3': { + path: null, + ui: { + path: null, + component: 'group', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + 'balise-n4': { + path: null, + ui: { + path: null, + component: 'group', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + 'datepicker-date': { + path: null, + ui: { + path: null, + component: 'datepicker', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + 'datepicker-datetime': { + path: null, + ui: { + path: null, + component: 'datetime', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + 'select-mono': { + path: null, + ui: { + path: null, + component: 'select', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + 'select-multi': { + path: null, + ui: { + path: null, + component: 'select', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + 'textfield-large-mono': { + path: null, + ui: { + path: null, + component: 'textfield', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + 'textfield-large-multi': { + path: null, + ui: { + path: null, + component: 'textarea', + layout: { + columns: 2, + size: 'large', + }, + }, + }, + 'textfield-medium-mono': { + path: null, + ui: { + path: null, + component: 'textfield', + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + 'textfield-medium-multi': { + path: null, + ui: { + path: null, + component: 'textarea', + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + 'textfield-short-mono': { + path: null, + ui: { + path: null, + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + 'textfield-short-multi': { + path: null, + ui: { + path: null, + component: 'textarea', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + }; + + public mapOntologyToComponent(ontology: ExtendedOntology): ComponentName { + const defaultComponent: ComponentName = 'textfield-short-mono'; + + if (!ontology) { + return defaultComponent; + } + + if (ontology.DataType === 'object') { + const computedDepth = ontology.path.split('.').length - 1; + + if (computedDepth !== ontology.Depth) { + throw new Error("Computed ontogoly depth is not equal to it's attribute Depth"); + } + + if (computedDepth === 0) { + return 'balise-n1'; + } + if (computedDepth === 1) { + return 'balise-n2'; + } + if (computedDepth === 2) { + return 'balise-n3'; + } + if (computedDepth === 3) { + return 'balise-n4'; + } + + return defaultComponent; + } + + if (ontology.DataType === 'string') { + const isUnique = ontology.Cardinality.endsWith('1') || ontology.Cardinality === 'one'; + const isMultiple = !isUnique; + const isSpecial = ontology.path.includes('_.'); + + if (isSpecial) { + if (isUnique && ontology.DataSize === 'short') { + return 'attribut-short-mono'; + } + if (isMultiple && ontology.DataSize === 'short') { + return 'attribut-short-multi'; + } + if (isUnique) { + return 'attribut-mono'; + } + if (isMultiple) { + return 'attribut-multi'; + } + + return defaultComponent; + } + + if (isUnique && ontology.DataSize === 'short') { + return 'textfield-short-mono'; + } + if (isUnique && ontology.DataSize === 'medium') { + return 'textfield-medium-mono'; + } + if (isUnique && ontology.DataSize === 'large') { + return 'textfield-large-mono'; + } + if (isMultiple && ontology.DataSize === 'short') { + return 'textfield-short-multi'; + } + if (isMultiple && ontology.DataSize === 'medium') { + return 'textfield-medium-multi'; + } + if (isMultiple && ontology.DataSize === 'large') { + return 'textfield-large-multi'; + } + + return defaultComponent; + } + + if (ontology.DataType === 'enum') { + const isUnique = ontology.Cardinality.endsWith('1') || ontology.Cardinality === 'one'; + const isMultiple = !isUnique; + + if (isUnique) { + return 'select-mono'; + } + if (isMultiple) { + return 'select-multi'; + } + + return defaultComponent; + } + + if (ontology.DataType === 'date') { + return 'datepicker-date'; + } + if (ontology.DataType === 'datetime') { + return 'datepicker-datetime'; + } + if (ontology.DataType === 'number') { + return defaultComponent; + } + + return defaultComponent; + } + + private mapComponentToDisplayRule(component: ComponentName, path: string = null): DisplayRule { + const displayRule = this.ontologyComponentTypeToDisplayRule[component]; + const { ui } = displayRule; + + return { ...displayRule, path, ui: { ...ui, path } }; + } + + public mapOntologyToDisplayRule(ontology: ExtendedOntology): DisplayRule { + const path = this.getOntologyFrontendModelPath(ontology); + const component: ComponentName = this.mapOntologyToComponent(ontology); + const displayRule = this.mapComponentToDisplayRule(component, path); + + return displayRule; + } + + public mapOntologiesToDisplayRules(ontologies: ExtendedOntology[]): DisplayRule[] { + return ontologies.map((ontology) => this.mapOntologyToDisplayRule(ontology)); + } + + public getOntologyFrontendModelPath(ontology: ExtendedOntology): string { + const fragments = ontology.path.split('.'); + + if (ontology.ApiField) { + fragments.pop(); + fragments.push(ontology.ApiField); + } + + return fragments.join('.'); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/path-strategy-display-object.service.spec.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/path-strategy-display-object.service.spec.ts new file mode 100644 index 00000000000..470af56e1af --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/path-strategy-display-object.service.spec.ts @@ -0,0 +1,653 @@ +import { TestBed } from '@angular/core/testing'; +import { LoggerModule } from '../../logger/logger.module'; +import { DisplayObject, DisplayRule } from '../models'; +import { DisplayObjectType } from '../types'; +import { DataStructureService } from './data-structure.service'; +import { DisplayObjectHelperService } from './display-object-helper.service'; +import { DisplayRuleHelperService } from './display-rule-helper.service'; +import { PathStrategyDisplayObjectService } from './path-strategy-display-object.service'; +import { TypeService } from './type.service'; + +describe('PathStrategyDisplayObjectService', () => { + let service: PathStrategyDisplayObjectService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [LoggerModule.forRoot()], + providers: [ + PathStrategyDisplayObjectService, + TypeService, + DataStructureService, + DisplayObjectHelperService, + DisplayRuleHelperService, + ], + }); + service = TestBed.inject(PathStrategyDisplayObjectService); + }); + + describe('Data driven mode', () => { + it('should map to display object', () => { + const inputs: { data: any; template: DisplayRule[]; expected: DisplayObject }[] = [ + { + data: { id: '1', name: 'core', tags: ['low', 'medium', 'high'] }, + template: [ + { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['name'], + }, + }, + { + path: '', + ui: { + path: 'Generalities', + component: 'group', + favoriteKeys: ['name'], + }, + }, + { + path: 'name', + ui: { + path: 'Generalities.name', + component: 'group', + }, + }, + ], + expected: { + type: DisplayObjectType.GROUP, + path: '', + key: '', + value: { id: '1', name: 'core', tags: ['low', 'medium', 'high'] }, + component: 'group', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: 'id', + key: 'id', + value: '1', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'id', + ui: { + path: 'id', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'name', + key: 'name', + value: 'core', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'name', + ui: { + path: 'name', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.LIST, + path: 'tags', + key: 'tags', + value: ['low', 'medium', 'high'], + component: 'textfield', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[0]', + key: 'tags[0]', + value: 'low', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[0]', + ui: { + path: 'tags[0]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[1]', + key: 'tags[1]', + value: 'medium', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[1]', + ui: { + path: 'tags[1]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[2]', + key: 'tags[2]', + value: 'high', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[2]', + ui: { + path: 'tags[2]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags', + ui: { + path: 'tags', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + }, + ]; + + service.setMode('data-driven'); + + expect(service).toBeTruthy(); + + const { data, template, expected }: { data: any; template: DisplayRule[]; expected: DisplayObject } = inputs[0]; + + expect(data).toBeTruthy(); + expect(template).toBeTruthy(); + expect(expected).toBeTruthy(); + + service.setTemplate(template); + service.setData(data); + service.displayObject$.subscribe((displayObject) => { + expect(displayObject).toEqual(expected); + }); + }); + }); + + describe('Template driven mode', () => { + it('should map to display object', () => { + const inputs: { data: any; template: DisplayRule[]; expected: DisplayObject }[] = [ + { + data: { id: '1', name: 'core', tags: ['low', 'medium', 'high'] }, + template: [ + { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: null, + ui: { + path: 'Generalities', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['name'], + }, + }, + { + path: 'name', + ui: { + path: 'Generalities.name', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + ], + expected: { + type: DisplayObjectType.GROUP, + path: '', + key: '', + value: { Generalities: { name: 'core' } }, + component: 'group', + children: [ + { + type: DisplayObjectType.GROUP, + path: 'Generalities', + key: 'Generalities', + value: { name: 'core' }, + component: 'group', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: 'Generalities.name', + key: 'name', + value: 'core', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'name', + ui: { + path: 'Generalities.name', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: ['name'], + open: true, + displayRule: { + path: null, + ui: { + path: 'Generalities', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['name'], + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + }, + ]; + + expect(service).toBeTruthy(); + + service.setMode('template-driven'); + + const { data, template, expected }: { data: any; template: DisplayRule[]; expected: DisplayObject } = inputs[0]; + + expect(data).toBeTruthy(); + expect(template).toBeTruthy(); + expect(expected).toBeTruthy(); + + service.setTemplate(template); + service.setData(data); + service.displayObject$.subscribe((displayObject) => { + expect(displayObject).toEqual(expected); + }); + }); + }); + + describe('Mixed driven mode', () => { + it('should map to display object', () => { + const inputs: { data: any; template: DisplayRule[]; expected: DisplayObject }[] = [ + { + data: { id: '1', name: 'core', tags: ['low', 'medium', 'high'] }, + template: [ + { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + }, + }, + { + path: null, + ui: { + path: 'Generalities', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + favoriteKeys: ['name'], + }, + }, + { + path: 'name', + ui: { + path: 'Generalities.name', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + }, + }, + ], + expected: { + type: DisplayObjectType.GROUP, + path: '', + key: '', + value: { id: '1', name: 'core', tags: ['low', 'medium', 'high'], Generalities: { name: 'core' } }, + component: 'group', + children: [ + { + type: DisplayObjectType.GROUP, + path: 'Generalities', + key: 'Generalities', + value: { name: 'core' }, + component: 'group', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: 'Generalities.name', + key: 'name', + value: 'core', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'name', + ui: { + path: 'Generalities.name', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: ['name'], + open: true, + displayRule: { + path: null, + ui: { + path: 'Generalities', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + favoriteKeys: ['name'], + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'id', + key: 'id', + value: '1', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'id', + ui: { + path: 'id', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'name', + key: 'name', + value: 'core', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'name', + ui: { + path: 'name', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.LIST, + path: 'tags', + key: 'tags', + value: ['low', 'medium', 'high'], + component: 'textfield', + children: [ + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[0]', + key: 'tags[0]', + value: 'low', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[0]', + ui: { + path: 'tags[0]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[1]', + key: 'tags[1]', + value: 'medium', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[1]', + ui: { + path: 'tags[1]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + { + type: DisplayObjectType.PRIMITIVE, + path: 'tags[2]', + key: 'tags[2]', + value: 'high', + component: 'textfield', + children: [], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags[2]', + ui: { + path: 'tags[2]', + component: 'textfield', + layout: { + columns: 1, + size: 'small', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: 'tags', + ui: { + path: 'tags', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + ], + favoriteKeys: [], + open: true, + displayRule: { + path: '', + ui: { + path: '', + component: 'group', + layout: { + columns: 2, + size: 'medium', + }, + open: true, + display: true, + }, + }, + }, + }, + ]; + + expect(service).toBeTruthy(); + + service.setMode('mixed-driven'); + + const { data, template, expected }: { data: any; template: DisplayRule[]; expected: DisplayObject } = inputs[0]; + + expect(data).toBeTruthy(); + expect(template).toBeTruthy(); + expect(expected).toBeTruthy(); + + service.setTemplate(template); + service.setData(data); + service.displayObject$.subscribe((displayObject) => { + console.log({ displayObject, expected }); + expect(displayObject).toEqual(expected); + }); + }); + }); +}); diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/path-strategy-display-object.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/path-strategy-display-object.service.ts new file mode 100644 index 00000000000..f12d9463bf2 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/path-strategy-display-object.service.ts @@ -0,0 +1,112 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { Logger } from '../../logger/logger'; +import { DisplayObject, DisplayObjectService, DisplayRule } from '../models'; +import { DisplayObjectHelperService } from './display-object-helper.service'; + +enum Mode { + DATE_DRIVEN = 'data-driven', + TEMPLATE_DRIVEN = 'template-driven', + MIXED_DRIVEN = 'mixed-driven', +} + +const NO_MODE_MESSAGE = 'Mode is not set'; +const DATA_MODE_MESSAGE = 'The data mode is enabled, the computed display object will follow object structure'; +const TEMPLATE_MODE_MESSAGE = 'The template mode is enabled, the computed display object will follow the provided template structure'; +const MIXED_MODE_MESSAGE = + 'The mixed mode is enabled, the computed display object will follow the provided template structure and data structure otherwise'; + +@Injectable() +export class PathStrategyDisplayObjectService implements DisplayObjectService { + private readonly configuration = { + displayEmptyValues: false, + }; + private displayObject = new BehaviorSubject(null); + private data = new BehaviorSubject(null); + private template = new BehaviorSubject([]); + private mode = new BehaviorSubject(Mode.DATE_DRIVEN); + + displayObject$: Observable = this.displayObject.asObservable(); + + constructor(private logger: Logger, private displayObjectHelper: DisplayObjectHelperService) { + const handleDisplayObjectComputing = (): void => { + if (!this.data.value) { + return; + } + + let message = NO_MODE_MESSAGE; + let displayObject = this.displayObjectHelper.toDisplayObject({}); + + if (this.mode.value === Mode.DATE_DRIVEN) { + message = DATA_MODE_MESSAGE; + displayObject = this.displayObjectHelper.dataDrivenDisplayObject(this.data.value, this.configuration); + } + + if (this.mode.value === Mode.TEMPLATE_DRIVEN) { + message = TEMPLATE_MODE_MESSAGE; + displayObject = this.displayObjectHelper.templateDrivenDisplayObject(this.data.value, this.template.value, this.configuration); + } + + if (this.mode.value === Mode.MIXED_DRIVEN) { + message = MIXED_MODE_MESSAGE; + displayObject = this.displayObjectHelper.mixedDrivenDisplayObject(this.data.value, this.template.value, this.configuration); + } + + this.logger.info(this, message); + + this.displayObject.next(displayObject); + }; + + this.data.subscribe(handleDisplayObjectComputing); + this.template.subscribe(handleDisplayObjectComputing); + this.mode.subscribe(handleDisplayObjectComputing); + } + + setData(object: any): void { + this.data.next(object); + } + + setTemplate(template: DisplayRule[]): void { + this.template.next(template); + } + + setMode(mode: string): void { + this.mode.next(mode as Mode); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/type.service.spec.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/type.service.spec.ts new file mode 100644 index 00000000000..7d769090712 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/type.service.spec.ts @@ -0,0 +1,27 @@ +import { TestBed } from '@angular/core/testing'; +import { ObjectViewerModule } from '../object-viewer.module'; +import { TypeService } from './type.service'; + +describe('TypeService', () => { + let service: TypeService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ObjectViewerModule], + }); + service = TestBed.inject(TypeService); + }); + + describe('isConsistent', () => { + it('should value be consistent', () => { + const consistentValues = [['ok'], { key: 'name' }, [{ children: [{ key: 'name' }] }], [{ children: [{ key: null, value: 'ok' }] }]]; + + consistentValues.forEach((value) => expect(service.isConsistent(value)).toBeTruthy()); + }); + it('should value be inconsistent', () => { + const unconsistentValues = [[''], [], [[]], [{}], [{ children: [{ key: null }] }]]; + + unconsistentValues.forEach((value) => expect(service.isConsistent(value)).toBeFalsy()); + }); + }); +}); diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/services/type.service.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/services/type.service.ts new file mode 100644 index 00000000000..904687d9408 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/services/type.service.ts @@ -0,0 +1,112 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +import { Injectable } from '@angular/core'; +import { DisplayObjectType } from '../types'; + +@Injectable() +export class TypeService { + public isPrimitive(value: any): boolean { + const type = typeof value; + + switch (type) { + case 'string': + case 'number': + case 'undefined': + return true; + default: + return false; + } + } + + public isList(value: any): boolean { + return Array.isArray(value); + } + + public isGroup(value: any): boolean { + return !this.isPrimitive(value) && !this.isList(value); + } + + public isPrimitiveList(value: any): boolean { + return this.isList(value) && value.every((item: any) => this.isPrimitive(item)); + } + + public dataType(value: any): DisplayObjectType { + if (this.isPrimitive(value)) { + return DisplayObjectType.PRIMITIVE; + } + if (this.isList(value)) { + return DisplayObjectType.LIST; + } + if (this.isGroup(value)) { + return DisplayObjectType.GROUP; + } + + return null; + } + + public isConsistent(value: any): boolean { + if (this.isPrimitive(value)) { + return Boolean(value) && value !== ''; + } + if (this.isList(value)) { + return value.some((item: any) => this.isConsistent(item)); + } + if (!value) { + return false; + } + + return Object.values(value).some((v: any) => this.isConsistent(v)); + } + + public hasDefined(value: any): boolean { + if (value === null) { + return true; + } + if (this.isPrimitive(value)) { + return value !== undefined; + } + if (this.isList(value)) { + if (value.length) { + return value.some((item: any) => this.hasDefined(item)); + } + + return true; + } + + return Object.values(value).some((item: any) => this.hasDefined(item)); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/object-viewer/types/index.ts b/ui/ui-frontend-common/src/app/modules/object-viewer/types/index.ts new file mode 100644 index 00000000000..7a382da5ee8 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/object-viewer/types/index.ts @@ -0,0 +1,59 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020) + * and the signatories of the "VITAM - Accord du Contributeur" agreement. + * + * contact@programmevitam.fr + * + * This software is a computer program whose purpose is to implement + * implement a digital archiving front-office system for the secure and + * efficient high volumetry VITAM solution. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +export enum DisplayObjectType { + PRIMITIVE = 'primitive', + LIST = 'list', + GROUP = 'group', +} + +export type ComponentType = + | 'textfield' + | 'textarea' + | 'select' + | 'select+textfield' + | 'select+textarea' + | 'datepicker' + | 'datetime' + | 'group'; + +export type UiComponentDateFormatMapName = 'wanted' | 'pretty'; + +export type SedaVersion = '2.1' | '2.2' | '2.3' | string; + +export type Cardinality = '0-1' | '1-1' | '0-N' | '1-N' | 'one' | 'many'; + +export type LayoutSize = 'small' | 'medium' | 'large'; diff --git a/ui/ui-frontend-common/src/app/modules/pipes/plural.pipe.spec.ts b/ui/ui-frontend-common/src/app/modules/pipes/plural.pipe.spec.ts index 7c406ede2d1..000f1420321 100644 --- a/ui/ui-frontend-common/src/app/modules/pipes/plural.pipe.spec.ts +++ b/ui/ui-frontend-common/src/app/modules/pipes/plural.pipe.spec.ts @@ -7,7 +7,7 @@ describe('PluralPipe', () => { expect(pipe).toBeTruthy(); }); - it("should add 's' after the word when count is greater than 1", () => { + it('should add \'s\' after the word when count is greater than 1', () => { const pipe = new PluralPipe(); const word = 'archive'; const count = 2; @@ -18,7 +18,7 @@ describe('PluralPipe', () => { expect(result).toEqual(expectation); }); - it("should not add 's' after the word when count is lesser than 2", () => { + it('should not add \'s\' after the word when count is lesser than 2', () => { const pipe = new PluralPipe(); const word = 'archive'; const count = 1; @@ -29,7 +29,7 @@ describe('PluralPipe', () => { expect(result).toEqual(expectation); }); - it("should not add 's' after the word when it already finished by 's'", () => { + it('should not add \'s\' after the word when it already finished by \'s\'', () => { const pipe = new PluralPipe(); const word = 'archives'; const count = 2; diff --git a/ui/ui-frontend-common/src/app/modules/schema/index.ts b/ui/ui-frontend-common/src/app/modules/schema/index.ts new file mode 100644 index 00000000000..aed772f10fd --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/schema/index.ts @@ -0,0 +1,33 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + * + * + */ + +export * from './model/index'; +export * from './schema-api.service'; +export * from './schema.module'; +export * from './schema.service'; diff --git a/ui/ui-frontend-common/src/app/modules/schema/model/collection.enum.ts b/ui/ui-frontend-common/src/app/modules/schema/model/collection.enum.ts new file mode 100644 index 00000000000..35d02090f95 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/schema/model/collection.enum.ts @@ -0,0 +1,33 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + * + * + */ + +export enum Collection { + ARCHIVE_UNIT = 'ARCHIVE_UNIT', + OBJECT_GROUP = 'OBJECT_GROUP', +} diff --git a/ui/ui-frontend-common/src/app/modules/schema/model/index.ts b/ui/ui-frontend-common/src/app/modules/schema/model/index.ts new file mode 100644 index 00000000000..d210760f029 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/schema/model/index.ts @@ -0,0 +1,31 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + * + * + */ + +export * from './collection.enum'; +export * from './schema.interface'; diff --git a/ui/ui-frontend-common/src/app/modules/schema/model/schema.interface.ts b/ui/ui-frontend-common/src/app/modules/schema/model/schema.interface.ts new file mode 100644 index 00000000000..4ba348f1728 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/schema/model/schema.interface.ts @@ -0,0 +1,32 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + * + * + */ + +import { ExtendedOntology } from '../../object-viewer/models'; + +export interface Schema extends Array {} diff --git a/ui/ui-frontend-common/src/app/modules/schema/schema-api.service.ts b/ui/ui-frontend-common/src/app/modules/schema/schema-api.service.ts new file mode 100644 index 00000000000..e937eabd949 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/schema/schema-api.service.ts @@ -0,0 +1,53 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + * + * + */ + +import { HttpClient } from '@angular/common/http'; +import { Inject, Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { BaseHttpClient } from '../base-http-client'; +import { BASE_URL } from '../injection-tokens'; +import { Ontology } from '../models'; +import { Collection } from './model/collection.enum'; +import { Schema } from './model/schema.interface'; + +@Injectable() +export class SchemaApiService extends BaseHttpClient { + constructor(http: HttpClient, @Inject(BASE_URL) baseUrl: string) { + super(http, `${baseUrl}/schemas`); + } + + public getSchemas(collections: Collection[]): Observable { + return this.http.get(this.apiUrl, { params: { collections } }); + } + + public getSchema(collection: Collection): Observable { + return this.getSchemas([collection]).pipe(map((schemas) => schemas[0])); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/schema/schema.module.ts b/ui/ui-frontend-common/src/app/modules/schema/schema.module.ts new file mode 100644 index 00000000000..6862a9e7362 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/schema/schema.module.ts @@ -0,0 +1,37 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + * + * + */ + +import { NgModule } from '@angular/core'; +import { SchemaApiService } from './schema-api.service'; +import { SchemaService } from './schema.service'; + +@NgModule({ + providers: [SchemaApiService, SchemaService], +}) +export class SchemaModule {} diff --git a/ui/ui-frontend-common/src/app/modules/schema/schema.service.ts b/ui/ui-frontend-common/src/app/modules/schema/schema.service.ts new file mode 100644 index 00000000000..7e86797c492 --- /dev/null +++ b/ui/ui-frontend-common/src/app/modules/schema/schema.service.ts @@ -0,0 +1,47 @@ +/* + * Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022) + * + * contact.vitam@culture.gouv.fr + * + * This software is a computer program whose purpose is to implement a digital archiving back-office system managing + * high volumetry securely and efficiently. + * + * This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free + * software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as + * circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, + * users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the + * successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or + * developing or reproducing the software by the user in light of its specific status of free software, that may mean + * that it is complicated to manipulate, and that also therefore means that it is reserved for developers and + * experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the + * software's suitability as regards their requirements in conditions enabling the security of their systems and/or data + * to be ensured and, more generally, to use and operate it in the same conditions as regards security. + * + * The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you + * accept its terms. + * + * + */ + +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { Collection } from './model/collection.enum'; +import { Schema } from './model/schema.interface'; +import { SchemaApiService } from './schema-api.service'; + +@Injectable() +export class SchemaService { + constructor(private api: SchemaApiService) {} + + public getSchemas(collections: Collection[]): Observable { + return this.api.getSchemas(collections); + } + + public getSchema(collection: Collection): Observable { + return this.api.getSchema(collection); + } +} diff --git a/ui/ui-frontend-common/src/app/modules/utils/role.enum.ts b/ui/ui-frontend-common/src/app/modules/utils/role.enum.ts index 3ca3ae02399..05876935582 100644 --- a/ui/ui-frontend-common/src/app/modules/utils/role.enum.ts +++ b/ui/ui-frontend-common/src/app/modules/utils/role.enum.ts @@ -81,7 +81,7 @@ export enum Role { ROLE_IMPORT_RULES = 'ROLE_IMPORT_RULES', ROLE_EXPORT_RULES = 'ROLE_EXPORT_RULES', - ROLE_UPDATE_FILE_FORMATS = "ROLE_UPDATE_FILE_FORMATS", - ROLE_CREATE_FILE_FORMATS = "ROLE_CREATE_FILE_FORMATS", - ROLE_IMPORT_FILE_FORMATS = "ROLE_IMPORT_FILE_FORMATS" + ROLE_UPDATE_FILE_FORMATS = 'ROLE_UPDATE_FILE_FORMATS', + ROLE_CREATE_FILE_FORMATS = 'ROLE_CREATE_FILE_FORMATS', + ROLE_IMPORT_FILE_FORMATS = 'ROLE_IMPORT_FILE_FORMATS' } diff --git a/ui/ui-frontend-common/src/app/modules/vitamui-common.module.ts b/ui/ui-frontend-common/src/app/modules/vitamui-common.module.ts index 4619f8cbf3e..d40ffce2a24 100644 --- a/ui/ui-frontend-common/src/app/modules/vitamui-common.module.ts +++ b/ui/ui-frontend-common/src/app/modules/vitamui-common.module.ts @@ -35,7 +35,7 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ import { CommonModule } from '@angular/common'; -import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http'; +import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { APP_INITIALIZER, NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { MatDatepickerModule } from '@angular/material/datepicker'; @@ -106,7 +106,9 @@ import { ErrorDialogComponent } from './error-dialog/error-dialog.component'; import { ENVIRONMENT, SUBROGRATION_REFRESH_RATE_MS, WINDOW_LOCATION } from './injection-tokens'; import { LogbookModule } from './logbook/logbook.module'; import { LoggerModule } from './logger/logger.module'; +import { ObjectViewerModule } from './object-viewer/object-viewer.module'; import { PipesModule } from './pipes/pipes.module'; +import { SchemaModule } from './schema/schema.module'; import { SecurityModule } from './security/security.module'; import { StartupService } from './startup.service'; import { SubrogationModule } from './subrogation/subrogation.module'; @@ -114,13 +116,15 @@ import { VitamUIHttpInterceptor } from './vitamui-http-interceptor'; export function loadConfigFactory(configService: ConfigService, environment: any) { // tslint:disable-next-line: semicolon whitespace - return () => configService.load(environment.configUrls).toPromise();; + const p = () => configService.load(environment.configUrls).toPromise(); + + return p; } export function startupServiceFactory(startupService: StartupService, authService: AuthService) { // leave it like this due to run packagr issue : // https://github.com/ng-packagr/ng-packagr/issues/696 & https://github.com/angular/angular/issues/ - return () => + const p = () => new Promise((resolve) => { authService .login() @@ -129,64 +133,73 @@ export function startupServiceFactory(startupService: StartupService, authServic switchMap(() => startupService.load()) ) .subscribe(() => resolve(true)); - // tslint:disable-next-line: semicolon whitespace - });; + // tslint:disable-next-line: semicolon whitespace + }); + + return p; } @NgModule({ declarations: [BlankComponent, ErrorDialogComponent, VitamuiIntervalDatePickerComponent], imports: [ - CommonModule, - HttpClientModule, - MatDialogModule, - MatSnackBarModule, AccountModule, ApplicationSelectContentModule, + ArchiveModule, + AutocompletePositionDirectiveModule, CancelledSnackBarModule, CollapseDirectiveModule, - EllipsisDirectiveModule, + CommonModule, + CommonProgressBarModule, ConfirmDialogModule, CustomerSelectContentModule, - PipesModule, - VitamUICustomerSelectModule, - VitamUIDisplayNodeModule, - VitamUIDurationInputModule, - VitamUIFieldErrorModule, - VitamUIInputModule, - VitamUIMenuTileModule, - VitamUIListInputModule, - VitamUISnackBarModule, - VitamUITenantSelectModule, DownloadSnackBarModule, DragAndDropModule, EditableFieldModule, + EllipsisDirectiveModule, + FooterModule, + HeaderModule, + HttpClientModule, InfiniteScrollModule, LogbookModule, + LogbookOperationFacetModule, LoggerModule, + MatDatepickerModule, + MatDialogModule, + MatSnackBarModule, NavbarModule, - HeaderModule, - SelectTenantDialogModule, + ObjectViewerModule, OrderByButtonModule, OrderDropdownModule, + PipesModule, + ReactiveFormsModule, + ResizeSidebarModule, RowCollapseModule, + ScrollTopModule, SearchBarModule, SearchBarWithSiblingButtonModule, SecurityModule, + SelectTenantDialogModule, SlideToggleModule, StepperModule, SubrogationModule, TooltipModule, - CommonProgressBarModule, - VitamuiCommonSelectModule, - VitamuiDragDropFileModule, + TranslateModule, + UserPhotoModule, VitamUIAutocompleteModule, - ScrollTopModule, - FooterModule, VitamuiBodyModule, - VitamuiContentBreadcrumbModule, VitamuiCommonBannerModule, - UserPhotoModule, + VitamuiCommonSelectModule, + VitamuiContentBreadcrumbModule, + VitamUICustomerSelectModule, + VitamUIDisplayNodeModule, + VitamuiDragDropFileModule, + VitamUIDurationInputModule, + VitamuiFacetModule, + VitamUIFieldErrorModule, + VitamUIInputModule, + VitamUIListInputModule, VitamuiMenuButtonModule, + VitamUIMenuTileModule, VitamuiSidenavHeaderModule, TranslateModule, ResizeSidebarModule, @@ -199,68 +212,74 @@ export function startupServiceFactory(startupService: StartupService, authServic ArchiveModule, UserAlertCardModule, ApplicationCardModule, + SchemaModule, + VitamUISnackBarModule, + VitamUITenantSelectModule, ], entryComponents: [ErrorDialogComponent], exports: [ AccountModule, - TranslateModule, - SelectLanguageModule, ApplicationSelectContentModule, + ArchiveModule, + AutocompletePositionDirectiveModule, BlankComponent, - ConfirmDialogModule, - CollapseModule, CollapseDirectiveModule, - EllipsisDirectiveModule, - VitamUICustomerSelectModule, - VitamUIDisplayNodeModule, - VitamUIDurationInputModule, - VitamUIFieldErrorModule, - VitamUIInputModule, - VitamUIListInputModule, - VitamUIMenuTileModule, - VitamUITenantSelectModule, + CollapseModule, + CommonProgressBarModule, + CommonTooltipModule, + ConfirmDialogModule, DragAndDropModule, EditableFieldModule, + EllipsisDirectiveModule, + FooterModule, + HeaderModule, InfiniteScrollModule, LogbookModule, + LogbookOperationFacetModule, LoggerModule, NavbarModule, - HeaderModule, - SelectTenantDialogModule, + ObjectViewerModule, OrderByButtonModule, OrderDropdownModule, + PipesModule, + ResizeSidebarModule, RowCollapseModule, + ScrollTopModule, SearchBarModule, SearchBarWithSiblingButtonModule, SecurityModule, + SelectLanguageModule, + SelectTenantDialogModule, SlideToggleModule, StepperModule, SubrogationModule, TooltipModule, - VitamuiCommonSelectModule, - VitamuiDragDropFileModule, + TranslateModule, + UserPhotoModule, VitamUIAutocompleteModule, - ScrollTopModule, - FooterModule, VitamuiBodyModule, - PipesModule, - VitamuiContentBreadcrumbModule, VitamuiCommonBannerModule, - UserPhotoModule, - CommonProgressBarModule, - CommonTooltipModule, - VitamuiSidenavHeaderModule, - VitamuiMenuButtonModule, - ResizeSidebarModule, - AutocompletePositionDirectiveModule, - LogbookOperationFacetModule, + VitamuiCommonSelectModule, + VitamuiContentBreadcrumbModule, + VitamUICustomerSelectModule, + VitamUIDisplayNodeModule, + VitamuiDragDropFileModule, + VitamUIDurationInputModule, VitamuiFacetModule, + VitamUIFieldErrorModule, + VitamUIInputModule, VitamuiIntervalDatePickerComponent, + VitamUIListInputModule, + VitamuiMenuButtonModule, + VitamUIMenuTileModule, VitamuiMultiInputsModule, UserAlertCardModule, + VitamuiSidenavHeaderModule, + VitamUITenantSelectModule, VitamuiTreeNodeModule, ArchiveModule, ApplicationCardModule, + SchemaModule, ], providers: [ { provide: SUBROGRATION_REFRESH_RATE_MS, useValue: 10000 }, diff --git a/ui/ui-frontend-common/src/assets/shared-i18n/en.json b/ui/ui-frontend-common/src/assets/shared-i18n/en.json index 43417721451..a956d5335ce 100644 --- a/ui/ui-frontend-common/src/assets/shared-i18n/en.json +++ b/ui/ui-frontend-common/src/assets/shared-i18n/en.json @@ -4559,5 +4559,255 @@ "ELEMENTS_TO_CHECK": "Systematic verification of the presence of the following elements:" } } - } + }, + "TAB.DESCRIPTION": "Description", + "_sp": "Producer department responsible for entry(*)", + "_sps": "Producer service(s) having rights to the unit", + "Generalities": "General", + "Generalities.DescriptionLevel": "Description level *", + "Generalities.Title": "Titled *", + "Generalities.Title_.*": "Title(s) [language]", + "Generalities.Description": "Description", + "Generalities.Description_.*": "Description [language]", + "Generalities.Tag": "Tags", + "Generalities.Dates": "date(s)", + "Generalities.Dates.StartDate": "Start date", + "Generalities.Dates.EndDate": "End date", + "Generalities.Dates.CreatedDate": "Creation date", + "Generalities.Dates.TransactedDate": "Transaction date", + "Generalities.Dates.SentDate": "Sending date", + "Generalities.Dates.ReceivedDate": "Date of receipt", + "Generalities.Dates.RegisteredDate": "Registration Date", + "Generalities.Dates.AcquiredDate": "Scan Date", + "Generalities.Dates.DateLitteral": "Text date", + "Generalities.Identifiers": "Identifier(s)", + "Generalities.Identifiers.SystemId": "System technical identifier", + "Generalities.Identifiers.OriginatingSystemId": "Identifier assigned by the originating system", + "Generalities.Identifiers.OriginatingAgencyArchiveUnitIdentifier": "Identifier assigned by the producing service", + "Generalities.Identifiers.TransferringAgencyArchiveUnitIdentifier": "Identifier assigned by the paying service", + "Generalities.Identifiers.ArchivalAgencyArchiveUnitIdentifier": "Identifier assigned by the archive service", + "Generalities.Identifiers.FilePlanPosition": "Position in the filing plan", + "Generalities.PersistentIdentifier": "Permanent identifier", + "Generalities.PersistentIdentifier.PersistentIdentifierType": "Kind", + "Generalities.PersistentIdentifier.PersistentIdentifierOrigin": "Origin", + "Generalities.PersistentIdentifier.PersistentIdentifierReference": "Reference", + "Generalities.PersistentIdentifier.PersistentIdentifierContent": "ID", + "Generalities.Characteristics": "Features)", + "Generalities.Characteristics.Type": "type of information", + "Generalities.Characteristics.DocumentType": "Document type", + "Generalities.Characteristics.Language": "Language", + "Generalities.Characteristics.DescriptionLanguage": "Description language", + "Generalities.Characteristics.Status": "Status", + "Generalities.Characteristics.Source": "Source", + "Generalities.Characteristics.Version": "Version", + "Generalities.Characteristics.OriginatingSystemIdReplyTo": "Reply to the message in reference", + "Generalities.Characteristics.TextContent": "Content", + "CustodialHistory": "Custody history", + "CustodialHistory.CustodialHistoryItem": "Detail", + "CustodialHistory.CustodialHistoryFile": "Reference to an external journal", + "CustodialHistory.CustodialHistoryFile.DataObjectGroupReferenceId": "Reference to a group of objects", + "CustodialHistory.CustodialHistoryFile.DataObjectReferenceId": "Reference to an object", + "AuthorizedAgent": "Rights holder", + "AuthorizedAgent.FirstName": "First name", + "AuthorizedAgent.BirthName": "Birth name", + "AuthorizedAgent.FullName": "Full Name", + "AuthorizedAgent.GivenName": "Use name", + "AuthorizedAgent.Gender": "Sex", + "AuthorizedAgent.BirthDate": "Date of birth", + "AuthorizedAgent.DeathDate": "date of death", + "AuthorizedAgent.BirthPlace": "Place of birth", + "AuthorizedAgent.BirthPlace.Geogname": "Name of place", + "AuthorizedAgent.BirthPlace.Address": "Address", + "AuthorizedAgent.BirthPlace.PostalCode": "Postal code", + "AuthorizedAgent.BirthPlace.City": "City", + "AuthorizedAgent.BirthPlace.Region": "Region", + "AuthorizedAgent.BirthPlace.Country": "Country", + "AuthorizedAgent.DeathPlace": "Place of death", + "AuthorizedAgent.DeathPlace.Geogname": "Name of place", + "AuthorizedAgent.DeathPlace.Address": "Address", + "AuthorizedAgent.DeathPlace.PostalCode": "Postal code", + "AuthorizedAgent.DeathPlace.City": "City", + "AuthorizedAgent.DeathPlace.Region": "Region", + "AuthorizedAgent.DeathPlace.Country": "Country", + "AuthorizedAgent.Nationality": "Nationality", + "AuthorizedAgent.Corpname": "Name of entity", + "AuthorizedAgent.Identifier": "ID", + "AuthorizedAgent.Function": "Function", + "AuthorizedAgent.Activity": "Activity", + "AuthorizedAgent.Position": "Position", + "AuthorizedAgent.Role": "Role", + "AuthorizedAgent.Mandate": "Rights", + "Agent": "Agent", + "Agent.FirstName": "First name", + "Agent.BirthName": "Birth name", + "Agent.FullName": "Full Name", + "Agent.GivenName": "Use name", + "Agent.Gender": "Sex", + "Agent.BirthDate": "Date of birth", + "Agent.DeathDate": "date of death", + "Agent.BirthPlace": "Place of birth", + "Agent.BirthPlace.Geogname": "Name of place", + "Agent.BirthPlace.Address": "Address", + "Agent.BirthPlace.PostalCode": "Postal code", + "Agent.BirthPlace.City": "City", + "Agent.BirthPlace.Region": "Region", + "Agent.BirthPlace.Country": "Country", + "Agent.DeathPlace": "Place of death", + "Agent.DeathPlace.Geogname": "Name of place", + "Agent.DeathPlace.Address": "Address", + "Agent.DeathPlace.PostalCode": "Postal code", + "Agent.DeathPlace.City": "City", + "Agent.DeathPlace.Region": "Region", + "Agent.DeathPlace.Country": "Country", + "Agent.Nationality": "Nationality", + "Agent.Corpname": "Name of entity", + "Agent.Identifier": "ID", + "Agent.Function": "Function", + "Agent.Activity": "Activity", + "Agent.Position": "Position", + "Agent.Role": "Role", + "Agent.Mandate": "Rights", + "Writer": "Editor", + "Writer.FirstName": "First name", + "Writer.BirthName": "Birth name", + "Writer.FullName": "Full Name", + "Writer.GivenName": "Use name", + "Writer.Gender": "Sex", + "Writer.BirthDate": "Date of birth", + "Writer.DeathDate": "date of death", + "Writer.BirthPlace": "Place of birth", + "Writer.BirthPlace.Geogname": "Name of place", + "Writer.BirthPlace.Address": "Address", + "Writer.BirthPlace.PostalCode": "Postal code", + "Writer.BirthPlace.City": "City", + "Writer.BirthPlace.Region": "Region", + "Writer.BirthPlace.Country": "Country", + "Writer.DeathPlace": "Place of death", + "Writer.DeathPlace.Geogname": "Name of place", + "Writer.DeathPlace.Address": "Address", + "Writer.DeathPlace.PostalCode": "Postal code", + "Writer.DeathPlace.City": "City", + "Writer.DeathPlace.Region": "Region", + "Writer.DeathPlace.Country": "Country", + "Writer.Nationality": "Nationality", + "Writer.Corpname": "Name of entity", + "Writer.Identifier": "ID", + "Writer.Function": "Function", + "Writer.Activity": "Activity", + "Writer.Position": "Position", + "Writer.Role": "Role", + "Writer.Mandate": "Rights", + "Addressee": "RECIPIENT", + "Addressee.FirstName": "First name", + "Addressee.BirthName": "Birth name", + "Addressee.Fullpname": "Full Name", + "Addressee.GivenName": "Use name", + "Addressee.Gender": "Sex", + "Addressee.BirthDate": "Date of birth", + "Addressee.DeathDate": "date of death", + "Addressee.BirthPlace": "Place of birth", + "Addressee.BirthPlace.Geogname": "Name of place", + "Addressee.BirthPlace.Address": "Address", + "Addressee.BirthPlace.PostalCode": "Postal code", + "Addressee.BirthPlace.City": "City", + "Addressee.BirthPlace.Region": "Region", + "Addressee.BirthPlace.Country": "Country", + "Addressee.DeathPlace": "Place of death", + "Addressee.DeathPlace.Geogname": "Name of place", + "Addressee.DeathPlace.Address": "Address", + "Addressee.DeathPlace.PostalCode": "Postal code", + "Addressee.DeathPlace.City": "City", + "Addressee.DeathPlace.Region": "Region", + "Addressee.DeathPlace.Country": "Country", + "Addressee.Nationality": "Nationality", + "Addressee.Corpname": "Name of entity", + "Addressee.Identifier": "ID", + "Addressee.Function": "Function", + "Addressee.Activity": "Activity", + "Addressee.Position": "Position", + "Addressee.Role": "Role", + "Addressee.Mandate": "Rights", + "Recipient": "Addressee for information", + "Recipient.FirstName": "First name", + "Recipient.BirthName": "Birth name", + "Recipient.FullName": "Full Name", + "Recipient.GivenName": "Use name", + "Recipient.Gender": "Sex", + "Recipient.BirthDate": "Date of birth", + "Recipient.DeathDate": "date of death", + "Recipient.BirthPlace": "Place of birth", + "Recipient.BirthPlace.Geogname": "Name of place", + "Recipient.BirthPlace.Address": "Address", + "Recipient.BirthPlace.PostalCode": "Postal code", + "Recipient.BirthPlace.City": "City", + "Recipient.BirthPlace.Region": "Region", + "Recipient.BirthPlace.Country": "Country", + "Recipient.DeathPlace": "Place of death", + "Recipient.DeathPlace.Geogname": "Name of place", + "Recipient.DeathPlace.Address": "Address", + "Recipient.DeathPlace.PostalCode": "Postal code", + "Recipient.DeathPlace.City": "City", + "Recipient.DeathPlace.Region": "Region", + "Recipient.DeathPlace.Country": "Country", + "Recipient.Nationality": "Nationality", + "Recipient.Corpname": "Name of entity", + "Recipient.Identifier": "ID", + "Recipient.Function": "Function", + "Recipient.Activity": "Activity", + "Recipient.Position": "Position", + "Recipient.Role": "Role", + "Recipient.Mandate": "Rights", + "Transmitter": "Issuer", + "Transmitter.FirstName": "First name", + "Transmitter.BirthName": "Birth name", + "Transmitter.FullName": "Full Name", + "Transmitter.GivenName": "Use name", + "Transmitter.Gender": "Sex", + "Transmitter.BirthDate": "Date of birth", + "Transmitter.DeathDate": "date of death", + "Transmitter.BirthPlace": "Place of birth", + "Transmitter.BirthPlace.Geogname": "Name of place", + "Transmitter.BirthPlace.Address": "Address", + "Transmitter.BirthPlace.PostalCode": "Postal code", + "Transmitter.BirthPlace.City": "City", + "Transmitter.BirthPlace.Region": "Region", + "Transmitter.BirthPlace.Country": "Country", + "Transmitter.DeathPlace": "Place of death", + "Transmitter.DeathPlace.Geogname": "Name of place", + "Transmitter.DeathPlace.Address": "Address", + "Transmitter.DeathPlace.PostalCode": "Postal code", + "Transmitter.DeathPlace.City": "City", + "Transmitter.DeathPlace.Region": "Region", + "Transmitter.DeathPlace.Country": "Country", + "Transmitter.Nationality": "Nationality", + "Transmitter.Corpname": "Name of entity", + "Transmitter.Identifier": "ID", + "Transmitter.Function": "Function", + "Transmitter.Activity": "Activity", + "Transmitter.Position": "Position", + "Transmitter.Role": "Role", + "Transmitter.Mandate": "Rights", + "Sender": "Sender", + "Sender.FirstName": "First name", + "Sender.BirthName": "Birth name", + "Sender.FullName": "Full Name", + "Sender.GivenName": "Use name", + "Sender.Gender": "Sex", + "Sender.BirthDate": "Date of birth", + "Sender.DeathDate": "date of death", + "Sender.BirthPlace": "Place of birth", + "Sender.BirthPlace.Geogname": "Name of place", + "Sender.BirthPlace.Address": "Address", + "Sender.BirthPlace.PostalCode": "Postal code", + "Sender.BirthPlace.City": "City", + "Sender.BirthPlace.Region": "Region", + "Sender.BirthPlace.Country": "Country", + "Sender.DeathPlace": "Place of death", + "Sender.DeathPlace.Geogname": "Name of place", + "Sender.DeathPlace.Address": "Address", + "Sender.DeathPlace.PostalCode": "Postal code", + "Sender.DeathPlace.City": "City", + "Sender.DeathPlace.Region": "Region", + "Sender.DeathPlace.Country": "Country", + "OtherMetadata": "Other metadata" } diff --git a/ui/ui-frontend-common/src/assets/shared-i18n/fr.json b/ui/ui-frontend-common/src/assets/shared-i18n/fr.json index f937cdd18e9..a4d523c2101 100644 --- a/ui/ui-frontend-common/src/assets/shared-i18n/fr.json +++ b/ui/ui-frontend-common/src/assets/shared-i18n/fr.json @@ -5405,5 +5405,408 @@ "ELEMENTS_TO_CHECK": "Vérification systématique de la présence des éléments suivants:" } } - } + }, + "TAB.DESCRIPTION": "Description", + "_sp": "Service producteur responsable de l'entrée(*)", + "_sps": "Service(s) producteur(s) ayant des droits sur l'unité", + "Generalities": "Généralités", + "Generalities.DescriptionLevel": "Niveau de description *", + "Generalities.Title": "Intitulé *", + "Generalities.Title_.*": "Intitulé(s) [langue]", + "Generalities.Description": "Description", + "Generalities.Description_.*": "Description [langue]", + "Generalities.Tag": "Tag", + "Generalities.Dates": "Date(s)", + "Generalities.Dates.StartDate": "Date de début", + "Generalities.Dates.EndDate": "Date de fin", + "Generalities.Dates.CreatedDate": "Date de création", + "Generalities.Dates.TransactedDate": "Date de transaction", + "Generalities.Dates.SentDate": "Date d'envoi", + "Generalities.Dates.ReceivedDate": "Date de réception", + "Generalities.Dates.RegisteredDate": "Date d’enregistrement", + "Generalities.Dates.AcquiredDate": "Date de numérisation", + "Generalities.Dates.DateLitteral": "Date textuelle", + "Generalities.Identifiers": "Identifiant(s)", + "Generalities.Identifiers.SystemId": "Identifiant technique du système", + "Generalities.Identifiers.OriginatingSystemId": "Identifiant attribué par le système d'origine", + "Generalities.Identifiers.OriginatingAgencyArchiveUnitIdentifier": "Identifiant attribué par le service producteur", + "Generalities.Identifiers.TransferringAgencyArchiveUnitIdentifier": "Identifiant attribué par le service versant", + "Generalities.Identifiers.ArchivalAgencyArchiveUnitIdentifier": "Identifiant attribué par le service d'archives", + "Generalities.Identifiers.FilePlanPosition": "Position dans le plan de classement", + "Generalities.PersistentIdentifier": "Identifiant pérenne", + "Generalities.PersistentIdentifier.PersistentIdentifierType": "Type", + "Generalities.PersistentIdentifier.PersistentIdentifierOrigin": "Origine", + "Generalities.PersistentIdentifier.PersistentIdentifierReference": "Référence", + "Generalities.PersistentIdentifier.PersistentIdentifierContent": "Identifiant", + "Generalities.Characteristics": "Caractéristique(s)", + "Generalities.Characteristics.Type": "Type d'information", + "Generalities.Characteristics.DocumentType": "Type de document", + "Generalities.Characteristics.Language": "Langue", + "Generalities.Characteristics.DescriptionLanguage": "Langue de la description", + "Generalities.Characteristics.Status": "Statut", + "Generalities.Characteristics.Source": "Source", + "Generalities.Characteristics.Version": "Version", + "Generalities.Characteristics.OriginatingSystemIdReplyTo": "Réponse au message en référence", + "Generalities.Characteristics.TextContent": "Contenu", + "CustodialHistory": "Historique de la conservation", + "CustodialHistory.CustodialHistoryItem": "Détail", + "CustodialHistory.CustodialHistoryFile": "Référence à un journal externe", + "CustodialHistory.CustodialHistoryFile.DataObjectGroupReferenceId": "Référence à un groupe d'objets", + "CustodialHistory.CustodialHistoryFile.DataObjectReferenceId": "Référence à un objet", + "AuthorizedAgent": "Titulaire des droits", + "AuthorizedAgent.FirstName": "Prénom", + "AuthorizedAgent.BirthName": "Nom de naissance", + "AuthorizedAgent.FullName": "Nom complet", + "AuthorizedAgent.GivenName": "Nom d'usage", + "AuthorizedAgent.Gender": "Sexe", + "AuthorizedAgent.BirthDate": "Date de naissance", + "AuthorizedAgent.DeathDate": "date de décès", + "AuthorizedAgent.BirthPlace": "Lieu de naissance", + "AuthorizedAgent.BirthPlace.Geogname": "Nom de lieu", + "AuthorizedAgent.BirthPlace.Address": "Adresse", + "AuthorizedAgent.BirthPlace.PostalCode": "Code postal", + "AuthorizedAgent.BirthPlace.City": "Ville", + "AuthorizedAgent.BirthPlace.Region": "Région", + "AuthorizedAgent.BirthPlace.Country": "Pays", + "AuthorizedAgent.DeathPlace": "Lieu de décès", + "AuthorizedAgent.DeathPlace.Geogname": "Nom de lieu", + "AuthorizedAgent.DeathPlace.Address": "Adresse", + "AuthorizedAgent.DeathPlace.PostalCode": "Code postal", + "AuthorizedAgent.DeathPlace.City": "Ville", + "AuthorizedAgent.DeathPlace.Region": "Région", + "AuthorizedAgent.DeathPlace.Country": "Pays", + "AuthorizedAgent.Nationality": "nationalité", + "AuthorizedAgent.Corpname": "Nom de l'entité", + "AuthorizedAgent.Identifier": "Identifiant", + "AuthorizedAgent.Function": "Fonction", + "AuthorizedAgent.Activity": "Activité", + "AuthorizedAgent.Position": "Position", + "AuthorizedAgent.Role": "Rôle", + "AuthorizedAgent.Mandate": "Droits", + "Agent": "Agent", + "Agent.FirstName": "Prénom", + "Agent.BirthName": "Nom de naissance", + "Agent.FullName": "Nom complet", + "Agent.GivenName": "Nom d'usage", + "Agent.Gender": "Sexe", + "Agent.BirthDate": "Date de naissance", + "Agent.DeathDate": "date de décès", + "Agent.BirthPlace": "Lieu de naissance", + "Agent.BirthPlace.Geogname": "Nom de lieu", + "Agent.BirthPlace.Address": "Adresse", + "Agent.BirthPlace.PostalCode": "Code postal", + "Agent.BirthPlace.City": "Ville", + "Agent.BirthPlace.Region": "Région", + "Agent.BirthPlace.Country": "Pays", + "Agent.DeathPlace": "Lieu de décès", + "Agent.DeathPlace.Geogname": "Nom de lieu", + "Agent.DeathPlace.Address": "Adresse", + "Agent.DeathPlace.PostalCode": "Code postal", + "Agent.DeathPlace.City": "Ville", + "Agent.DeathPlace.Region": "Région", + "Agent.DeathPlace.Country": "Pays", + "Agent.Nationality": "nationalité", + "Agent.Corpname": "Nom de l'entité", + "Agent.Identifier": "Identifiant", + "Agent.Function": "Fonction", + "Agent.Activity": "Activité", + "Agent.Position": "Position", + "Agent.Role": "Rôle", + "Agent.Mandate": "Droits", + "Writer": "Rédacteur", + "Writer.FirstName": "Prénom", + "Writer.BirthName": "Nom de naissance", + "Writer.FullName": "Nom complet", + "Writer.GivenName": "Nom d'usage", + "Writer.Gender": "Sexe", + "Writer.BirthDate": "Date de naissance", + "Writer.DeathDate": "date de décès", + "Writer.BirthPlace": "Lieu de naissance", + "Writer.BirthPlace.Geogname": "Nom de lieu", + "Writer.BirthPlace.Address": "Adresse", + "Writer.BirthPlace.PostalCode": "Code postal", + "Writer.BirthPlace.City": "Ville", + "Writer.BirthPlace.Region": "Région", + "Writer.BirthPlace.Country": "Pays", + "Writer.DeathPlace": "Lieu de décès", + "Writer.DeathPlace.Geogname": "Nom de lieu", + "Writer.DeathPlace.Address": "Adresse", + "Writer.DeathPlace.PostalCode": "Code postal", + "Writer.DeathPlace.City": "Ville", + "Writer.DeathPlace.Region": "Région", + "Writer.DeathPlace.Country": "Pays", + "Writer.Nationality": "nationalité", + "Writer.Corpname": "Nom de l'entité", + "Writer.Identifier": "Identifiant", + "Writer.Function": "Fonction", + "Writer.Activity": "Activité", + "Writer.Position": "Position", + "Writer.Role": "Rôle", + "Writer.Mandate": "Droits", + "Addressee": "Destinataire", + "Addressee.FirstName": "Prénom", + "Addressee.BirthName": "Nom de naissance", + "Addressee.Fullpname": "Nom complet", + "Addressee.GivenName": "Nom d'usage", + "Addressee.Gender": "Sexe", + "Addressee.BirthDate": "Date de naissance", + "Addressee.DeathDate": "date de décès", + "Addressee.BirthPlace": "Lieu de naissance", + "Addressee.BirthPlace.Geogname": "Nom de lieu", + "Addressee.BirthPlace.Address": "Adresse", + "Addressee.BirthPlace.PostalCode": "Code postal", + "Addressee.BirthPlace.City": "Ville", + "Addressee.BirthPlace.Region": "Région", + "Addressee.BirthPlace.Country": "Pays", + "Addressee.DeathPlace": "Lieu de décès", + "Addressee.DeathPlace.Geogname": "Nom de lieu", + "Addressee.DeathPlace.Address": "Adresse", + "Addressee.DeathPlace.PostalCode": "Code postal", + "Addressee.DeathPlace.City": "Ville", + "Addressee.DeathPlace.Region": "Région", + "Addressee.DeathPlace.Country": "Pays", + "Addressee.Nationality": "nationalité", + "Addressee.Corpname": "Nom de l'entité", + "Addressee.Identifier": "Identifiant", + "Addressee.Function": "Fonction", + "Addressee.Activity": "Activité", + "Addressee.Position": "Position", + "Addressee.Role": "Rôle", + "Addressee.Mandate": "Droits", + "Recipient": "Destinataire pour information", + "Recipient.FirstName": "Prénom", + "Recipient.BirthName": "Nom de naissance", + "Recipient.FullName": "Nom complet", + "Recipient.GivenName": "Nom d'usage", + "Recipient.Gender": "Sexe", + "Recipient.BirthDate": "Date de naissance", + "Recipient.DeathDate": "date de décès", + "Recipient.BirthPlace": "Lieu de naissance", + "Recipient.BirthPlace.Geogname": "Nom de lieu", + "Recipient.BirthPlace.Address": "Adresse", + "Recipient.BirthPlace.PostalCode": "Code postal", + "Recipient.BirthPlace.City": "Ville", + "Recipient.BirthPlace.Region": "Région", + "Recipient.BirthPlace.Country": "Pays", + "Recipient.DeathPlace": "Lieu de décès", + "Recipient.DeathPlace.Geogname": "Nom de lieu", + "Recipient.DeathPlace.Address": "Adresse", + "Recipient.DeathPlace.PostalCode": "Code postal", + "Recipient.DeathPlace.City": "Ville", + "Recipient.DeathPlace.Region": "Région", + "Recipient.DeathPlace.Country": "Pays", + "Recipient.Nationality": "nationalité", + "Recipient.Corpname": "Nom de l'entité", + "Recipient.Identifier": "Identifiant", + "Recipient.Function": "Fonction", + "Recipient.Activity": "Activité", + "Recipient.Position": "Position", + "Recipient.Role": "Rôle", + "Recipient.Mandate": "Droits", + "Transmitter": "Emetteur", + "Transmitter.FirstName": "Prénom", + "Transmitter.BirthName": "Nom de naissance", + "Transmitter.FullName": "Nom complet", + "Transmitter.GivenName": "Nom d'usage", + "Transmitter.Gender": "Sexe", + "Transmitter.BirthDate": "Date de naissance", + "Transmitter.DeathDate": "date de décès", + "Transmitter.BirthPlace": "Lieu de naissance", + "Transmitter.BirthPlace.Geogname": "Nom de lieu", + "Transmitter.BirthPlace.Address": "Adresse", + "Transmitter.BirthPlace.PostalCode": "Code postal", + "Transmitter.BirthPlace.City": "Ville", + "Transmitter.BirthPlace.Region": "Région", + "Transmitter.BirthPlace.Country": "Pays", + "Transmitter.DeathPlace": "Lieu de décès", + "Transmitter.DeathPlace.Geogname": "Nom de lieu", + "Transmitter.DeathPlace.Address": "Adresse", + "Transmitter.DeathPlace.PostalCode": "Code postal", + "Transmitter.DeathPlace.City": "Ville", + "Transmitter.DeathPlace.Region": "Région", + "Transmitter.DeathPlace.Country": "Pays", + "Transmitter.Nationality": "nationalité", + "Transmitter.Corpname": "Nom de l'entité", + "Transmitter.Identifier": "Identifiant", + "Transmitter.Function": "Fonction", + "Transmitter.Activity": "Activité", + "Transmitter.Position": "Position", + "Transmitter.Role": "Rôle", + "Transmitter.Mandate": "Droits", + "Sender": "Expéditeur", + "Sender.FirstName": "Prénom", + "Sender.BirthName": "Nom de naissance", + "Sender.FullName": "Nom complet", + "Sender.GivenName": "Nom d'usage", + "Sender.Gender": "Sexe", + "Sender.BirthDate": "Date de naissance", + "Sender.DeathDate": "date de décès", + "Sender.BirthPlace": "Lieu de naissance", + "Sender.BirthPlace.Geogname": "Nom de lieu", + "Sender.BirthPlace.Address": "Adresse", + "Sender.BirthPlace.PostalCode": "Code postal", + "Sender.BirthPlace.City": "Ville", + "Sender.BirthPlace.Region": "Région", + "Sender.BirthPlace.Country": "Pays", + "Sender.DeathPlace": "Lieu de décès", + "Sender.DeathPlace.Geogname": "Nom de lieu", + "Sender.DeathPlace.Address": "Adresse", + "Sender.DeathPlace.PostalCode": "Code postal", + "Sender.DeathPlace.City": "Ville", + "Sender.DeathPlace.Region": "Région", + "Sender.DeathPlace.Country": "Pays", + "Sender.Nationality": "nationalité", + "Sender.Corpname": "Nom de l'entité", + "Sender.Identifier": "Identifiant", + "Sender.Function": "Fonction", + "Sender.Activity": "Activité", + "Sender.Position": "Position", + "Sender.Role": "Rôle", + "Sender.Mandate": "Droits", + "Signature": "Signature", + "Signature.Masterdata": "Référentiel des personnes et des organisations", + "Signature.ReferencedObject": "Référence à l'objet signé", + "Signature.ReferencedObject.SignedObjectId": "Identifiant de l'Objet de données signé", + "Signature.ReferencedObject.SignedObjectDigest": "Empreinte de l'objet signé", + "Signature.Signer": "Signataire", + "Signature.Signer.SigningTime": "Date de signature", + "Signature.Signer.FirstName": "Prénom", + "Signature.Signer.BirthName": "Nom de naissance", + "Signature.Signer.Fullpname": "Nom complet", + "Signature.Signer.GivenName": "Nom d'usage", + "Signature.Signer.Gender": "Sexe", + "Signature.Signer.BirthDate": "Date de naissance", + "Signature.Signer.DeathDate": "Date de décès", + "Signature.Signer.BirthPlace": "Lieu de naissance", + "Signature.Signer.BirthPlace.Geogname": "Nom de lieu", + "Signature.Signer.BirthPlace.Address": "Adresse", + "Signature.Signer.BirthPlace.PostalCode": "Code postal", + "Signature.Signer.BirthPlace.City": "Ville", + "Signature.Signer.BirthPlace.Region": "Région", + "Signature.Signer.BirthPlace.Country": "Pays", + "Signature.Signer.DeathPlace": "Lieu de décès", + "Signature.Signer.DeathPlace.Geogname": "Nom de lieu", + "Signature.Signer.DeathPlace.Address": "Adresse", + "Signature.Signer.DeathPlace.PostalCode": "Code postal", + "Signature.Signer.DeathPlace.City": "Ville", + "Signature.Signer.DeathPlace.Region": "Région", + "Signature.Signer.DeathPlace.Country": "Pays", + "Signature.Signer.Nationality": "nationalité", + "Signature.Signer.Corpname": "Nom de l'entité", + "Signature.Signer.Identifier": "Identifiant", + "Signature.Signer.Function": "Fonction", + "Signature.Signer.Activity": "Activité", + "Signature.Signer.Position": "Position", + "Signature.Signer.Role": "Rôle", + "Signature.Signer.Mandate": "Droits", + "Signature.Validator": "Validateur", + "Signature.Validator.ValidationTime": "Date de validation *", + "Signature.Validator.FirstName": "Prénom", + "Signature.Validator.BirthName": "Nom de naissance", + "Signature.Validator.Fullpname": "Nom complet", + "Signature.Validator.GivenName": "Nom d'usage", + "Signature.Validator.Gender": "Sexe", + "Signature.Validator.BirthDate": "Date de naissance", + "Signature.Validator.DeathDate": "date de décès", + "Signature.Validator.BirthPlace": "Lieu de naissance", + "Signature.Validator.BirthPlace.Geogname": "Nom de lieu", + "Signature.Validator.BirthPlace.Address": "Adresse", + "Signature.Validator.BirthPlace.PostalCode": "Code postal", + "Signature.Validator.BirthPlace.City": "Ville", + "Signature.Validator.BirthPlace.Region": "Région", + "Signature.Validator.BirthPlace.Country": "Pays", + "Signature.Validator.DeathPlace": "Lieu de décès", + "Signature.Validator.DeathPlace.Geogname": "Nom de lieu", + "Signature.Validator.DeathPlace.Address": "Adresse", + "Signature.Validator.DeathPlace.PostalCode": "Code postal", + "Signature.Validator.DeathPlace.City": "Ville", + "Signature.Validator.DeathPlace.Region": "Région", + "Signature.Validator.DeathPlace.Country": "Pays", + "Signature.Validator.Nationality": "nationalité", + "Signature.Validator.Corpname": "Nom de l'entité", + "Signature.Validator.Identifier": "Identifiant", + "Signature.Validator.Function": "Fonction", + "Signature.Validator.Activity": "Activité", + "Signature.Validator.Position": "Position", + "Signature.Validator.Role": "Rôle", + "Signature.Validator.Mandate": "Droits", + "Event": "Événement", + "Event.evId": "Identifiant", + "Event.evTypeProc": "Code", + "Event.evType": "Type", + "Event.evDateTime": "Date", + "Event.evTypeDetail": "Détail de l’événement", + "Event.outcome": "Résultat", + "Event.outDetail": "Détail sur le résultat", + "Event.outMessg": "Description détaillée de l'événement", + "Event.evDetData": "Message technique détaillant l'événement", + "Event.LinkingAgentIdentifier": "Agent", + "Event.LinkingAgentIdentifier.LinkingAgentIdentifierType": "Identifiant", + "Event.LinkingAgentIdentifier.LinkingAgentIdentifierValue": "Valeur", + "Event.LinkingAgentIdentifier.LinkingAgentRole": "Rôle", + "RelatedObjectReference": "Référence(s)", + "RelatedObjectReference.IsVersionOf": "Est une version de", + "RelatedObjectReference.IsVersionOf.ArchiveUnitRefId": "Unité", + "RelatedObjectReference.IsVersionOf.DataObjectReference": "Objet", + "RelatedObjectReference.IsVersionOf.DataObjectReference.DataObjectGroupReferenceId": "ID du groupe d'objets", + "RelatedObjectReference.IsVersionOf.DataObjectReference.DataObjectReferenceId": "ID de l'objet", + "RelatedObjectReference.IsVersionOf.RepositoryArchiveUnitPID": "Unité déjà archivée", + "RelatedObjectReference.IsVersionOf.RepositoryObjectPID": "Objet déjà archivé", + "RelatedObjectReference.IsVersionOf.ExternalReference": "Référence externe", + "RelatedObjectReference.Replaces": "Remplace", + "RelatedObjectReference.Replaces.ArchiveUnitRefId": "Unité", + "RelatedObjectReference.Replaces.DataObjectReference": "Objet", + "RelatedObjectReference.Replaces.DataObjectReference.DataObjectGroupReferenceId": "ID du groupe d'objets", + "RelatedObjectReference.Replaces.DataObjectReference.DataObjectReferenceId": "ID de l'objet", + "RelatedObjectReference.Replaces.ExternalReference": "Unité déjà archivée", + "RelatedObjectReference.Replaces.RepositoryArchiveUnitPID": "Objet déjà archivé", + "RelatedObjectReference.Replaces.RepositoryObjectPID": "Référence externe", + "RelatedObjectReference.Requires": "Requiert", + "RelatedObjectReference.Requires.ArchiveUnitRefId": "Unité", + "RelatedObjectReference.Requires.DataObjectReference": "Objet", + "RelatedObjectReference.Requires.DataObjectReference.DataObjectGroupReferenceId": "ID du groupe d'objets", + "RelatedObjectReference.Requires.DataObjectReference.DataObjectReferenceId": "ID de l'objet", + "RelatedObjectReference.Requires.ExternalReference": "Unité déjà archivée", + "RelatedObjectReference.Requires.RepositoryArchiveUnitPID": "Objet déjà archivé", + "RelatedObjectReference.Requires.RepositoryObjectPID": "Référence externe", + "RelatedObjectReference.IsPartOf": "Est une partie de", + "RelatedObjectReference.IsPartOf.ArchiveUnitRefId": "Unité", + "RelatedObjectReference.IsPartOf.DataObjectReference": "Objet", + "RelatedObjectReference.IsPartOf.DataObjectReference.DataObjectGroupReferenceId": "ID du groupe d'objets", + "RelatedObjectReference.IsPartOf.DataObjectReference.DataObjectReferenceId": "ID de l'objet", + "RelatedObjectReference.IsPartOf.ExternalReference": "Unité déjà archivée", + "RelatedObjectReference.IsPartOf.RepositoryArchiveUnitPID": "Objet déjà archivé", + "RelatedObjectReference.IsPartOf.RepositoryObjectPID": "Référence externe", + "References": "Référence", + "References.ArchiveUnitRefId": "Unité", + "References.DataObjectReference": "Objet", + "References.DataObjectReference.DataObjectReferenceId": "ID du groupe d'objets", + "References.DataObjectReference.DataObjectGroupReferenceId": "ID de l'objet", + "References.RepositoryArchiveUnitPID": "Unité déjà archivée", + "References.RepositoryObjectPID": "Objet déjà archivé", + "References.ExternalReference": "Référence externe", + "OriginatingAgency": "Service producteur", + "OriginatingAgency.Identifier": "Identifiant du service producteur", + "OriginatingAgency.[EXTENSIONS-POSSIBLES]": "[EXTENSIONS-POSSIBLES]", + "SubmissionAgency": "Service versant", + "SubmissionAgency.Identifier": "Identifiant du service versant", + "SubmissionAgency.[EXTENSIONS-POSSIBLES]": "[EXTENSIONS-POSSIBLES]", + "Keyword": "Mot-clé", + "Keyword.KeywordContent": "Valeur du mot-clé", + "Keyword.KeywordReference": "Référence du mot-clé", + "Keyword.KeywordType": "Type de mot-clé", + "Coverage": "Couverture(s)", + "Coverage.Spatial": "Couverture spatiale", + "Coverage.Temporal": "Couverture temporelle", + "Coverage.Juridictional": "Couverture juridictionnelle", + "Gps": "Coordonnées GPS", + "Gps.GpsAltitude": "Identifiant de la version", + "Gps.GpsAltitudeRef": "Altitude", + "Gps.GpsDateStamp": "Référence de l’altitude", + "Gps.GpsLatitude": "Latitude", + "Gps.GpsLatitudeRef": "Référence de la latitude", + "Gps.GpsLongitude": "Longitude", + "Gps.GpsLongitudeRef": "Référence de la longitude", + "Gps.GpsVersionID": "Heure et date de la position", + "OtherMetadata": "Métadonnées complémentaires" } diff --git a/ui/ui-frontend/package.json b/ui/ui-frontend/package.json index 5784a60c9ce..1f0eec24f93 100644 --- a/ui/ui-frontend/package.json +++ b/ui/ui-frontend/package.json @@ -162,6 +162,7 @@ "@angular-builders/custom-webpack": "^8.4.1", "@angular-devkit/build-angular": "^0.1001.3", "@angular-devkit/build-ng-packagr": "^0.1001.3", + "@angular-devkit/core": "^10.1.3", "@angular/cli": "^10.1.3", "@angular/compiler-cli": "10.1.3", "@angular/language-service": "10.1.3", diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.html b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.html index b591eef9516..026acd530d0 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.html +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.html @@ -22,7 +22,7 @@ matTooltipClass="vitamui-tooltip" [matTooltipShowDelay]="300" (click)="updateMetadataDesc()" - [disabled]="updateStarted || (!accessContractAllowUpdating || !hasUpdateDescriptiveUnitMetadataRole)" + [disabled]="updateStarted || !accessContractAllowUpdating || !hasUpdateDescriptiveUnitMetadataRole" > {{ 'UNIT_UPDATE.UPDATE_DESC_METADATA' | translate }} @@ -30,10 +30,11 @@
- - + + + + + - + @@ -54,7 +58,8 @@ + [tenantIdentifier]="tenantIdentifier" + > diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.spec.ts index 4598446b4e1..3510d721e67 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive-preview/archive-preview.component.spec.ts @@ -47,7 +47,15 @@ import { RouterTestingModule } from '@angular/router/testing'; import { TranslateModule } from '@ngx-translate/core'; import { of } from 'rxjs'; import { - BASE_URL, DescriptionLevel, ENVIRONMENT, InjectorModule, LoggerModule, StartupService, Unit, UnitType, WINDOW_LOCATION + BASE_URL, + DescriptionLevel, + ENVIRONMENT, + InjectorModule, + LoggerModule, + StartupService, + Unit, + UnitType, + WINDOW_LOCATION, } from 'ui-frontend-common'; import { environment } from '../../../environments/environment.prod'; import { ArchiveService } from '../archive.service'; @@ -205,13 +213,13 @@ describe('ArchivePreviewComponent', () => { }); describe('DOM', () => { - it('should have 3 mat-tab', () => { + it('should have 4 mat-tab', () => { // When const nativeElement = fixture.nativeElement; const matTabElements = nativeElement.querySelectorAll('mat-tab'); // Then - expect(matTabElements.length).toEqual(3); + expect(matTabElements.length).toEqual(4); }); it('should have 1 mat-tab-group', () => { diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive.component.spec.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive.component.spec.ts index 53b9b6fa33b..9901ea202cf 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive.component.spec.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive.component.spec.ts @@ -55,6 +55,7 @@ import { BASE_URL, InjectorModule, LoggerModule, + SchemaModule, SearchBarModule, SecurityService, WINDOW_LOCATION, @@ -122,6 +123,7 @@ describe('ArchiveComponent', () => { SearchBarModule, TranslateModule.forRoot(), MatSnackBarModule, + SchemaModule, ], declarations: [ArchiveComponent], providers: [ diff --git a/ui/ui-frontend/projects/archive-search/src/app/archive/archive.component.ts b/ui/ui-frontend/projects/archive-search/src/app/archive/archive.component.ts index 69f7f70748f..d4a2b2aee7b 100644 --- a/ui/ui-frontend/projects/archive-search/src/app/archive/archive.component.ts +++ b/ui/ui-frontend/projects/archive-search/src/app/archive/archive.component.ts @@ -43,10 +43,12 @@ import { Subscription } from 'rxjs'; import { map } from 'rxjs/operators'; import { AccessContract, + Collection, ExternalParameters, ExternalParametersService, GlobalEventService, Logger, + SchemaService, SidenavPage, Unit, } from 'ui-frontend-common'; @@ -83,9 +85,11 @@ export class ArchiveComponent extends SidenavPage implements OnInit, OnDest private snackBar: MatSnackBar, private managementRulesSharedDataService: ManagementRulesSharedDataService, private archiveService: ArchiveService, - private loggerService: Logger + private loggerService: Logger, + private schemaService: SchemaService ) { super(route, globalEventService); + this.schemaService.getSchema(Collection.ARCHIVE_UNIT); } ngOnInit() { diff --git a/ui/ui-referential/src/main/java/fr/gouv/vitamui/referential/config/ReferentialContextConfiguration.java b/ui/ui-referential/src/main/java/fr/gouv/vitamui/referential/config/ReferentialContextConfiguration.java index 757a239d1bb..19ee5854051 100644 --- a/ui/ui-referential/src/main/java/fr/gouv/vitamui/referential/config/ReferentialContextConfiguration.java +++ b/ui/ui-referential/src/main/java/fr/gouv/vitamui/referential/config/ReferentialContextConfiguration.java @@ -63,6 +63,7 @@ import fr.gouv.vitamui.referential.external.client.ReferentialExternalWebClientFactory; import fr.gouv.vitamui.referential.external.client.RuleExternalRestClient; import fr.gouv.vitamui.referential.external.client.RuleExternalWebClient; +import fr.gouv.vitamui.referential.external.client.SchemaClient; import fr.gouv.vitamui.referential.external.client.SecurityProfileExternalRestClient; import fr.gouv.vitamui.referential.external.client.UnitExternalRestClient; import fr.gouv.vitamui.ui.commons.property.UIProperties; @@ -212,4 +213,8 @@ public OntologyExternalRestClient ontologyExternalRestClient(final ReferentialEx return referentialExternalRestClientFactory.getOntologyRestClient(); } + @Bean + public SchemaClient schemaClient(final ReferentialExternalRestClientFactory referentialExternalRestClientFactory) { + return referentialExternalRestClientFactory.getSchemaClient(); + } }