From 50214ebd345c681ef05f8ab9d60c071b704fb5d5 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Mon, 30 Sep 2024 17:25:21 +0200
Subject: [PATCH 01/11] [ResourceFlyout] added tabs for JSON and Markdown
 content

---
 src/pages/results/ResourceFlyout.js           | 42 ------------
 .../results/ResourceFlyout/DataSheetJSON.js   | 23 +++++++
 .../ResourceFlyout/DataSheetMarkdown.js       | 15 +++++
 .../results/ResourceFlyout/ResourceFlyout.js  | 65 +++++++++++++++++++
 src/pages/results/Results.js                  |  2 +-
 5 files changed, 104 insertions(+), 43 deletions(-)
 delete mode 100644 src/pages/results/ResourceFlyout.js
 create mode 100644 src/pages/results/ResourceFlyout/DataSheetJSON.js
 create mode 100644 src/pages/results/ResourceFlyout/DataSheetMarkdown.js
 create mode 100644 src/pages/results/ResourceFlyout/ResourceFlyout.js

diff --git a/src/pages/results/ResourceFlyout.js b/src/pages/results/ResourceFlyout.js
deleted file mode 100644
index 0ef21f3..0000000
--- a/src/pages/results/ResourceFlyout.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import { EuiFlyout, EuiFlyoutBody, EuiText } from '@elastic/eui';
-import { useTranslation } from 'react-i18next';
-import ReactJson from '@microlink/react-json-view';
-
-const ResourceFlyout = ({
-  resourceFlyoutData,
-  setResourceFlyoutData,
-  isResourceFlyoutOpen,
-  setIsResourceFlyoutOpen,
-}) => {
-  const { t } = useTranslation('results');
-
-  const closeResourceFlyout = () => {
-    setResourceFlyoutData({});
-    setIsResourceFlyoutOpen(false);
-  };
-
-  return (
-    isResourceFlyoutOpen && (
-      <EuiFlyout
-        onClose={() => closeResourceFlyout()}
-        aria-labelledby={t('results:flyout.label')}
-      >
-        <EuiFlyoutBody>
-          <EuiText size="s">
-            <ReactJson
-              src={resourceFlyoutData}
-              name={t('results:flyout.JSON.title')}
-              iconStyle={'triangle'}
-              displayDataTypes={false}
-              enableClipboard={false}
-              collapsed={true}
-            />
-          </EuiText>
-        </EuiFlyoutBody>
-      </EuiFlyout>
-    )
-  );
-};
-
-export default ResourceFlyout;
diff --git a/src/pages/results/ResourceFlyout/DataSheetJSON.js b/src/pages/results/ResourceFlyout/DataSheetJSON.js
new file mode 100644
index 0000000..235482f
--- /dev/null
+++ b/src/pages/results/ResourceFlyout/DataSheetJSON.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import { EuiText } from '@elastic/eui';
+import { useTranslation } from 'react-i18next';
+import ReactJson from '@microlink/react-json-view';
+
+const DataSheetJSON = ({ resourceData }) => {
+  const { t } = useTranslation('results');
+
+  return (
+    <EuiText size="s">
+      <ReactJson
+        src={resourceData}
+        name={t('results:flyout.JSON.title')}
+        iconStyle={'triangle'}
+        displayDataTypes={false}
+        enableClipboard={false}
+        collapsed={true}
+      />
+    </EuiText>
+  );
+};
+
+export default DataSheetJSON;
diff --git a/src/pages/results/ResourceFlyout/DataSheetMarkdown.js b/src/pages/results/ResourceFlyout/DataSheetMarkdown.js
new file mode 100644
index 0000000..9d76cb9
--- /dev/null
+++ b/src/pages/results/ResourceFlyout/DataSheetMarkdown.js
@@ -0,0 +1,15 @@
+import React from 'react';
+import { EuiText } from '@elastic/eui';
+import { useTranslation } from 'react-i18next';
+
+const DataSheetMarkdown = ({ resourceFlyoutData }) => {
+  const { t } = useTranslation('results');
+
+  return (
+    <EuiText size="s">
+      <p>test</p>
+    </EuiText>
+  );
+};
+
+export default DataSheetMarkdown;
diff --git a/src/pages/results/ResourceFlyout/ResourceFlyout.js b/src/pages/results/ResourceFlyout/ResourceFlyout.js
new file mode 100644
index 0000000..bbacb26
--- /dev/null
+++ b/src/pages/results/ResourceFlyout/ResourceFlyout.js
@@ -0,0 +1,65 @@
+import React, { useMemo, useState } from 'react';
+import { EuiFlyout, EuiFlyoutBody, EuiTabs, EuiTab, EuiFlyoutHeader } from '@elastic/eui';
+import { useTranslation } from 'react-i18next';
+import DataSheetJSON from './DataSheetJSON';
+import DataSheetMarkdown from './DataSheetMarkdown';
+
+const ResourceFlyout = ({
+  resourceFlyoutData,
+  setResourceFlyoutData,
+  isResourceFlyoutOpen,
+  setIsResourceFlyoutOpen,
+}) => {
+  const { t } = useTranslation('results');
+  const [selectedTabId, setSelectedTabId] = useState('0');
+
+  const closeResourceFlyout = () => {
+    setResourceFlyoutData({});
+    setIsResourceFlyoutOpen(false);
+  };
+
+  const resourceDataTabs = [
+    {
+      id: '0',
+      name: 'Markdown',
+      content: <DataSheetMarkdown resourceData={resourceFlyoutData} />,
+    },
+    {
+      id: '1',
+      name: 'JSON',
+      content: <DataSheetJSON resourceData={resourceFlyoutData} />,
+    },
+  ];
+
+  const selectedTabContent = useMemo(() => {
+    return resourceDataTabs.find((tab) => tab.id === selectedTabId)?.content;
+  }, [selectedTabId]);
+
+  const renderTabs = () => {
+    return resourceDataTabs.map((tab, index) => (
+      <EuiTab
+        onClick={() => setSelectedTabId(tab.id)}
+        isSelected={tab.id === selectedTabId}
+        key={index}
+      >
+        {tab.name}
+      </EuiTab>
+    ));
+  };
+
+  return (
+    isResourceFlyoutOpen && (
+      <EuiFlyout
+        onClose={() => closeResourceFlyout()}
+        aria-labelledby={t('results:flyout.label')}
+      >
+        <EuiFlyoutHeader>
+          <EuiTabs>{renderTabs()}</EuiTabs>
+        </EuiFlyoutHeader>
+        <EuiFlyoutBody>{selectedTabContent}</EuiFlyoutBody>
+      </EuiFlyout>
+    )
+  );
+};
+
+export default ResourceFlyout;
diff --git a/src/pages/results/Results.js b/src/pages/results/Results.js
index 3584081..5d42904 100644
--- a/src/pages/results/Results.js
+++ b/src/pages/results/Results.js
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
 import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
 import { useTranslation } from 'react-i18next';
 import ResultsTableMUI from './ResultsTableMUI';
