From 74e61e9591d412ef67a87c40c4279393a8ae0812 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 11:11:10 +0200 Subject: [PATCH 01/25] feat(SLB-300): add accordion block --- .../src/blocks/accordion-item-text.tsx | 90 +++++++++++++++++++ .../gutenberg_blocks/src/blocks/accordion.tsx | 25 ++++++ packages/drupal/gutenberg_blocks/src/index.ts | 2 + 3 files changed, 117 insertions(+) create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/accordion.tsx diff --git a/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx b/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx new file mode 100644 index 000000000..774c0a96c --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx @@ -0,0 +1,90 @@ +import React, { Fragment } from 'react'; +import { InspectorControls, RichText } from 'wordpress__block-editor'; +import { registerBlockType } from 'wordpress__blocks'; +import { PanelBody, SelectControl } from 'wordpress__components'; +import { compose, withState } from 'wordpress__compose'; + +// @ts-ignore +const { t: __ } = Drupal; +// @ts-ignore +registerBlockType('custom/accordion-item-text', { + title: 'Accordion Item Text', + icon: 'text', + category: 'layout', + parent: ['custom/accordion'], + attributes: { + title: { + type: 'string', + }, + text: { + type: 'string', + }, + icon: { + type: 'string', + }, + }, + // @ts-ignore + edit: compose(withState())((props) => { + const { attributes, setAttributes } = props; + const icons = [ + { label: __('- Select an optional icon -'), value: '' }, + { label: __('Checkmark'), value: 'checkmark' }, + { label: __('Questionmark'), value: 'questionmark' }, + { label: __('Arrow'), value: 'arrow' }, + ]; + setAttributes({ + icon: attributes.icon === undefined ? '' : attributes.icon, + }); + + return ( + + + + { + setAttributes({ + icon: newValue, + }); + }} + /> + + +
+
{__('Accordion Item Text')}
+
+ { + setAttributes({ title: newValue }); + }} + /> + { + setAttributes({ text: newValue }); + }} + /> +
+
+
+ ); + }), + + save() { + return null; + }, +}); diff --git a/packages/drupal/gutenberg_blocks/src/blocks/accordion.tsx b/packages/drupal/gutenberg_blocks/src/blocks/accordion.tsx new file mode 100644 index 000000000..924746dd8 --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/accordion.tsx @@ -0,0 +1,25 @@ +import { InnerBlocks } from 'wordpress__block-editor'; +import { registerBlockType } from 'wordpress__blocks'; + +// @ts-ignore +const { t: __ } = Drupal; + +registerBlockType('custom/accordion', { + title: __('Accordion'), + icon: 'menu', + category: 'layout', + attributes: {}, + edit: () => { + return ( +
+
{__('Accordion')}
+ +
+ ); + }, + save: () => , +}); diff --git a/packages/drupal/gutenberg_blocks/src/index.ts b/packages/drupal/gutenberg_blocks/src/index.ts index 2763bdad8..1a936eb57 100644 --- a/packages/drupal/gutenberg_blocks/src/index.ts +++ b/packages/drupal/gutenberg_blocks/src/index.ts @@ -9,3 +9,5 @@ import './blocks/image-with-text'; import './filters/list'; import './blocks/cta'; import './blocks/quote'; +import './blocks/accordion'; +import './blocks/accordion-item-text'; From abec41f839406203bf54cb7c061a80be6e2b32d5 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 11:30:28 +0200 Subject: [PATCH 02/25] feat(SLB-300): accordion validators --- .../AccordionItemTextValidator.php | 37 ++++++++++++++++++ .../GutenbergValidator/AccordionValidator.php | 39 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php create mode 100644 packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php diff --git a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php new file mode 100644 index 000000000..6f9a6dcee --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php @@ -0,0 +1,37 @@ + [ + 'field_label' => $this->t('Title'), + 'rules' => ['required'], + ], + // @todo check if we want text as rich text or inner blocks. + ]; + } + +} diff --git a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php new file mode 100644 index 000000000..6e7443e53 --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php @@ -0,0 +1,39 @@ + 'custom/accordion-item-text', + 'blockLabel' => $this->t('Accordion'), + 'min' => 1, + 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED, + ], + ]; + return $this->validateCardinality($block, $expectedChildren); + } + +} From b6a65f4f4f489e858c1025fa0812df13ffa74f4a Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 11:43:19 +0200 Subject: [PATCH 03/25] feat(SLB-300): accordion schema --- packages/schema/src/schema.graphql | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/schema/src/schema.graphql b/packages/schema/src/schema.graphql index ca52d0ef3..1114a2cea 100644 --- a/packages/schema/src/schema.graphql +++ b/packages/schema/src/schema.graphql @@ -206,6 +206,7 @@ union PageContent @resolveEditorBlockType = | BlockCta | BlockImageWithText | BlockQuote + | BlockAccordion type BlockForm @type(id: "custom/form") { url: Url @resolveEditorBlockAttribute(key: "formId") @webformIdToUrl(id: "$") @@ -245,6 +246,24 @@ type BlockImageTeaser @default @value { ctaUrl: Url @resolveEditorBlockAttribute(key: "ctaUrl") } +type BlockAccordion @type(id: "custom/accordion") { + items: [BlockAccordionItem]! @resolveEditorBlockChildren +} + +interface BlockAccordionItemInterface { + title: String! +} + +union BlockAccordionItem @resolveEditorBlockType = BlockAccordionItemText + +type BlockAccordionItemText implements BlockAccordionItemInterface + @type(id: "custom/accordion-item-text") { + title: String! @resolveEditorBlockAttribute(key: "title") + icon: String! @resolveEditorBlockAttribute(key: "icon") + # @todo check if we want inner blocks here. + text: String! @resolveEditorBlockAttribute(key: "text") +} + type BlockCta @type(id: "custom/cta") { url: Url @resolveEditorBlockAttribute(key: "url") text: String @resolveEditorBlockAttribute(key: "text") From cca79348f01e9356df9fc7778abe414f93f5555a Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 12:38:36 +0200 Subject: [PATCH 04/25] chore(SLB-300): add placeholder for storybook integration --- packages/ui/src/components/Organisms/PageDisplay.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/ui/src/components/Organisms/PageDisplay.tsx b/packages/ui/src/components/Organisms/PageDisplay.tsx index 86813de03..6369f68f6 100644 --- a/packages/ui/src/components/Organisms/PageDisplay.tsx +++ b/packages/ui/src/components/Organisms/PageDisplay.tsx @@ -60,6 +60,10 @@ export function PageDisplay(page: PageFragment) { ); case 'BlockQuote': return
; + case 'BlockAccordion': + // @todo implement. + // eslint-disable-next-line react/jsx-no-literals + return
BlockAccordion goes here
; default: throw new UnreachableCaseError(block); } From 7d5cd0674ae4b7dbcf62ab553752e271a03439d5 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 13:09:06 +0200 Subject: [PATCH 05/25] feat(SLB-300): add accordion fragments --- packages/schema/src/fragments/Page.gql | 1 + .../src/fragments/PageContent/BlockAccordion.gql | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 packages/schema/src/fragments/PageContent/BlockAccordion.gql diff --git a/packages/schema/src/fragments/Page.gql b/packages/schema/src/fragments/Page.gql index cbf2227eb..53a741be7 100644 --- a/packages/schema/src/fragments/Page.gql +++ b/packages/schema/src/fragments/Page.gql @@ -35,6 +35,7 @@ fragment Page on Page { ...BlockCta ...BlockImageWithText ...BlockQuote + ...BlockAccordion } metaTags { tag diff --git a/packages/schema/src/fragments/PageContent/BlockAccordion.gql b/packages/schema/src/fragments/PageContent/BlockAccordion.gql new file mode 100644 index 000000000..d98beaa51 --- /dev/null +++ b/packages/schema/src/fragments/PageContent/BlockAccordion.gql @@ -0,0 +1,11 @@ +fragment BlockAccordion on BlockAccordion { + items { + ...BlockAccordionItemText + } +} + +fragment BlockAccordionItemText on BlockAccordionItemText { + title + icon + text +} From 8b75635e9e001b1ed6b7f7755d85458e5b5566f0 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 14:16:18 +0200 Subject: [PATCH 06/25] fix(SLB-300): don't use union for now Types implementing queryable interfaces must also implement the Node interface. --- packages/schema/src/schema.graphql | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/schema/src/schema.graphql b/packages/schema/src/schema.graphql index 1114a2cea..c65d6f320 100644 --- a/packages/schema/src/schema.graphql +++ b/packages/schema/src/schema.graphql @@ -247,17 +247,10 @@ type BlockImageTeaser @default @value { } type BlockAccordion @type(id: "custom/accordion") { - items: [BlockAccordionItem]! @resolveEditorBlockChildren + items: [BlockAccordionItemText]! @resolveEditorBlockChildren } -interface BlockAccordionItemInterface { - title: String! -} - -union BlockAccordionItem @resolveEditorBlockType = BlockAccordionItemText - -type BlockAccordionItemText implements BlockAccordionItemInterface - @type(id: "custom/accordion-item-text") { +type BlockAccordionItemText @default @value { title: String! @resolveEditorBlockAttribute(key: "title") icon: String! @resolveEditorBlockAttribute(key: "icon") # @todo check if we want inner blocks here. From f93cc5e0fbe8ca4a99c0d3118bb49dc9fd0c2c1c Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 15:31:00 +0200 Subject: [PATCH 07/25] refactor(SLB-300): use InnerBlocks instead of RichText --- .../AccordionItemTextValidator.php | 16 ++++++++++- .../GutenbergValidator/AccordionValidator.php | 3 +++ .../src/blocks/accordion-item-text.tsx | 27 ++++++++----------- .../fragments/PageContent/BlockAccordion.gql | 4 ++- packages/schema/src/schema.graphql | 3 +-- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php index 6f9a6dcee..4ab6b31ab 100644 --- a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php +++ b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php @@ -3,6 +3,8 @@ namespace Drupal\gutenberg_blocks\Plugin\Validation\GutenbergValidator; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergCardinalityValidatorInterface; +use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergCardinalityValidatorTrait; use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergValidatorBase; /** @@ -12,6 +14,7 @@ * ) */ class AccordionItemTextValidator extends GutenbergValidatorBase { + use GutenbergCardinalityValidatorTrait; use StringTranslationTrait; /** @@ -30,8 +33,19 @@ public function validatedFields($block = []): array { 'field_label' => $this->t('Title'), 'rules' => ['required'], ], - // @todo check if we want text as rich text or inner blocks. ]; } + /** + * {@inheritDoc} + */ + public function validateContent($block = []): array { + $expectedChildren = [ + 'validationType' => GutenbergCardinalityValidatorInterface::CARDINALITY_ANY, + 'min' => 1, + 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED, + ]; + return $this->validateCardinality($block, $expectedChildren); + } + } diff --git a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php index 6e7443e53..d0bae38b0 100644 --- a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php +++ b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php @@ -24,6 +24,9 @@ public function applies(array $block): bool { return $block['blockName'] === 'custom/accordion'; } + /** + * {@inheritDoc} + */ public function validateContent($block = []): array { $expectedChildren = [ [ diff --git a/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx b/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx index 774c0a96c..dd50cd99e 100644 --- a/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx +++ b/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx @@ -1,5 +1,9 @@ import React, { Fragment } from 'react'; -import { InspectorControls, RichText } from 'wordpress__block-editor'; +import { + InnerBlocks, + InspectorControls, + RichText, +} from 'wordpress__block-editor'; import { registerBlockType } from 'wordpress__blocks'; import { PanelBody, SelectControl } from 'wordpress__components'; import { compose, withState } from 'wordpress__compose'; @@ -16,9 +20,6 @@ registerBlockType('custom/accordion-item-text', { title: { type: 'string', }, - text: { - type: 'string', - }, icon: { type: 'string', }, @@ -67,16 +68,10 @@ registerBlockType('custom/accordion-item-text', { setAttributes({ title: newValue }); }} /> - { - setAttributes({ text: newValue }); - }} + @@ -84,7 +79,7 @@ registerBlockType('custom/accordion-item-text', { ); }), - save() { - return null; + save: () => { + return ; }, }); diff --git a/packages/schema/src/fragments/PageContent/BlockAccordion.gql b/packages/schema/src/fragments/PageContent/BlockAccordion.gql index d98beaa51..0f77b257d 100644 --- a/packages/schema/src/fragments/PageContent/BlockAccordion.gql +++ b/packages/schema/src/fragments/PageContent/BlockAccordion.gql @@ -7,5 +7,7 @@ fragment BlockAccordion on BlockAccordion { fragment BlockAccordionItemText on BlockAccordionItemText { title icon - text + textContent { + markup + } } diff --git a/packages/schema/src/schema.graphql b/packages/schema/src/schema.graphql index c65d6f320..28a5f02ce 100644 --- a/packages/schema/src/schema.graphql +++ b/packages/schema/src/schema.graphql @@ -253,8 +253,7 @@ type BlockAccordion @type(id: "custom/accordion") { type BlockAccordionItemText @default @value { title: String! @resolveEditorBlockAttribute(key: "title") icon: String! @resolveEditorBlockAttribute(key: "icon") - # @todo check if we want inner blocks here. - text: String! @resolveEditorBlockAttribute(key: "text") + textContent: BlockMarkup @resolveEditorBlockChildren @seek(pos: 0) } type BlockCta @type(id: "custom/cta") { From 6835bb619c4aed89f017f8ca82ab2d79267750b9 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 15:44:40 +0200 Subject: [PATCH 08/25] test(SLB-300): accordion block --- .../a397ca48-8fad-411e-8901-0eba2feb989c.yml | 16 +++++++- tests/schema/specs/blocks.spec.ts | 40 +++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) 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 ebd66747b..50a8cccb2 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 @@ -117,9 +117,23 @@ default: + + -

+

Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.

+ + + + + +
  • Moitié-moitié
  • Fribourgeoise
+ + + +

Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.

+ + format: gutenberg summary: '' diff --git a/tests/schema/specs/blocks.spec.ts b/tests/schema/specs/blocks.spec.ts index 4730f8d2a..a7fa91331 100644 --- a/tests/schema/specs/blocks.spec.ts +++ b/tests/schema/specs/blocks.spec.ts @@ -71,6 +71,19 @@ test('Blocks', async () => { __typename } } + ... on BlockAccordion { + items { + __typename + ... on BlockAccordionItemText { + __typename + title + icon + textContent { + markup + } + } + } + } } } { @@ -210,10 +223,31 @@ test('Blocks', async () => { "role": "Project manager", }, { - "__typename": "BlockMarkup", - "markup": " -

+ "__typename": "BlockAccordion", + "items": [ + { + "__typename": "BlockAccordionItemText", + "icon": "", + "textContent": { + "markup": " +

Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.

+ ", + }, + "title": "With a single paragraph and no icon", + }, + { + "__typename": "BlockAccordionItemText", + "icon": "arrow", + "textContent": { + "markup": " +
  • Moitié-moitié
  • Fribourgeoise
+ +

Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.

", + }, + "title": "With a list and a paragraph and arrow icon", + }, + ], }, ], "hero": { From 18d3aa51cfb0365e95a689a9e3281cacc49eb8d5 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 18:03:29 +0200 Subject: [PATCH 09/25] feat(SLB-301): accordion storybook --- packages/schema/src/schema.graphql | 2 +- .../PageContent/BlockAccordion.stories.tsx | 56 +++++++++++++++ .../Organisms/PageContent/BlockAccordion.tsx | 68 +++++++++++++++++++ .../src/components/Organisms/PageDisplay.tsx | 5 +- 4 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx create mode 100644 packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx diff --git a/packages/schema/src/schema.graphql b/packages/schema/src/schema.graphql index 28a5f02ce..e41512dcb 100644 --- a/packages/schema/src/schema.graphql +++ b/packages/schema/src/schema.graphql @@ -247,7 +247,7 @@ type BlockImageTeaser @default @value { } type BlockAccordion @type(id: "custom/accordion") { - items: [BlockAccordionItemText]! @resolveEditorBlockChildren + items: [BlockAccordionItemText!]! @resolveEditorBlockChildren } type BlockAccordionItemText @default @value { diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx new file mode 100644 index 000000000..867eaef1b --- /dev/null +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx @@ -0,0 +1,56 @@ +import { Markup } from '@custom/schema'; +import { Meta, StoryObj } from '@storybook/react'; + +import { BlockAccordion } from './BlockAccordion'; + +export default { + component: BlockAccordion, +} satisfies Meta; + +export const AccordionItemText = { + args: { + items: [ + { + title: 'Cheese Fondue', + icon: '', + textContent: { + markup: ` +

The earliest known recipe for the modern form of cheese fondue comes from a 1699 book published in Zürich, under the name "Käss mit Wein zu kochen" 'to cook cheese with wine'. It calls for grated or cut-up cheese to be melted with wine, and for bread to be dipped in it.

+
    +
  • Fribourgeoise
  • +
  • Moitié-Moitié
  • +
+ ` as Markup, + }, + }, + { + title: 'Rösti', + icon: 'questionmark', + textContent: { + markup: ` +

Rösti is a kind of fried potato cake served as a main course or side dish.

+

As a main dish, rösti is usually accompanied with cheese, onions and cold meat or eggs. This dish, originally from Zürich, was first simply made by frying grated raw potatoes in a pan. It has then spread towards Bern where it is made with boiled potatoes instead. This is where it took the name Rösti.[20] There are many variants in Switzerland and outside the borders.[21] This culinary specialty gives its name to the röstigraben, which designates the cultural differences between the German- and French-speaking parts of the country.

+ ` as Markup, + }, + }, + { + title: 'Älplermagronen', + icon: 'checkmark', + textContent: { + markup: ` +

Älplermagronen are now regarded as a traditional dish of the Swiss Alps and a classic of Swiss comfort foods. According to a popular theory, pasta became widespread in northern Switzerland in the late 19th century, when the Gotthard Tunnel was built, partly by Italian workers who brought dry pasta with them.

+ ` as Markup, + }, + }, + { + title: 'Meringue with double cream', + icon: 'arrow', + textContent: { + markup: ` +

The Oxford English Dictionary states that the French word is of unknown origin. The name meringue for this confection first appeared in print in François Massialot's cookbook of 1692.

+ ` as Markup, + }, + }, + ], + }, +} satisfies StoryObj; diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx new file mode 100644 index 000000000..4fa234038 --- /dev/null +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx @@ -0,0 +1,68 @@ +import { + BlockAccordionFragment, + BlockAccordionItemTextFragment, +} from '@custom/schema'; +import { + ArrowRightCircleIcon, + CheckCircleIcon, + QuestionMarkCircleIcon, +} from '@heroicons/react/20/solid'; +import React from 'react'; + +import { BlockMarkup } from './BlockMarkup'; + +export function BlockAccordion(props: BlockAccordionFragment) { + return ( +
+ {props.items.map((item, index) => ( + + ))} +
+ ); +} + +function AccordionItemText( + props: BlockAccordionItemTextFragment & { + id: number; + }, +) { + return ( + <> +

+ +

+
+
+ {props.textContent?.markup && } +
+
+ + ); +} + +function AccordionIcon({ icon }: { icon: string }) { + switch (icon) { + case 'questionmark': + return ; + case 'checkmark': + return ; + case 'arrow': + return ; + default: + return null; + } +} diff --git a/packages/ui/src/components/Organisms/PageDisplay.tsx b/packages/ui/src/components/Organisms/PageDisplay.tsx index 6369f68f6..1e01edf5b 100644 --- a/packages/ui/src/components/Organisms/PageDisplay.tsx +++ b/packages/ui/src/components/Organisms/PageDisplay.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { isTruthy } from '../../utils/isTruthy'; import { UnreachableCaseError } from '../../utils/unreachable-case-error'; import { PageTransition } from '../Molecules/PageTransition'; +import { BlockAccordion } from './PageContent/BlockAccordion'; import { BlockCta } from './PageContent/BlockCta'; import { BlockForm } from './PageContent/BlockForm'; import { BlockMarkup } from './PageContent/BlockMarkup'; @@ -61,9 +62,7 @@ export function PageDisplay(page: PageFragment) { case 'BlockQuote': return
; case 'BlockAccordion': - // @todo implement. - // eslint-disable-next-line react/jsx-no-literals - return
BlockAccordion goes here
; + return ; default: throw new UnreachableCaseError(block); } From 46520712f9ab7548a26f47bc772ef8de8d98b847 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 19:05:16 +0200 Subject: [PATCH 10/25] refactor(SLB-301): use custom theme --- packages/ui/package.json | 1 + .../Organisms/PageContent/BlockAccordion.tsx | 108 ++++--- pnpm-lock.yaml | 276 +++++++++++++++--- 3 files changed, 293 insertions(+), 92 deletions(-) diff --git a/packages/ui/package.json b/packages/ui/package.json index f3320b5ce..967e148ea 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -44,6 +44,7 @@ "@heroicons/react": "^2.1.1", "@hookform/resolvers": "^3.3.3", "clsx": "^2.1.0", + "flowbite-react": "^0.9.0", "framer-motion": "^10.17.4", "hast-util-is-element": "^2.1.3", "hast-util-select": "^5.0.5", diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx index 4fa234038..d9838dce7 100644 --- a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx @@ -1,67 +1,85 @@ -import { - BlockAccordionFragment, - BlockAccordionItemTextFragment, -} from '@custom/schema'; +import { BlockAccordionFragment } from '@custom/schema'; import { ArrowRightCircleIcon, CheckCircleIcon, QuestionMarkCircleIcon, } from '@heroicons/react/20/solid'; +import { Accordion, CustomFlowbiteTheme, Flowbite } from 'flowbite-react'; import React from 'react'; import { BlockMarkup } from './BlockMarkup'; -export function BlockAccordion(props: BlockAccordionFragment) { - return ( -
- {props.items.map((item, index) => ( - - ))} -
- ); -} - -function AccordionItemText( - props: BlockAccordionItemTextFragment & { - id: number; +const accordionTheme: CustomFlowbiteTheme['accordion'] = { + root: { + base: 'divide-y divide-gray-200 border-gray-200 dark:divide-gray-700 dark:border-gray-700', + flush: { + off: 'border-b', + on: 'border-b', + }, }, -) { + content: { + base: 'p-2 m-0 text-gray-200 dark:bg-gray-900', + }, + title: { + arrow: { + base: 'h-0 w-0', + }, + base: 'flex w-full items-center justify-between p-5 text-left font-medium text-gray-500 dark:text-gray-400', + flush: { + off: 'hover:bg-gray-100 dark:hover:bg-gray-800 dark:focus:ring-gray-800', + on: 'bg-transparent dark:bg-transparent', + }, + heading: '', + open: { + off: '', + on: 'text-gray-900 dark:text-gray-100', + }, + }, +}; + +// Applying the custom theme to the Accordion component +// doesn't work out, wrapping it in a Flowbite component. +const theme: CustomFlowbiteTheme = { + accordion: accordionTheme, +}; + +export function BlockAccordion(props: BlockAccordionFragment) { return ( - <> -

- -

-
-
- {props.textContent?.markup && } -
-
- + + + {props.items.map((item, index) => ( + + + + {item.icon && } {item.title} + + + + {item.textContent?.markup && ( + + )} + + + ))} + + ); } function AccordionIcon({ icon }: { icon: string }) { switch (icon) { case 'questionmark': - return ; + return ( + + ); case 'checkmark': - return ; + return ( + + ); case 'arrow': - return ; + return ( + + ); default: return null; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 05006d49f..2d882578c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: devDependencies: '@commitlint/cli': specifier: ^18.4.3 - version: 18.4.3(@types/node@18.19.31)(typescript@5.3.3) + version: 18.4.3(@types/node@20.11.17)(typescript@5.3.3) '@commitlint/config-conventional': specifier: ^18.4.3 version: 18.4.3 @@ -64,7 +64,7 @@ importers: version: 5.3.3 vitest: specifier: ^1.1.1 - version: 1.1.1(@types/node@18.19.31) + version: 1.1.1(@types/node@20.11.17) apps/cms: dependencies: @@ -532,6 +532,9 @@ importers: clsx: specifier: ^2.1.0 version: 2.1.0 + flowbite-react: + specifier: ^0.9.0 + version: 0.9.0(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.4.0) framer-motion: specifier: ^10.17.4 version: 10.17.4(react-dom@18.2.0)(react@18.2.0) @@ -601,7 +604,7 @@ importers: version: 8.0.0-alpha.14(jest@29.7.0)(vitest@1.1.1) '@storybook/test-runner': specifier: ^0.16.0 - version: 0.16.0(@types/node@18.19.31) + version: 0.16.0(@types/node@20.11.17) '@swc/cli': specifier: ^0.1.63 version: 0.1.63(@swc/core@1.3.102) @@ -694,7 +697,7 @@ importers: version: 5.3.3 vite: specifier: ^5.0.10 - version: 5.0.10(@types/node@18.19.31) + version: 5.0.10(@types/node@20.11.17) vite-imagetools: specifier: ^6.2.9 version: 6.2.9 @@ -703,7 +706,7 @@ importers: version: 1.0.3 vitest: specifier: ^1.1.1 - version: 1.1.1(@types/node@18.19.31)(happy-dom@12.10.3) + version: 1.1.1(@types/node@20.11.17)(happy-dom@12.10.3) tests/e2e: devDependencies: @@ -2687,14 +2690,14 @@ packages: resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} - /@commitlint/cli@18.4.3(@types/node@18.19.31)(typescript@5.3.3): + /@commitlint/cli@18.4.3(@types/node@20.11.17)(typescript@5.3.3): resolution: {integrity: sha512-zop98yfB3A6NveYAZ3P1Mb6bIXuCeWgnUfVNkH4yhIMQpQfzFwseadazOuSn0OOfTt0lWuFauehpm9GcqM5lww==} engines: {node: '>=v18'} hasBin: true dependencies: '@commitlint/format': 18.6.1 '@commitlint/lint': 18.6.1 - '@commitlint/load': 18.6.1(@types/node@18.19.31)(typescript@5.3.3) + '@commitlint/load': 18.6.1(@types/node@20.11.17)(typescript@5.3.3) '@commitlint/read': 18.6.1 '@commitlint/types': 18.6.1 execa: 5.1.1 @@ -2765,7 +2768,7 @@ packages: '@commitlint/types': 18.6.1 dev: true - /@commitlint/load@18.6.1(@types/node@18.19.31)(typescript@5.3.3): + /@commitlint/load@18.6.1(@types/node@20.11.17)(typescript@5.3.3): resolution: {integrity: sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA==} engines: {node: '>=v18'} dependencies: @@ -2775,7 +2778,7 @@ packages: '@commitlint/types': 18.6.1 chalk: 4.1.2 cosmiconfig: 8.3.6(typescript@5.3.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@18.19.31)(cosmiconfig@8.3.6)(typescript@5.3.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.11.17)(cosmiconfig@8.3.6)(typescript@5.3.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -4158,14 +4161,12 @@ packages: resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} dependencies: '@floating-ui/utils': 0.2.1 - dev: true /@floating-ui/dom@1.6.3: resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} dependencies: '@floating-ui/core': 1.6.0 '@floating-ui/utils': 0.2.1 - dev: true /@floating-ui/react-dom@2.0.8(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==} @@ -4176,11 +4177,22 @@ packages: '@floating-ui/dom': 1.6.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - dev: true + + /@floating-ui/react@0.26.10(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sh6f9gVvWQdEzLObrWbJ97c0clJObiALsFe0LiR/kb3tDRKwEhObASEH2QyfdoO/ZBPzwxa9j+nYFo+sqgbioA==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) + '@floating-ui/utils': 0.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tabbable: 6.2.0 + dev: false /@floating-ui/utils@0.2.1: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} - dev: true /@formatjs/cli@6.2.4: resolution: {integrity: sha512-g1o9O143F5TGB55skib3fKbyjifPa9YoDcX9L07hVJocRKngCcu4JhKViyUSN55KGcN2ttfBomM+wihN6wtBSQ==} @@ -5683,7 +5695,7 @@ packages: magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.3.3) typescript: 5.3.3 - vite: 5.0.10(@types/node@18.19.31) + vite: 5.0.10(@types/node@20.11.17) dev: true /@jridgewell/gen-mapping@0.3.5: @@ -7273,6 +7285,10 @@ packages: resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} dev: true + /@popperjs/core@2.11.8: + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + dev: false + /@radix-ui/number@1.0.1: resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==} dependencies: @@ -8352,7 +8368,7 @@ packages: magic-string: 0.30.9 rollup: 3.29.4 typescript: 5.3.3 - vite: 5.0.10(@types/node@18.19.31) + vite: 5.0.10(@types/node@20.11.17) transitivePeerDependencies: - encoding - supports-color @@ -8861,7 +8877,7 @@ packages: react: 18.2.0 react-docgen: 7.0.3 react-dom: 18.2.0(react@18.2.0) - vite: 5.0.10(@types/node@18.19.31) + vite: 5.0.10(@types/node@20.11.17) transitivePeerDependencies: - '@preact/preset-vite' - encoding @@ -8935,7 +8951,7 @@ packages: - supports-color dev: true - /@storybook/test-runner@0.16.0(@types/node@18.19.31): + /@storybook/test-runner@0.16.0(@types/node@20.11.17): resolution: {integrity: sha512-LDmNbKFoEDW/VS9o6KR8e1r5MnbCc5ZojUfi5yqLdq80gFD7BvilgKgV0lUh/xWHryzoy+Ids5LYgrPJZmU2dQ==} engines: {node: ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true @@ -8955,7 +8971,7 @@ packages: commander: 9.5.0 expect-playwright: 0.8.0 glob: 10.3.12 - jest: 29.7.0(@types/node@18.19.31) + jest: 29.7.0(@types/node@20.11.17) jest-circus: 29.7.0 jest-environment-node: 29.7.0 jest-junit: 16.0.0 @@ -9413,10 +9429,10 @@ packages: chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.6.3 - jest: 29.7.0(@types/node@18.19.31) + jest: 29.7.0(@types/node@20.11.17) lodash: 4.17.21 redent: 3.0.0 - vitest: 1.1.1(@types/node@18.19.31)(happy-dom@12.10.3) + vitest: 1.1.1(@types/node@20.11.17)(happy-dom@12.10.3) dev: true /@testing-library/react@14.1.2(react-dom@18.2.0)(react@18.2.0): @@ -11017,7 +11033,7 @@ packages: vite: ^4 || ^5 dependencies: '@swc/core': 1.4.13 - vite: 5.0.10(@types/node@18.0.0) + vite: 5.0.10(@types/node@20.11.17) transitivePeerDependencies: - '@swc/helpers' dev: true @@ -11044,7 +11060,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.4) magic-string: 0.27.0 react-refresh: 0.14.0 - vite: 5.0.10(@types/node@18.19.31) + vite: 5.0.10(@types/node@20.11.17) transitivePeerDependencies: - supports-color dev: true @@ -13793,6 +13809,10 @@ packages: static-extend: 0.1.2 dev: false + /classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + dev: false + /clean-deep@3.4.0: resolution: {integrity: sha512-Lo78NV5ItJL/jl+B5w0BycAisaieJGXK1qYi/9m4SjR8zbqmrUtO7Yhro40wEShGmmxs/aJLI/A+jNhdkXK8mw==} engines: {node: '>=4'} @@ -14425,7 +14445,7 @@ packages: object-assign: 4.1.1 vary: 1.1.2 - /cosmiconfig-typescript-loader@5.0.0(@types/node@18.19.31)(cosmiconfig@8.3.6)(typescript@5.3.3): + /cosmiconfig-typescript-loader@5.0.0(@types/node@20.11.17)(cosmiconfig@8.3.6)(typescript@5.3.3): resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} engines: {node: '>=v16'} peerDependencies: @@ -14433,7 +14453,7 @@ packages: cosmiconfig: '>=8.2' typescript: '>=4' dependencies: - '@types/node': 18.19.31 + '@types/node': 20.11.17 cosmiconfig: 8.3.6(typescript@5.3.3) jiti: 1.21.0 typescript: 5.3.3 @@ -14559,7 +14579,7 @@ packages: dependencies: '@babel/runtime': 7.24.4 - /create-jest@29.7.0(@types/node@18.19.31): + /create-jest@29.7.0(@types/node@20.11.17): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -14568,7 +14588,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.19.31) + jest-config: 29.7.0(@types/node@20.11.17) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -14981,6 +15001,11 @@ packages: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} dev: true + /debounce@2.0.0: + resolution: {integrity: sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==} + engines: {node: '>=18'} + dev: false + /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -18577,6 +18602,32 @@ packages: engines: {node: '>=0.4.0'} dev: true + /flowbite-react@0.9.0(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.4.0): + resolution: {integrity: sha512-wRGzTPHaEuRSXiAFhdTuksezABE/AjI/iyOOBGZpsFAz/sq7zuorAqjRud9FWgy3TlFPtldl7kL93wNY2nOnKQ==} + peerDependencies: + react: '>=18' + react-dom: '>=18' + tailwindcss: ^3 + dependencies: + '@floating-ui/core': 1.6.0 + '@floating-ui/react': 0.26.10(react-dom@18.2.0)(react@18.2.0) + classnames: 2.5.1 + debounce: 2.0.0 + flowbite: 2.3.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-icons: 5.0.1(react@18.2.0) + tailwind-merge: 2.2.2 + tailwindcss: 3.4.0 + dev: false + + /flowbite@2.3.0: + resolution: {integrity: sha512-pm3JRo8OIJHGfFYWgaGpPv8E+UdWy0Z3gEAGufw+G/1dusaU/P1zoBLiQpf2/+bYAi+GBQtPVG86KYlV0W+AFQ==} + dependencies: + '@popperjs/core': 2.11.8 + mini-svg-data-uri: 1.4.4 + dev: false + /flush-write-stream@2.0.0: resolution: {integrity: sha512-uXClqPxT4xW0lcdSBheb2ObVU+kuqUk3Jk64EwieirEXZx9XUrVwp/JuBfKAWaM4T5Td/VL7QLDWPXp/MvGm/g==} dependencies: @@ -22480,7 +22531,7 @@ packages: - supports-color dev: true - /jest-cli@29.7.0(@types/node@18.19.31): + /jest-cli@29.7.0(@types/node@20.11.17): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -22494,10 +22545,10 @@ packages: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.19.31) + create-jest: 29.7.0(@types/node@20.11.17) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@18.19.31) + jest-config: 29.7.0(@types/node@20.11.17) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -22548,6 +22599,46 @@ packages: - supports-color dev: true + /jest-config@29.7.0(@types/node@20.11.17): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.24.4 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.17 + babel-jest: 29.7.0(@babel/core@7.24.4) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true + /jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -22686,7 +22777,7 @@ packages: jest-runner: ^29.3.1 dependencies: expect-playwright: 0.8.0 - jest: 29.7.0(@types/node@18.19.31) + jest: 29.7.0(@types/node@20.11.17) jest-circus: 29.7.0 jest-environment-node: 29.7.0 jest-process-manager: 0.4.0 @@ -22897,7 +22988,7 @@ packages: dependencies: ansi-escapes: 6.2.1 chalk: 5.3.0 - jest: 29.7.0(@types/node@18.19.31) + jest: 29.7.0(@types/node@20.11.17) jest-regex-util: 29.6.3 jest-watcher: 29.7.0 slash: 5.1.0 @@ -22945,7 +23036,7 @@ packages: supports-color: 8.1.1 dev: true - /jest@29.7.0(@types/node@18.19.31): + /jest@29.7.0(@types/node@20.11.17): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -22958,7 +23049,7 @@ packages: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@18.19.31) + jest-cli: 29.7.0(@types/node@20.11.17) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -24667,7 +24758,6 @@ packages: /mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true - dev: true /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -25903,6 +25993,7 @@ packages: /p-limit@4.0.0: resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + requiresBuild: true dependencies: yocto-queue: 1.0.0 @@ -26660,7 +26751,6 @@ packages: postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - dev: true /postcss-import@15.1.0(postcss@8.4.38): resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} @@ -26695,7 +26785,6 @@ packages: dependencies: camelcase-css: 2.0.1 postcss: 8.4.32 - dev: true /postcss-js@4.0.1(postcss@8.4.38): resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} @@ -26723,7 +26812,6 @@ packages: lilconfig: 3.1.1 postcss: 8.4.32 yaml: 2.3.4 - dev: true /postcss-load-config@4.0.2(postcss@8.4.38): resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} @@ -26946,7 +27034,6 @@ packages: dependencies: postcss: 8.4.32 postcss-selector-parser: 6.0.16 - dev: true /postcss-nested@6.0.1(postcss@8.4.38): resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} @@ -27288,7 +27375,6 @@ packages: nanoid: 3.3.7 picocolors: 1.0.0 source-map-js: 1.2.0 - dev: true /postcss@8.4.38: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} @@ -28112,6 +28198,14 @@ packages: source-map: 0.7.4 dev: false + /react-icons@5.0.1(react@18.2.0): + resolution: {integrity: sha512-WqLZJ4bLzlhmsvme6iFdgO8gfZP17rfjYEJ2m9RsZjZ+cc4k1hTzknEz63YS1MeT50kVzoa1Nz36f4BEx+Wigw==} + peerDependencies: + react: '*' + dependencies: + react: 18.2.0 + dev: false + /react-immutable-proptypes@2.2.0(immutable@3.8.2): resolution: {integrity: sha512-Vf4gBsePlwdGvSZoLSBfd4HAP93HDauMY4fDjXhreg/vg6F3Fj/MXDNyTbltPC/xZKmZc+cjLu3598DdYK6sgQ==} peerDependencies: @@ -30871,6 +30965,10 @@ packages: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} engines: {node: '>=18'} + /tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: false + /table@5.4.6: resolution: {integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==} engines: {node: '>=6.0.0'} @@ -30904,6 +31002,12 @@ packages: - supports-color dev: false + /tailwind-merge@2.2.2: + resolution: {integrity: sha512-tWANXsnmJzgw6mQ07nE3aCDkCK4QdT3ThPMCzawoYA2Pws7vSTCvz3Vrjg61jVUGfFZPJzxEP+NimbcW+EdaDw==} + dependencies: + '@babel/runtime': 7.24.4 + dev: false + /tailwindcss@3.4.0: resolution: {integrity: sha512-VigzymniH77knD1dryXbyxR+ePHihHociZbXnLZHUyzf2MMs2ZVqlUrZ3FvpXP8pno9JzmILt1sZPD19M3IxtA==} engines: {node: '>=14.0.0'} @@ -30933,7 +31037,6 @@ packages: sucrase: 3.35.0 transitivePeerDependencies: - ts-node - dev: true /tailwindcss@3.4.3: resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} @@ -32640,6 +32743,27 @@ packages: - terser dev: true + /vite-node@1.1.1(@types/node@20.11.17): + resolution: {integrity: sha512-2bGE5w4jvym5v8llF6Gu1oBrmImoNSs4WmRVcavnG2me6+8UQntTqLiAMFyiAobp+ZXhj5ZFhI7SmLiFr/jrow==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.0 + vite: 5.2.8(@types/node@20.11.17) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vite-plugin-istanbul@3.0.4: resolution: {integrity: sha512-DJy3cq6yOFbsM3gLQf/3zeuaJNJsfBv5dLFdZdv8sUV30xLtZI+66QeYfHUyP/5vBUYyLA+xNUCSG5uHY6w+5g==} dependencies: @@ -32691,7 +32815,7 @@ packages: fsevents: 2.3.3 dev: true - /vite@5.0.10(@types/node@18.19.31): + /vite@5.0.10(@types/node@20.11.17): resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -32719,7 +32843,7 @@ packages: terser: optional: true dependencies: - '@types/node': 18.19.31 + '@types/node': 20.11.17 esbuild: 0.19.12 postcss: 8.4.32 rollup: 4.14.1 @@ -33026,7 +33150,7 @@ packages: - terser dev: true - /vitest@1.1.1(@types/node@18.19.31): + /vitest@1.1.1(@types/node@18.19.31)(happy-dom@12.10.3): resolution: {integrity: sha512-Ry2qs4UOu/KjpXVfOCfQkTnwSXYGrqTbBZxw6reIYEFjSy1QUARRg5pxiI5BEXy+kBVntxUYNMlq4Co+2vD3fQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -33062,6 +33186,7 @@ packages: chai: 4.4.1 debug: 4.3.4 execa: 8.0.1 + happy-dom: 12.10.3 local-pkg: 0.5.0 magic-string: 0.30.9 pathe: 1.1.2 @@ -33083,7 +33208,7 @@ packages: - terser dev: true - /vitest@1.1.1(@types/node@18.19.31)(happy-dom@12.10.3): + /vitest@1.1.1(@types/node@20.11.17): resolution: {integrity: sha512-Ry2qs4UOu/KjpXVfOCfQkTnwSXYGrqTbBZxw6reIYEFjSy1QUARRg5pxiI5BEXy+kBVntxUYNMlq4Co+2vD3fQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -33108,7 +33233,64 @@ packages: jsdom: optional: true dependencies: - '@types/node': 18.19.31 + '@types/node': 20.11.17 + '@vitest/expect': 1.1.1 + '@vitest/runner': 1.1.1 + '@vitest/snapshot': 1.1.1 + '@vitest/spy': 1.1.1 + '@vitest/utils': 1.1.1 + acorn-walk: 8.3.2 + cac: 6.7.14 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.9 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 1.3.0 + tinybench: 2.6.0 + tinypool: 0.8.3 + vite: 5.2.8(@types/node@20.11.17) + vite-node: 1.1.1(@types/node@20.11.17) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vitest@1.1.1(@types/node@20.11.17)(happy-dom@12.10.3): + resolution: {integrity: sha512-Ry2qs4UOu/KjpXVfOCfQkTnwSXYGrqTbBZxw6reIYEFjSy1QUARRg5pxiI5BEXy+kBVntxUYNMlq4Co+2vD3fQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': ^1.0.0 + '@vitest/ui': ^1.0.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 20.11.17 '@vitest/expect': 1.1.1 '@vitest/runner': 1.1.1 '@vitest/snapshot': 1.1.1 @@ -33128,8 +33310,8 @@ packages: strip-literal: 1.3.0 tinybench: 2.6.0 tinypool: 0.8.3 - vite: 5.2.8(@types/node@18.19.31) - vite-node: 1.1.1(@types/node@18.19.31) + vite: 5.2.8(@types/node@20.11.17) + vite-node: 1.1.1(@types/node@20.11.17) why-is-node-running: 2.2.2 transitivePeerDependencies: - less From 0186299000c585a002cb9f65f5c497d5e4ff5dd5 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 20:00:05 +0200 Subject: [PATCH 11/25] refactor(SLB-301): styling --- .../Organisms/PageContent/BlockAccordion.tsx | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx index d9838dce7..da90274c1 100644 --- a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx @@ -1,13 +1,21 @@ -import { BlockAccordionFragment } from '@custom/schema'; +import { BlockAccordionFragment, Html } from '@custom/schema'; import { ArrowRightCircleIcon, CheckCircleIcon, QuestionMarkCircleIcon, } from '@heroicons/react/20/solid'; +import clsx from 'clsx'; import { Accordion, CustomFlowbiteTheme, Flowbite } from 'flowbite-react'; -import React from 'react'; +import type { Element } from 'hast'; +import { selectAll } from 'hast-util-select'; +import React, { PropsWithChildren } from 'react'; +import { Plugin } from 'unified'; -import { BlockMarkup } from './BlockMarkup'; +const unorderedItems: Plugin<[], Element> = () => (tree) => { + selectAll('ul > li', tree).forEach((node) => { + node.properties!.unordered = true; + }); +}; const accordionTheme: CustomFlowbiteTheme['accordion'] = { root: { @@ -18,7 +26,7 @@ const accordionTheme: CustomFlowbiteTheme['accordion'] = { }, }, content: { - base: 'p-2 m-0 text-gray-200 dark:bg-gray-900', + base: 'pb-5 pt-5 text-base font-normal text-gray-500 dark:bg-gray-900 dark:text-gray-100', }, title: { arrow: { @@ -56,7 +64,32 @@ export function BlockAccordion(props: BlockAccordionFragment) { {item.textContent?.markup && ( - + ) => { + return ( +
  • + {children} +
  • + ); + }, + }} + markup={item.textContent.markup} + /> )}
    From faf98ca890dc826058aef89bd0e2e84d881f28db Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 20:52:51 +0200 Subject: [PATCH 12/25] refactor(SLB-301): styling --- .../ui/src/components/Organisms/PageContent/BlockAccordion.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx index da90274c1..0d357e500 100644 --- a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx @@ -26,7 +26,7 @@ const accordionTheme: CustomFlowbiteTheme['accordion'] = { }, }, content: { - base: 'pb-5 pt-5 text-base font-normal text-gray-500 dark:bg-gray-900 dark:text-gray-100', + base: 'pb-5 pt-5 text-base font-light text-gray-500 dark:bg-gray-900 dark:text-gray-100', }, title: { arrow: { From c3da87c3c0f1e7a02056a848402379b15cdc0bec Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Fri, 3 May 2024 21:13:27 +0200 Subject: [PATCH 13/25] refactor(SLB-301): styling --- .../Organisms/PageContent/BlockAccordion.stories.tsx | 2 +- .../components/Organisms/PageContent/BlockAccordion.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx index 867eaef1b..6f7be4e00 100644 --- a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx @@ -29,7 +29,7 @@ export const AccordionItemText = { textContent: { markup: `

    Rösti is a kind of fried potato cake served as a main course or side dish.

    -

    As a main dish, rösti is usually accompanied with cheese, onions and cold meat or eggs. This dish, originally from Zürich, was first simply made by frying grated raw potatoes in a pan. It has then spread towards Bern where it is made with boiled potatoes instead. This is where it took the name Rösti.[20] There are many variants in Switzerland and outside the borders.[21] This culinary specialty gives its name to the röstigraben, which designates the cultural differences between the German- and French-speaking parts of the country.

    +

    As a main dish, rösti is usually accompanied with cheese, onions and cold meat or eggs. This dish, originally from Zürich, was first simply made by frying grated raw potatoes in a pan. It has then spread towards Bern where it is made with boiled potatoes instead. This is where it took the name Rösti. There are many variants in Switzerland and outside the borders. This culinary specialty gives its name to the röstigraben, which designates the cultural differences between the German- and French-speaking parts of the country.

    ` as Markup, }, }, diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx index 0d357e500..c53495d9a 100644 --- a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx @@ -21,8 +21,8 @@ const accordionTheme: CustomFlowbiteTheme['accordion'] = { root: { base: 'divide-y divide-gray-200 border-gray-200 dark:divide-gray-700 dark:border-gray-700', flush: { - off: 'border-b', - on: 'border-b', + off: 'border-b last:border-0', + on: 'border-b last:border-0', }, }, content: { @@ -32,7 +32,7 @@ const accordionTheme: CustomFlowbiteTheme['accordion'] = { arrow: { base: 'h-0 w-0', }, - base: 'flex w-full items-center justify-between p-5 text-left font-medium text-gray-500 dark:text-gray-400', + base: 'flex w-full items-center justify-between p-4 pl-1 text-left font-normal text-lg text-gray-500 dark:text-gray-400', flush: { off: 'hover:bg-gray-100 dark:hover:bg-gray-800 dark:focus:ring-gray-800', on: 'bg-transparent dark:bg-transparent', @@ -62,7 +62,7 @@ export function BlockAccordion(props: BlockAccordionFragment) { {item.icon && } {item.title} - + {item.textContent?.markup && ( Date: Fri, 3 May 2024 22:11:41 +0200 Subject: [PATCH 14/25] fix(SLB-301): adjust width --- .../Organisms/PageContent/BlockAccordion.tsx | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx index c53495d9a..b1434696f 100644 --- a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx @@ -63,34 +63,36 @@ export function BlockAccordion(props: BlockAccordionFragment) { - {item.textContent?.markup && ( - ) => { - return ( -
  • - {children} -
  • - ); - }, - }} - markup={item.textContent.markup} - /> - )} +
    + {item.textContent?.markup && ( + ) => { + return ( +
  • + {children} +
  • + ); + }, + }} + markup={item.textContent.markup} + /> + )} +
    ))} From bc0ba2ba1f23a41baf07d49fd335a6bd7079b8f2 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Mon, 6 May 2024 10:03:08 +0200 Subject: [PATCH 15/25] feat(SLB-299): adjust accordion style, add to page story --- .../src/components/Organisms/PageContent/BlockAccordion.tsx | 4 ++-- packages/ui/src/components/Routes/Page.stories.tsx | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx index b1434696f..5f4e19453 100644 --- a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx @@ -19,7 +19,7 @@ const unorderedItems: Plugin<[], Element> = () => (tree) => { const accordionTheme: CustomFlowbiteTheme['accordion'] = { root: { - base: 'divide-y divide-gray-200 border-gray-200 dark:divide-gray-700 dark:border-gray-700', + base: 'mt-10 divide-y divide-gray-200 border-gray-200 dark:divide-gray-700 dark:border-gray-700', flush: { off: 'border-b last:border-0', on: 'border-b last:border-0', @@ -63,7 +63,7 @@ export function BlockAccordion(props: BlockAccordionFragment) { -
    +
    {item.textContent?.markup && ( ['content'], }, }, From 3480cf3f3c18f6918d28f548a8c6be60ace2cb36 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Mon, 6 May 2024 16:39:09 +0200 Subject: [PATCH 16/25] chore: zhinst demo setup --- .lagoon.yml | 13 +++++++++++++ apps/cms/.lagoon.env.demo-zhinst | 7 +++++++ apps/preview/.lagoon.env.demo-zhinst | 1 + apps/website/.lagoon.env.demo-zhinst | 29 ++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 apps/cms/.lagoon.env.demo-zhinst create mode 100644 apps/preview/.lagoon.env.demo-zhinst create mode 100644 apps/website/.lagoon.env.demo-zhinst diff --git a/.lagoon.yml b/.lagoon.yml index 22179218c..ecaee933c 100644 --- a/.lagoon.yml +++ b/.lagoon.yml @@ -69,3 +69,16 @@ environments: schedule: '*/15 * * * *' command: drush cron service: cli + demo-zhinst: + routes: + - nginx: + - zhinst.cms.amazeelabs.dev + - build: + - zhinst.build.amazeelabs.dev + - preview: + - zhinst.preview.amazeelabs.dev + cronjobs: + - name: drush cron + schedule: '*/15 * * * *' + command: drush cron + service: cli diff --git a/apps/cms/.lagoon.env.demo-zhinst b/apps/cms/.lagoon.env.demo-zhinst new file mode 100644 index 000000000..e2eb34eb2 --- /dev/null +++ b/apps/cms/.lagoon.env.demo-zhinst @@ -0,0 +1,7 @@ +PROJECT_NAME=example +PUBLISHER_URL="https://zhinst.build.amazeelabs.dev" +NETLIFY_URL="https://zhinst.amazeelabs.dev" +PREVIEW_URL="https://zhinst.preview.amazeelabs.dev" + +# Used to set the original client secret. +PUBLISHER_OAUTH2_CLIENT_SECRET=REPLACE_ME diff --git a/apps/preview/.lagoon.env.demo-zhinst b/apps/preview/.lagoon.env.demo-zhinst new file mode 100644 index 000000000..b26e5d193 --- /dev/null +++ b/apps/preview/.lagoon.env.demo-zhinst @@ -0,0 +1 @@ +DRUPAL_URL="https://zhinst.cms.amazeelabs.dev" diff --git a/apps/website/.lagoon.env.demo-zhinst b/apps/website/.lagoon.env.demo-zhinst new file mode 100644 index 000000000..dc05ba1f7 --- /dev/null +++ b/apps/website/.lagoon.env.demo-zhinst @@ -0,0 +1,29 @@ +PROJECT_NAME=example +DRUPAL_INTERNAL_URL="http://nginx:8080" +DRUPAL_EXTERNAL_URL="https://zhinst.cms.amazeelabs.dev" +NETLIFY_URL="https://zhinst.amazeelabs.dev" +NETLIFY_SITE_ID="4ec8534f-e75c-47bb-8052-20a96842c1fe" + +# ----------------------------------------------- +# Publisher authentication with Drupal (OAuth2). +# See main ./README.md for more information. +# ----------------------------------------------- +# Set to true to fully skip authentication. +PUBLISHER_SKIP_AUTHENTICATION=false + +# Secret from the Drupal Publisher Consumer. +PUBLISHER_OAUTH2_CLIENT_SECRET=REPLACE_ME + +# Client id from the Drupal Publisher Consumer. +PUBLISHER_OAUTH2_CLIENT_ID=publisher + +# A random string, used to encrypt the session. +PUBLISHER_OAUTH2_SESSION_SECRET=REPLACE_ME + +# "development" or "production", production will trust first proxy +# and serve secure cookies. +PUBLISHER_OAUTH2_ENVIRONMENT_TYPE=production + +# DRUPAL_EXTERNAL_URL is used by default, but can be overridden +# to match the Drupal production url, without the nginx prefix. +PUBLISHER_OAUTH2_TOKEN_HOST="${DRUPAL_EXTERNAL_URL}" From d87bd475bd212023ee4bc7d7d680bcaebb8f6f8b Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Mon, 6 May 2024 17:00:07 +0200 Subject: [PATCH 17/25] Trigger a build From 0f314aec2a8d739557a4a99032feae062aba4d24 Mon Sep 17 00:00:00 2001 From: Christophe Jossart Date: Mon, 6 May 2024 19:47:36 +0200 Subject: [PATCH 18/25] feat: blogs --- apps/cms/composer.json | 2 + apps/cms/composer.lock | 182 +++++++++++- ....base_field_override.node.blog.promote.yml | 22 ++ ....entity_form_display.node.blog.default.yml | 127 +++++++++ ....entity_form_display.node.page.default.yml | 26 +- ....entity_view_display.node.blog.default.yml | 47 +++ ...e.entity_view_display.node.blog.teaser.yml | 48 ++++ .../sync/field.field.node.blog.body.yml | 24 ++ .../field.field.node.blog.field_blog_tags.yml | 29 ++ .../field.field.node.blog.field_metatags.yml | 21 ++ ...eld.field.node.blog.field_teaser_image.yml | 29 ++ .../field.storage.node.field_blog_tags.yml | 20 ++ .../field.storage.node.field_teaser_image.yml | 20 ++ apps/cms/config/sync/gutenberg.settings.yml | 97 +++++++ .../language.content_settings.node.blog.yml | 16 ++ ...ntent_settings.taxonomy_term.blog_tags.yml | 16 ++ apps/cms/config/sync/node.type.blog.yml | 17 ++ apps/cms/config/sync/node.type.page.yml | 2 +- .../sync/taxonomy.vocabulary.blog_tags.yml | 8 + apps/cms/scaffold/settings.php.append.txt | 4 +- apps/website/src/templates/blog.tsx | 53 ++++ packages/drupal/gutenberg_blocks/css/edit.css | 112 +++++++- .../src/blocks/content-blog.tsx | 48 ++++ .../gutenberg_blocks/src/blocks/cta.tsx | 15 +- .../src/blocks/image-with-caption.tsx | 82 ++++++ .../src/blocks/image-with-link.tsx | 72 +++++ .../gutenberg_blocks/src/blocks/image.tsx | 49 ++++ .../gutenberg_blocks/src/blocks/mathjax.tsx | 61 ++++ .../src/blocks/slider-item.tsx | 205 ++++++++++++++ .../gutenberg_blocks/src/blocks/slider.tsx | 25 ++ .../src/blocks/teaser-item.tsx | 91 ++++++ .../gutenberg_blocks/src/blocks/teasers.tsx | 25 ++ packages/drupal/gutenberg_blocks/src/index.ts | 9 + .../1ee434f2-f813-45b2-84ef-a516b8e6e445.yml | 27 ++ .../86b7ab11-44d7-4d3d-b521-67a932317af1.yml | 27 ++ .../c160f499-b758-4511-808e-50bdc2f62c77.yml | 27 ++ .../ed4185b6-8e75-4899-9c85-1ca7613b6e0f.yml | 27 ++ .../content/file/fig2_qasm_blog.png | Bin 0 -> 20817 bytes .../content/file/fig3_qasm_blog.png | Bin 0 -> 33165 bytes .../content/file/finalfigqasm_v1.jpg | Bin 0 -> 485068 bytes .../content/file/qiskit_circuit.png | Bin 0 -> 150680 bytes .../28ac124d-2e71-4ddf-a1ba-a535709b41a8.yml | 39 +++ .../7d249268-74d0-4fe4-a84d-484d16515abe.yml | 39 +++ .../a5fb1d1c-74d6-4d70-a055-1035221da57c.yml | 39 +++ .../c414cc0a-0687-4166-bba4-e44dd4476c36.yml | 39 +++ .../fb74ee1a-6464-4954-b789-618564906d15.yml | 267 ++++++++++++++++++ .../7b737603-c1d0-4c0a-a7d4-d503b592c121.yml | 36 +++ .../9d319586-f3a8-4f3d-8299-632748e2bcc5.yml | 36 +++ .../9de2a2d0-7d65-4a9b-9e16-8cb56ca19eab.yml | 36 +++ .../a715c0e8-7162-44f1-99ab-f42d24c3d774.yml | 36 +++ .../c275a57d-f6ca-41ce-8f33-722ccf00411d.yml | 36 +++ .../f8b84069-625e-4ab2-bd5b-d457fa0786e2.yml | 36 +++ .../f98dcb5e-ea31-4248-8d0e-66f0120c2b7e.yml | 36 +++ packages/schema/src/schema.graphql | 46 +++ packages/ui/src/components/Routes/Blog.tsx | 24 ++ 55 files changed, 2434 insertions(+), 23 deletions(-) create mode 100644 apps/cms/config/sync/core.base_field_override.node.blog.promote.yml create mode 100644 apps/cms/config/sync/core.entity_form_display.node.blog.default.yml create mode 100644 apps/cms/config/sync/core.entity_view_display.node.blog.default.yml create mode 100644 apps/cms/config/sync/core.entity_view_display.node.blog.teaser.yml create mode 100644 apps/cms/config/sync/field.field.node.blog.body.yml create mode 100644 apps/cms/config/sync/field.field.node.blog.field_blog_tags.yml create mode 100644 apps/cms/config/sync/field.field.node.blog.field_metatags.yml create mode 100644 apps/cms/config/sync/field.field.node.blog.field_teaser_image.yml create mode 100644 apps/cms/config/sync/field.storage.node.field_blog_tags.yml create mode 100644 apps/cms/config/sync/field.storage.node.field_teaser_image.yml create mode 100644 apps/cms/config/sync/language.content_settings.node.blog.yml create mode 100644 apps/cms/config/sync/language.content_settings.taxonomy_term.blog_tags.yml create mode 100644 apps/cms/config/sync/node.type.blog.yml create mode 100644 apps/cms/config/sync/taxonomy.vocabulary.blog_tags.yml create mode 100644 apps/website/src/templates/blog.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/content-blog.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/image-with-caption.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/image-with-link.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/image.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/mathjax.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/slider-item.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/slider.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/teaser-item.tsx create mode 100644 packages/drupal/gutenberg_blocks/src/blocks/teasers.tsx create mode 100644 packages/drupal/test_content/content/file/1ee434f2-f813-45b2-84ef-a516b8e6e445.yml create mode 100644 packages/drupal/test_content/content/file/86b7ab11-44d7-4d3d-b521-67a932317af1.yml create mode 100644 packages/drupal/test_content/content/file/c160f499-b758-4511-808e-50bdc2f62c77.yml create mode 100644 packages/drupal/test_content/content/file/ed4185b6-8e75-4899-9c85-1ca7613b6e0f.yml create mode 100644 packages/drupal/test_content/content/file/fig2_qasm_blog.png create mode 100644 packages/drupal/test_content/content/file/fig3_qasm_blog.png create mode 100644 packages/drupal/test_content/content/file/finalfigqasm_v1.jpg create mode 100644 packages/drupal/test_content/content/file/qiskit_circuit.png create mode 100644 packages/drupal/test_content/content/media/28ac124d-2e71-4ddf-a1ba-a535709b41a8.yml create mode 100644 packages/drupal/test_content/content/media/7d249268-74d0-4fe4-a84d-484d16515abe.yml create mode 100644 packages/drupal/test_content/content/media/a5fb1d1c-74d6-4d70-a055-1035221da57c.yml create mode 100644 packages/drupal/test_content/content/media/c414cc0a-0687-4166-bba4-e44dd4476c36.yml create mode 100644 packages/drupal/test_content/content/node/fb74ee1a-6464-4954-b789-618564906d15.yml create mode 100644 packages/drupal/test_content/content/taxonomy_term/7b737603-c1d0-4c0a-a7d4-d503b592c121.yml create mode 100644 packages/drupal/test_content/content/taxonomy_term/9d319586-f3a8-4f3d-8299-632748e2bcc5.yml create mode 100644 packages/drupal/test_content/content/taxonomy_term/9de2a2d0-7d65-4a9b-9e16-8cb56ca19eab.yml create mode 100644 packages/drupal/test_content/content/taxonomy_term/a715c0e8-7162-44f1-99ab-f42d24c3d774.yml create mode 100644 packages/drupal/test_content/content/taxonomy_term/c275a57d-f6ca-41ce-8f33-722ccf00411d.yml create mode 100644 packages/drupal/test_content/content/taxonomy_term/f8b84069-625e-4ab2-bd5b-d457fa0786e2.yml create mode 100644 packages/drupal/test_content/content/taxonomy_term/f98dcb5e-ea31-4248-8d0e-66f0120c2b7e.yml create mode 100644 packages/ui/src/components/Routes/Blog.tsx diff --git a/apps/cms/composer.json b/apps/cms/composer.json index bb6feeb43..1cff7be62 100644 --- a/apps/cms/composer.json +++ b/apps/cms/composer.json @@ -58,11 +58,13 @@ "drupal/entity_usage": "^2.0@beta", "drupal/environment_indicator": "^4.0.14", "drupal/field_group": "^3.4", + "drupal/highlight_php": "^1.0", "drupal/honeypot": "^2.1.2", "drupal/key_auth": "^2.1", "drupal/lagoon_logs": "^2.1.1", "drupal/linkit": "^6.0@beta", "drupal/masquerade": "^2.0@RC", + "drupal/mathjax": "^4.0", "drupal/menu_admin_per_menu": "^1.5", "drupal/metatag": "^2.0", "drupal/pathauto": "^1.11", diff --git a/apps/cms/composer.lock b/apps/cms/composer.lock index 6aa58607b..9ec90adff 100644 --- a/apps/cms/composer.lock +++ b/apps/cms/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f2375207790855cc777235f699c7c2b9", + "content-hash": "b8008c19736458ea93a6705341df0fec", "packages": [ { "name": "amazeeio/drupal_integrations", @@ -3301,6 +3301,56 @@ "issues": "https://www.drupal.org/project/issues/gutenberg" } }, + { + "name": "drupal/highlight_php", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/highlight_php.git", + "reference": "1.0.1" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/highlight_php-1.0.1.zip", + "reference": "1.0.1", + "shasum": "3bb0c8f15bf39de9157e0a98981bd60b29e891f0" + }, + "require": { + "drupal/core": "^9 || ^10", + "scrivo/highlight.php": "^9.17" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "1.0.1", + "datestamp": "1694018897", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Sam Mortenson", + "homepage": "https://www.drupal.org/user/3547706", + "email": "samuel@mortenson.coffee" + }, + { + "name": "samuel.mortenson", + "homepage": "https://www.drupal.org/user/2582268" + } + ], + "description": "highlight.php filter integration.", + "homepage": "https://www.drupal.org/project/highlight_php", + "support": { + "source": "https://git.drupalcode.org/project/highlight_php" + } + }, { "name": "drupal/honeypot", "version": "2.1.3", @@ -3619,6 +3669,58 @@ "irc": "irc://irc.freenode.org/drupal-contribute" } }, + { + "name": "drupal/mathjax", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://git.drupalcode.org/project/mathjax.git", + "reference": "4.0.2" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/mathjax-4.0.2.zip", + "reference": "4.0.2", + "shasum": "e92f2f50aa8149e55af8b1f744cad84cf680d91f" + }, + "require": { + "drupal/core": "^9.1 || ^10" + }, + "type": "drupal-module", + "extra": { + "drupal": { + "version": "4.0.2", + "datestamp": "1673381514", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "cilefen", + "homepage": "https://www.drupal.org/user/1850070" + }, + { + "name": "joelpittet", + "homepage": "https://www.drupal.org/user/160302" + }, + { + "name": "julou", + "homepage": "https://www.drupal.org/user/273952" + } + ], + "description": "Javascript-based LaTeX rendering solution for your Drupal website.", + "homepage": "https://www.drupal.org/project/mathjax", + "support": { + "source": "https://git.drupalcode.org/project/mathjax" + } + }, { "name": "drupal/menu_admin_per_menu", "version": "1.5.0", @@ -7158,6 +7260,84 @@ }, "time": "2019-03-08T08:55:37+00:00" }, + { + "name": "scrivo/highlight.php", + "version": "v9.18.1.10", + "source": { + "type": "git", + "url": "https://github.com/scrivo/highlight.php.git", + "reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/850f4b44697a2552e892ffe71490ba2733c2fc6e", + "reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.7", + "sabberworm/php-css-parser": "^8.3", + "symfony/finder": "^2.8|^3.4|^5.4", + "symfony/var-dumper": "^2.8|^3.4|^5.4" + }, + "suggest": { + "ext-mbstring": "Allows highlighting code with unicode characters and supports language with unicode keywords" + }, + "type": "library", + "autoload": { + "files": [ + "HighlightUtilities/functions.php" + ], + "psr-0": { + "Highlight\\": "", + "HighlightUtilities\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Geert Bergman", + "homepage": "http://www.scrivo.org/", + "role": "Project Author" + }, + { + "name": "Vladimir Jimenez", + "homepage": "https://allejo.io", + "role": "Maintainer" + }, + { + "name": "Martin Folkers", + "homepage": "https://twobrain.io", + "role": "Contributor" + } + ], + "description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js", + "keywords": [ + "code", + "highlight", + "highlight.js", + "highlight.php", + "syntax" + ], + "support": { + "issues": "https://github.com/scrivo/highlight.php/issues", + "source": "https://github.com/scrivo/highlight.php" + }, + "funding": [ + { + "url": "https://github.com/allejo", + "type": "github" + } + ], + "time": "2022-12-17T21:53:22+00:00" + }, { "name": "sebastian/diff", "version": "4.0.5", diff --git a/apps/cms/config/sync/core.base_field_override.node.blog.promote.yml b/apps/cms/config/sync/core.base_field_override.node.blog.promote.yml new file mode 100644 index 000000000..40609226d --- /dev/null +++ b/apps/cms/config/sync/core.base_field_override.node.blog.promote.yml @@ -0,0 +1,22 @@ +uuid: 788b4898-b392-4178-a030-afec42ece15d +langcode: en +status: true +dependencies: + config: + - node.type.blog +id: node.blog.promote +field_name: promote +entity_type: node +bundle: blog +label: 'Promoted to front page' +description: '' +required: false +translatable: true +default_value: + - + value: 0 +default_value_callback: '' +settings: + on_label: 'On' + off_label: 'Off' +field_type: boolean diff --git a/apps/cms/config/sync/core.entity_form_display.node.blog.default.yml b/apps/cms/config/sync/core.entity_form_display.node.blog.default.yml new file mode 100644 index 000000000..847429c5c --- /dev/null +++ b/apps/cms/config/sync/core.entity_form_display.node.blog.default.yml @@ -0,0 +1,127 @@ +uuid: 04c755ba-8a45-464c-8050-931066d30d22 +langcode: en +status: true +dependencies: + config: + - field.field.node.blog.body + - field.field.node.blog.field_blog_tags + - field.field.node.blog.field_metatags + - field.field.node.blog.field_teaser_image + - node.type.blog + module: + - content_moderation + - media_library + - metatag + - path + - text +id: node.blog.default +targetEntityType: node +bundle: blog +mode: default +content: + body: + type: text_textarea_with_summary + weight: 11 + region: content + settings: + rows: 9 + summary_rows: 3 + placeholder: '' + show_summary: false + third_party_settings: { } + created: + type: datetime_timestamp + weight: 3 + region: content + settings: { } + third_party_settings: { } + field_blog_tags: + type: options_buttons + weight: 13 + region: content + settings: { } + third_party_settings: { } + field_metatags: + type: metatag_firehose + weight: 14 + region: content + settings: + sidebar: true + use_details: true + third_party_settings: { } + field_teaser_image: + type: media_library_widget + weight: 12 + region: content + settings: + media_types: { } + third_party_settings: { } + langcode: + type: language_select + weight: 1 + region: content + settings: + include_locked: true + third_party_settings: { } + moderation_state: + type: moderation_state_default + weight: 9 + region: content + settings: { } + third_party_settings: { } + path: + type: path + weight: 7 + region: content + settings: { } + third_party_settings: { } + promote: + type: boolean_checkbox + weight: 5 + region: content + settings: + display_label: true + third_party_settings: { } + status: + type: boolean_checkbox + weight: 10 + region: content + settings: + display_label: true + third_party_settings: { } + sticky: + type: boolean_checkbox + weight: 6 + region: content + settings: + display_label: true + third_party_settings: { } + title: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + translation: + weight: 4 + region: content + settings: { } + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 2 + region: content + settings: + match_operator: CONTAINS + match_limit: 10 + size: 60 + placeholder: '' + third_party_settings: { } + url_redirects: + weight: 8 + region: content + settings: { } + third_party_settings: { } +hidden: { } diff --git a/apps/cms/config/sync/core.entity_form_display.node.page.default.yml b/apps/cms/config/sync/core.entity_form_display.node.page.default.yml index 7ec9ef2a3..ab107b92b 100644 --- a/apps/cms/config/sync/core.entity_form_display.node.page.default.yml +++ b/apps/cms/config/sync/core.entity_form_display.node.page.default.yml @@ -19,7 +19,7 @@ mode: default content: body: type: text_textarea_with_summary - weight: 121 + weight: 11 region: content settings: rows: 9 @@ -29,13 +29,13 @@ content: third_party_settings: { } created: type: datetime_timestamp - weight: 10 + weight: 3 region: content settings: { } third_party_settings: { } field_metatags: type: metatag_firehose - weight: 122 + weight: 13 region: content settings: sidebar: true @@ -43,60 +43,60 @@ content: third_party_settings: { } langcode: type: language_select - weight: 2 + weight: 1 region: content settings: include_locked: true third_party_settings: { } moderation_state: type: moderation_state_default - weight: 100 + weight: 9 region: content settings: { } third_party_settings: { } path: type: path - weight: 30 + weight: 7 region: content settings: { } third_party_settings: { } promote: type: boolean_checkbox - weight: 15 + weight: 5 region: content settings: display_label: true third_party_settings: { } status: type: boolean_checkbox - weight: 120 + weight: 10 region: content settings: display_label: true third_party_settings: { } sticky: type: boolean_checkbox - weight: 16 + weight: 6 region: content settings: display_label: true third_party_settings: { } title: type: string_textfield - weight: -5 + weight: 0 region: content settings: size: 60 placeholder: '' third_party_settings: { } translation: - weight: 10 + weight: 4 region: content settings: { } third_party_settings: { } uid: type: entity_reference_autocomplete - weight: 5 + weight: 2 region: content settings: match_operator: CONTAINS @@ -105,7 +105,7 @@ content: placeholder: '' third_party_settings: { } url_redirects: - weight: 50 + weight: 8 region: content settings: { } third_party_settings: { } diff --git a/apps/cms/config/sync/core.entity_view_display.node.blog.default.yml b/apps/cms/config/sync/core.entity_view_display.node.blog.default.yml new file mode 100644 index 000000000..679d2442b --- /dev/null +++ b/apps/cms/config/sync/core.entity_view_display.node.blog.default.yml @@ -0,0 +1,47 @@ +uuid: 76d7ee89-96a3-4abe-8d5e-54adda6b8242 +langcode: en +status: true +dependencies: + config: + - field.field.node.blog.body + - field.field.node.blog.field_blog_tags + - field.field.node.blog.field_metatags + - field.field.node.blog.field_teaser_image + - node.type.blog + module: + - silverback_external_preview + - user +id: node.blog.default +targetEntityType: node +bundle: blog +mode: default +content: + external_preview_link: + type: external_preview_iframe_formatter + label: hidden + settings: + width: 100% + height: 900 + view_live_link: true + third_party_settings: { } + weight: 0 + region: content + field_teaser_image: + type: entity_reference_entity_view + label: above + settings: + view_mode: default + link: false + third_party_settings: { } + weight: 3 + region: content + links: + settings: { } + third_party_settings: { } + weight: 1 + region: content +hidden: + body: true + field_blog_tags: true + field_metatags: true + langcode: true diff --git a/apps/cms/config/sync/core.entity_view_display.node.blog.teaser.yml b/apps/cms/config/sync/core.entity_view_display.node.blog.teaser.yml new file mode 100644 index 000000000..f561dd0b2 --- /dev/null +++ b/apps/cms/config/sync/core.entity_view_display.node.blog.teaser.yml @@ -0,0 +1,48 @@ +uuid: 440355e0-b2da-4e44-bf70-781ce3a32de5 +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.blog.body + - field.field.node.blog.field_blog_tags + - field.field.node.blog.field_metatags + - field.field.node.blog.field_teaser_image + - node.type.blog + module: + - silverback_external_preview + - text + - user +id: node.blog.teaser +targetEntityType: node +bundle: blog +mode: teaser +content: + body: + type: text_summary_or_trimmed + label: hidden + settings: + trim_length: 600 + third_party_settings: { } + weight: 101 + region: content + external_preview_link: + type: external_preview_iframe_formatter + label: hidden + settings: + width: 100% + height: 900 + view_live_link: true + third_party_settings: { } + weight: -5 + region: content + links: + settings: { } + third_party_settings: { } + weight: 100 + region: content +hidden: + field_blog_tags: true + field_metatags: true + field_teaser_image: true + langcode: true diff --git a/apps/cms/config/sync/field.field.node.blog.body.yml b/apps/cms/config/sync/field.field.node.blog.body.yml new file mode 100644 index 000000000..895592d1d --- /dev/null +++ b/apps/cms/config/sync/field.field.node.blog.body.yml @@ -0,0 +1,24 @@ +uuid: 96e2ccd4-0d2e-4c73-9c5d-ccfc2a9e4976 +langcode: en +status: true +dependencies: + config: + - field.storage.node.body + - node.type.blog + module: + - text +id: node.blog.body +field_name: body +entity_type: node +bundle: blog +label: Body +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + display_summary: true + required_summary: false + allowed_formats: { } +field_type: text_with_summary diff --git a/apps/cms/config/sync/field.field.node.blog.field_blog_tags.yml b/apps/cms/config/sync/field.field.node.blog.field_blog_tags.yml new file mode 100644 index 000000000..2d3767919 --- /dev/null +++ b/apps/cms/config/sync/field.field.node.blog.field_blog_tags.yml @@ -0,0 +1,29 @@ +uuid: c6568e98-731e-4505-9cd8-4745f8738818 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_blog_tags + - node.type.blog + - taxonomy.vocabulary.blog_tags +id: node.blog.field_blog_tags +field_name: field_blog_tags +entity_type: node +bundle: blog +label: Tags +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: + target_bundles: + blog_tags: blog_tags + sort: + field: name + direction: asc + auto_create: false + auto_create_bundle: '' +field_type: entity_reference diff --git a/apps/cms/config/sync/field.field.node.blog.field_metatags.yml b/apps/cms/config/sync/field.field.node.blog.field_metatags.yml new file mode 100644 index 000000000..ac73188e1 --- /dev/null +++ b/apps/cms/config/sync/field.field.node.blog.field_metatags.yml @@ -0,0 +1,21 @@ +uuid: ceb9d0ce-b1d7-4602-a99b-d70b42895816 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_metatags + - node.type.blog + module: + - metatag +id: node.blog.field_metatags +field_name: field_metatags +entity_type: node +bundle: blog +label: Metatags +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: { } +field_type: metatag diff --git a/apps/cms/config/sync/field.field.node.blog.field_teaser_image.yml b/apps/cms/config/sync/field.field.node.blog.field_teaser_image.yml new file mode 100644 index 000000000..fd1f79c3c --- /dev/null +++ b/apps/cms/config/sync/field.field.node.blog.field_teaser_image.yml @@ -0,0 +1,29 @@ +uuid: e2cae156-a26f-4cb6-914f-88e351e37db8 +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_teaser_image + - media.type.image + - node.type.blog +id: node.blog.field_teaser_image +field_name: field_teaser_image +entity_type: node +bundle: blog +label: 'Teaser image' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:media' + handler_settings: + target_bundles: + image: image + sort: + field: _none + direction: ASC + auto_create: false + auto_create_bundle: '' +field_type: entity_reference diff --git a/apps/cms/config/sync/field.storage.node.field_blog_tags.yml b/apps/cms/config/sync/field.storage.node.field_blog_tags.yml new file mode 100644 index 000000000..19903ebe9 --- /dev/null +++ b/apps/cms/config/sync/field.storage.node.field_blog_tags.yml @@ -0,0 +1,20 @@ +uuid: 512dd294-b775-489a-b5ce-2b59c3bb1de5 +langcode: en +status: true +dependencies: + module: + - node + - taxonomy +id: node.field_blog_tags +field_name: field_blog_tags +entity_type: node +type: entity_reference +settings: + target_type: taxonomy_term +module: core +locked: false +cardinality: -1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/apps/cms/config/sync/field.storage.node.field_teaser_image.yml b/apps/cms/config/sync/field.storage.node.field_teaser_image.yml new file mode 100644 index 000000000..d9e4e4020 --- /dev/null +++ b/apps/cms/config/sync/field.storage.node.field_teaser_image.yml @@ -0,0 +1,20 @@ +uuid: 56710af2-f42a-4d50-a138-e95680d8ac4b +langcode: en +status: true +dependencies: + module: + - media + - node +id: node.field_teaser_image +field_name: field_teaser_image +entity_type: node +type: entity_reference +settings: + target_type: media +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/apps/cms/config/sync/gutenberg.settings.yml b/apps/cms/config/sync/gutenberg.settings.yml index ed9ef9d7d..047b36044 100644 --- a/apps/cms/config/sync/gutenberg.settings.yml +++ b/apps/cms/config/sync/gutenberg.settings.yml @@ -95,3 +95,100 @@ page_allowed_drupal_blocks: drupalblock/all_webform: 0 webform_block: 0 webform_submission_limit_block: 0 +blog_enable_full: 1 +blog_template: "[\r\n [\"custom/content-blog\", {}]\r\n]" +blog_template_lock: all +blog_allowed_blocks: + core/paragraph: core/paragraph + core/list: core/list + core/quote: core/quote + core/code: core/code + core/table: core/table + core/all: 0 + core/image: 0 + core/heading: 0 + core/gallery: 0 + core/audio: 0 + core/button: 0 + core/buttons: 0 + core/group: 0 + core/columns: 0 + core/column: 0 + core/cover: 0 + core/embed: 0 + core/file: 0 + core/freeform: 0 + core/html: 0 + core/media-text: 0 + core/preformatted: 0 + core/pullquote: 0 + core/separator: 0 + core/block: 0 + core/spacer: 0 + core/subhead: 0 + core/text-columns: 0 + core/verse: 0 + core/video: 0 + core-embed/all: 0 + core-embed/twitter: 0 + core-embed/youtube: 0 + core-embed/facebook: 0 + core-embed/instagram: 0 + core-embed/wordpress: 0 + core-embed/soundcloud: 0 + core-embed/spotify: 0 + core-embed/flickr: 0 + core-embed/vimeo: 0 + core-embed/amazon-kindle: 0 + core-embed/animoto: 0 + core-embed/cloudup: 0 + core-embed/collegehumor: 0 + core-embed/crowdsignal: 0 + core-embed/dailymotion: 0 + embed: 0 + core-embed/hulu: 0 + core-embed/imgur: 0 + core-embed/issuu: 0 + core-embed/kickstarter: 0 + core-embed/meetup-com: 0 + core-embed/mixcloud: 0 + core-embed/polldaddy: 0 + core-embed/reddit: 0 + core-embed/reverbnation: 0 + core-embed/screencast: 0 + core-embed/scribd: 0 + core-embed/slideshare: 0 + core-embed/smugmug: 0 + core-embed/speaker-deck: 0 + core-embed/speaker: 0 + core-embed/tiktok: 0 + core-embed/ted: 0 + core-embed/tumblr: 0 + core-embed/videopress: 0 + core-embed/wordpress-tv: 0 +blog_allowed_drupal_blocks: + drupalblock/all_config_pages: 0 + config_pages_block: 0 + 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 + 'views_block:who_s_online-who_s_online_block': 0 + drupalblock/all_menus: 0 + 'system_menu_block:footer': 0 + 'system_menu_block:main': 0 + 'system_menu_block:account': 0 + drupalblock/all_system: 0 + system_breadcrumb_block: 0 + 'language_block:language_interface': 0 + system_messages_block: 0 + system_powered_by_block: 0 + 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/apps/cms/config/sync/language.content_settings.node.blog.yml b/apps/cms/config/sync/language.content_settings.node.blog.yml new file mode 100644 index 000000000..fd82bd6cf --- /dev/null +++ b/apps/cms/config/sync/language.content_settings.node.blog.yml @@ -0,0 +1,16 @@ +uuid: d459f363-8f57-49ca-a141-e68eabcce715 +langcode: en +status: true +dependencies: + config: + - node.type.blog + module: + - content_translation +third_party_settings: + content_translation: + enabled: true +id: node.blog +target_entity_type_id: node +target_bundle: blog +default_langcode: site_default +language_alterable: true diff --git a/apps/cms/config/sync/language.content_settings.taxonomy_term.blog_tags.yml b/apps/cms/config/sync/language.content_settings.taxonomy_term.blog_tags.yml new file mode 100644 index 000000000..5e98fad2e --- /dev/null +++ b/apps/cms/config/sync/language.content_settings.taxonomy_term.blog_tags.yml @@ -0,0 +1,16 @@ +uuid: 7a0b7fdd-d913-4443-acc0-27a0b5534937 +langcode: en +status: true +dependencies: + config: + - taxonomy.vocabulary.blog_tags + module: + - content_translation +third_party_settings: + content_translation: + enabled: true +id: taxonomy_term.blog_tags +target_entity_type_id: taxonomy_term +target_bundle: blog_tags +default_langcode: site_default +language_alterable: true diff --git a/apps/cms/config/sync/node.type.blog.yml b/apps/cms/config/sync/node.type.blog.yml new file mode 100644 index 000000000..2f2fa7d96 --- /dev/null +++ b/apps/cms/config/sync/node.type.blog.yml @@ -0,0 +1,17 @@ +uuid: b1839ba8-be8d-44d4-b356-8e9191652564 +langcode: en +status: true +dependencies: + module: + - menu_ui +third_party_settings: + menu_ui: + available_menus: { } + parent: '' +name: Blog +type: blog +description: '' +help: '' +new_revision: true +preview_mode: 1 +display_submitted: false diff --git a/apps/cms/config/sync/node.type.page.yml b/apps/cms/config/sync/node.type.page.yml index f40b23647..b3d357422 100644 --- a/apps/cms/config/sync/node.type.page.yml +++ b/apps/cms/config/sync/node.type.page.yml @@ -10,7 +10,7 @@ third_party_settings: - footer - main parent: 'main:' -name: 'Basic page' +name: Page type: page description: '' help: '' diff --git a/apps/cms/config/sync/taxonomy.vocabulary.blog_tags.yml b/apps/cms/config/sync/taxonomy.vocabulary.blog_tags.yml new file mode 100644 index 000000000..248dd0974 --- /dev/null +++ b/apps/cms/config/sync/taxonomy.vocabulary.blog_tags.yml @@ -0,0 +1,8 @@ +uuid: 4d9a4e65-f824-4622-8522-e29bf009f317 +langcode: en +status: true +dependencies: { } +name: 'Blog tags' +vid: blog_tags +description: '' +weight: 0 diff --git a/apps/cms/scaffold/settings.php.append.txt b/apps/cms/scaffold/settings.php.append.txt index 00575f853..e8c60b5a2 100644 --- a/apps/cms/scaffold/settings.php.append.txt +++ b/apps/cms/scaffold/settings.php.append.txt @@ -19,8 +19,8 @@ $config['graphql.graphql_servers.main']['schema_configuration']['directable']['b $settings['silverback_graphql_persisted_map'] = '../node_modules/@custom/schema/build/operations.json'; // Environment indicator. -$config['environment_indicator.indicator']['name'] = 'Local Silverback'; -$config['environment_indicator.indicator']['bg_color'] = '#42a877'; +$config['environment_indicator.indicator']['name'] = 'Gutenberg demo'; +$config['environment_indicator.indicator']['bg_color'] = '#009ee0'; $config['environment_indicator.indicator']['fg_color'] = '#ffffff'; if (getenv('LAGOON')) { diff --git a/apps/website/src/templates/blog.tsx b/apps/website/src/templates/blog.tsx new file mode 100644 index 000000000..94f17f312 --- /dev/null +++ b/apps/website/src/templates/blog.tsx @@ -0,0 +1,53 @@ +import { graphql } from '@amazeelabs/gatsby-plugin-operations'; +import { OperationExecutor, useLocation, ViewPageQuery } from '@custom/schema'; +import { Blog } from '@custom/ui/routes/Blog'; +import { HeadProps, PageProps } from 'gatsby'; +import React from 'react'; + +export const query = graphql(ViewPageQuery); + +export function Head({ data }: HeadProps) { + return data.page ? ( + <> + {data.page.title} + {data.page.metaTags?.map((metaTag, index) => { + if (metaTag?.tag === 'meta') { + return ( + + ); + } else if (metaTag?.tag === 'link') { + return ( + + ); + } + return null; + }) || null} + + ) : null; +} + +export default function BlogTemplate({ data }: PageProps) { + // Retrieve the current location and prefill the + // "ViewPageQuery" with these arguments. + // That makes shure the `useOperation(ViewPageQuery, ...)` with this + // path immediately returns this data. + const [location] = useLocation(); + return ( + + + + ); +} diff --git a/packages/drupal/gutenberg_blocks/css/edit.css b/packages/drupal/gutenberg_blocks/css/edit.css index 39ab66473..f1fa3afcb 100644 --- a/packages/drupal/gutenberg_blocks/css/edit.css +++ b/packages/drupal/gutenberg_blocks/css/edit.css @@ -1,10 +1,16 @@ /* We can put any editor specific styling in here */ +/* We can put any editor specific styling in here */ .gutenberg__editor .editor-styles-wrapper { - font-family:inherit; + font-family: inherit; } .gutenberg__editor blockquote { - margin:0; + margin: 0; +} + +/* We do not want the preview button in the editor, we have the external preview feature. */ +.block-editor-post-preview__dropdown { + display: none; } .gutenberg__editor blockquote .quote-image img { @@ -18,13 +24,30 @@ content: ''; } +.components-toolbar-group button[aria-label='Align'] { + display: none; +} + +body a { + color: inherit; +} + +body a:hover, +body a:focus { + color: inherit; +} + .gutenberg__editor .container-wrapper { display: block; position: relative; margin: 40px 0; - border-left: 34px solid #666666; + border-left: 34px solid #373530; padding-left: 10px; - min-height: 250px; + min-height: 200px; +} + +.gutenberg__editor .container-wrapper.container-wrapper-long { + min-height: 300px; } .gutenberg__editor .container-wrapper .container-label { @@ -40,4 +63,83 @@ left: 0; transform-origin: 0 0; transform: rotate(90deg); -} \ No newline at end of file +} + +.gutenberg__editor .circle-wrapper { + height: 29px; + width: 29px; + float: right; + border-radius: 50%; + background-color: #fff; + margin-top: 10px; + margin-right: 10px; +} + +.gutenberg__editor .circle { + height: 25px; + width: 25px; + border-radius: 50%; + float: right; + margin-top: 2px; + margin-right: 2px; +} + +div[data-type='custom/remote-video'] iframe { + max-width: 100%; +} + +.components-panel .indent-0 { + margin-left: 0; +} + +.components-panel .indent-2 { + margin-left: 20px; +} + +.components-panel .indent-4 { + margin-left: 40px; +} + +.components-panel .components-base-control.components-checkbox-control { + margin-bottom: 0; +} + +.link-hidden span.block-editor-link-control__search-item-info { + display: none !important; +} + +.gutenberg__editor .edit-post-visual-editor__content-area hr { + border-color: #373530; +} + +@media (min-width: 1024px) { + .gutenberg__editor blockquote .lg\:text-3xl { + font-size: 2rem !important; + } +} + +.page-node-type-blog .gutenberg__editor .edit-post-visual-editor__content-area .lg\:prose-xl { + font-size: inherit; + line-height: inherit; +} + +/* +.gutenberg__editor .wp-block-custom-heading .block-editor-rich-text__editable { + color: #009ee0; +} +*/ + +.gutenberg__editor div[data-type="custom/image-with-caption"] .wp-block-paragraph { + color: #2e2e2e; + font-style: italic; +} + +.gutenberg__editor .two-columns { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 50px; +} + +.gutenberg__editor .button--primary { + background-color: #009ee0; +} diff --git a/packages/drupal/gutenberg_blocks/src/blocks/content-blog.tsx b/packages/drupal/gutenberg_blocks/src/blocks/content-blog.tsx new file mode 100644 index 000000000..4b7e2bf96 --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/content-blog.tsx @@ -0,0 +1,48 @@ +import { InnerBlocks } from 'wordpress__block-editor'; +import { registerBlockType } from 'wordpress__blocks'; + +// @ts-ignore +const { t: __ } = Drupal; + +const style = { + minHeight: '40px', + margin: '0 -40px', + padding: '0 40px', +}; + +registerBlockType(`custom/content-blog`, { + title: __('Content'), + category: 'layout', + icon: 'media-document', + attributes: {}, + supports: { + inserter: false, + align: true, + html: false, + }, + edit() { + return ( +
    + +
    + ); + }, + + save() { + return ; + }, +}); diff --git a/packages/drupal/gutenberg_blocks/src/blocks/cta.tsx b/packages/drupal/gutenberg_blocks/src/blocks/cta.tsx index 83bfd63de..5b3ae523f 100644 --- a/packages/drupal/gutenberg_blocks/src/blocks/cta.tsx +++ b/packages/drupal/gutenberg_blocks/src/blocks/cta.tsx @@ -34,6 +34,9 @@ registerBlockType('custom/cta', { 'data-entity-type': { type: 'string', }, + primary: { + type: 'boolean', + }, openInNewTab: { type: 'boolean', }, @@ -48,11 +51,12 @@ registerBlockType('custom/cta', { }, // @ts-ignore edit: compose(withState({}))((props) => { + const buttonType = props.attributes.primary ? 'button--primary' : 'button--secondary'; return (
    + { + props.setAttributes({ + primary, + }); + }} + /> { + return ( + <> + + + { + props.setAttributes({ + useModal, + }); + }} + /> + + +
    +
    {__('Image with Caption')}
    + { + // @ts-ignore + error = typeof error === 'string' ? error : error[2]; + dispatch('core/notices').createWarningNotice(error); + }} + /> +

    {__('Caption')}

    + +
    + + ); + }, + save: () => , +}); diff --git a/packages/drupal/gutenberg_blocks/src/blocks/image-with-link.tsx b/packages/drupal/gutenberg_blocks/src/blocks/image-with-link.tsx new file mode 100644 index 000000000..46454cedd --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/image-with-link.tsx @@ -0,0 +1,72 @@ +import { + // @ts-ignore + __experimentalLinkControl as LinkControl, + InnerBlocks, + InspectorControls, + RichText, +} from 'wordpress__block-editor'; +import { registerBlockType } from 'wordpress__blocks'; +import { PanelBody, ToggleControl } from 'wordpress__components'; +import { dispatch } from 'wordpress__data'; + +import { DrupalMediaEntity } from '../utils/drupal-media'; + +// @ts-ignore +const { t: __ } = Drupal; + +registerBlockType('custom/image-with-link', { + title: __('Image with Link'), + icon: 'cover-image', + category: 'layout', + attributes: { + mediaEntityIds: { + type: 'array', + }, + link: { + type: 'string', + }, + uuid: { + type: 'string', + }, + }, + edit: (props) => { + return ( + <> + + + { + props.setAttributes({ + link: link.url, + uuid: link.id, + }) + }} + /> + + +
    +
    {__('Image with Link')}
    + { + // @ts-ignore + error = typeof error === 'string' ? error : error[2]; + dispatch('core/notices').createWarningNotice(error); + }} + /> +
    + + ); + }, + save: () => , +}); diff --git a/packages/drupal/gutenberg_blocks/src/blocks/image.tsx b/packages/drupal/gutenberg_blocks/src/blocks/image.tsx new file mode 100644 index 000000000..a42b1160b --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/image.tsx @@ -0,0 +1,49 @@ +import { + // @ts-ignore + __experimentalLinkControl as LinkControl, + InnerBlocks, + InspectorControls, + RichText, +} from 'wordpress__block-editor'; +import { registerBlockType } from 'wordpress__blocks'; +import { PanelBody, ToggleControl } from 'wordpress__components'; +import { dispatch } from 'wordpress__data'; + +import { DrupalMediaEntity } from '../utils/drupal-media'; + +// @ts-ignore +const { t: __ } = Drupal; + +registerBlockType('custom/image', { + title: __('Image'), + icon: 'cover-image', + category: 'layout', + attributes: { + mediaEntityIds: { + type: 'array', + }, + }, + edit: (props) => { + return ( + <> + { + // @ts-ignore + error = typeof error === 'string' ? error : error[2]; + dispatch('core/notices').createWarningNotice(error); + }} + /> + + ); + }, + save: () => , +}); diff --git a/packages/drupal/gutenberg_blocks/src/blocks/mathjax.tsx b/packages/drupal/gutenberg_blocks/src/blocks/mathjax.tsx new file mode 100644 index 000000000..1d5ab4233 --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/mathjax.tsx @@ -0,0 +1,61 @@ +import { registerBlockType } from 'wordpress__blocks'; +import { compose, withState } from 'wordpress__compose'; +import { useEffect, useState } from 'react'; + +// @ts-ignore +const { t: __ } = Drupal; + +registerBlockType(`custom/mathjax`, { + title: __('MathJax'), + category: 'layout', + icon: 'media-document', + attributes: { + formula: { + source: 'html', + selector: 'div', + type: 'string', + }, + }, + // @ts-ignore + edit: compose(withState({}))((props) => { + const { isSelected, attributes, setAttributes, className } = props; + const { formula } = attributes; + const id = `mathjax-${Math.random().toString(36).substr(2, 9)}`; + + if ( isSelected ) { + return ( +
    + +