Skip to content

Commit

Permalink
feat: added Callout block
Browse files Browse the repository at this point in the history
  • Loading branch information
giuliaghisini committed Oct 3, 2023
1 parent a9dc7b2 commit 3f04f5c
Show file tree
Hide file tree
Showing 31 changed files with 1,115 additions and 452 deletions.
143 changes: 143 additions & 0 deletions src/components/ItaliaTheme/Blocks/Callout/Edit.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/**
* Edit Callout block.
* @module components/ItaliaTheme/Blocks/Callout/Edit
*/

import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { defineMessages, useIntl } from 'react-intl';
import { isEqual } from 'lodash';
import { SidebarPortal } from '@plone/volto/components';

import { Callout, CalloutTitle, CalloutText } from 'design-react-kit';
import { Icon } from 'design-comuni-plone-theme/components/ItaliaTheme';
import Sidebar from './Sidebar.jsx';
import { TextEditorWidget } from 'design-comuni-plone-theme/components/ItaliaTheme';

const messages = defineMessages({
title: {
id: 'Type the title…',
defaultMessage: 'Type the title…',
},
text: {
id: 'Type text…',
defaultMessage: 'Digita il testo…',
},
});
/**
* Edit Calloout block class.
* @class Edit
* @extends Component
*/
const Edit = ({
data,
onChangeBlock,
block,
onSelectBlock,
onAddBlock,
index,
selected,
onFocusPreviousBlock,
onFocusNextBlock,
}) => {
const intl = useIntl();
const [selectedField, setSelectedField] = useState('title');

useEffect(() => {
if (selected) {
setSelectedField('title');
} else {
setSelectedField(null);
}
}, [selected]);
/**
* Change handler
* @method onChange
* @param {object} editorState Editor state.
* @returns {undefined}
*/
const onChange = (obj, fieldname) => {
if (!isEqual(obj[fieldname], data[fieldname])) {
onChangeBlock(block, {
...data,
[fieldname]: obj[fieldname],
});
}
};

return __SERVER__ ? (
<div />
) : (
<div className="public-ui" id={block}>
<Callout
highlight={data.style === 'highlight'}
color={data.color?.replace('callout_', '')}
>
<CalloutTitle tag="h4">
<Icon icon="it-check-circle" padding={false} aria-hidden />

<TextEditorWidget
data={data}
block={block}
setSelected={() => setSelectedField('title')}
onSelectBlock={(block) => setSelectedField('title')}
onChangeBlock={(block, data) => {
onChange({ ...data, title: data.plaintext }, 'title');
}}
selected={selectedField === 'title'}
placeholder={intl.formatMessage(messages.title)}
showToolbar={false}
index={index}
wrapClass={`title-edit-wrapper ${
data.title?.blocks?.[0]?.text?.length > 0 ? 'has-text' : ''
}`}
// onAddBlock={() => {
// setSelectedField('text');
// }}
// onFocusNextBlock={() => {
// setSelectedField('text');
// }}
// onFocusPreviousBlock={onFocusPreviousBlock}
/>
</CalloutTitle>
<CalloutText>
<TextEditorWidget
data={data}
block={block}
setSelected={() => setSelectedField('text')}
onSelectBlock={(block) => setSelectedField('text')}
onChangeBlock={(block, data) => {
onChange({ ...data, title: data.value }, 'text');
}}
selected={selectedField === 'text'}
placeholder={intl.formatMessage(messages.text)}
index={index}
// onFocusNextBlock={onFocusNextBlock}
// onFocusPreviousBlock={() => {
// setSelectedField('title');
// }}
/>
</CalloutText>
</Callout>

<SidebarPortal selected={selected || false}>
<Sidebar data={data} block={block} onChangeBlock={onChangeBlock} />
</SidebarPortal>
</div>
);
};

Edit.propTypes = {
properties: PropTypes.objectOf(PropTypes.any).isRequired,
selected: PropTypes.bool.isRequired,
index: PropTypes.number.isRequired,
onChangeField: PropTypes.func.isRequired,
onSelectBlock: PropTypes.func.isRequired,
onDeleteBlock: PropTypes.func.isRequired,
onAddBlock: PropTypes.func.isRequired,
onFocusPreviousBlock: PropTypes.func.isRequired,
onFocusNextBlock: PropTypes.func.isRequired,
block: PropTypes.string.isRequired,
};

export default Edit;
135 changes: 135 additions & 0 deletions src/components/ItaliaTheme/Blocks/Callout/Sidebar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { Segment } from 'semantic-ui-react';
import { FormattedMessage, injectIntl } from 'react-intl';
import { /*TextWidget,*/ SelectWidget } from '@plone/volto/components';

import { defineMessages, useIntl } from 'react-intl';
import IconWidget from 'design-comuni-plone-theme/components/ItaliaTheme/manage/Widgets/IconWidget';
import { defaultIconWidgetOptions } from 'design-comuni-plone-theme/helpers/index';
import { ColorListWidget } from 'design-comuni-plone-theme/components/ItaliaTheme';

