diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index b71a4d03..b152514d 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -542,6 +542,22 @@ "name": "Name", "compose": "Compose", "upload": "Upload" + }, + "embed": { + "tab": "Embed", + "no-embed": "To add an embed, click on", + "allow": "Enable", + "allow-display-data-embed": "Disable", + "all-fields": "Embeds", + "icon": "Icon", + "title": "Embed title", + "title-help": "", + "src": "Address", + "src-help": "Embed address (iframe)", + "preview": "Preview", + "fullscreen": "Fullscreen", + "width": "Width (px)", + "height": "Height (px)" } } }, diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 011fa295..766d2d10 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -594,6 +594,22 @@ "name": "Nom", "compose": "Composer", "upload": "Envoyer" + }, + "embed": { + "tab": "Inclusions", + "no-embed": "Pour activer les inclusions, cliquer sur", + "allow": "Activer", + "allow-display-data-embed": "Désactiver", + "all-fields": "Inclusions", + "icon": "Icône", + "title": "Titre de l'inclusion", + "title-help": "", + "src": "Adresse", + "src-help": "Adresse de la page à inclure (iframe)", + "preview": "Prévisualiser", + "fullscreen": "Plein écran", + "width": "Largeur (px)", + "height": "Hauteur (px)" } } }, diff --git a/src/components/BPIcon.js b/src/components/BPIcon.js new file mode 100644 index 00000000..c1085f48 --- /dev/null +++ b/src/components/BPIcon.js @@ -0,0 +1,71 @@ +import React from 'react'; +import { Icon } from '@blueprintjs/core'; + +export const graphIcons = [ + 'chart', + 'curved-range-chart', + 'database', + 'diagram-tree', + 'doughnut-chart', + 'flow-branch', + 'flow-end', + 'flow-linear', + 'flow-review', + 'flow-review-branch', + 'flows', + 'form', + 'full-stacked-chart', + 'gantt-chart', + 'graph', + 'grid', + 'grouped-bar-chart', + 'heat-grid', + 'heatmap', + 'horizontal-bar-chart', + 'horizontal-bar-chart-asc', + 'horizontal-bar-chart-desc', + 'layout', + 'layout-auto', + 'layout-balloon', + 'layout-circle', + 'layout-grid', + 'layout-group-by', + 'layout-hierarchy', + 'layout-linear', + 'layout-skew-grid', + 'layout-sorted-clusters', + 'many-to-many', + 'many-to-one', + 'one-to-many', + 'one-to-one', + 'pie-chart', + 'polygon-filter', + 'regression-chart', + 'scatter-plot', + 'series-add', + 'series-configuration', + 'series-derived', + 'series-filtered', + 'series-search', + 'stacked-chart', + 'step-chart', + 'timeline-area-chart', + 'timeline-bar-chart', + 'timeline-line-chart', + 'trending-down', + 'trending-up', + 'vertical-bar-chart-asc', + 'vertical-bar-chart-desc', + 'waterfall-chart', +].sort(); + +const BPIcon = ({ icon, displayIconName, style = {}, ...rest }) => + (displayIconName ? ( + <> + {icon} + + ) : ( + + )); + +export default BPIcon; diff --git a/src/modules/RA/DataLayer/components/DataLayerForm.js b/src/modules/RA/DataLayer/components/DataLayerForm.js index 82e89cb1..84a4cbec 100644 --- a/src/modules/RA/DataLayer/components/DataLayerForm.js +++ b/src/modules/RA/DataLayer/components/DataLayerForm.js @@ -13,6 +13,7 @@ import MinisheetTab from './tabs/MinisheetTab'; import FilterTab from './tabs/FilterTab'; import TableTab from './tabs/TableTab'; import StyleImageField from './StyleImageField'; +import EmbedTab from './tabs/EmbedTab'; const initialErrorState = { definition: false, @@ -22,6 +23,7 @@ const initialErrorState = { minisheet: false, filter: false, table: false, + embed: false, }; const inErrorReducer = (state, { type, payload }) => { @@ -91,6 +93,10 @@ const DataLayerForm = React.memo(props => { dispatch({ type: 'minisheet', payload: inError }); }, []); + const onEmbedErrorChange = React.useCallback(() => { + dispatch({ type: 'embed', paylaod: false }); + }, []); + const onTableErrorChange = React.useCallback(({ values: { fields = [], table_enable: tableEnable }, }) => { @@ -205,6 +211,16 @@ const DataLayerForm = React.memo(props => { + + + + ); }); diff --git a/src/modules/RA/DataLayer/components/tabs/EmbedTab/EmbedConfigField.js b/src/modules/RA/DataLayer/components/tabs/EmbedTab/EmbedConfigField.js new file mode 100644 index 00000000..39725468 --- /dev/null +++ b/src/modules/RA/DataLayer/components/tabs/EmbedTab/EmbedConfigField.js @@ -0,0 +1,45 @@ +import React from 'react'; +import { + useTranslate, + useInput, + ArrayInput, + SimpleFormIterator, +} from 'react-admin'; +import Typography from '@material-ui/core/Typography'; + +import EmbedItemInput from './EmbedItemInput'; + +const EmbedConfigField = ({ label, ...rest }) => { + const translate = useTranslate(); + const { + meta: { error }, + } = useInput(rest); + + return ( + <> + + {translate(label)} + + + {error?.length > 0 && + error.flatMap( + err => + err && + Object.entries(err).map(([key, value]) => ( + + {key}: {translate(value)} + + )), + )} +
+ + + + + +
+ + ); +}; + +export default EmbedConfigField; diff --git a/src/modules/RA/DataLayer/components/tabs/EmbedTab/EmbedItemInput.js b/src/modules/RA/DataLayer/components/tabs/EmbedTab/EmbedItemInput.js new file mode 100644 index 00000000..288d8c93 --- /dev/null +++ b/src/modules/RA/DataLayer/components/tabs/EmbedTab/EmbedItemInput.js @@ -0,0 +1,111 @@ +import React, { useEffect } from 'react'; +import { BooleanInput, NumberInput, SelectInput, TextInput, useTranslate } from 'react-admin'; + +import { + Accordion, + AccordionDetails, + AccordionSummary, + Typography, +} from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { useField } from 'react-final-form'; +import Condition from '../../../../../../components/react-admin/Condition'; +import BPIcon, { graphIcons } from '../../../../../../components/BPIcon'; + +const EmbedItemInput = ({ source }) => { + const [previewExpanded, setPreviewExpanded] = React.useState(false); + const translate = useTranslate(); + + const iconChoices = React.useMemo( + () => + graphIcons.map(bpIcon => ({ + id: bpIcon, + name: , + })), + [], + ); + + const { + input: { value: url }, + } = useField(`${source}.src`); + + useEffect(() => { + setPreviewExpanded(false); + }, [url]); + + return ( +
+
+ , + }} + style={{ width: '5em', minWidth: '5em' }} + /> + + +
+ + val.match(/(^(https?:)?\/\/.)/)} + > + setPreviewExpanded(val)} + style={{ width: '40em', marginBottom: '2em' }} + > + }> + {translate('datalayer.form.embed.preview')} + + + {previewExpanded && ( +