From ddb025f25f7938cc0f00d83db3377add640d316c Mon Sep 17 00:00:00 2001
From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr>
Date: Mon, 16 Jan 2023 15:59:58 +0100
Subject: [PATCH 1/4] Ajout de tags dans reference

+ filtre par tag dans referenceManagement
---
 .../fr/inra/oresing/model/Configuration.java  |   5 +-
 .../InternationalizationReferenceMap.java     |   1 +
 .../inra/oresing/rest/ApplicationResult.java  |   9 +-
 .../inra/oresing/rest/GetReferenceResult.java |   1 +
 .../fr/inra/oresing/rest/OreSiResources.java  |   2 +-
 .../inra/oresing/rest/OreSiResourcesTest.java |  18 ++
 .../data/monsore/monsore-with-repository.yaml |  50 ++++++
 src/test/resources/data/monsore/monsore.yaml  |  50 ++++++
 ui/src/components/common/CollapsibleTree.vue  |   3 +
 .../references/ReferencesDetailsPanel.vue     |   6 +-
 .../references/ReferencesManagementView.vue   | 154 ++++++++++++------
 11 files changed, 243 insertions(+), 56 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/model/Configuration.java b/src/main/java/fr/inra/oresing/model/Configuration.java
index 743b5bbd1..344474ca7 100644
--- a/src/main/java/fr/inra/oresing/model/Configuration.java
+++ b/src/main/java/fr/inra/oresing/model/Configuration.java
@@ -187,6 +187,8 @@ public class Configuration {
             return doGetStaticColumnDescriptions().keySet();
         }
 