-import ResourceFlyout from './ResourceFlyout';
+import ResourceFlyout from './ResourceFlyout/ResourceFlyout';
 import ResultsDownload from './ResultsDownload';
 
 const Results = ({ searchResults, searchQuery, selectedRowsIds, setSelectedRowsIds }) => {
-- 
GitLab


From 4c12e0b30c1677b52ef9bf8bc8c5d708f72e6acf Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Thu, 3 Oct 2024 17:16:21 +0200
Subject: [PATCH 02/11] [BasicSearch] corrected bug causing page refresh on
 input submit

---
 src/pages/search/BasicSearch/BasicSearch.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/pages/search/BasicSearch/BasicSearch.js b/src/pages/search/BasicSearch/BasicSearch.js
index 397091a..6a42b29 100644
--- a/src/pages/search/BasicSearch/BasicSearch.js
+++ b/src/pages/search/BasicSearch/BasicSearch.js
@@ -26,7 +26,8 @@ const BasicSearch = ({
   const { t } = useTranslation('search');
   const [isLoading, setIsLoading] = useState(false);
 
-  const onFormSubmit = () => {
+  const onFormSubmit = (e) => {
+    e.preventDefault();
     setIsLoading(true);
     const queriesWithIndices = createBasicQueriesBySource(
       standardFields,
@@ -59,7 +60,7 @@ const BasicSearch = ({
       <EuiFlexGroup>
         <EuiFlexItem>
           <EuiSpacer size="s" />
-          <form onSubmit={() => onFormSubmit()}>
+          <form onSubmit={onFormSubmit}>
             <EuiFlexGroup>
               <EuiFlexItem>
                 <EuiFieldSearch
-- 
GitLab


From 15ac4883a9d5a6dc0d2f6fd880db343052633bc0 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Thu, 3 Oct 2024 17:29:02 +0200
Subject: [PATCH 03/11] [BasicSearch][AdvancedSearch] chore: replaced code
 duplicate by new generic component

---
 .../search/AdvancedSearch/AdvancedSearch.js   | 20 +++++-------
 src/pages/search/BasicSearch/BasicSearch.js   | 17 +++-------
 src/pages/search/SearchModeSwitcher.js        | 31 +++++++++++++++++++
 3 files changed, 43 insertions(+), 25 deletions(-)
 create mode 100644 src/pages/search/SearchModeSwitcher.js

diff --git a/src/pages/search/AdvancedSearch/AdvancedSearch.js b/src/pages/search/AdvancedSearch/AdvancedSearch.js
index d977c81..ce31434 100644
--- a/src/pages/search/AdvancedSearch/AdvancedSearch.js
+++ b/src/pages/search/AdvancedSearch/AdvancedSearch.js
@@ -48,6 +48,7 @@ import { addUserHistory, fetchUserHistory } from '../../../actions/user';
 import { useTranslation } from 'react-i18next';
 import styles from './styles.js';
 import moment from 'moment';
+import SearchModeSwitcher from '../SearchModeSwitcher';
 
 const updateSources = (
   searchFields,
@@ -58,10 +59,10 @@ const updateSources = (
   let updatedSources = [];
   let availableSources = [];
   let noPrivateField = true;
-  //search for policy fields to filter sources
+  // Search for policy fields to filter sources
   searchFields.forEach((field) => {
     if (field.isValidated) {
-      //if sources haven't already been filtered
+      // If sources haven't already been filtered
       if (noPrivateField && !updatedSources.length) {
         availableSources = sources;
       } else {
@@ -1464,17 +1465,10 @@ const AdvancedSearch = ({
 
   return (
     <>
-      <EuiFlexGroup>
-        <EuiFlexItem grow={false}>
-          <EuiButtonEmpty
-            onClick={() => {
-              setIsAdvancedSearch(!isAdvancedSearch);
-            }}
-          >
-            {t('search:advancedSearch.switchSearchMode')}
-          </EuiButtonEmpty>
-        </EuiFlexItem>
-      </EuiFlexGroup>
+      <SearchModeSwitcher
+        isAdvancedSearch={isAdvancedSearch}
+        setIsAdvancedSearch={setIsAdvancedSearch}
+      />
       <EuiFlexGroup>
         <EuiFlexItem>
           <EuiSpacer size="s" />
diff --git a/src/pages/search/BasicSearch/BasicSearch.js b/src/pages/search/BasicSearch/BasicSearch.js
index 6a42b29..0a27477 100644
--- a/src/pages/search/BasicSearch/BasicSearch.js
+++ b/src/pages/search/BasicSearch/BasicSearch.js
@@ -1,7 +1,6 @@
 import React, { useState } from 'react';
 import {
   EuiButton,
-  EuiButtonEmpty,
   EuiFieldSearch,
   EuiFlexGroup,
   EuiFlexItem,
@@ -11,6 +10,7 @@ import {
 import { createBasicQueriesBySource } from '../../../Utils';
 import { searchQuery } from '../../../actions/source';
 import { useTranslation } from 'react-i18next';
+import SearchModeSwitcher from '../SearchModeSwitcher';
 
 const BasicSearch = ({
   standardFields,
@@ -46,17 +46,10 @@ const BasicSearch = ({
 
   return (
     <>
-      <EuiFlexGroup>
-        <EuiFlexItem grow={false}>
-          <EuiButtonEmpty
-            onClick={() => {
-              setIsAdvancedSearch(!isAdvancedSearch);
-            }}
-          >
-            {t('basicSearch.switchSearchMode')}
-          </EuiButtonEmpty>
-        </EuiFlexItem>
-      </EuiFlexGroup>
+      <SearchModeSwitcher
+        isAdvancedSearch={isAdvancedSearch}
+        setIsAdvancedSearch={setIsAdvancedSearch}
+      />
       <EuiFlexGroup>
         <EuiFlexItem>
           <EuiSpacer size="s" />
diff --git a/src/pages/search/SearchModeSwitcher.js b/src/pages/search/SearchModeSwitcher.js
new file mode 100644
index 0000000..59567d5
--- /dev/null
+++ b/src/pages/search/SearchModeSwitcher.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+
+const SearchModeSwitcher = ({ isAdvancedSearch, setIsAdvancedSearch }) => {
+  const { t } = useTranslation('search');
+
+  const buildSwitcherText = () => {
+    if (!isAdvancedSearch) {
+      return t('search:basicSearch.switchSearchMode');
+    } else {
+      return t('search:advancedSearch.switchSearchMode');
+    }
+  };
+
+  return (
+    <EuiFlexGroup>
+      <EuiFlexItem grow={false}>
+        <EuiButtonEmpty
+          onClick={() => {
+            setIsAdvancedSearch(!isAdvancedSearch);
+          }}
+        >
+          {buildSwitcherText()}
+        </EuiButtonEmpty>
+      </EuiFlexItem>
+    </EuiFlexGroup>
+  );
+};
+
+export default SearchModeSwitcher;
-- 
GitLab


From f24e07b2952885178b2f0f9e62ec20e21d670168 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Fri, 4 Oct 2024 11:41:47 +0200
Subject: [PATCH 04/11] [ResourceFlyout] added markdown display

---
 package.json                                  |    1 +
 .../ResourceFlyout/DataSheetMarkdown.js       |   15 -
 src/pages/results/ResourceFlyout/JSON2MD.js   |  304 ++++
 .../results/ResourceFlyout/ResourceFlyout.js  |   36 +-
 .../{DataSheetJSON.js => ResourceJSON.js}     |   10 +-
 .../ResourceFlyout/ResourceMarkdown.js        |   23 +
 .../standard_markdown_styles_FR_EN.json       | 1598 +++++++++++++++++
 7 files changed, 1962 insertions(+), 25 deletions(-)
 delete mode 100644 src/pages/results/ResourceFlyout/DataSheetMarkdown.js
 create mode 100644 src/pages/results/ResourceFlyout/JSON2MD.js
 rename src/pages/results/ResourceFlyout/{DataSheetJSON.js => ResourceJSON.js} (68%)
 create mode 100644 src/pages/results/ResourceFlyout/ResourceMarkdown.js
 create mode 100644 src/pages/results/ResourceFlyout/standard_markdown_styles_FR_EN.json

diff --git a/package.json b/package.json
index f6dad8f..fc3084f 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
     "react": "^18.3.1",
     "react-dom": "^18.3.1",
     "react-i18next": "^14.1.1",
+    "react-markdown": "^9.0.1",
     "react-router-dom": "^6.24.1",
     "react-scripts": "^5.0.1",
     "react-use-storage": "^0.5.1"
diff --git a/src/pages/results/ResourceFlyout/DataSheetMarkdown.js b/src/pages/results/ResourceFlyout/DataSheetMarkdown.js
deleted file mode 100644
index 9d76cb9..0000000
--- a/src/pages/results/ResourceFlyout/DataSheetMarkdown.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react';
-import { EuiText } from '@elastic/eui';
-import { useTranslation } from 'react-i18next';
-
-const DataSheetMarkdown = ({ resourceFlyoutData }) => {
-  const { t } = useTranslation('results');
-
-  return (
-    <EuiText size="s">
-      <p>test</p>
-    </EuiText>
-  );
-};
-
-export default DataSheetMarkdown;
diff --git a/src/pages/results/ResourceFlyout/JSON2MD.js b/src/pages/results/ResourceFlyout/JSON2MD.js
new file mode 100644
index 0000000..16d52c2
--- /dev/null
+++ b/src/pages/results/ResourceFlyout/JSON2MD.js
@@ -0,0 +1,304 @@
+import standard_markdown_styles from './standard_markdown_styles_FR_EN.json';
+
+const DEFAULT_ARRAY_SEPARATOR = ',';
+
+const handleString = (
+  key,
+  value,
+  styles,
+  lang,
+  indent = '',
+  level,
+  labelType,
+  rejectNull
+) => {
+  const indentLocal = ' '.repeat((level - 1) * 2);
+  const style = styles[key]
+    ? styles[key][lang]
+    : { value_style: '**', title_style: '', label: key, definition: '' };
+  if (
+    (typeof value !== 'undefined' && value !== null && value !== '') ||
+    !rejectNull ||
+    !style
+  ) {
+    if (labelType === 'HT') {
+      return `\n${indentLocal}- ${style.label}: ${style.value_style}${value}${style.value_style}`;
+    } else {
+      return `\n${indentLocal}- ${key}: ${style.value_style}${value}${style.value_style}`;
+    }
+  }
+};
+
+const handleObject = (
+  key,
+  value,
+  styles,
+  lang,
+  indent = '',
+  level,
+  labelType,
+  rejectNull
+) => {
+  const style = styles[key]
+    ? styles[key][lang]
+    : { value_style: '**', title_style: '', label: key, definition: '' };
+  let result = '';
+  let style_section;
+  let localLabel;
+
+  if (level === 1) {
+    style_section = '#';
+  } else {
+    style_section = '- ###';
+  }
+  if (labelType === 'HT') {
+    localLabel = style.label;
+  } else {
+    localLabel = key;
+  }
+
+  result += `\n${style_section} ${localLabel}`;
+  for (let subKey in value) {
+    let value = '';
+    value = processKeyValue(
+      key + '.' + subKey,
+      value[subKey],
+      styles,
+      lang,
+      '',
+      level + 1,
+      rejectNull
+    );
+    if (typeof value != 'undefined') {
+      result += value;
+    }
+  }
+  return result;
+};
+
+const handleArray = (
+  key,
+  value,
+  styles,
+  lang,
+  indent = '',
+  level,
+  labelType,
+  rejectNull,
+  arraySeparator = DEFAULT_ARRAY_SEPARATOR
+) => {
+  const style = styles[key]
+    ? styles[key][lang]
+    : { value_style: '**', title_style: '', label: key, definition: '' };
+  // 2 more chars at each level
+  let indentLocal = ' '.repeat((level - 1) * 2);
+  let result = '';
+  let localLabel;
+
+  if (labelType === 'HT') {
+    localLabel = style.label;
+  } else {
+    localLabel = key;
+  }
+
+  if (value.every((item) => typeof item === 'string')) {
+    // cas: contact_mail dans responsable_organisation
+    result += `\n${indentLocal}- ${localLabel}: ${style.value_style}${value.join(arraySeparator)}${style.value_style}`;
+  } else if (value === null && !rejectNull) {
+    result += `\n${indentLocal}- ${localLabel}:`;
+  } else {
+    value.forEach((item, index) => {
+      let value = '';
+      value += processKeyValue(
+        index + 1,
+        item,
+        styles,
+        lang,
+        indent,
+        level + 1,
+        labelType,
+        rejectNull
+      );
+      if (typeof value != 'undefined') {
+        result += value;
+      }
+    });
+  }
+  return result;
+};
+
+const handleArrayOfObjects = (
+  key,
+  value,
+  styles,
+  lang,
+  indent = '',
+  level,
+  labelType,
+  rejectNull
+) => {
+  const style = styles[key]
+    ? styles[key][lang]
+    : { value_style: '**', title_style: '', label: key, definition: '' };
+  let indentLocal = ' '.repeat((level - 1) * 2); // 2 caractères de plus à chaque niveau
+  let result = '';
+  let style_section = '';
+  let localLabel = '';
+
+  if (labelType === 'HT') {
+    localLabel = style.label;
+  } else {
+    localLabel = key;
+  }
+
+  value.forEach((item, index) => {
+    if (value.length > 1) {
+      // cas metadata/responsible_organisation[*]
+      result += `\n${indentLocal}- ### ${localLabel} [${index + 1}]`;
+    } else if (item === null && !rejectNull) {
+      // cas related_publication, other_related_publication, published_data_identifier
+      result += `\n${indentLocal}- ${localLabel} =`;
+    } else {
+      if (level === 1) {
+        style_section = '#';
+      } else {
+        // cas responsible_organisation,variable
+        style_section = '- ###';
+      }
+      // cas resource/date , keyword / Controlled_vocabulary / date
+      result += `\n${indentLocal}${style_section} ${localLabel}`;
+    }
+    for (let subKey in item) {
+      let value = '';
+      value = processKeyValue(
+        key + '.' + subKey,
+        item[subKey],
+        styles,
+        lang,
+        indent,
+        level + 1,
+        labelType,
+        rejectNull
+      );
+      if (typeof value != 'undefined') {
+        result += value;
+      }
+    }
+  });
+  return result;
+};
+
+const processKeyValue = (
+  key,
+  value,
+  styles,
+  lang,
+  indent = '',
+  level,
+  labelType,
+  rejectNull
+) => {
+  const style = styles[key]
+    ? styles[key][lang]
+    : { value_style: '**', title_style: '', label: key, definition: '' };
+  let indentLocal = ' '.repeat((level - 1) * 2);
+  let localLabel;
+
+  if (labelType === 'HT') {
+    localLabel = style.label;
+  } else {
+    localLabel = key;
+  }
+
+  switch (typeof value) {
+    case 'undefined':
+      break;
+    case 'boolean':
+      break;
+    case 'number':
+      break;
+    case 'function':
+      break;
+    case 'symbol':
+      break;
+    case 'bigint':
+      break;
+    case 'string':
+      return handleString(key, value, styles, lang, indent, level, labelType, rejectNull);
+    case 'object':
+      if (Array.isArray(value)) {
+        if (value.length > 0 && typeof value[0] === 'object') {
+          return handleArrayOfObjects(
+            key,
+            value,
+            styles,
+            lang,
+            indent,
+            level,
+            labelType,
+            rejectNull
+          );
+        } else {
+          return handleArray(
+            key,
+            value,
+            styles,
+            lang,
+            indent,
+            level,
+            labelType,
+            rejectNull
+          );
+        }
+      } else if (value !== null) {
+        return handleObject(
+          key,
+          value,
+          styles,
+          lang,
+          indent,
+          level,
+          labelType,
+          rejectNull
+        );
+      } else if ((typeof value !== 'undefined' && false && value !== '') || !rejectNull) {
+        return `\n${indentLocal}- ${localLabel} = `;
+      } else {
+        // No value, ignored
+        return '';
+      }
+    default:
+      if (
+        (typeof value !== 'undefined' && value !== null && value !== '') ||
+        !rejectNull
+      ) {
+        return `\n${indentLocal}- ${localLabel}: ${value}`;
+      }
+      break;
+  }
+};
+
+/*
+  json: JSON data you want to convert to markdown.
+  lang: Language for displayed labels.
+  labelType: Choice for label display. Either 'ST' for standard label, or 'HT' for a human-readable label.
+  rejectNull: Boolean to choose to display null variables or not.
+ */
+export const JSON2MD = (json, lang, labelType, rejectNull) => {
+  const styles = standard_markdown_styles;
+  let markdown = '';
+
+  for (let key in json) {
+    markdown += processKeyValue(
+      key,
+      json[key],
+      styles,
+      lang,
+      '',
+      1,
+      labelType,
+      rejectNull
+    );
+  }
+  return markdown;
+};
diff --git a/src/pages/results/ResourceFlyout/ResourceFlyout.js b/src/pages/results/ResourceFlyout/ResourceFlyout.js
index bbacb26..267207f 100644
--- a/src/pages/results/ResourceFlyout/ResourceFlyout.js
+++ b/src/pages/results/ResourceFlyout/ResourceFlyout.js
@@ -1,8 +1,20 @@
 import React, { useMemo, useState } from 'react';
-import { EuiFlyout, EuiFlyoutBody, EuiTabs, EuiTab, EuiFlyoutHeader } from '@elastic/eui';
+import {
+  EuiFlyout,
+  EuiFlyoutBody,
+  EuiTabs,
+  EuiTab,
+  EuiFlyoutHeader,
+  EuiText,
+  EuiTitle,
+  EuiSpacer,
+  EuiIconTip,
+  EuiFlexGroup,
+  EuiFlexItem,
+} from '@elastic/eui';
 import { useTranslation } from 'react-i18next';
-import DataSheetJSON from './DataSheetJSON';
-import DataSheetMarkdown from './DataSheetMarkdown';
+import ResourceJSON from './ResourceJSON';
+import ResourceMarkdown from './ResourceMarkdown';
 
 const ResourceFlyout = ({
   resourceFlyoutData,
@@ -22,18 +34,19 @@ const ResourceFlyout = ({
     {
       id: '0',
       name: 'Markdown',
-      content: <DataSheetMarkdown resourceData={resourceFlyoutData} />,
+      content: <ResourceMarkdown resourceData={resourceFlyoutData} />,
     },
     {
       id: '1',
       name: 'JSON',
-      content: <DataSheetJSON resourceData={resourceFlyoutData} />,
+      content: <ResourceJSON resourceData={resourceFlyoutData} />,
     },
   ];
 
+  // Update tab content on tab selection or on flyout open
   const selectedTabContent = useMemo(() => {
     return resourceDataTabs.find((tab) => tab.id === selectedTabId)?.content;
-  }, [selectedTabId]);
+  }, [selectedTabId, isResourceFlyoutOpen]);
 
   const renderTabs = () => {
     return resourceDataTabs.map((tab, index) => (
@@ -54,6 +67,17 @@ const ResourceFlyout = ({
         aria-labelledby={t('results:flyout.label')}
       >
         <EuiFlyoutHeader>
+          <EuiTitle size="m">
+            <h2>{resourceFlyoutData?.resource?.title}</h2>
+          </EuiTitle>
+          <EuiSpacer size="s" />
+          <EuiText color="subdued">
+            <p>{resourceFlyoutData?.context?.related_experimental_network_title}</p>
+          </EuiText>
+          <EuiSpacer size="s" />
+          <EuiText color="subdued">
+            <p>{resourceFlyoutData?.resource?.external_information.description}</p>
+          </EuiText>
           <EuiTabs>{renderTabs()}</EuiTabs>
         </EuiFlyoutHeader>
         <EuiFlyoutBody>{selectedTabContent}</EuiFlyoutBody>
diff --git a/src/pages/results/ResourceFlyout/DataSheetJSON.js b/src/pages/results/ResourceFlyout/ResourceJSON.js
similarity index 68%
rename from src/pages/results/ResourceFlyout/DataSheetJSON.js
rename to src/pages/results/ResourceFlyout/ResourceJSON.js
index 235482f..bd12c0b 100644
--- a/src/pages/results/ResourceFlyout/DataSheetJSON.js
+++ b/src/pages/results/ResourceFlyout/ResourceJSON.js
@@ -3,7 +3,7 @@ import { EuiText } from '@elastic/eui';
 import { useTranslation } from 'react-i18next';
 import ReactJson from '@microlink/react-json-view';
 
-const DataSheetJSON = ({ resourceData }) => {
+const ResourceJSON = ({ resourceData }) => {
   const { t } = useTranslation('results');
 
   return (
@@ -12,12 +12,14 @@ const DataSheetJSON = ({ resourceData }) => {
         src={resourceData}
         name={t('results:flyout.JSON.title')}
         iconStyle={'triangle'}
+        quotesOnKeys={false}
+        displayArrayKey={false}
         displayDataTypes={false}
-        enableClipboard={false}
-        collapsed={true}
+        displayObjectSize={false}
+        collapsed={false}
       />
     </EuiText>
   );
 };
 
-export default DataSheetJSON;
+export default ResourceJSON;
diff --git a/src/pages/results/ResourceFlyout/ResourceMarkdown.js b/src/pages/results/ResourceFlyout/ResourceMarkdown.js
new file mode 100644
index 0000000..b7e2fb9
--- /dev/null
+++ b/src/pages/results/ResourceFlyout/ResourceMarkdown.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import { EuiText } from '@elastic/eui';
+import { JSON2MD } from './JSON2MD';
+import { useTranslation } from 'react-i18next';
+import Markdown from 'react-markdown';
+
+const ResourceMarkdown = ({ resourceData }) => {
+  const { i18n } = useTranslation();
+
+  const buildMarkdown = () => {
+    return JSON2MD(resourceData, i18n.language, 'HT', true);
+  };
+
+  const markdownString = buildMarkdown();
+
+  return (
+    <EuiText size="s">
+      <Markdown>{markdownString}</Markdown>
+    </EuiText>
+  );
+};
+
+export default ResourceMarkdown;
diff --git a/src/pages/results/ResourceFlyout/standard_markdown_styles_FR_EN.json b/src/pages/results/ResourceFlyout/standard_markdown_styles_FR_EN.json
new file mode 100644
index 0000000..4d9af7e
--- /dev/null
+++ b/src/pages/results/ResourceFlyout/standard_markdown_styles_FR_EN.json
@@ -0,0 +1,1598 @@
+{
+  "resource": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Description de la ressource",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Resource description",
+      "definition": "resource"
+    }
+  },
+  "resource.date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date",
+      "definition": "resource"
+    }
+  },
+  "metadata": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Description des métadonnées",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Metadata description",
+      "definition": "resource"
+    }
+  },
+  "metadata.responsible_organisation": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Organisation responsable des métadonnées",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible organisation of metadata",
+      "definition": "resource"
+    }
+  },
+  "responsible_organisation": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Organisation responsable",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible organisation",
+      "definition": "resource"
+    }
+  },
+  "experimental_site": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Site expérimental",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Experimental site",
+      "definition": "resource"
+    }
+  },
+  "context": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Contexte",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Context",
+      "definition": "resource"
+    }
+  },
+  "variable": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Description des variables",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Variable description",
+      "definition": "resource"
+    }
+  },
+  "variable.data": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Données sur la variable",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Variable informations",
+      "definition": "resource"
+    }
+  },
+  "experimental_site.geo_point": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Coordonnées géographiques du site",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Site geographic coordinates",
+      "definition": "resource"
+    }
+  },
+  "experimental_site.geo_bounding_box": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Emprise géographique du site",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Site spatial extent",
+      "definition": "resource"
+    }
+  },
+  "studied_factor": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Facteurs étudiés",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Studied factors",
+      "definition": "resource"
+    }
+  },
+  "keyword": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Mot(s)-Clé(s)",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Keyword(s)",
+      "definition": "resource"
+    }
+  },
+  "keyword.controlled_vocabulary.date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date",
+      "definition": "resource"
+    }
+  },
+  "keyword.controlled_vocabulary": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Thésaurus",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Thesaurus",
+      "definition": "resource"
+    }
+  },
+  "resource.external_information": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Information externe",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "External information",
+      "definition": "resource"
+    }
+  },
+  "biological_material.taxonomy_vocabulary": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom du vocabulaire",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Vocabulary name",
+      "definition": "resource"
+    }
+  },
+  "biological_material.taxonomy_vocabulary.date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date",
+      "definition": "resource"
+    }
+  },
+  "biological_material": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Matériel biologique",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Biological material",
+      "definition": "resource"
+    }
+  },
+  "biological_material.seed_origin": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Origine des semences du matériel",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Origin of material seeds",
+      "definition": "resource"
+    }
+  },
+  "biological_material.bio_origin": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Origine biologique du matériel",
+      "definition": "resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Biological origin of the material",
+      "definition": "resource"
+    }
+  },
+  "resource.identifier": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Identifiant unique de la ressource",
+      "definition": "Unique resource identifier"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Unique resource identifier",
+      "definition": "Unique resource identifier"
+    }
+  },
+  "resource.date.value": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date de référence pour la ressource",
+      "definition": "Reference date value for the cited resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Reference date for the resource",
+      "definition": "Reference date value for the cited resource"
+    }
+  },
+  "resource.date.type": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type de date de référence",
+      "definition": "The type of reference date for the cited resource. (Creation, publication or revision)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type of reference date",
+      "definition": "The type of reference date for the cited resource. (Creation, publication or revision)"
+    }
+  },
+  "resource.IN-SYLVA_type": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type de ressource IN-SYLVA",
+      "definition": "The IN-SYLVA type of resource that is described by the metadata record"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "The IN-SYLVA type of resource",
+      "definition": "The IN-SYLVA type of resource that is described by the metadata record"
+    }
+  },
+  "resource.INSPIRE_type": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type de ressource INSPIRE",
+      "definition": "The INSPIRE type of resource that is described by the metadata record"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "The INSPIRE type of resource",
+      "definition": "The INSPIRE type of resource that is described by the metadata record"
+    }
+  },
+  "resource.lineage": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Explication sur la lignée d'un jeu de données",
+      "definition": "General explanation of the data producer’s knowledge about the lineage of a dataset. Correspond also to provenance concept"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "General explanation about the lineage of a dataset",
+      "definition": "General explanation of the data producer’s knowledge about the lineage of a dataset. Correspond also to provenance concept"
+    }
+  },
+  "resource.language": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Langue de la ressource",
+      "definition": "Language to produce the resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Language ofthe resource",
+      "definition": "Language to produce the resource"
+    }
+  },
+  "resource.abstract": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Résumé de la ressource",
+      "definition": "Brief narrative summary of the content of the resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Summary of the resource",
+      "definition": "Brief narrative summary of the content of the resource"
+    }
+  },
+  "resource.IN-SYLVA_theme": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Principaux thèmes IN-SYLVA",
+      "definition": "Main IN-SYLVA theme(s) of the resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Main IN-SYLVA theme(s)",
+      "definition": "Main IN-SYLVA theme(s) of the resource"
+    }
+  },
+  "resource.INSPIRE_theme": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Principaux thèmes INSPIRE",
+      "definition": "Main INSPIRE theme(s) of the resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Main INSPIRE theme(s)",
+      "definition": "Main INSPIRE theme(s) of the resource"
+    }
+  },
+  "resource.published_data_identifier": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type des jeux de données générés par la ressource",
+      "definition": "Identifier of the datasets generated by the resource. (Measurements, observations, experiment description, environment description)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type of the datasets generated by the resource",
+      "definition": "Identifier of the datasets generated by the resource. (Measurements, observations, experiment description, environment description)"
+    }
+  },
+  "resource.data_access_procedure": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Description de la procédure pour accéder aux données",
+      "definition": "Description of the procedure for accessing data related to the resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Description of the procedure for accessing data",
+      "definition": "Description of the procedure for accessing data related to the resource"
+    }
+  },
+  "resource.data_access_url": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Lien d'accès aux données",
+      "definition": "Access link to data related to the resource, if is available"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Access link to data",
+      "definition": "Access link to data related to the resource, if is available"
+    }
+  },
+  "resource.related_publication": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Identifiant de la publication pour la ressource",
+      "definition": "Identifier of the publication about the resource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Identifier of the publication",
+      "definition": "Identifier of the publication about the resource"
+    }
+  },
+  "resource.other_related_publication": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Liens vers d'autres documents et publications connexes",
+      "definition": "Links to other documents and related publication"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Links to other documents and related publication",
+      "definition": "Links to other documents and related publication"
+    }
+  },
+  "resource.external_information.source": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Lien d'accès aux informations externes",
+      "definition": "Access link to external information(s). (ex:meteofrance)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Access link to external information(s)",
+      "definition": "Access link to external information(s). (ex:meteofrance)"
+    }
+  },
+  "resource.external_information.description": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Description des informations externes",
+      "definition": "External information description"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "External information description",
+      "definition": "External information description"
+    }
+  },
+  "context.forest_type": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Types de forêts",
+      "definition": "Forest types studied in the IN-SYLVA networks. Contains the 14 European Forest Types (EFT) and tropical forest types of the TmFO network"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Forest types",
+      "definition": "Forest types studied in the IN-SYLVA networks. Contains the 14 European Forest Types (EFT) and tropical forest types of the TmFO network"
+    }
+  },
+  "context.reference_soil_group": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type de sols",
+      "definition": "International classification of 32 soil types"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Soil types",
+      "definition": "International classification of 32 soil types"
+    }
+  },
+  "context.humus_type": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Formes d'humus",
+      "definition": "Humus forms described in « TerrHum: An iOS Application for Classifying Terrestrial Humipedons and Some Considerations about Soil Classification »"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Humus forms",
+      "definition": "Humus forms described in « TerrHum: An iOS Application for Classifying Terrestrial Humipedons and Some Considerations about Soil Classification »"
+    }
+  },
+  "context.related_experimental_network_title": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom du réseau expérimental",
+      "definition": "Name of the experimental network"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Name of the experimental network",
+      "definition": "Name of the experimental network"
+    }
+  },
+  "context.studied_compartment": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Compartiment dans lequel la variable est étudiée",
+      "definition": "Compartment in which the variable is studied"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Compartment in which the variable is studied",
+      "definition": "Compartment in which the variable is studied"
+    }
+  },
+  "responsible_organisation.name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Organisation responsable",
+      "definition": "Name of the organisation responsible for the ressource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible organisation",
+      "definition": "Name of the organisation responsible for the ressource"
+    }
+  },
+  "responsible_organisation.unit_name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Unité de recherche responsable",
+      "definition": "Name of the research unit responsible for the ressource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible research unit name",
+      "definition": "Name of the research unit responsible for the ressource"
+    }
+  },
+  "responsible_organisation.contact_name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom du responsable",
+      "definition": "Name of the person, team or group responsible for the ressource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible name",
+      "definition": "Name of the person, team or group responsible for the ressource"
+    }
+  },
+  "responsible_organisation.contact_role": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Rôle du responsable",
+      "definition": "Type of contribution (role) of the person, team or group responsible for the ressource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible role",
+      "definition": "Type of contribution (role) of the person, team or group responsible for the ressource"
+    }
+  },
+  "responsible_organisation.contact_mail": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Courriel du responsable",
+      "definition": "The electronic mail address(es) of the person, team or group responsible for the ressource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible email",
+      "definition": "The electronic mail address(es) of the person, team or group responsible for the ressource"
+    }
+  },
+  "responsible_organisation.contact_tel": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Numéro de téléphone du responsable",
+      "definition": "Telephone number(s) of the person, team or group responsible for the ressource"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible phone number",
+      "definition": "Telephone number(s) of the person, team or group responsible for the ressource"
+    }
+  },
+  "keyword.value": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Mot(s)-Clé(s)",
+      "definition": "Value of keyword(s)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Keyword(s)",
+      "definition": "Value of keyword(s)"
+    }
+  },
+  "keyword.theme": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Thème du mot-clé",
+      "definition": "Theme of keyword. This theme may be part of controlled vocabulary or not"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Theme of keyword",
+      "definition": "Theme of keyword. This theme may be part of controlled vocabulary or not"
+    }
+  },
+  "keyword.controlled_vocabulary.title": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Titre du vocabulaire contrôlé",
+      "definition": "Controlled vocabulary title (thesaurus, referential name)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Controlled vocabulary title",
+      "definition": "Controlled vocabulary title (thesaurus, referential name)"
+    }
+  },
+  "keyword.controlled_vocabulary.date.value": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Valeur de la date",
+      "definition": "Date value"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date value",
+      "definition": "Date value"
+    }
+  },
+  "keyword.controlled_vocabulary.date.type": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type de date",
+      "definition": "Date type (Creation, publication or revision)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date type",
+      "definition": "Date type (Creation, publication or revision)"
+    }
+  },
+  "studied_factor.name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom du facteur étudié",
+      "definition": "Name of the studied factor"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Name of the studied factor",
+      "definition": "Name of the studied factor"
+    }
+  },
+  "studied_factor.comparison_modality": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Modalité de comparaison du facteur étudié",
+      "definition": "Comparison modality of studied factor"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Comparison modality of studied factor",
+      "definition": "Comparison modality of studied factor"
+    }
+  },
+  "studied_factor.description": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Description du facteur étudié",
+      "definition": "Description of studied factor"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Description of studied factor",
+      "definition": "Description of studied factor"
+    }
+  },
+  "biological_material.identifier": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Code d'identification du matériel biologique",
+      "definition": "Code used to identify the biological material in the data file. Should be unique within the investigation"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Code used to identify the biological material",
+      "definition": "Code used to identify the biological material in the data file. Should be unique within the investigation"
+    }
+  },
+  "biological_material.name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom du matériel biologique",
+      "definition": "Name of biologic material"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Name of biologic material",
+      "definition": "Name of biologic material"
+    }
+  },
+  "biological_material.genetic_level": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Niveau génétique du matériel biologique",
+      "definition": "Genetic level of biologic material"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Genetic level of biologic material",
+      "definition": "Genetic level of biologic material"
+    }
+  },
+  "biological_material.genus": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Genre",
+      "definition": "Genus name for the organisation under study (standard scientific nomenclature)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Genus",
+      "definition": "Genus name for the organisation under study (standard scientific nomenclature)"
+    }
+  },
+  "biological_material.species": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Espèce",
+      "definition": "Species name for the organisation under study (standard scientific nomenclature)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Species",
+      "definition": "Species name for the organisation under study (standard scientific nomenclature)"
+    }
+  },
+  "biological_material.taxonomy_vocabulary.title": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Titre du vocabulaire de taxonomie",
+      "definition": "Taxonomy vocabulary title (thesaurus, referential name)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Taxonomy vocabulary title",
+      "definition": "Taxonomy vocabulary title (thesaurus, referential name)"
+    }
+  },
+  "biological_material.taxonomy_vocabulary.date.value": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Valeur de la date",
+      "definition": "Date value"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date value",
+      "definition": "Date value"
+    }
+  },
+  "biological_material.taxonomy_vocabulary.date.type": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Type de date",
+      "definition": "Date type (Creation, publication or revision)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date type",
+      "definition": "Date type (Creation, publication or revision)"
+    }
+  },
+  "biological_material.seed_origin.name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom de l'origine de la graine",
+      "definition": "name of the origin seed of the biological material"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "name of the origin seed",
+      "definition": "name of the origin seed of the biological material"
+    }
+  },
+  "biological_material.seed_origin.latitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Latitude de l'origine de la graine",
+      "definition": "Latitude of the origin seed of the biological material"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Latitude of the origin seed",
+      "definition": "Latitude of the origin seed of the biological material"
+    }
+  },
+  "biological_material.seed_origin.longitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Longitude de l'origine de la graine",
+      "definition": "Longitude of the origin seed of the biological material"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Longitude of the origin seed",
+      "definition": "Longitude of the origin seed of the biological material"
+    }
+  },
+  "biological_material.seed_origin.altitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Altitude de l'origine de la graine (m)",
+      "definition": "Altitude of the origin seed of the biological material, provided in meters (m)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Altitude of the origin seed (m)",
+      "definition": "Altitude of the origin seed of the biological material, provided in meters (m)"
+    }
+  },
+  "biological_material.bio_origin.name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom de l'origine biologique",
+      "definition": "name of the biological origin of the biological material"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "name of the biological origin",
+      "definition": "name of the biological origin of the biological material"
+    }
+  },
+  "biological_material.bio_origin.latitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Latitude de l'origine biologique",
+      "definition": "Latitude of the biological origin of the biological material"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Latitude of the biological origin",
+      "definition": "Latitude of the biological origin of the biological material"
+    }
+  },
+  "biological_material.bio_origin.longitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Longitude de l'origine biologique",
+      "definition": "Longitude of the biological origin of the biological material"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Longitude of the biological origin",
+      "definition": "Longitude of the biological origin of the biological material"
+    }
+  },
+  "biological_material.bio_origin.altitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Altitude de l'origine biologique (m)",
+      "definition": "Altitude of the biological origin of the biological material, provided in meters (m)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Altitude of the biological origin (m)",
+      "definition": "Altitude of the biological origin of the biological material, provided in meters (m)"
+    }
+  },
+  "variable.observable_property": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom de la propriété observable de la variable",
+      "definition": "Variable observable property name. Must be unique"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Variable observable property name",
+      "definition": "Variable observable property name. Must be unique"
+    }
+  },
+  "variable.object_of_interest": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom de l'objet mesuré",
+      "definition": "Variable measured object name (tree, branch, leaf …) object may be studied compartment"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Variable measured object name",
+      "definition": "Variable measured object name (tree, branch, leaf …) object may be studied compartment"
+    }
+  },
+  "variable.data.acquisition_mode": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Mode d'acquisition variable",
+      "definition": "Variable acquisition mode (notation measurement calculation)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Variable acquisition mode",
+      "definition": "Variable acquisition mode (notation measurement calculation)"
+    }
+  },
+  "variable.data.acquisition_date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date d'acquisition de la variable",
+      "definition": "Acquisition date of the variable considered"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Acquisition date",
+      "definition": "Acquisition date of the variable considered"
+    }
+  },
+  "variable.data.acquisition_temp_extent": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Intervalle d'acquisition de la variable",
+      "definition": "Acquisition interval of the variable considered"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Acquisition interval",
+      "definition": "Acquisition interval of the variable considered"
+    }
+  },
+  "variable.data.acquisition_frequency": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Fréquence d'acquisition",
+      "definition": "frequency of acquisition date or interval of the variable considered"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "frequency of acquisition",
+      "definition": "frequency of acquisition date or interval of the variable considered"
+    }
+  },
+  "variable.data.mean_value": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Valeur moyenne",
+      "definition": "Mean value of the measure"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Mean value",
+      "definition": "Mean value of the measure"
+    }
+  },
+  "variable.data.mean_value_unit": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Unité",
+      "definition": "Unit of mean value"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Unit",
+      "definition": "Unit of mean value"
+    }
+  },
+  "variable.data.information_granularity": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Granularité des données",
+      "definition": "Granularity of data information"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Granularity of data",
+      "definition": "Granularity of data information"
+    }
+  },
+  "experimental_site.blurring_rule_parameter": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Paramètres de floutage des coordonnées",
+      "definition": "Rule parameter to blur exact geographic coordinates with a variable width ring"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Rule parameter to blur geographic coordinates",
+      "definition": "Rule parameter to blur exact geographic coordinates with a variable width ring"
+    }
+  },
+  "experimental_site.geo_point.latitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Latitude du site expérimental",
+      "definition": "Exact latitude of the experimental site"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Latitude of experimental site",
+      "definition": "Exact latitude of the experimental site"
+    }
+  },
+  "experimental_site.geo_point.longitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Longitude du site expérimental",
+      "definition": "Exact longitude of the experimental site"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Longitude of experimental site",
+      "definition": "Exact longitude of the experimental site"
+    }
+  },
+  "experimental_site.geo_point.altitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Altitude du site expérimental",
+      "definition": "Exact altitude of the experimental site"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Altitude of experimental site",
+      "definition": "Exact altitude of the experimental site"
+    }
+  },
+  "experimental_site.geo_bounding_box.min_latitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Latitude minimale de la zone de délimitation",
+      "definition": "Minimum latitude of the bounding box"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Minimum latitude of the bounding box",
+      "definition": "Minimum latitude of the bounding box"
+    }
+  },
+  "experimental_site.geo_bounding_box.max_latitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Latitude maximale de la zone de délimitation",
+      "definition": "Maximum latitude of the bounding box"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Maximum latitude of the bounding box",
+      "definition": "Maximum latitude of the bounding box"
+    }
+  },
+  "experimental_site.geo_bounding_box.min_longitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Longitude minimale de la zone de délimitation",
+      "definition": "Minimum longitude of the bounding box"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Minimum longitude of the bounding box",
+      "definition": "Minimum longitude of the bounding box"
+    }
+  },
+  "experimental_site.geo_bounding_box.max_longitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Longitude maximale de la zone de délimitation",
+      "definition": "Maximum longitude of the bounding box"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Maximum longitude of the bounding box",
+      "definition": "Maximum longitude of the bounding box"
+    }
+  },
+  "experimental_site.geo_bounding_box.altitude": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Altitude moyenne du site expérimental",
+      "definition": "Mean altitude of the experimental site"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Mean altitude of the experimental site",
+      "definition": "Mean altitude of the experimental site"
+    }
+  },
+  "experimental_site.start_date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date de début de l'expérience",
+      "definition": "Start date of the experiment on the experimental site"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Start date of the experiment",
+      "definition": "Start date of the experiment on the experimental site"
+    }
+  },
+  "experimental_site.end_date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date de fin de l'expérience ",
+      "definition": "Date of ending the experiment on the experimental site. Either finished or abandoned"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date of ending the experiment",
+      "definition": "Date of ending the experiment on the experimental site. Either finished or abandoned"
+    }
+  },
+  "experimental_site.stand_rotation_start_date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date de révolution",
+      "definition": "Date of revolution (plantation, regen stand). May differ from the experiment installation date"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date of revolution",
+      "definition": "Date of revolution (plantation, regen stand). May differ from the experiment installation date"
+    }
+  },
+  "experimental_site.stand_age_at_start_date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Âge fourni en nombre d'années",
+      "definition": "Age provided in number of year"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Age provided in number of year",
+      "definition": "Age provided in number of year"
+    }
+  },
+  "experimental_site.stand_structure": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Structure de peuplement du site expérimental",
+      "definition": "Stand structure of the experimental site"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Stand structure of the experimental site",
+      "definition": "Stand structure of the experimental site"
+    }
+  },
+  "experimental_site.initial_density": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nombre d'arbres/surface de l'expérience",
+      "definition": "Number of trees/surface of the experiment"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Number of trees/surface of the experiment",
+      "definition": "Number of trees/surface of the experiment"
+    }
+  },
+  "experimental_site.surface": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Surface de l'expérience (ha)",
+      "definition": "Surface of the experiment of experimental site, Provided in hectare (ha)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Surface of the experiment  (ha)",
+      "definition": "Surface of the experiment of experimental site, Provided in hectare (ha)"
+    }
+  },
+  "experimental_site.initial_nb_trees": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nombre initial d'arbres du site ",
+      "definition": "Initial number of trees of the experimental site"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Initial number of trees of the site",
+      "definition": "Initial number of trees of the experimental site"
+    }
+  },
+  "experimental_site.experiment_status": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "État de l'expérience",
+      "definition": "Status of the experiment (in progress, completed, abandoned)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Status of the experiment",
+      "definition": "Status of the experiment (in progress, completed, abandoned)"
+    }
+  },
+  "experimental_site.experiment_design": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Conception de l'expérience",
+      "definition": "Design of the experiment"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Design of the experiment",
+      "definition": "Design of the experiment"
+    }
+  },
+  "experimental_site.replication_number": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nombre de répétitions de l'expérience",
+      "definition": "Replication number of the experiment"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Replication number of the experiment",
+      "definition": "Replication number of the experiment"
+    }
+  },
+  "experimental_site.other_information_available": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Autres informations sur le site",
+      "definition": "Availability of others ecologic data provided by IN-SYLVA (if the field is chosen, data is provided by IN-SYLVA, if not, certain datas are provided by extern services"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Other informations about the site",
+      "definition": "Availability of others ecologic data provided by IN-SYLVA (if the field is chosen, data is provided by IN-SYLVA, if not, certain datas are provided by extern services"
+    }
+  },
+  "metadata.standard_identifier": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Identifiant du standard de métadonnées",
+      "definition": "Value uniquely identifying an object within a namespace"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Metadata standard identifier",
+      "definition": "Value uniquely identifying an object within a namespace"
+    }
+  },
+  "metadata.standard_name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom du standard",
+      "definition": "Standard name (ex: IN-SYLVA)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Standard name",
+      "definition": "Standard name (ex: IN-SYLVA)"
+    }
+  },
+  "metadata.standard_source": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Lien vers le standard des métadonnées",
+      "definition": "Link to standart source of the metadata"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Link to standard metadata",
+      "definition": "Link to standart source of the metadata"
+    }
+  },
+  "metadata.standard_version": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Version du standard IN-SYLVA",
+      "definition": "The version of IN-SYLVA standard used (ex: 1.0)"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "IN-SYLVA standard version",
+      "definition": "The version of IN-SYLVA standard used (ex: 1.0)"
+    }
+  },
+  "metadata.language": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Langue des métadonnées",
+      "definition": "Language used for documenting metadata"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Language used for metadata",
+      "definition": "Language used for documenting metadata"
+    }
+  },
+  "metadata.date": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Date des métadonnées",
+      "definition": "Date that the metadata was created or updated"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Creation or update date of metadata",
+      "definition": "Date that the metadata was created or updated"
+    }
+  },
+  "metadata.responsible_organisation.name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsable des métadonnées",
+      "definition": "Party responsible for the metadata information"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Responsible for the metadata",
+      "definition": "Party responsible for the metadata information"
+    }
+  },
+  "metadata.responsible_organisation.contact_name": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Nom du responsable des métadonnées",
+      "definition": "Name of the person or group responsible for the metadata information"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Name of the person responsible for the metadata",
+      "definition": "Name of the person or group responsible for the metadata information"
+    }
+  },
+  "metadata.responsible_organisation.contact_role": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Rôle de la personne responsable des métadonnées",
+      "definition": "Role of the person or group responsible for the metadata information"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Role of the person responsible for the metadata",
+      "definition": "Role of the person or group responsible for the metadata information"
+    }
+  },
+  "metadata.responsible_organisation.contact_mail": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Courriel de la personne responsable des métadonnées",
+      "definition": "Electronic mail address of the person or group responsible for the metadata information"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Email address of the person responsible",
+      "definition": "Electronic mail address of the person or group responsible for the metadata information"
+    }
+  },
+  "metadata.responsible_organisation.contact_tel": {
+    "fr": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Numéro de téléphone de la personne ou du groupe responsable des informations métadonnées",
+      "definition": "Phone number of the person or group responsible for the metadata information"
+    },
+    "en": {
+      "value_style": "**",
+      "title_style": "-",
+      "label": "Phone number of the person or group responsible for the metadata information",
+      "definition": "Phone number of the person or group responsible for the metadata information"
+    }
+  }
+}
-- 
GitLab


