diff --git a/apps/cms/config/sync/gutenberg.settings.yml b/apps/cms/config/sync/gutenberg.settings.yml index e58422162..ed9ef9d7d 100644 --- a/apps/cms/config/sync/gutenberg.settings.yml +++ b/apps/cms/config/sync/gutenberg.settings.yml @@ -4,12 +4,12 @@ page_template_lock: all page_allowed_blocks: core/paragraph: core/paragraph core/list: core/list - core/quote: core/quote core/table: core/table core/all: 0 core/image: 0 core/heading: 0 core/gallery: 0 + core/quote: 0 core/audio: 0 core/button: 0 core/buttons: 0 @@ -75,6 +75,7 @@ page_allowed_drupal_blocks: drupalblock/all_core: 0 page_title_block: 0 drupalblock/all_forms: 0 + masquerade: 0 user_login_block: 0 drupalblock/all_lists_views_: 0 'views_block:content_recent-block_1': 0 @@ -91,3 +92,6 @@ page_allowed_drupal_blocks: system_branding_block: 0 node_syndicate_block: 0 drupalblock/all_user: 0 + drupalblock/all_webform: 0 + webform_block: 0 + webform_submission_limit_block: 0 diff --git a/packages/drupal/gutenberg_blocks/css/edit.css b/packages/drupal/gutenberg_blocks/css/edit.css index f4a49c277..1c603451e 100644 --- a/packages/drupal/gutenberg_blocks/css/edit.css +++ b/packages/drupal/gutenberg_blocks/css/edit.css @@ -12,6 +12,11 @@ content: ''; } +.gutenberg__editor blockquote .quote-author, +.gutenberg__editor blockquote .quote-role { + text-align: right; +} + .gutenberg__editor .container-wrapper { display: block; position: relative; diff --git a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/QuoteValidator.php b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/QuoteValidator.php new file mode 100644 index 000000000..53df53041 --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/QuoteValidator.php @@ -0,0 +1,40 @@ + [ + 'field_label' => $this->t('Quote text'), + 'rules' => ['required'], + ], + 'author' => [ + 'field_label' => $this->t('Quote author'), + 'rules' => ['required'], + ], + ]; + } + +} diff --git a/packages/drupal/gutenberg_blocks/src/blocks/quote.tsx b/packages/drupal/gutenberg_blocks/src/blocks/quote.tsx new file mode 100644 index 000000000..1aea31b6a --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/quote.tsx @@ -0,0 +1,100 @@ +import { RichText } from 'wordpress__block-editor'; +import { registerBlockType } from 'wordpress__blocks'; +import { compose, withState } from 'wordpress__compose'; +import { dispatch } from 'wordpress__data'; + +import { cleanUpText } from '../utils/clean-up-text'; +import { DrupalMediaEntity } from '../utils/drupal-media'; + +declare const Drupal: { t: (s: string) => string }; + +const { t: __ } = Drupal; + +// @ts-ignore +const { setPlainTextAttribute } = silverbackGutenbergUtils; + +// @ts-ignore +registerBlockType(`custom/quote`, { + title: __('Quote'), + icon: 'format-quote', + category: 'text', + attributes: { + quote: { + type: 'string', + }, + author: { + tpye: 'string', + }, + role: { + type: 'string', + }, + mediaEntityIds: { + type: 'array', + }, + }, + // @ts-ignore + edit: compose(withState())((props) => { + return ( +
++ ); + }), + save() { + return null; + }, +}); diff --git a/packages/drupal/gutenberg_blocks/src/index.ts b/packages/drupal/gutenberg_blocks/src/index.ts index a0aff90af..332b5720f 100644 --- a/packages/drupal/gutenberg_blocks/src/index.ts +++ b/packages/drupal/gutenberg_blocks/src/index.ts @@ -6,3 +6,4 @@ import './blocks/form'; import './blocks/image-teaser'; import './blocks/image-teasers'; import './blocks/cta'; +import './blocks/quote'; diff --git a/packages/drupal/test_content/content/node/a397ca48-8fad-411e-8901-0eba2feb989c.yml b/packages/drupal/test_content/content/node/a397ca48-8fad-411e-8901-0eba2feb989c.yml index 2a18b3664..0ee37d6aa 100644 --- a/packages/drupal/test_content/content/node/a397ca48-8fad-411e-8901-0eba2feb989c.yml +++ b/packages/drupal/test_content/content/node/a397ca48-8fad-411e-8901-0eba2feb989c.yml @@ -10,31 +10,43 @@ _meta: 72187a1f-3e48-4b45-a9b7-189c6fd7ee26: media default: revision_uid: - - target_id: 1 + - + target_id: 1 status: - - value: true + - + value: true uid: - - target_id: 1 + - + target_id: 1 title: - - value: 'Blocks: complete' + - + value: 'Blocks: complete' created: - - value: 1686759493 + - + value: 1686759493 promote: - - value: false + - + value: false sticky: - - value: false + - + value: false moderation_state: - - value: published + - + value: published path: - - alias: /blocks-complete + - + alias: /blocks-complete langcode: en pathauto: 0 content_translation_source: - - value: und + - + value: und content_translation_outdated: - - value: false + - + value: false body: - - value: |- + - + value: |- @@ -79,6 +91,9 @@ default: + + + @@ -88,29 +103,40 @@ default: translations: de: status: - - value: true + - + value: true uid: - - target_id: 1 + - + target_id: 1 title: - - value: 'Blocks: complete DE' + - + value: 'Blocks: complete DE' created: - - value: 1687338353 + - + value: 1687338353 promote: - - value: false + - + value: false sticky: - - value: false + - + value: false moderation_state: - - value: published + - + value: published path: - - alias: /blocks-complete + - + alias: /blocks-complete langcode: de pathauto: 0 content_translation_source: - - value: en + - + value: en content_translation_outdated: - - value: false + - + value: false body: - - value: |- + - + value: |- @@ -149,6 +175,8 @@ translations: + + format: gutenberg summary: '' diff --git a/packages/drupal/test_content/content/node/ceb9b2a7-4c4c-4084-ada9-d5f6505d466b.yml b/packages/drupal/test_content/content/node/ceb9b2a7-4c4c-4084-ada9-d5f6505d466b.yml index 6c19a491d..704d39565 100644 --- a/packages/drupal/test_content/content/node/ceb9b2a7-4c4c-4084-ada9-d5f6505d466b.yml +++ b/packages/drupal/test_content/content/node/ceb9b2a7-4c4c-4084-ada9-d5f6505d466b.yml @@ -67,6 +67,8 @@ default: + + format: gutenberg summary: '' diff --git a/packages/schema/src/fragments/Page.gql b/packages/schema/src/fragments/Page.gql index 38c057340..4c3fe1e11 100644 --- a/packages/schema/src/fragments/Page.gql +++ b/packages/schema/src/fragments/Page.gql @@ -33,6 +33,7 @@ fragment Page on Page { ...BlockForm ...BlockImageTeasers ...BlockCta + ...BlockQuote } metaTags { tag diff --git a/packages/schema/src/fragments/PageContent/BlockQuote.gql b/packages/schema/src/fragments/PageContent/BlockQuote.gql new file mode 100644 index 000000000..785efb620 --- /dev/null +++ b/packages/schema/src/fragments/PageContent/BlockQuote.gql @@ -0,0 +1,9 @@ +fragment BlockQuote on BlockQuote { + quote + author + role + image { + source(width: 1536, sizes: [[768, 768], [1536, 1536]]) + alt + } +} diff --git a/packages/schema/src/schema.graphql b/packages/schema/src/schema.graphql index 9300972cb..43bff39d9 100644 --- a/packages/schema/src/schema.graphql +++ b/packages/schema/src/schema.graphql @@ -199,6 +199,7 @@ union PageContent @resolveEditorBlockType = | BlockForm | BlockImageTeasers | BlockCta + | BlockQuote type BlockForm @type(id: "custom/form") { url: Url @resolveEditorBlockAttribute(key: "formId") @webformIdToUrl(id: "$") @@ -244,6 +245,13 @@ type BlockCta @type(id: "custom/cta") { openInNewTab: Boolean @resolveEditorBlockAttribute(key: "openInNewTab") } +type BlockQuote @type(id: "custom/quote") { + quote: Markup @resolveEditorBlockAttribute(key: "quote") + author: String @resolveEditorBlockAttribute(key: "author") + role: String @resolveEditorBlockAttribute(key: "role") + image: MediaImage @resolveEditorBlockMedia +} + input PaginationInput { limit: Int! offset: Int! diff --git a/packages/ui/src/components/Organisms/PageContent/BlockMarkup.tsx b/packages/ui/src/components/Organisms/PageContent/BlockMarkup.tsx index 54f29a9fb..a83f81b79 100644 --- a/packages/ui/src/components/Organisms/PageContent/BlockMarkup.tsx +++ b/packages/ui/src/components/Organisms/PageContent/BlockMarkup.tsx @@ -18,7 +18,6 @@ export function BlockMarkup(props: BlockMarkupFragment) { className={clsx([ 'mx-auto max-w-3xl prose lg:prose-xl mt-10', 'prose-a:text-indigo-600', - 'prose-blockquote:border-indigo-200', 'prose-em:text-indigo-600', 'prose-strong:text-indigo-600', 'marker:text-indigo-600 marker:font-bold', @@ -49,6 +48,25 @@ export function BlockMarkup(props: BlockMarkupFragment) { ); }, + blockquote: ({ children }: PropsWithChildren<{}>) => { + return ( +{ + props.setAttributes({ + quote: cleanUpText(quote, ['strong']), + }); + }} + /> + { + setPlainTextAttribute(props, 'author', author); + }} + /> + { + setPlainTextAttribute(props, 'role', role); + }} + /> + { + // @ts-ignore + error = typeof error === 'string' ? error : error[2]; + dispatch('core/notices').createWarningNotice(error); + }} + /> +
+ + {children} ++ ); + }, }} markup={props.markup} /> diff --git a/packages/ui/src/components/Organisms/PageContent/BlockQuote.stories.ts b/packages/ui/src/components/Organisms/PageContent/BlockQuote.stories.ts new file mode 100644 index 000000000..e5efd0c53 --- /dev/null +++ b/packages/ui/src/components/Organisms/PageContent/BlockQuote.stories.ts @@ -0,0 +1,23 @@ +import { Markup } from '@custom/schema'; +import Portrait from '@stories/portrait.jpg?as=metadata'; +import { Meta, StoryObj } from '@storybook/react'; + +import { image } from '../../../helpers/image'; +import { BlockQuote } from './BlockQuote'; + +export default { + component: BlockQuote, +} satisfies Meta
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
' as Markup, + }, +} satisfies StoryObj+ + {props.quote &&} +
{props.author}
} ++ / + + {props.role} + +
+ )} +