Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to declare "embed" content to be displayed as iframe #556

Merged
merged 2 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,18 @@
"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)"
}
}
},
Expand Down
12 changes: 12 additions & 0 deletions public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,18 @@
"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)"
}
}
},
Expand Down
16 changes: 16 additions & 0 deletions src/modules/RA/DataLayer/components/DataLayerForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -22,6 +23,7 @@ const initialErrorState = {
minisheet: false,
filter: false,
table: false,
embed: false,
};

const inErrorReducer = (state, { type, payload }) => {
Expand Down Expand Up @@ -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 },
}) => {
Expand Down Expand Up @@ -205,6 +211,16 @@ const DataLayerForm = React.memo(props => {
<FormTab disabled={external} label="datalayer.form.widget.tab" path="other">
<JSONInput source="settings.widgets" label="resources.datalayer.fields.settings-widgets" fullWidth />
</FormTab>

<CustomFormTab
disabled={external}
label="datalayer.form.embed.tab"
path="embed"
inError={errorState.embed}
onChange={onEmbedErrorChange}
>
<EmbedTab />
</CustomFormTab>
</TabbedForm>
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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 (
<>
<Typography variant="h5" component="h2">{translate(label)}</Typography>

{error && error.length > 0 && error.flatMap(err =>
err && Object.entries(err).map(([key, value]) => (
<Typography color="error">{key}: {translate(value)}</Typography>)))}

<ArrayInput source="settings.embed" label="">
<SimpleFormIterator>
<EmbedItemInput />
</SimpleFormIterator>
</ArrayInput>
</>
);
};

export default EmbedConfigField;
101 changes: 101 additions & 0 deletions src/modules/RA/DataLayer/components/tabs/EmbedTab/EmbedItemInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React from 'react';
import { SelectInput, TextInput } from 'react-admin';

import { Icon } from '@blueprintjs/core';

const bpIcons = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should have this in a seperate file? A list of all usable bp icons is not a bad idea and could be used elsewhere

'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 EmbedItemInput = ({ source }) => {
const iconChoices = React.useMemo(
() => bpIcons.map(bpIcon => ({
id: bpIcon,
name: <><Icon icon={bpIcon} style={{ marginRight: '1em' }} /> {bpIcon}</>,
})),
[],
);

return (
<div style={{ display: 'flex', alignItems: 'flex-start', gap: '1em' }}>
<SelectInput
source={`${source}.icon`}
label="datalayer.form.embed.icon"
choices={iconChoices}
translateChoice={false}
helperText={false}
/>

<TextInput
label="datalayer.form.embed.title"
source={`${source}.title`}
type="text"
helperText="datalayer.form.embed.title-help"
/>

<TextInput
label="datalayer.form.embed.src"
source={`${source}.src`}
type="url"
placeholder="https://myiframe.page"
helperText="datalayer.form.embed.src-help"
/>
</div>
);
};

export default EmbedItemInput;
70 changes: 70 additions & 0 deletions src/modules/RA/DataLayer/components/tabs/EmbedTab/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';

import { BooleanInput, useTranslate } from 'react-admin';
import { useField } from 'react-final-form';

import Typography from '@material-ui/core/Typography';
import Placeholder from '../../../../../../components/Placeholder';

import EmbedConfigField from './EmbedConfigField';

const validateEmbedFields = data => {
const valid = !data.some(({ label }) => label && !label.length);
if (!valid) {
return 'datalayer.form.embed.row-in-error';
}
return undefined;
};

const EmbedConfigTabContent = props => {
const { input: { value: embedEnable, onChange: onEmbedEnableChange } } = useField('settings.embed_enable');
const { input: { value: source } } = useField('source');
const { input: { value: embedExportEnable } } = useField('embed_export_enable');
const translate = useTranslate();

if (!source) {
return (
<Placeholder>
<Typography variant="h5" component="h2">
{translate('datalayer.form.embed.no-source')}
</Typography>
</Placeholder>
);
}

// No embed yet
if (!embedEnable) {
return (
<Placeholder>
<div style={{ display: 'flex', flexDirection: 'column', gap: '1em', alignItems: 'center' }}>
<Typography variant="h5" component="h2">{translate('datalayer.form.embed.no-embed')}</Typography>
<BooleanInput
source="settings.embed_enable"
label="datalayer.form.embed.allow"
onChange={onEmbedEnableChange}
/>
</div>
</Placeholder>
);
}

return (
<>
<BooleanInput
source="settings.embed_enable"
label="datalayer.form.embed.allow-display-data-embed"
onChange={onEmbedEnableChange}
/>
<EmbedConfigField
source="fields"
label="datalayer.form.embed.all-fields"
exportEnabled={embedExportEnable}
validate={validateEmbedFields}
{...props}
/>
</>
);
};


export default EmbedConfigTabContent;