From ee28b1e6a1a407905196f9006dddd64d75cdec75 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Fri, 4 Oct 2024 11:45:27 +0200
Subject: [PATCH 05/11] [ResourceFlyout] removed forgotten useless imports

---
 src/pages/results/ResourceFlyout/ResourceFlyout.js | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/pages/results/ResourceFlyout/ResourceFlyout.js b/src/pages/results/ResourceFlyout/ResourceFlyout.js
index 267207f..b694e91 100644
--- a/src/pages/results/ResourceFlyout/ResourceFlyout.js
+++ b/src/pages/results/ResourceFlyout/ResourceFlyout.js
@@ -8,9 +8,6 @@ import {
   EuiText,
   EuiTitle,
   EuiSpacer,
-  EuiIconTip,
-  EuiFlexGroup,
-  EuiFlexItem,
 } from '@elastic/eui';
 import { useTranslation } from 'react-i18next';
 import ResourceJSON from './ResourceJSON';
-- 
GitLab


From 6a0c36fbde50c9c0b1a6fa93527deac52c729b32 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Fri, 4 Oct 2024 11:48:25 +0200
Subject: [PATCH 06/11] [ResourceFlyout] corrected comments on JSON2MD
 converter

---
 src/pages/results/ResourceFlyout/JSON2MD.js | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/src/pages/results/ResourceFlyout/JSON2MD.js b/src/pages/results/ResourceFlyout/JSON2MD.js
