@plone/volto
Version:
Volto
192 lines (176 loc) • 4.97 kB
JSX
import React from 'react';
import { useDispatch } from 'react-redux';
import { defineMessages, useIntl } from 'react-intl';
import { Button } from 'semantic-ui-react';
import { toast } from 'react-toastify';
import Icon from '@plone/volto/components/theme/Icon/Icon';
import Toast from '@plone/volto/components/manage/Toast/Toast';
import { BlockDataForm } from '@plone/volto/components/manage/Form';
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
import { messages as defaultMessages } from '@plone/volto/helpers/MessageLabels/MessageLabels';
import { getContent } from '@plone/volto/actions/content/content';
import isEmpty from 'lodash/isEmpty';
import reloadSVG from '@plone/volto/icons/reload.svg';
import trashSVG from '@plone/volto/icons/delete.svg';
const messages = defineMessages({
resetTeaser: {
id: 'Reset the block',
defaultMessage: 'Reset the block',
},
refreshTeaser: {
id: 'Refresh source content',
defaultMessage: 'Reset to target',
},
invalidTeaser: {
id: 'Invalid teaser source',
defaultMessage: 'Invalid teaser source',
},
});
function getImageField(resp) {
if (!resp) return null;
if (resp.preview_image_link) return 'preview_image_link';
if (resp.preview_image) return 'preview_image';
if (resp.image) return 'image';
return null;
}
const TeaserData = (props) => {
const {
block,
blocksConfig,
blocksErrors,
data,
onChangeBlock,
navRoot,
contentType,
} = props;
const dispatch = useDispatch();
const intl = useIntl();
const reset = () => {
onChangeBlock(block, {
...data,
href: '',
title: '',
description: '',
head_title: '',
});
};
const dataTransformer = (resp, data) => {
let hrefData = {
'@id': flattenToAppURL(resp['@id']),
'@type': resp?.['@type'],
Description: resp?.description,
Title: resp.title,
hasPreviewImage: getImageField(resp) ? true : false,
head_title: resp.head_title ?? null,
image_field: getImageField(resp),
image_scales: {
preview_image: [resp?.preview_image],
image: [resp?.image],
preview_image_link: resp?.preview_image_link
? [
{
...resp?.preview_image_link?.['image_scales']?.image?.[0],
base_path: resp?.preview_image_link?.['@id'],
},
]
: [],
},
title: resp.title,
};
let blockData = {
'@type': data['@type'],
description: resp?.description,
head_title: resp?.head_title,
overwrite: data.overwrite,
href: [hrefData],
styles: data.styles,
title: resp.title,
};
return blockData;
};
const refresh = () => {
if (data.href?.[0]?.['@id']) {
dispatch(
getContent(
flattenToAppURL(data.href[0]['@id']),
null,
`${block}-teaser`,
),
)
.then((resp) => {
if (resp) {
let blockData = dataTransformer(resp, data);
onChangeBlock(block, blockData);
}
})
.catch((e) => {
toast.error(
<Toast
error
title={props.intl.formatMessage(defaultMessages.error)}
content={props.intl.formatMessage(messages.invalidTeaser)}
/>,
);
});
}
};
const isReseteable =
isEmpty(data.href) && !data.title && !data.description && !data.head_title;
const HeaderActions = (
<Button.Group>
<Button
aria-label={intl.formatMessage(messages.resetTeaser)}
type="button"
basic
disabled={isReseteable}
onClick={() => reset()}
>
<Icon name={trashSVG} size="24px" color="red" />
</Button>
</Button.Group>
);
const ActionButton = (
<Button.Group className="refresh teaser">
<Button
aria-label={intl.formatMessage(messages.refreshTeaser)}
type="button"
basic
onClick={() => refresh()}
disabled={isEmpty(data.href)}
>
{intl.formatMessage(messages.refreshTeaser)}
<Icon name={reloadSVG} size="20px" color="#00000099" />
</Button>
</Button.Group>
);
const schema = blocksConfig[data['@type']].blockSchema({
data,
intl,
});
const dataAdapter = blocksConfig[data['@type']].dataAdapter;
return (
<BlockDataForm
schema={schema}
title={schema.title}
onChangeField={(id, value) => {
dataAdapter({
block,
data,
id,
onChangeBlock,
value,
});
}}
onChangeBlock={onChangeBlock}
formData={data}
block={block}
blocksConfig={blocksConfig}
headerActions={HeaderActions}
actionButton={data.overwrite && ActionButton}
navRoot={navRoot}
contentType={contentType}
errors={blocksErrors}
/>
);
};
export default TeaserData;