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