+        public Map<String, Internationalization> tags;
+
         public Map<String, ReferenceColumnDescription> doGetAllColumnDescriptions() {
             Map<String, ReferenceColumnDescription> allColumnDescriptions = new LinkedHashMap<>();
             allColumnDescriptions.putAll(doGetStaticColumnDescriptions());
@@ -220,8 +222,9 @@ public class Configuration {
                 internationalizationReferenceMap.put(reference, internationalizationReference);
                 Map<String, Internationalization> internationalizedDynamicColumns =
                         Maps.transformValues(referenceDescription.getDynamicColumns(), ReferenceDynamicColumnDescription::getInternationalizationName);
-
                 internationalizationReference.setInternationalizedDynamicColumns(internationalizedDynamicColumns);
+                Map<String, Internationalization> internationalizedtags = referenceDescription.getTags();
+                internationalizationReference.setInternationalizedTags(internationalizedtags);
                 internationalizationReferenceMap.put(reference, internationalizationReference);
             }
             return internationalizationReferenceMap;
diff --git a/src/main/java/fr/inra/oresing/model/internationalization/InternationalizationReferenceMap.java b/src/main/java/fr/inra/oresing/model/internationalization/InternationalizationReferenceMap.java
index 51389ec35..72a2891e1 100644
--- a/src/main/java/fr/inra/oresing/model/internationalization/InternationalizationReferenceMap.java
+++ b/src/main/java/fr/inra/oresing/model/internationalization/InternationalizationReferenceMap.java
@@ -13,4 +13,5 @@ public class InternationalizationReferenceMap {
     Map<String, Internationalization> internationalizedDynamicColumns;
     InternationalizationDisplay internationalizationDisplay;
     Map<String, Internationalization> internationalizedValidations;
+    Map<String, Internationalization> internationalizedTags;
 }
\ No newline at end of file
diff --git a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java
index 5732bb5b6..fdf513451 100644
--- a/src/main/java/fr/inra/oresing/rest/ApplicationResult.java
+++ b/src/main/java/fr/inra/oresing/rest/ApplicationResult.java
@@ -2,12 +2,16 @@ package fr.inra.oresing.rest;
 
 import fr.inra.oresing.model.Configuration;
 import fr.inra.oresing.model.VariableComponentKey;
+import fr.inra.oresing.model.internationalization.Internationalization;
 import fr.inra.oresing.model.internationalization.InternationalizationMap;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.Value;
 
-import java.util.*;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
 
 @Value
 public class ApplicationResult {
@@ -28,6 +32,7 @@ public class ApplicationResult {
         Set<String> children;
         Map<String, Column> columns;
         Map<String, DynamicColumn> dynamicColumns;
+        Set<String> tags;
 
         @Value
         public static class Column {
@@ -62,6 +67,7 @@ public class ApplicationResult {
         Map<String, Variable> variables;
         Repository repository;
         boolean hasAuthorizations;
+
         @Value
         public static class Repository {
             String filePattern;
@@ -69,6 +75,7 @@ public class ApplicationResult {
             TokenDateDescription startDate;
             TokenDateDescription endDate;
         }
+
         @Value
         public static class TokenDateDescription {
             Integer token;
diff --git a/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java b/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java
index 2618763e7..c744894c0 100644
--- a/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java
+++ b/src/main/java/fr/inra/oresing/rest/GetReferenceResult.java
@@ -1,5 +1,6 @@
 package fr.inra.oresing.rest;
 
+import fr.inra.oresing.model.internationalization.Internationalization;
 import lombok.Value;
 
 import java.util.Map;
diff --git a/src/main/java/fr/inra/oresing/rest/OreSiResources.java b/src/main/java/fr/inra/oresing/rest/OreSiResources.java
index 02a95ddf3..a139f7288 100644
--- a/src/main/java/fr/inra/oresing/rest/OreSiResources.java
+++ b/src/main/java/fr/inra/oresing/rest/OreSiResources.java
@@ -147,7 +147,7 @@ public class OreSiResources {
                                     dynamicColumnDescription.getReferenceColumnToLookForHeader(),
                                     dynamicColumnDescription.getPresenceConstraint().isMandatory()));
                     Set<String> children = childrenPerReferences.get(reference);
-                    return new ApplicationResult.Reference(reference, reference, children, columns, dynamicColumns);
+                    return new ApplicationResult.Reference(reference, reference, children, columns, dynamicColumns, referenceDescription.getTags().keySet());
                 }):Map.of();
         Map<String, ApplicationResult.DataType> dataTypes = withDatatypes?Maps.transformEntries(application.getConfiguration().getDataTypes(), (dataType, dataTypeDescription) -> {
             Map<String, ApplicationResult.DataType.Variable> variables = Maps.transformEntries(dataTypeDescription.getData(), (variable, variableDescription) -> {
diff --git a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
index ae220c7d5..7afa3b1b1 100644
--- a/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
+++ b/src/test/java/fr/inra/oresing/rest/OreSiResourcesTest.java
@@ -592,6 +592,24 @@ public class OreSiResourcesTest {
                     .andReturn().getResponse().getContentAsString();
 
             JsonPath.parse(response).read("$.id");
+            mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/applications/monsore", "ALL,REFERENCETYPE")
+                    .cookie(authCookie)
+                    .param("filter","ALL"))
+                    .andExpect(status().is2xxSuccessful())
+                    ///vérification de la sauvegarde des tags
+                    .andExpect(jsonPath("$.references.type_de_sites.tags", Matchers.hasItem("context")))
+                    .andExpect(jsonPath("$.references.sites.tags", Matchers.hasItem("context")))
+                    .andExpect(jsonPath("$.references.projet.tags", Matchers.hasItem("context")))
+                    .andExpect(jsonPath("$.references.types_de_donnees_par_themes_de_sites_et_projet.tags", Matchers.hasItem("context")))
+                    .andExpect(jsonPath("$.references.especes.tags", Matchers.hasItem("context")))
+                    .andExpect(jsonPath("$.references.especes.tags", Matchers.hasItem("data")))
+                    .andExpect(jsonPath("$.references['type de fichiers'].tags", Matchers.hasItem("context")))
+                    .andExpect(jsonPath("$.references['type de fichiers'].tags", Matchers.hasItem("data")))
+                    .andExpect(jsonPath("$.references.variables.tags", Matchers.hasItem("data")))
+                    .andExpect(jsonPath("$.references.unites.tags", Matchers.hasItem("data")))
+                    .andExpect(jsonPath("$.references.valeurs_qualitatives.tags", Matchers.hasItem("data")))
+                    .andExpect(jsonPath("$.references.variables_et_unites_par_types_de_donnees.tags", Matchers.hasItem("data")))
+                    .andExpect(jsonPath("$.internationalization.references.sites.internationalizedTags.context.fr", Is.is("contexte")));
         }
 
         String response = null;
diff --git a/src/test/resources/data/monsore/monsore-with-repository.yaml b/src/test/resources/data/monsore/monsore-with-repository.yaml
index 77a8d94de..2648a2405 100644
--- a/src/test/resources/data/monsore/monsore-with-repository.yaml
+++ b/src/test/resources/data/monsore/monsore-with-repository.yaml
@@ -18,6 +18,13 @@ compositeReferences:
       - reference: projet
 references:
   especes:
+    tags:
+      context:
+        fr: contexte
+        en: context
+      data:
+        fr: données
+        en: data
     internationalizationName:
       fr: Espèces
       en: Species
@@ -37,6 +44,10 @@ references:
       esp_definition_en: null
       colonne_homonyme_entre_referentiels: null
   projet:
+    tags:
+      context:
+        fr: contexte
+        en: context
     internationalizationName:
       fr: Projet
       en: Project
@@ -61,6 +72,10 @@ references:
       definition_en: null
       colonne_homonyme_entre_referentiels: null
   sites:
+    tags:
+      context:
+        fr: contexte
+        en: context
     validations:
       typeSitesRef:
         internationalizationName:
@@ -105,6 +120,10 @@ references:
       zet_description_en: null
       zet_chemin_parent: null
   themes:
+    tags:
+      context:
+        fr: contexte
+        en: context
     keyColumns:
       - nom_key
     internationalizationName:
@@ -128,6 +147,13 @@ references:
       description_fr: null
       description_en: null
   type de fichiers:
+    tags:
+      context:
+        fr: contexte
+        en: context
+      data:
+        fr: données
+        en: data
     keyColumns:
       - nom_key
     internationalizationName:
@@ -151,6 +177,10 @@ references:
       description_fr: null
       description_en: null
   type_de_sites:
+    tags:
+      context:
+        fr: contexte
+        en: context
     keyColumns:
       - tze_nom_key
     internationalizationName:
@@ -174,6 +204,10 @@ references:
       tze_definition_fr: null
       tze_definition_en: null
   types_de_donnees_par_themes_de_sites_et_projet:
+    tags:
+      context:
+        fr: contexte
+        en: context
     internationalizationName:
       fr: Types de données par site et projet
       en: Data types by site and project
@@ -234,6 +268,10 @@ references:
       nom du thème: null
       nom du type de données: null
   unites:
+    tags:
+      data:
+        fr: données
+        en: data
     keyColumns:
       - nom_key
     internationalizationName:
@@ -258,6 +296,10 @@ references:
       nom_fr: null
       nom_en: null
   valeurs_qualitatives:
+    tags:
+      data:
+        fr: données
+        en: data
     keyColumns:
       - nom_key
       - valeur_key
@@ -283,6 +325,10 @@ references:
       valeur_fr: null
       valeur_en: null
   variables:
+    tags:
+      data:
+        fr: données
+        en: data
     keyColumns:
       - nom_key
     internationalizationName:
@@ -307,6 +353,10 @@ references:
       definition_en: null
       isQualitative: null
   variables_et_unites_par_types_de_donnees:
+    tags:
+      data:
+        fr: données
+        en: data
     validations:
       variableRef:
         internationalizationName:
diff --git a/src/test/resources/data/monsore/monsore.yaml b/src/test/resources/data/monsore/monsore.yaml
index d8f9bb7c1..32c40d8e6 100644
--- a/src/test/resources/data/monsore/monsore.yaml
+++ b/src/test/resources/data/monsore/monsore.yaml
@@ -18,6 +18,13 @@ compositeReferences:
       - reference: projet
 references:
   especes:
+    tags:
+      context:
+        fr: contexte
+        en: context
+      data:
+        fr: données
+        en: data
     internationalizationName:
       fr: Espèces
       en: Species
@@ -37,6 +44,10 @@ references:
       esp_definition_en: null
       colonne_homonyme_entre_referentiels: null
   projet:
+    tags:
+      context:
+        fr: contexte
+        en: context
     internationalizationName:
       fr: Projet
       en: Project
@@ -61,6 +72,10 @@ references:
       definition_en: null
       colonne_homonyme_entre_referentiels: null
   sites:
+    tags:
+      context:
+        fr: contexte
+        en: context
     validations:
       typeSitesRef:
         internationalizationName:
@@ -105,6 +120,10 @@ references:
       zet_description_en: null
       zet_chemin_parent: null
   themes:
+    tags:
+      context:
+        fr: contexte
+        en: context
     keyColumns:
       - nom_key
     internationalizationName:
@@ -128,6 +147,13 @@ references:
       description_fr: null
       description_en: null
   type de fichiers:
+    tags:
+      context:
+        fr: contexte
+        en: context
+      data:
+        fr: données
+        en: data
     keyColumns:
       - nom_key
     internationalizationName:
@@ -151,6 +177,10 @@ references:
       description_fr: null
       description_en: null
   type_de_sites:
+    tags:
+      context:
+        fr: contexte
+        en: context
     keyColumns:
       - tze_nom_key
     internationalizationName:
@@ -174,6 +204,10 @@ references:
       tze_definition_fr: null
       tze_definition_en: null
   types_de_donnees_par_themes_de_sites_et_projet:
+    tags:
+      context:
+        fr: contexte
+        en: context
     internationalizationName:
       fr: Types de données par site et projet
       en: Data types by site and project
@@ -234,6 +268,10 @@ references:
       nom du thème: null
       nom du type de données: null
   unites:
+    tags:
+      data:
+        fr: données
+        en: data
     keyColumns:
       - nom_key
     internationalizationName:
@@ -258,6 +296,10 @@ references:
       nom_fr: null
       nom_en: null
   valeurs_qualitatives:
+    tags:
+      data:
+        fr: données
+        en: data
     keyColumns:
       - nom_key
       - valeur_key
@@ -283,6 +325,10 @@ references:
       valeur_fr: null
       valeur_en: null
   variables:
+    tags:
+      data:
+        fr: données
+        en: data
     keyColumns:
       - nom_key
     internationalizationName:
@@ -307,6 +353,10 @@ references:
       definition_en: null
       isQualitative: null
   variables_et_unites_par_types_de_donnees:
+    tags:
+      data:
+        fr: données
+        en: data
     validations:
       variableRef:
         internationalizationName:
diff --git a/ui/src/components/common/CollapsibleTree.vue b/ui/src/components/common/CollapsibleTree.vue
index 83c093024..e31563581 100644
--- a/ui/src/components/common/CollapsibleTree.vue
+++ b/ui/src/components/common/CollapsibleTree.vue
@@ -95,6 +95,9 @@
             {{ $t("validation.data-empty") }}
           </span>
         </div>
+        <b-tag v-for="tag in option.localtags" :key="tag" class="is-primary is-light">
+          {{tag}}
+        </b-tag>
       </div>
       <div class="CollapsibleTree-buttons column is-2">
         <div class="file button is-small is-info" v-if="onUploadCb">
diff --git a/ui/src/components/references/ReferencesDetailsPanel.vue b/ui/src/components/references/ReferencesDetailsPanel.vue
index 6bf69db84..255ea1f87 100644
--- a/ui/src/components/references/ReferencesDetailsPanel.vue
+++ b/ui/src/components/references/ReferencesDetailsPanel.vue
@@ -5,6 +5,9 @@
     :title="reference && (reference.refNameLocal || reference.label)"
     :close-cb="closeCb"
   >
+    <b-tag v-for="tag in reference.tags" :key="tag" class="is-primary is-light">
+      {{tags[tag].localName}}
+    </b-tag>
     <div class="Panel-buttons">
       <b-button type="is-danger" icon-left="trash-alt" @click="askDeletionConfirmation">{{
         $t("referencesManagement.delete")
@@ -26,6 +29,7 @@ export default class ReferencesDetailsPanel extends Vue {
   @Prop({ default: false }) open;
   @Prop() reference;
   @Prop() closeCb;
+  @Prop() tags;
 
   alertService = AlertService.INSTANCE;
 
@@ -54,4 +58,4 @@ export default class ReferencesDetailsPanel extends Vue {
     margin-bottom: 0.5rem;
   }
 }
-</style>
+</style>
\ No newline at end of file
diff --git a/ui/src/views/references/ReferencesManagementView.vue b/ui/src/views/references/ReferencesManagementView.vue
index bb3ad8f45..bb259abaa 100644
--- a/ui/src/views/references/ReferencesManagementView.vue
+++ b/ui/src/views/references/ReferencesManagementView.vue
@@ -1,71 +1,81 @@
 <template>
   <PageView class="with-submenu">
     <SubMenu
-      :root="application.localName"
-      :paths="subMenuPaths"
-      role="navigation"
-      :aria-label="$t('menu.aria-sub-menu')"
+        :aria-label="$t('menu.aria-sub-menu')"
+        :paths="subMenuPaths"
+        :root="application.localName"
+        role="navigation"
     />
     <h1 class="title main-title">
-      {{ $t("titles.references-page", { applicationName: application.localName }) }}
+      {{ $t("titles.references-page", {applicationName: application.localName}) }}
     </h1>
     <div v-if="errorsMessages.length" style="margin: 10px">
       <div v-for="msg in errorsMessages" :key="msg">
         <b-message
-          :title="$t('message.data-type-config-error')"
-          type="is-danger"
-          has-icon
-          :aria-close-label="$t('message.close')"
-          class="mt-4"
+            :aria-close-label="$t('message.close')"
+            :title="$t('message.data-type-config-error')"
+            class="mt-4"
+            has-icon
+            type="is-danger"
         >
-          <span v-html="msg" />
+          <span v-html="msg"/>
         </b-message>
       </div>
     </div>
-    <div>
+    <b-field class="section">
+      <b-taglist>
+        <b-tag v-for="(tag, index) in tags" :key="index" :icon="tag.selected?'times':'check'"
+               :type="tag.selected?'is-primary':'is-warning'"
+               rounded @click="toggle(index)">
+          {{ tag.localName }}
+        </b-tag>
+      </b-taglist>
+    </b-field>
+    <div class="section">
       <CollapsibleTree
-        class="liste"
-        v-for="(ref, i) in references"
-        :key="ref.id"
-        :option="ref"
-        :level="0"
-        :id="i + 1"
-        :on-click-label-cb="(event, label) => openRefDetails(event, label)"
-        :on-upload-cb="(label, refFile) => uploadReferenceCsv(label, refFile)"
-        :buttons="buttons"
-        :application-title="$t('titles.references-page')"
-        :line-count="lineCount(ref)"
+          v-for="(ref, i) in referencesToBeShown"
+          :id="i + 1"
+          :key="ref.id"
+          :application-title="$t('titles.references-page')"
+          :buttons="buttons"
+          :level="0"
+          :line-count="lineCount(ref)"
+          :on-click-label-cb="(event, label) => openRefDetails(event, label)"
+          :on-upload-cb="(label, refFile) => uploadReferenceCsv(label, refFile)"
+          :option="ref"
+          class="liste"
       >
       </CollapsibleTree>
       <ReferencesDetailsPanel
-        :left-align="false"
-        :open="openPanel"
-        :reference="chosenRef"
-        :close-cb="(newVal) => (openPanel = newVal)"
+          :close-cb="(newVal) => (openPanel = newVal)"
+          :left-align="false"
+          :open="openPanel"
+          :reference="chosenRef"
+          :tags="tags"
       />
     </div>
   </PageView>
 </template>
 
 <script>
-import { Component, Prop, Vue } from "vue-property-decorator";
-import { convertReferencesToTrees } from "@/utils/ConversionUtils";
+import {Component, Prop, Vue} from "vue-property-decorator";
+import {convertReferencesToTrees} from "@/utils/ConversionUtils";
 import CollapsibleTree from "@/components/common/CollapsibleTree.vue";
 import ReferencesDetailsPanel from "@/components/references/ReferencesDetailsPanel.vue";
-import { ApplicationService } from "@/services/rest/ApplicationService";
-import { InternationalisationService } from "@/services/InternationalisationService";
-import { ReferenceService } from "@/services/rest/ReferenceService";
+import {ApplicationService} from "@/services/rest/ApplicationService";
+import {InternationalisationService} from "@/services/InternationalisationService";
+import {ReferenceService} from "@/services/rest/ReferenceService";
 
 import PageView from "../common/PageView.vue";
-import { ApplicationResult } from "@/model/ApplicationResult";
-import SubMenu, { SubMenuPath } from "@/components/common/SubMenu.vue";
-import { AlertService } from "@/services/AlertService";
-import { Button } from "@/model/Button";
-import { HttpStatusCodes } from "@/utils/HttpUtils";
-import { ErrorsService } from "@/services/ErrorsService";
+import {ApplicationResult} from "@/model/ApplicationResult";
+import SubMenu, {SubMenuPath} from "@/components/common/SubMenu.vue";
+import {AlertService} from "@/services/AlertService";
+import {Button} from "@/model/Button";
+import {HttpStatusCodes} from "@/utils/HttpUtils";
+import {ErrorsService} from "@/services/ErrorsService";
 
 @Component({
-  components: { CollapsibleTree, ReferencesDetailsPanel, PageView, SubMenu },
+  components: {CollapsibleTree, ReferencesDetailsPanel, PageView, SubMenu},
 })
 export default class ReferencesManagementView extends Vue {
   @Prop() applicationName;
@@ -86,40 +96,79 @@ export default class ReferencesManagementView extends Vue {
   errorsList = [];
   buttons = [
     new Button(
-      this.$t("referencesManagement.consult"),
-      "eye",
-      (label) => this.consultReference(label),
-      "is-dark"
+        this.$t("referencesManagement.consult"),
+        "eye",
+        (label) => this.consultReference(label),
+        "is-dark"
     ),
     new Button(this.$t("referencesManagement.download"), "download", (label) =>
-      this.downloadReference(label)
+        this.downloadReference(label)
     ),
   ];
 
+  get tags() {
+    let tags = {}
+    for (const reference of this.references) {
+      let currentTags = reference.tags;
+      if (!currentTags) {
+        continue;
+      }
+      for (const tagName of currentTags) {
+        if (tags[tagName]) {
+          continue;
+        }
+        tags[tagName] = {};
+        tags[tagName].selected = true;
+        let locale = this.internationalisationService
+            .getLocaleforPath(this.application, 'references.' + reference.id + '.internationalizedTags.' + tagName, tagName)
+        tags[tagName].localName = locale;
+      }
+      reference.localtags = reference.tags.map(tag=>tags[tag]?.localName || tag)
+    }
+    return tags;
+  }
+
+  get referencesToBeShown() {
+    let selectedTags = Object.keys(this.tags).filter(t => this.tags[t].selected)
+    if (!Object.keys(this.tags).length) {
+      return this.references
+    }
+    return this.references
+        .filter(reference => {
+          return reference.tags.some(t => {
+            return selectedTags.includes(t)
+          })
+        });
+  }
+
   created() {
     this.subMenuPaths = [
       new SubMenuPath(
-        this.$t("referencesManagement.references").toLowerCase(),
-        () => this.$router.push(`/applications/${this.applicationName}/references`),
-        () => this.$router.push(`/applications`)
+          this.$t("referencesManagement.references").toLowerCase(),
+          () => this.$router.push(`/applications/${this.applicationName}/references`),
+          () => this.$router.push(`/applications`)
       ),
     ];
     this.init();
   }
 
+  toggle(tag) {
+    this.tags[tag] = !this.tags[tag]
+  }
+
   async init() {
     try {
-      this.application = await this.applicationService.getApplication(this.applicationName,['CONFIGURATION','REFERENCETYPE']);
+      this.application = await this.applicationService.getApplication(this.applicationName, ['CONFIGURATION', 'REFERENCETYPE']);
       this.application = {
         ...this.application,
         localName: this.internationalisationService.mergeInternationalization(this.application)
-          .localName,
+            .localName,
       };
       if (!this.application?.id) {
         return;
       }
       this.references = convertReferencesToTrees(
-        Object.values(this.internationalisationService.treeReferenceName(this.application))
+          Object.values(this.internationalisationService.treeReferenceName(this.application))
       );
     } catch (error) {
       this.alertService.toastServerError();
@@ -153,8 +202,8 @@ export default class ReferencesManagementView extends Vue {
           } else {
             for (let j = 0; j < ref.children[n].children.length; j++) {
               if (
-                this.application.referenceSynthesis[i].referenceType ===
-                ref.children[n].children[j].label
+                  this.application.referenceSynthesis[i].referenceType ===
+                  ref.children[n].children[j].label
               ) {
                 ref.children[n].children[j] = {
                   ...ref.children[n].children[j],
@@ -214,6 +263,7 @@ export default class ReferencesManagementView extends Vue {
     var ref = Object.values(this.application.references).find((ref) => ref.label === label);
     return ref;
   }
+
 }
 </script>
 <style lang="scss" scoped>
-- 
GitLab


From 4867d67508492bf54a526ef0434290d521547b57 Mon Sep 17 00:00:00 2001
From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr>
Date: Tue, 17 Jan 2023 09:19:00 +0100
Subject: [PATCH 2/4] Coorection lorsqu'il n'y a pas de tags

---
 .../fr/inra/oresing/model/Configuration.java  |  2 +-
 .../fr/inra/oresing/rest/OreSiResources.java  | 25 ++++++++++---------
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/src/main/java/fr/inra/oresing/model/Configuration.java b/src/main/java/fr/inra/oresing/model/Configuration.java
index 344474ca7..e222b0ea0 100644
--- a/src/main/java/fr/inra/oresing/model/Configuration.java
+++ b/src/main/java/fr/inra/oresing/model/Configuration.java
@@ -187,7 +187,7 @@ public class Configuration {
             return doGetStaticColumnDescriptions().keySet();
         }
 
-        public Map<String, Internationalization> tags;
+        public Map<String, Internationalization> tags = new HashMap<>();
 
         public Map<String, ReferenceColumnDescription> doGetAllColumnDescriptions() {
             Map<String, ReferenceColumnDescription> allColumnDescriptions = new LinkedHashMap<>();
diff --git a/src/main/java/fr/inra/oresing/rest/OreSiResources.java b/src/main/java/fr/inra/oresing/rest/OreSiResources.java
index a139f7288..21ce70f12 100644
--- a/src/main/java/fr/inra/oresing/rest/OreSiResources.java
+++ b/src/main/java/fr/inra/oresing/rest/OreSiResources.java
@@ -84,7 +84,7 @@ public class OreSiResources {
     @GetMapping(value = "/applications", produces = MediaType.APPLICATION_JSON_VALUE)
     public List<Application> getApplications(@RequestParam(required = false, defaultValue = "") String[] filter) {
         List<ApplicationInformation> filters = Arrays.stream(filter)
-                .map(s ->ApplicationInformation.valueOf(s))
+                .map(s -> ApplicationInformation.valueOf(s))
                 .collect(Collectors.toList());
         return service.getApplications(filters);
     }
@@ -107,18 +107,18 @@ public class OreSiResources {
     }
 
     @GetMapping(value = "/applications/{nameOrId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<ApplicationResult> getApplication(@PathVariable("nameOrId") String nameOrId,@RequestParam(required = false, defaultValue = "") String[] filter) {
+    public ResponseEntity<ApplicationResult> getApplication(@PathVariable("nameOrId") String nameOrId, @RequestParam(required = false, defaultValue = "") String[] filter) {
         Application application = service.getApplication(nameOrId);
         List<ApplicationInformation> filters = Arrays.stream(filter)
-                .map(s ->ApplicationInformation.valueOf(s))
+                .map(s -> ApplicationInformation.valueOf(s))
                 .collect(Collectors.toList());
         boolean withSynthesis = filters.contains(ApplicationInformation.ALL) || filters.contains(ApplicationInformation.SYNTHESIS);
         boolean withDatatypes = filters.contains(ApplicationInformation.ALL) || filters.contains(ApplicationInformation.DATATYPE);
         boolean withReferenceType = filters.contains(ApplicationInformation.ALL) || filters.contains(ApplicationInformation.REFERENCETYPE);
         boolean withConfiguration = filters.contains(ApplicationInformation.ALL) || filters.contains(ApplicationInformation.CONFIGURATION);
-        final List<ApplicationResult.ReferenceSynthesis> referenceSynthesis = withSynthesis?service.getReferenceSynthesis(application):List.of();
+        final List<ApplicationResult.ReferenceSynthesis> referenceSynthesis = withSynthesis ? service.getReferenceSynthesis(application) : List.of();
         TreeMultimap<String, String> childrenPerReferences = TreeMultimap.create();
-        if(withReferenceType){
+        if (withReferenceType) {
             application.getConfiguration().getCompositeReferences().values().forEach(compositeReferenceDescription -> {
                 ImmutableList<String> referenceTypes = compositeReferenceDescription.getComponents().stream()
                         .map(Configuration.CompositeReferenceComponentDescription::getReference)
@@ -134,7 +134,7 @@ public class OreSiResources {
                 });
             });
         }
-        Map<String, ApplicationResult.Reference> references = withReferenceType?Maps.transformEntries(
+        Map<String, ApplicationResult.Reference> references = withReferenceType ? Maps.transformEntries(
                 application.getConfiguration().getReferences(),
                 (reference, referenceDescription) -> {
                     Map<String, ApplicationResult.Reference.Column> columns = Maps.transformEntries(referenceDescription.doGetStaticColumnDescriptions(), (column, columnDescription) -> new ApplicationResult.Reference.Column(column, column, referenceDescription.getKeyColumns().contains(column), null));
@@ -147,9 +147,10 @@ public class OreSiResources {
                                     dynamicColumnDescription.getReferenceColumnToLookForHeader(),
                                     dynamicColumnDescription.getPresenceConstraint().isMandatory()));
                     Set<String> children = childrenPerReferences.get(reference);
-                    return new ApplicationResult.Reference(reference, reference, children, columns, dynamicColumns, referenceDescription.getTags().keySet());
-                }):Map.of();
-        Map<String, ApplicationResult.DataType> dataTypes = withDatatypes?Maps.transformEntries(application.getConfiguration().getDataTypes(), (dataType, dataTypeDescription) -> {
+                    final Set<String> tags = Optional.ofNullable(referenceDescription.getTags()).map(Map::keySet).orElse(Set.of());
+                    return new ApplicationResult.Reference(reference, reference, children, columns, dynamicColumns, tags);
+                }) : Map.of();
+        Map<String, ApplicationResult.DataType> dataTypes = withDatatypes ? Maps.transformEntries(application.getConfiguration().getDataTypes(), (dataType, dataTypeDescription) -> {
             Map<String, ApplicationResult.DataType.Variable> variables = Maps.transformEntries(dataTypeDescription.getData(), (variable, variableDescription) -> {
                 Map<String, ApplicationResult.DataType.Variable.Component> components = Maps.transformEntries(variableDescription.doGetAllComponentDescriptions(), (component, componentDescription) -> {
                     return new ApplicationResult.DataType.Variable.Component(component, component);
@@ -178,8 +179,8 @@ public class OreSiResources {
                     })
                     .orElse(null);
             return new ApplicationResult.DataType(dataType, dataType, variables, repositoryResult, hasAuthorizations);
-        }):Map.of();
-        Configuration configuration = withConfiguration? application.getConfiguration() : null;
+        }) : Map.of();
+        Configuration configuration = withConfiguration ? application.getConfiguration() : null;
         ApplicationResult applicationResult = new ApplicationResult(application.getId().toString(), application.getName(), application.getConfiguration().getApplication().getName(), application.getComment(), application.getConfiguration().getInternationalization(), references, dataTypes, referenceSynthesis, configuration);
         return ResponseEntity.ok(applicationResult);
     }
@@ -334,7 +335,7 @@ public class OreSiResources {
             for (Map.Entry<String, LineChecker> referenceCheckersByVariableComponentKey : referenceLineCheckers.entrySet()) {
                 String variableComponentKey = referenceCheckersByVariableComponentKey.getKey();
                 ReferenceLineChecker referenceLineChecker = (ReferenceLineChecker) referenceCheckersByVariableComponentKey.getValue();
-                if(referenceLineCheckers.get(variableComponentKey) instanceof ReferenceLineCheckerDisplay){
+                if (referenceLineCheckers.get(variableComponentKey) instanceof ReferenceLineCheckerDisplay) {
                     continue;
                 }
                 referenceLineChecker.getReferenceValues().entrySet().stream()
-- 
GitLab


From 462234dcc7766cc3cb975977588d2aac48a11a37 Mon Sep 17 00:00:00 2001
From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr>
Date: Tue, 17 Jan 2023 14:23:09 +0100
Subject: [PATCH 3/4] =?UTF-8?q?Correction=20mais=20je=20ne=20sais=20pas=20?=
 =?UTF-8?q?pourquoi=20(code=20chang=C3=A9=3F)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../references/ReferencesDetailsPanel.vue     | 45 ++++++++++---------
 .../references/ReferencesManagementView.vue   | 42 ++++++++++-------
 2 files changed, 50 insertions(+), 37 deletions(-)

diff --git a/ui/src/components/references/ReferencesDetailsPanel.vue b/ui/src/components/references/ReferencesDetailsPanel.vue
index 255ea1f87..0538ef971 100644
--- a/ui/src/components/references/ReferencesDetailsPanel.vue
+++ b/ui/src/components/references/ReferencesDetailsPanel.vue
@@ -1,32 +1,37 @@
 <template>
   <SidePanel
-    :open="open"
-    :left-align="leftAlign"
-    :title="reference && (reference.refNameLocal || reference.label)"
-    :close-cb="closeCb"
+      :close-cb="closeCb"
+      :left-align="leftAlign"
+      :open="open"
+      :title="reference && (reference.refNameLocal || reference.label)"
   >
-    <b-tag v-for="tag in reference.tags" :key="tag" class="is-primary is-light">
-      {{tags[tag].localName}}
-    </b-tag>
+    <div v-if="tags">Etiquettes :
+      <b-tag v-for="(tag, index) in tags" :key="index" class="is-primary is-light">
+        <span v-if="tag">
+         {{ tag.localName }}
+        </span>
+      </b-tag>
+    </div>
     <div class="Panel-buttons">
-      <b-button type="is-danger" icon-left="trash-alt" @click="askDeletionConfirmation">{{
-        $t("referencesManagement.delete")
-      }}</b-button>
+      <b-button icon-left="trash-alt" type="is-danger" @click="askDeletionConfirmation">{{
+          $t("referencesManagement.delete")
+        }}
+      </b-button>
     </div>
   </SidePanel>
 </template>
 
 <script>
-import { AlertService } from "@/services/AlertService";
-import { Component, Prop, Vue } from "vue-property-decorator";
+import {AlertService} from "@/services/AlertService";
+import {Component, Prop, Vue} from "vue-property-decorator";
 import SidePanel from "../common/SidePanel.vue";
 
 @Component({
-  components: { SidePanel },
+  components: {SidePanel},
 })
 export default class ReferencesDetailsPanel extends Vue {
-  @Prop({ default: false }) leftAlign;
-  @Prop({ default: false }) open;
+  @Prop({default: false}) leftAlign;
+  @Prop({default: false}) open;
   @Prop() reference;
   @Prop() closeCb;
   @Prop() tags;
@@ -35,11 +40,11 @@ export default class ReferencesDetailsPanel extends Vue {
 
   askDeletionConfirmation() {
     this.alertService.dialog(
-      this.$t("alert.warning"),
-      this.$t("alert.reference-deletion-msg", { label: this.reference.label }),
-      this.$t("alert.delete"),
-      "is-danger",
-      () => this.deleteReference()
+        this.$t("alert.warning"),
+        this.$t("alert.reference-deletion-msg", {label: this.reference.label}),
+        this.$t("alert.delete"),
+        "is-danger",
+        () => this.deleteReference()
     );
   }
 
diff --git a/ui/src/views/references/ReferencesManagementView.vue b/ui/src/views/references/ReferencesManagementView.vue
index bb259abaa..24975e8fe 100644
--- a/ui/src/views/references/ReferencesManagementView.vue
+++ b/ui/src/views/references/ReferencesManagementView.vue
@@ -23,6 +23,7 @@
       </div>
     </div>
     <b-field class="section">
+      Etiquettes :
       <b-taglist>
         <b-tag v-for="(tag, index) in tags" :key="index" :icon="tag.selected?'times':'check'"
                :type="tag.selected?'is-primary':'is-warning'"
@@ -105,8 +106,25 @@ export default class ReferencesManagementView extends Vue {
         this.downloadReference(label)
     ),
   ];
+  tags={};
 
-  get tags() {
+  get referencesToBeShown() {
+    if (!this.tags) {
+      return this.references
+    }
+    let selectedTags = Object.keys(this.tags).filter(t => this.tags[t].selected)
+    if (!Object.keys(this.tags).length) {
+      return this.references
+    }
+    return this.references
+        .filter(reference => {
+          return reference.tags.some(t => {
+            return selectedTags.includes(t)
+          })
+        });
+  }
+
+  buildTags() {
     let tags = {}
     for (const reference of this.references) {
       let currentTags = reference.tags;
@@ -123,22 +141,9 @@ export default class ReferencesManagementView extends Vue {
             .getLocaleforPath(this.application, 'references.' + reference.id + '.internationalizedTags.' + tagName, tagName)
         tags[tagName].localName = locale;
       }
-      reference.localtags = reference.tags.map(tag=>tags[tag]?.localName || tag)
-    }
-    return tags;
-  }
-
-  get referencesToBeShown() {
-    let selectedTags = Object.keys(this.tags).filter(t => this.tags[t].selected)
-    if (!Object.keys(this.tags).length) {
-      return this.references
+      reference.localtags = reference.tags.map(tag => tags[tag]?.localName || tag)
     }
-    return this.references
-        .filter(reference => {
-          return reference.tags.some(t => {
-            return selectedTags.includes(t)
-          })
-        });
+    this.tags= tags;
   }
 
   created() {
@@ -153,7 +158,9 @@ export default class ReferencesManagementView extends Vue {
   }
 
   toggle(tag) {
-    this.tags[tag] = !this.tags[tag]
+    let tags = this.tags
+    tags[tag].selected = !tags[tag].selected
+    this.tags = tags
   }
 
   async init() {
@@ -170,6 +177,7 @@ export default class ReferencesManagementView extends Vue {
       this.references = convertReferencesToTrees(
           Object.values(this.internationalisationService.treeReferenceName(this.application))
       );
+      this.buildTags();
     } catch (error) {
       this.alertService.toastServerError();
     }
-- 
GitLab


From 0f42eb4f455efd995918f49fa5578b1d1b212fdd Mon Sep 17 00:00:00 2001
From: TCHERNIATINSKY <philippe.tcherniatinsky@inrae.fr>
Date: Tue, 17 Jan 2023 14:40:36 +0100
Subject: [PATCH 4/4] openOnFocus manquant

---
 .../views/authorizations/DataTypeAuthorizationInfoView.vue   | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/ui/src/views/authorizations/DataTypeAuthorizationInfoView.vue b/ui/src/views/authorizations/DataTypeAuthorizationInfoView.vue
index 72965cfc2..ebec42784 100644
--- a/ui/src/views/authorizations/DataTypeAuthorizationInfoView.vue
+++ b/ui/src/views/authorizations/DataTypeAuthorizationInfoView.vue
@@ -179,6 +179,9 @@ export default class DataTypeAuthorizationInfoView extends Vue {
   isApplicationAdmin = false;
   isLoading;
 
+  openOnFocus=true
+
+
   periods = {
     FROM_DATE: this.$t("dataTypeAuthorizations.from-date"),
     TO_DATE: this.$t("dataTypeAuthorizations.to-date"),
@@ -738,4 +741,4 @@ ul li.card-content {
 a {
   color: $dark;
 }
-</style>
+</style>
\ No newline at end of file
-- 
GitLab