From da5d77d9753250b90683e7fa929249fe894b2856 Mon Sep 17 00:00:00 2001 From: Luca Bellenghi Date: Wed, 4 Sep 2024 11:18:17 +0200 Subject: [PATCH] add image and text block --- .../locales/en/LC_MESSAGES/volto.po | 22 +++ .../locales/it/LC_MESSAGES/volto.po | 22 +++ packages/volto-blocks/locales/volto.pot | 24 ++- .../blocks/ImageAndTextBox/Edit.tsx | 137 ++++++++++++++++++ .../blocks/ImageAndTextBox/EditItem.tsx | 33 +++++ .../blocks/ImageAndTextBox/View.tsx | 40 +++++ .../blocks/ImageAndTextBox/ViewItem.tsx | 14 ++ .../blocks/ImageAndTextBox/index.ts | 5 + .../blocks/ImageAndTextBox/schema.ts | 105 ++++++++++++++ .../blocks/ImageAndTextBox/styles.module.css | 27 ++++ packages/volto-blocks/src/config/blocks.ts | 37 +++-- 11 files changed, 456 insertions(+), 10 deletions(-) create mode 100644 packages/volto-blocks/src/components/blocks/ImageAndTextBox/Edit.tsx create mode 100644 packages/volto-blocks/src/components/blocks/ImageAndTextBox/EditItem.tsx create mode 100644 packages/volto-blocks/src/components/blocks/ImageAndTextBox/View.tsx create mode 100644 packages/volto-blocks/src/components/blocks/ImageAndTextBox/ViewItem.tsx create mode 100644 packages/volto-blocks/src/components/blocks/ImageAndTextBox/index.ts create mode 100644 packages/volto-blocks/src/components/blocks/ImageAndTextBox/schema.ts create mode 100644 packages/volto-blocks/src/components/blocks/ImageAndTextBox/styles.module.css diff --git a/packages/volto-blocks/locales/en/LC_MESSAGES/volto.po b/packages/volto-blocks/locales/en/LC_MESSAGES/volto.po index 5d52915..665bd29 100644 --- a/packages/volto-blocks/locales/en/LC_MESSAGES/volto.po +++ b/packages/volto-blocks/locales/en/LC_MESSAGES/volto.po @@ -16,6 +16,16 @@ msgstr "" msgid "Alignment" msgstr "" +#. Default: "Box" +#: components/blocks/ImageAndTextBox/schema +msgid "Box" +msgstr "" + +#. Default: "Boxes" +#: components/blocks/ImageAndTextBox/schema +msgid "Boxes" +msgstr "" + #. Default: "Link Title" #: components/blocks/extenders/cta msgid "Link title" @@ -28,6 +38,8 @@ msgstr "" #. Default: "Text" #: components/blocks/Accordion/EditItem +#: components/blocks/ImageAndTextBox/Edit +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Testimonials/Edit #: components/blocks/Testimonials/schema #: components/blocks/Text1/Edit @@ -41,6 +53,8 @@ msgstr "" #: components/blocks/Accordion/Edit #: components/blocks/Accordion/EditItem #: components/blocks/Accordion/schema +#: components/blocks/ImageAndTextBox/Edit +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Testimonials/Edit #: components/blocks/Testimonials/schema #: components/blocks/Text1/Edit @@ -52,6 +66,11 @@ msgstr "" msgid "Title" msgstr "" +#. Default: "Add column" +#: components/blocks/ImageAndTextBox/schema +msgid "addColumn" +msgstr "" + #. Default: "Columns" #: components/blocks/Accordion/schema msgid "redturtle__volto-blocks__accordion_columns_title" @@ -108,11 +127,13 @@ msgid "redturtle__volto-blocks__text6_title" msgstr "" #. Default: "Image" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_image_title" msgstr "" #. Default: "Images" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_images_title" msgstr "" @@ -128,6 +149,7 @@ msgid "redturtle__volto-blocks__text7_img_column_width_title" msgstr "" #. Default: "Text 7" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_title" msgstr "" diff --git a/packages/volto-blocks/locales/it/LC_MESSAGES/volto.po b/packages/volto-blocks/locales/it/LC_MESSAGES/volto.po index 8330a77..e457596 100644 --- a/packages/volto-blocks/locales/it/LC_MESSAGES/volto.po +++ b/packages/volto-blocks/locales/it/LC_MESSAGES/volto.po @@ -16,6 +16,16 @@ msgstr "" msgid "Alignment" msgstr "" +#. Default: "Box" +#: components/blocks/ImageAndTextBox/schema +msgid "Box" +msgstr "" + +#. Default: "Boxes" +#: components/blocks/ImageAndTextBox/schema +msgid "Boxes" +msgstr "" + #. Default: "Link Title" #: components/blocks/extenders/cta msgid "Link title" @@ -28,6 +38,8 @@ msgstr "" #. Default: "Text" #: components/blocks/Accordion/EditItem +#: components/blocks/ImageAndTextBox/Edit +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Testimonials/Edit #: components/blocks/Testimonials/schema #: components/blocks/Text1/Edit @@ -41,6 +53,8 @@ msgstr "Testo" #: components/blocks/Accordion/Edit #: components/blocks/Accordion/EditItem #: components/blocks/Accordion/schema +#: components/blocks/ImageAndTextBox/Edit +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Testimonials/Edit #: components/blocks/Testimonials/schema #: components/blocks/Text1/Edit @@ -52,6 +66,11 @@ msgstr "Testo" msgid "Title" msgstr "Titolo" +#. Default: "Add column" +#: components/blocks/ImageAndTextBox/schema +msgid "addColumn" +msgstr "" + #. Default: "Columns" #: components/blocks/Accordion/schema msgid "redturtle__volto-blocks__accordion_columns_title" @@ -108,11 +127,13 @@ msgid "redturtle__volto-blocks__text6_title" msgstr "" #. Default: "Image" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_image_title" msgstr "Immagine" #. Default: "Images" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_images_title" msgstr "" @@ -128,6 +149,7 @@ msgid "redturtle__volto-blocks__text7_img_column_width_title" msgstr "" #. Default: "Text 7" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_title" msgstr "" diff --git a/packages/volto-blocks/locales/volto.pot b/packages/volto-blocks/locales/volto.pot index 4618aa8..1d4dc1a 100644 --- a/packages/volto-blocks/locales/volto.pot +++ b/packages/volto-blocks/locales/volto.pot @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Plone\n" -"POT-Creation-Date: 2024-08-20T08:35:27.767Z\n" +"POT-Creation-Date: 2024-09-04T09:08:41.235Z\n" "Last-Translator: Plone i18n \n" "Language-Team: Plone i18n \n" "Content-Type: text/plain; charset=utf-8\n" @@ -18,6 +18,16 @@ msgstr "" msgid "Alignment" msgstr "" +#. Default: "Box" +#: components/blocks/ImageAndTextBox/schema +msgid "Box" +msgstr "" + +#. Default: "Boxes" +#: components/blocks/ImageAndTextBox/schema +msgid "Boxes" +msgstr "" + #. Default: "Link Title" #: components/blocks/extenders/cta msgid "Link title" @@ -30,6 +40,8 @@ msgstr "" #. Default: "Text" #: components/blocks/Accordion/EditItem +#: components/blocks/ImageAndTextBox/Edit +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Testimonials/Edit #: components/blocks/Testimonials/schema #: components/blocks/Text1/Edit @@ -43,6 +55,8 @@ msgstr "" #: components/blocks/Accordion/Edit #: components/blocks/Accordion/EditItem #: components/blocks/Accordion/schema +#: components/blocks/ImageAndTextBox/Edit +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Testimonials/Edit #: components/blocks/Testimonials/schema #: components/blocks/Text1/Edit @@ -54,6 +68,11 @@ msgstr "" msgid "Title" msgstr "" +#. Default: "Add column" +#: components/blocks/ImageAndTextBox/schema +msgid "addColumn" +msgstr "" + #. Default: "Columns" #: components/blocks/Accordion/schema msgid "redturtle__volto-blocks__accordion_columns_title" @@ -110,11 +129,13 @@ msgid "redturtle__volto-blocks__text6_title" msgstr "" #. Default: "Image" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_image_title" msgstr "" #. Default: "Images" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_images_title" msgstr "" @@ -130,6 +151,7 @@ msgid "redturtle__volto-blocks__text7_img_column_width_title" msgstr "" #. Default: "Text 7" +#: components/blocks/ImageAndTextBox/schema #: components/blocks/Text7/schema msgid "redturtle__volto-blocks__text7_title" msgstr "" diff --git a/packages/volto-blocks/src/components/blocks/ImageAndTextBox/Edit.tsx b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/Edit.tsx new file mode 100644 index 0000000..866107f --- /dev/null +++ b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/Edit.tsx @@ -0,0 +1,137 @@ +import { Icon, SidebarPortal } from '@plone/volto/components'; +import { BlockDataForm } from '@plone/volto/components/manage/Form'; +import cx from 'classnames'; +import { defineMessages, useIntl } from 'react-intl'; + +import type { BlockEditProps } from '@plone/types'; + +import type { ImageAndTextBoxData } from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/schema'; +import styles from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/styles.module.css'; +import { + TextEditorWidget, + useHandleDetachedBlockFocus, +} from '@redturtle/volto-rt-slate'; + +import config from '@plone/registry'; +// import EditItem from './EditItem'; + +type ImageAndTextBoxEditProps = Omit & { + data: ImageAndTextBoxData; +}; + +export default function Edit(props: ImageAndTextBoxEditProps) { + const { + data, + selected, + block, + onChangeBlock, + blocksConfig, + blocksErrors, + onFocusPreviousBlock, + onFocusNextBlock, + } = props; + const intl = useIntl(); + + const { selectedField, setSelectedField } = useHandleDetachedBlockFocus( + props, + 'title', + ); + + const schema = blocksConfig[data['@type']].blockSchema({ + data, + intl, + }); + + if (__SERVER__) { + return
; + } + + const Container = config.getComponent('Container').component || 'div'; + const Image = config.getComponent('Image').component; + + return ( + <> +
+ + {data.image ? ( + + ) : ( +
Upload image
+ )} +
+ { + setSelectedField('text'); + }} + showToolbar={false} + placeholder={intl.formatMessage(messages.title)} + /> + { + setSelectedField('title'); + }} + placeholder={intl.formatMessage(messages.text)} + /> + {/* {data.boxes ? : ''} */} +
+
+
+ {/* @ts-expect-error TODO */} + + {schema && ( + } + schema={schema} + title={schema.title} + onChangeField={(id: string, value: unknown) => { + onChangeBlock(block, { + ...data, + [id]: value, + }); + }} + onChangeBlock={onChangeBlock} + formData={data} + block={block} + errors={blocksErrors} + /> + )} + + + ); +} + +const messages = defineMessages({ + title: { + id: 'Title', + defaultMessage: 'Title', + }, + text: { + id: 'Text', + defaultMessage: 'Text', + }, +}); diff --git a/packages/volto-blocks/src/components/blocks/ImageAndTextBox/EditItem.tsx b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/EditItem.tsx new file mode 100644 index 0000000..261e75a --- /dev/null +++ b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/EditItem.tsx @@ -0,0 +1,33 @@ +import cx from 'classnames'; +import { defineMessages, useIntl } from 'react-intl'; + +import type { ArrayElement } from '@plone/types'; + +import type { ImageAndTextBoxData } from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/schema'; +import styles from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/styles.module.css'; + +type Props = { + data: ArrayElement; + focusOn: string; + setFocusOn: Function; + onChange: (id: string, field: string, value: unknown) => void; + selected: boolean; +}; + +export default function EditItem({ + data, + focusOn, + setFocusOn, + onChange, + selected, +}: Props) { + const intl = useIntl(); + + if (__SERVER__) { + return
; + } + + return
BOX
; +} + +const messages = defineMessages({}); diff --git a/packages/volto-blocks/src/components/blocks/ImageAndTextBox/View.tsx b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/View.tsx new file mode 100644 index 0000000..4cbdf73 --- /dev/null +++ b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/View.tsx @@ -0,0 +1,40 @@ +import type { BlockViewProps } from '@plone/types'; +import cx from 'classnames'; + +import type { ImageAndTextBoxData } from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/schema'; +import styles from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/styles.module.css'; +import ViewItem from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/ViewItem'; + +import config from '@plone/registry'; + +type Props = Omit & { + data: ImageAndTextBoxData; +}; + +export default function View({ data, className, style }: Props) { + const Container = config.getComponent('Container').component || 'div'; + + return ( +
+ + {data.title && ( +

+ {data.title} +

+ )} +
+ {data.boxes?.length > 0 && + data.boxes.map((item) => ( + + ))} +
+
+
+ ); +} diff --git a/packages/volto-blocks/src/components/blocks/ImageAndTextBox/ViewItem.tsx b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/ViewItem.tsx new file mode 100644 index 0000000..d98d758 --- /dev/null +++ b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/ViewItem.tsx @@ -0,0 +1,14 @@ +import cx from 'classnames'; + +import type { ArrayElement } from '@plone/types'; + +import type { ImageAndTextBoxData } from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/schema'; +import styles from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/styles.module.css'; + +type Props = { + data: ArrayElement; +}; + +export default function ViewItem({ data }: Props) { + return
BOX
; +} diff --git a/packages/volto-blocks/src/components/blocks/ImageAndTextBox/index.ts b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/index.ts new file mode 100644 index 0000000..e332e1a --- /dev/null +++ b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/index.ts @@ -0,0 +1,5 @@ +import loadable from '@loadable/component'; + +export const ImageAndTextBoxEdit = loadable( + () => import(/* webpackChunkName: "redturtle__volto-blocks" */ './Edit'), +); diff --git a/packages/volto-blocks/src/components/blocks/ImageAndTextBox/schema.ts b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/schema.ts new file mode 100644 index 0000000..fb85b31 --- /dev/null +++ b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/schema.ts @@ -0,0 +1,105 @@ +import type { BlockConfigBase, JSONSchema } from '@plone/types'; +import { + addCtaFieldset, + type CtaBlockExtender, +} from '@redturtle/volto-blocks/components/blocks/extenders/cta'; +import { defineMessages, type IntlShape } from 'react-intl'; +export interface ImageAndTextBoxData extends CtaBlockExtender { + '@type': 'imageandtextbox'; + image: string; + title: string; + text?: object; + boxes?: Array<{ title: string; text: object }>; +} + +const messages = defineMessages({ + title: { + id: 'redturtle__volto-blocks__text7_title', + defaultMessage: 'Text 7', + }, + images_title: { + id: 'redturtle__volto-blocks__text7_images_title', + defaultMessage: 'Images', + }, + image_title: { + id: 'redturtle__volto-blocks__text7_image_title', + defaultMessage: 'Image', + }, + title_title: { + id: 'Title', + defaultMessage: 'Title', + }, + text_title: { + id: 'Text', + defaultMessage: 'Text', + }, + boxes_title: { + id: 'Boxes', + defaultMessage: 'Boxes', + }, + box_title: { + id: 'Box', + defaultMessage: 'Box', + }, + addColumn: { + id: 'addColumn', + defaultMessage: 'Add column', + }, +}); + +export const ImageAndTextBoxSchema = ({ + data, + intl, +}: { + data: ImageAndTextBoxData; + intl: IntlShape; +}): JSONSchema => { + const schema = { + title: intl.formatMessage(messages.title), + fieldsets: [ + { + id: 'default', + title: 'Default', + fields: ['title', 'image', 'boxes'], + }, + ], + properties: { + title: { + title: intl.formatMessage(messages.title_title), + }, + image: { + title: intl.formatMessage(messages.image_title), + widget: 'image', + }, + boxes: { + title: intl.formatMessage(messages.boxes_title), + addMessage: intl.formatMessage(messages.addColumn), + widget: 'object_list', + schema: { + title: intl.formatMessage(messages.box_title), + fieldsets: [ + { + id: 'default', + title: 'Default', + fields: ['title'], + }, + ], + properties: { + title: { + title: intl.formatMessage(messages.box_title), + }, + }, + required: ['title'], + }, + }, + }, + required: ['title'], + }; + addCtaFieldset({ schema, intl }); + return schema; +}; + +export interface ImageAndTextBoxConfig + extends Omit { + blockSchema: typeof ImageAndTextBoxSchema; +} diff --git a/packages/volto-blocks/src/components/blocks/ImageAndTextBox/styles.module.css b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/styles.module.css new file mode 100644 index 0000000..38de9f6 --- /dev/null +++ b/packages/volto-blocks/src/components/blocks/ImageAndTextBox/styles.module.css @@ -0,0 +1,27 @@ +.imageandtextbox { + position: relative; + width: 100%; + height: 300px; + /* overflow: hidden; */ +} +.block-imageandtextbox-container img { + position: absolute; + z-index: 0; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; +} + +.box-wrapper { + position: relative; + z-index: 1; + top: 50%; + right: 100px; + width: 30%; + padding: 20px; + border-radius: 5px; + background-color: white; + float: right; +} diff --git a/packages/volto-blocks/src/config/blocks.ts b/packages/volto-blocks/src/config/blocks.ts index fada3ec..108e134 100644 --- a/packages/volto-blocks/src/config/blocks.ts +++ b/packages/volto-blocks/src/config/blocks.ts @@ -3,44 +3,50 @@ import type { BlocksConfigData } from '@plone/types'; import BlockSettingsSchema from '@plone/volto/components/manage/Blocks/Block/Schema'; import accordionSVG from '@plone/volto/icons/list-arrows.svg'; -import AccordionView from '@redturtle/volto-blocks/components/blocks/Accordion/View'; import { AccordionEdit } from '@redturtle/volto-blocks/components/blocks/Accordion'; import { AccordionSchema, type AccordionConfig, } from '@redturtle/volto-blocks/components/blocks/Accordion/schema'; +import AccordionView from '@redturtle/volto-blocks/components/blocks/Accordion/View'; -import text1SVG from '@redturtle/volto-blocks/icons/text1.svg'; -import Text1View from '@redturtle/volto-blocks/components/blocks/Text1/View'; import { Text1Edit } from '@redturtle/volto-blocks/components/blocks/Text1'; import { Text1Schema, type Text1Config, } from '@redturtle/volto-blocks/components/blocks/Text1/schema'; +import Text1View from '@redturtle/volto-blocks/components/blocks/Text1/View'; +import text1SVG from '@redturtle/volto-blocks/icons/text1.svg'; -import text6SVG from '@redturtle/volto-blocks/icons/text6.svg'; -import Text6View from '@redturtle/volto-blocks/components/blocks/Text6/View'; import { Text6Edit } from '@redturtle/volto-blocks/components/blocks/Text6'; import { Text6Schema, type Text6Config, } from '@redturtle/volto-blocks/components/blocks/Text6/schema'; +import Text6View from '@redturtle/volto-blocks/components/blocks/Text6/View'; +import text6SVG from '@redturtle/volto-blocks/icons/text6.svg'; -import text7SVG from '@redturtle/volto-blocks/icons/text7.svg'; -import Text7View from '@redturtle/volto-blocks/components/blocks/Text7/View'; import { Text7Edit } from '@redturtle/volto-blocks/components/blocks/Text7'; import { Text7Schema, type Text7Config, } from '@redturtle/volto-blocks/components/blocks/Text7/schema'; +import Text7View from '@redturtle/volto-blocks/components/blocks/Text7/View'; +import text7SVG from '@redturtle/volto-blocks/icons/text7.svg'; -import TestimonialsView from '@redturtle/volto-blocks/components/blocks/Testimonials/View'; import { TestimonialsEdit } from '@redturtle/volto-blocks/components/blocks/Testimonials'; import { TestimonialsSchema, type TestimonialsConfig, } from '@redturtle/volto-blocks/components/blocks/Testimonials/schema'; +import TestimonialsView from '@redturtle/volto-blocks/components/blocks/Testimonials/View'; +import { ImageAndTextBoxEdit } from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox'; +import { + ImageAndTextBoxSchema, + type ImageAndTextBoxConfig, +} from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/schema'; +import ImageAndTextBoxView from '@redturtle/volto-blocks/components/blocks/ImageAndTextBox/View'; declare module '@plone/types' { interface BlocksConfigData { accordion: AccordionConfig; @@ -48,12 +54,13 @@ declare module '@plone/types' { text6: Text6Config; text7: Text7Config; testimonials: TestimonialsConfig; + imageandtextbox: ImageAndTextBoxConfig; } } type RtBlocksConfig = Pick< BlocksConfigData, - 'accordion' | 'text1' | 'text6' | 'text7' | 'testimonials' + 'accordion' | 'text1' | 'text6' | 'text7' | 'testimonials' | 'imageandtextbox' >; const defaultBlocksConfig = { @@ -124,4 +131,16 @@ export const blocks: RtBlocksConfig = { blockHasOwnFocusManagement: true, blockSchema: TestimonialsSchema, }, + imageandtextbox: { + ...defaultBlocksConfig, + id: 'imageandtextbox', + title: 'Image and text box', + icon: accordionSVG, + group: 'text', + mostUsed: true, + view: ImageAndTextBoxView, + edit: ImageAndTextBoxEdit, + blockHasOwnFocusManagement: true, + blockSchema: ImageAndTextBoxSchema, + }, } as const;