const messages = defineMessages({
color: { id: 'color', defaultMessage: 'Colore' },
color_default: {
id: 'color_default',
defaultMessage: 'Default',
},
color_success: {
id: 'color_success',
defaultMessage: 'Success',
},
color_warning: {
id: 'color_warning',
defaultMessage: 'Warning',
},
color_danger: {
id: 'color_danger',
defaultMessage: 'Danger',
},
color_note: {
id: 'color_note',
defaultMessage: 'Note',
},
style: { id: 'callout_style', defaultMessage: 'Stile' },
style_basic: { id: 'callout_style_basic', defaultMessage: 'Base' },
style_highlight: {
id: 'callout_style_highlight',
defaultMessage: 'In evidenza',
},
});

const Sidebar = ({ data, block, onChangeBlock }) => {
const intl = useIntl();
const colors = [
{
name: 'callout_default',
label: intl.formatMessage(messages.color_default),
},
{ name: 'success', label: intl.formatMessage(messages.color_success) },
{ name: 'warning', label: intl.formatMessage(messages.color_warning) },
{ name: 'danger', label: intl.formatMessage(messages.color_danger) },
{ name: 'callout_note', label: intl.formatMessage(messages.color_note) },
];

const styles = [
['base', intl.formatMessage(messages.style_basic)],
['highlight', intl.formatMessage(messages.style_highlight)],
];

useEffect(() => {
if (!data.style) {
onChangeBlock(block, { ...data, style: styles[0][0] });
}
}, []);

return (
<Segment.Group raised>
<header className="header pulled">
<h2>
<FormattedMessage id="Callout" defaultMessage="Callout" />
</h2>
</header>
<div className="ui form">
<SelectWidget
id="style"
title={intl.formatMessage(messages.style)}
required={false}
value={data.style}
intl={intl}
onChange={(id, value) => {
onChangeBlock(block, { ...data, [id]: value });
}}
choices={styles}
noValueOption={false}
/>
<ColorListWidget
id="color"
title={intl.formatMessage(messages.color)}
value={data.color}
onChange={(id, value) => {
onChangeBlock(block, {
...data,
[id]: value,
});
}}
colors={colors}
/>

<IconWidget
id="icon"
value={data.icon ?? ''}
defaultOptions={defaultIconWidgetOptions}
onChange={(name, value) => {
onChangeBlock(block, {
...data,
[name]: value,
});
}}
/>

{/* <TextWidget
id="title"
title={intl.formatMessage(messages.linkMoreTitle)}
value={data.linkMoreTitle}
onChange={(name, value) => {
onChangeBlock(block, {
...data,
linkMoreTitle: value,
});
}}
/> */}
</div>
</Segment.Group>
);
};

Sidebar.propTypes = {
data: PropTypes.objectOf(PropTypes.any),
block: PropTypes.string,
onChangeBlock: PropTypes.func,
selected: PropTypes.any,
setSelected: PropTypes.func,
};

export default injectIntl(Sidebar);
44 changes: 44 additions & 0 deletions src/components/ItaliaTheme/Blocks/Callout/View.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* View Callout block.
* @module components/ItaliaTheme/Blocks/Callout/View
*/

import React from 'react';
import PropTypes from 'prop-types';

import { Callout, CalloutTitle, CalloutText } from 'design-react-kit';
import { Icon } from 'design-comuni-plone-theme/components/ItaliaTheme';
/**
* View Callout block class.
* @class CalloutView
* @extends Component
*/

const View = ({ data, id }) => {
return (
<div className="block callout_block" id={id}>
<Callout>
<CalloutTitle>
<Icon icon="it-check-circle" padding={false} aria-hidden />
<span className="sr-only">{data.title}</span>
{data.title}
</CalloutTitle>
<CalloutText>
Maecenas vulputate ante dictum vestibulum volutpat. Lorem ipsum dolor
sit amet, consectetur adipiscing elit. Aenean non augue non purus
vestibulum varius.
</CalloutText>
</Callout>
</div>
);
};
/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
View.propTypes = {
data: PropTypes.objectOf(PropTypes.any).isRequired,
};

export default View;
13 changes: 11 additions & 2 deletions src/components/ItaliaTheme/manage/Widgets/ColorListWidget.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,16 @@ class ColorListWidget extends Component {
* @returns {string} Markup for the component.
*/
render() {
const { id, title, required, value, onChange, intl, colors, className } =
this.props;
const {
id,
title,
required,
value,
onChange,
intl,
colors,
className,
} = this.props;
return colors.length > 0 ? (
<Form.Field
inline
Expand Down Expand Up @@ -78,6 +86,7 @@ class ColorListWidget extends Component {
active={value === color.name}
circular
aria-label={color.label}
title={color.label}
/>
);
})}
Expand Down
Loading

0 comments on commit 3f04f5c

Please sign in to comment.