index 16d52c2..902ad28 100644
--- a/src/pages/results/ResourceFlyout/JSON2MD.js
+++ b/src/pages/results/ResourceFlyout/JSON2MD.js
@@ -90,7 +90,6 @@ const handleArray = (
   const style = styles[key]
     ? styles[key][lang]
     : { value_style: '**', title_style: '', label: key, definition: '' };
-  // 2 more chars at each level
   let indentLocal = ' '.repeat((level - 1) * 2);
   let result = '';
   let localLabel;
@@ -102,7 +101,7 @@ const handleArray = (
   }
 
   if (value.every((item) => typeof item === 'string')) {
-    // cas: contact_mail dans responsable_organisation
+    // case: contact_mail in responsible_organisation
     result += `\n${indentLocal}- ${localLabel}: ${style.value_style}${value.join(arraySeparator)}${style.value_style}`;
   } else if (value === null && !rejectNull) {
     result += `\n${indentLocal}- ${localLabel}:`;
@@ -140,7 +139,7 @@ const handleArrayOfObjects = (
   const style = styles[key]
     ? styles[key][lang]
     : { value_style: '**', title_style: '', label: key, definition: '' };
-  let indentLocal = ' '.repeat((level - 1) * 2); // 2 caractères de plus à chaque niveau
+  let indentLocal = ' '.repeat((level - 1) * 2);
   let result = '';
   let style_section = '';
   let localLabel = '';
@@ -153,19 +152,19 @@ const handleArrayOfObjects = (
 
   value.forEach((item, index) => {
     if (value.length > 1) {
-      // cas metadata/responsible_organisation[*]
+      // case metadata/responsible_organisation[*]
       result += `\n${indentLocal}- ### ${localLabel} [${index + 1}]`;
     } else if (item === null && !rejectNull) {
-      // cas related_publication, other_related_publication, published_data_identifier
+      // case related_publication, other_related_publication, published_data_identifier
       result += `\n${indentLocal}- ${localLabel} =`;
     } else {
       if (level === 1) {
         style_section = '#';
       } else {
-        // cas responsible_organisation,variable
+        // case responsible_organisation, variable
         style_section = '- ###';
       }
-      // cas resource/date , keyword / Controlled_vocabulary / date
+      // case resource/date, keyword / Controlled_vocabulary / date
       result += `\n${indentLocal}${style_section} ${localLabel}`;
     }
     for (let subKey in item) {
-- 
GitLab


From c23750b6fccaaaba8a5dec17adfa0e9aadb228fd Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Fri, 4 Oct 2024 13:08:06 +0200
Subject: [PATCH 07/11] [locales] corrected error in translations

---
 public/locales/en/common.json | 2 +-
 public/locales/fr/common.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index aeeba79..7be8195 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -1,7 +1,7 @@
 {
   "languages": {
     "en": "English",
-    "fr": "French"
+    "fr": "Français"
   },
   "inSylvaLogoAlt": "In-Sylva logo",
   "validationActions": {
diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json
index cb15bc4..e77b65a 100644
--- a/public/locales/fr/common.json
+++ b/public/locales/fr/common.json
@@ -1,6 +1,6 @@
 {
   "languages": {
-    "en": "Anglais",
+    "en": "English",
     "fr": "Français"
   },
   "inSylvaLogoAlt": "Logo In-Sylva",
-- 
GitLab


From 0deb600d890c3c96e48f3db3dfacfe99a2135ed8 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Tue, 29 Oct 2024 11:44:42 +0100
Subject: [PATCH 08/11] [JSON2MD.js] corrected bug that created undefinied
 variables

---
 src/pages/results/ResourceFlyout/JSON2MD.js | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/pages/results/ResourceFlyout/JSON2MD.js b/src/pages/results/ResourceFlyout/JSON2MD.js
index 902ad28..1c25fdb 100644
--- a/src/pages/results/ResourceFlyout/JSON2MD.js
+++ b/src/pages/results/ResourceFlyout/JSON2MD.js
@@ -59,18 +59,19 @@ const handleObject = (
 
   result += `\n${style_section} ${localLabel}`;
   for (let subKey in value) {
-    let value = '';
-    value = processKeyValue(
+    let res = '';
+    res = processKeyValue(
       key + '.' + subKey,
       value[subKey],
       styles,
       lang,
       '',
       level + 1,
+      labelType,
       rejectNull
     );
-    if (typeof value != 'undefined') {
-      result += value;
+    if (typeof res != 'undefined') {
+      result += res;
     }
   }
   return result;
@@ -278,7 +279,7 @@ const processKeyValue = (
 };
 
 /*
-  json: JSON data you want to convert to markdown.
+  json: JSON data to convert to markdown.
   lang: Language for displayed labels.
   labelType: Choice for label display. Either 'ST' for standard label, or 'HT' for a human-readable label.
   rejectNull: Boolean to choose to display null variables or not.
-- 
GitLab


From 089a8ca611c4728ea9077b57a8dda3870ad35e61 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Tue, 29 Oct 2024 14:18:18 +0100
Subject: [PATCH 09/11] [ResourceFlyout.js] extracted component logic for
 better code readability and added comments

---
 .../results/ResourceFlyout/ResourceFlyout.js  | 39 +++++++++++++------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/src/pages/results/ResourceFlyout/ResourceFlyout.js b/src/pages/results/ResourceFlyout/ResourceFlyout.js
index b694e91..9de8890 100644
--- a/src/pages/results/ResourceFlyout/ResourceFlyout.js
+++ b/src/pages/results/ResourceFlyout/ResourceFlyout.js
@@ -13,6 +13,33 @@ import { useTranslation } from 'react-i18next';
 import ResourceJSON from './ResourceJSON';
 import ResourceMarkdown from './ResourceMarkdown';
 
+/*
+  Flyout header text. Displays some context for the resource.
+  It displays, if existing: resource title, lineage, related network, and studied factor description.
+  WARNING: this makes the search tool standard dependant, because displayed variables are chosen arbitrarily and hard-coded.
+ */
+const HeaderText = ({ data }) => {
+  return (
+    <>
+      <EuiTitle size="m">
+        <h2>{data?.resource?.title}</h2>
+      </EuiTitle>
+      <EuiSpacer size="s" />
+      <EuiText color="subdued">
+        <p>
+          {data?.resource?.lineage}
+          {' - '}
+          {data?.context?.related_experimental_network_title}
+        </p>
+      </EuiText>
+      <EuiSpacer size="s" />
+      <EuiText color="subdued">
+        <p>{data?.studied_factor?.description}</p>
+      </EuiText>
+    </>
+  );
+};
+
 const ResourceFlyout = ({
   resourceFlyoutData,
   setResourceFlyoutData,
@@ -64,17 +91,7 @@ const ResourceFlyout = ({
         aria-labelledby={t('results:flyout.label')}
       >
         <EuiFlyoutHeader>
-          <EuiTitle size="m">
-            <h2>{resourceFlyoutData?.resource?.title}</h2>
-          </EuiTitle>
-          <EuiSpacer size="s" />
-          <EuiText color="subdued">
-            <p>{resourceFlyoutData?.context?.related_experimental_network_title}</p>
-          </EuiText>
-          <EuiSpacer size="s" />
-          <EuiText color="subdued">
-            <p>{resourceFlyoutData?.resource?.external_information.description}</p>
-          </EuiText>
+          <HeaderText data={resourceFlyoutData} />
           <EuiTabs>{renderTabs()}</EuiTabs>
         </EuiFlyoutHeader>
         <EuiFlyoutBody>{selectedTabContent}</EuiFlyoutBody>
-- 
GitLab


From d27ac3dfc357d780076209cc81d7ace71b6eba8a Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Tue, 29 Oct 2024 14:55:07 +0100
Subject: [PATCH 10/11] added clarification for translations namespaces
 [Profile.js] added a missing translation

---
 public/locales/en/profile.json                |  1 +
 public/locales/fr/profile.json                |  1 +
 src/components/Header/HeaderUserMenu.js       |  8 +++---
 .../LanguageSwitcher/LanguageSwitcher.js      |  4 +--
 src/pages/profile/Profile.js                  | 28 +++++++++----------
 .../search/AdvancedSearch/AdvancedSearch.js   | 10 ++++---
 src/pages/search/BasicSearch/BasicSearch.js   |  4 +--
 src/pages/search/Search.js                    |  6 ++--
 8 files changed, 33 insertions(+), 29 deletions(-)

diff --git a/public/locales/en/profile.json b/public/locales/en/profile.json
index 76ab2db..dd6afb3 100644
--- a/public/locales/en/profile.json
+++ b/public/locales/en/profile.json
@@ -12,6 +12,7 @@
     "cancelRequest": "Cancel this request"
   },
   "groupRequests": {
+    "selectGroup": "Select group(s)",
     "requestGroupAssignment": "Request a group assignment",
     "currentGroups": "You currently belong to (or have a pending request for) these groups:",
     "noGroup": "You currently don't belong to any group."
diff --git a/public/locales/fr/profile.json b/public/locales/fr/profile.json
index 9f30ddb..826c160 100644
--- a/public/locales/fr/profile.json
+++ b/public/locales/fr/profile.json
@@ -12,6 +12,7 @@
     "cancelRequest": "Annuler cette requête"
   },
   "groupRequests": {
+    "selectGroup": "Selectionnez un groupe",
     "requestGroupAssignment": "Demander à faire parti d'un groupe",
     "currentGroups": "Vous faites actuellement parti (ou avez une demande pour) de ces groupes :",
     "noGroup": "Vous ne faites actuellement parti d'aucun groupe."
diff --git a/src/components/Header/HeaderUserMenu.js b/src/components/Header/HeaderUserMenu.js
index 630c017..761552a 100644
--- a/src/components/Header/HeaderUserMenu.js
+++ b/src/components/Header/HeaderUserMenu.js
@@ -43,8 +43,8 @@ const HeaderUserMenu = () => {
       size="s"
       onClick={onMenuButtonClick}
       iconType="user"
-      title={t('userMenu.title')}
-      aria-label={t('userMenu.title')}
+      title={t('header:userMenu.title')}
+      aria-label={t('header:userMenu.title')}
     />
   );
 
@@ -68,12 +68,12 @@ const HeaderUserMenu = () => {
               <EuiFlexGroup justifyContent="spaceBetween">
                 <EuiFlexItem grow={false}>
                   <EuiLink href="/profile" onClick={closeMenu}>
-                    {t('userMenu.editProfileButton')}
+                    {t('header:userMenu.editProfileButton')}
                   </EuiLink>
                 </EuiFlexItem>
                 <EuiFlexItem grow={false}>
                   <EuiLink onClick={() => signOut()}>
-                    {t('userMenu.logOutButton')}
+                    {t('header:userMenu.logOutButton')}
                   </EuiLink>
                 </EuiFlexItem>
               </EuiFlexGroup>
diff --git a/src/components/LanguageSwitcher/LanguageSwitcher.js b/src/components/LanguageSwitcher/LanguageSwitcher.js
index 7fb068c..3281f47 100644
--- a/src/components/LanguageSwitcher/LanguageSwitcher.js
+++ b/src/components/LanguageSwitcher/LanguageSwitcher.js
@@ -7,8 +7,8 @@ const LanguageSwitcher = () => {
   const { t, i18n } = useTranslation('common');
 
   const options = [
-    { text: t('languages.en'), value: 'en' },
-    { text: t('languages.fr'), value: 'fr' },
+    { text: t('common:languages.en'), value: 'en' },
+    { text: t('common:languages.fr'), value: 'fr' },
   ];
 
   const changeLanguage = (newLng) => {
diff --git a/src/pages/profile/Profile.js b/src/pages/profile/Profile.js
index 63303d0..f41b256 100644
--- a/src/pages/profile/Profile.js
+++ b/src/pages/profile/Profile.js
@@ -61,8 +61,8 @@ const Profile = () => {
   }, [userGroups]);
 
   const groupColumns = [
-    { field: 'label', name: t('groups.groupName'), width: '30%' },
-    { field: 'description', name: t('groups.groupDescription') },
+    { field: 'label', name: t('profile:groups.groupName'), width: '30%' },
+    { field: 'description', name: t('profile:groups.groupDescription') },
   ];
 
   const getUserRoles = () => {
@@ -106,7 +106,7 @@ const Profile = () => {
   const requestActions = [
     {
       name: t('common:validationActions.cancel'),
-      description: t('requestsList.cancelRequest'),
+      description: t('profile:requestsList.cancelRequest'),
       icon: 'trash',
       type: 'icon',
       onClick: onDeleteRequest,
@@ -116,10 +116,10 @@ const Profile = () => {
   const requestsColumns = [
     {
       field: 'request_message',
-      name: t('requestsList.requestsMessage'),
+      name: t('profile:requestsList.requestsMessage'),
       width: '85%',
     },
-    { field: 'is_processed', name: t('requestsList.processed') },
+    { field: 'is_processed', name: t('profile:requestsList.processed') },
     { name: t('common:validationActions.cancel'), actions: requestActions },
   ];
 
@@ -171,36 +171,36 @@ const Profile = () => {
   return (
     <>
       <EuiTitle>
-        <h2>{t('pageTitle')}</h2>
+        <h2>{t('profile:pageTitle')}</h2>
       </EuiTitle>
       <EuiSpacer size={'l'} />
       <EuiTitle size="s">
-        <h3>{t('groups.groupsList')}</h3>
+        <h3>{t('profile:groups.groupsList')}</h3>
       </EuiTitle>
       <EuiFormRow fullWidth label="">
         <EuiBasicTable items={groups} columns={groupColumns} />
       </EuiFormRow>
       <EuiSpacer size="l" />
       <EuiTitle size="s">
-        <h3>{t('requestsList.requestsList')}</h3>
+        <h3>{t('profile:requestsList.requestsList')}</h3>
       </EuiTitle>
       <EuiFormRow fullWidth label="">
         <EuiBasicTable items={userRequests} columns={requestsColumns} />
       </EuiFormRow>
       <EuiSpacer size="l" />
       <EuiTitle size="s">
-        <h3>{t('groupRequests.requestGroupAssignment')}</h3>
+        <h3>{t('profile:groupRequests.requestGroupAssignment')}</h3>
       </EuiTitle>
       {getUserGroupLabels() ? (
         <p
           style={styles.currentRoleOrGroupText}
-        >{`${t('groupRequests.currentGroups')} ${getUserGroupLabels()}`}</p>
+        >{`${t('profile:groupRequests.currentGroups')} ${getUserGroupLabels()}`}</p>
       ) : (
-        <p>{t('groupRequests.noGroup')}</p>
+        <p>{t('profile:groupRequests.noGroup')}</p>
       )}
       <EuiFormRow error={valueError} isInvalid={valueError !== undefined}>
         <EuiComboBox
-          placeholder={'Select groups'}
+          placeholder={t('profile:groupRequests.selectGroup')}
           options={groups}
           selectedOptions={userGroups}
           onChange={(selectedOptions) => {
@@ -221,12 +221,12 @@ const Profile = () => {
       </EuiButton>
       <EuiSpacer size="l" />
       <EuiTitle size="s">
-        <h3>{t('roleRequests.requestRoleAssignment')}</h3>
+        <h3>{t('profile:roleRequests.requestRoleAssignment')}</h3>
       </EuiTitle>
       {userRole ? (
         <p
           style={styles.currentRoleOrGroupText}
-        >{`${t('roleRequests.currentRole')} ${userRole}`}</p>
+        >{`${t('profile:roleRequests.currentRole')} ${userRole}`}</p>
       ) : (
         <></>
       )}
diff --git a/src/pages/search/AdvancedSearch/AdvancedSearch.js b/src/pages/search/AdvancedSearch/AdvancedSearch.js
index ce31434..f38cadc 100644
--- a/src/pages/search/AdvancedSearch/AdvancedSearch.js
+++ b/src/pages/search/AdvancedSearch/AdvancedSearch.js
@@ -346,12 +346,14 @@ const SearchBar = ({
         <EuiModal onClose={closeSaveSearchModal} initialFocus="[name=searchName]">
           <EuiModalHeader>
             <EuiModalHeaderTitle>
-              {t('advancedSearch.searchHistory.saveSearch')}
+              {t('search:advancedSearch.searchHistory.saveSearch')}
             </EuiModalHeaderTitle>
           </EuiModalHeader>
           <EuiModalBody>
             <EuiForm>
-              <EuiFormRow label={t('advancedSearch.searchHistory.addSavedSearchName')}>
+              <EuiFormRow
+                label={t('search:advancedSearch.searchHistory.addSavedSearchName')}
+              >
                 <EuiFieldText
                   name="searchName"
                   value={searchName}
@@ -359,13 +361,13 @@ const SearchBar = ({
                 />
               </EuiFormRow>
               <EuiFormRow
-                label={t('advancedSearch.searchHistory.addSavedSearchDescription')}
+                label={t('search:advancedSearch.searchHistory.addSavedSearchDescription')}
               >
                 <EuiTextArea
                   value={searchDescription}
                   onChange={(e) => setSearchDescription(e.target.value)}
                   placeholder={t(
-                    'advancedSearch.searchHistory.addSavedSearchDescriptionPlaceholder'
+                    'search:advancedSearch.searchHistory.addSavedSearchDescriptionPlaceholder'
                   )}
                   fullWidth
                   compressed
diff --git a/src/pages/search/BasicSearch/BasicSearch.js b/src/pages/search/BasicSearch/BasicSearch.js
index 0a27477..a4decdd 100644
--- a/src/pages/search/BasicSearch/BasicSearch.js
+++ b/src/pages/search/BasicSearch/BasicSearch.js
@@ -59,7 +59,7 @@ const BasicSearch = ({
                 <EuiFieldSearch
                   value={basicSearch}
                   onChange={(e) => setBasicSearch(e.target.value)}
-                  placeholder={t('basicSearch.searchInputPlaceholder')}
+                  placeholder={t('search:basicSearch.searchInputPlaceholder')}
                   autoFocus={true}
                   fullWidth
                 />
@@ -73,7 +73,7 @@ const BasicSearch = ({
               </EuiFlexItem>
               <EuiFlexItem grow={false}>
                 <EuiButton type="submit" fill isDisabled={isAdvancedSearch}>
-                  {t('sendSearchButton')}
+                  {t('search:sendSearchButton')}
                 </EuiButton>
               </EuiFlexItem>
             </EuiFlexGroup>
diff --git a/src/pages/search/Search.js b/src/pages/search/Search.js
index 80a364e..6acc61e 100644
--- a/src/pages/search/Search.js
+++ b/src/pages/search/Search.js
@@ -64,7 +64,7 @@ const Search = () => {
   const tabsContent = [
     {
       id: 'tab1',
-      name: t('tabs.composeSearch'),
+      name: t('search:tabs.composeSearch'),
       content: (
         <EuiFlexGroup>
           <EuiFlexItem>
@@ -104,7 +104,7 @@ const Search = () => {
     },
     {
       id: 'tab2',
-      name: t('tabs.results'),
+      name: t('search:tabs.results'),
       content: (
         <EuiFlexGroup>
           <EuiFlexItem>
@@ -121,7 +121,7 @@ const Search = () => {
     },
     {
       id: 'tab3',
-      name: t('tabs.map'),
+      name: t('search:tabs.map'),
       content: (
         <EuiFlexGroup>
           <EuiFlexItem>
-- 
GitLab


From 129c4a0978cb26a82120647f5a6e3b8a945fc9f4 Mon Sep 17 00:00:00 2001
From: rbisson <remi.bisson@inrae.fr>
Date: Tue, 29 Oct 2024 15:03:21 +0100
Subject: [PATCH 11/11] [HeaderUserMenu.js] Corrected bug that prevented to
 navigate to profile page

---
 src/components/Header/HeaderUserMenu.js | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/components/Header/HeaderUserMenu.js b/src/components/Header/HeaderUserMenu.js
index 761552a..524faa1 100644
--- a/src/components/Header/HeaderUserMenu.js
+++ b/src/components/Header/HeaderUserMenu.js
@@ -3,7 +3,6 @@ import {
   EuiAvatar,
   EuiFlexGroup,
   EuiFlexItem,
-  EuiLink,
   EuiText,
   EuiSpacer,
   EuiPopover,
@@ -12,6 +11,7 @@ import {
 import { signOut } from '../../context/UserContext';
 import { findOneUser } from '../../actions/user';
 import { useTranslation } from 'react-i18next';
+import { NavLink } from 'react-router-dom';
 
 const HeaderUserMenu = () => {
   const { t } = useTranslation('header');
@@ -67,14 +67,14 @@ const HeaderUserMenu = () => {
             <EuiFlexItem>
               <EuiFlexGroup justifyContent="spaceBetween">
                 <EuiFlexItem grow={false}>
-                  <EuiLink href="/profile" onClick={closeMenu}>
+                  <NavLink to={'/profile'}>
                     {t('header:userMenu.editProfileButton')}
-                  </EuiLink>
+                  </NavLink>
                 </EuiFlexItem>
                 <EuiFlexItem grow={false}>
-                  <EuiLink onClick={() => signOut()}>
+                  <NavLink to={'/'} onClick={() => signOut()}>
                     {t('header:userMenu.logOutButton')}
-                  </EuiLink>
+                  </NavLink>
                 </EuiFlexItem>
               </EuiFlexGroup>
             </EuiFlexItem>
-- 
GitLab