Skip to content

Commit

Permalink
Fix linking from block preview to block admin for non-trivial composi…
Browse files Browse the repository at this point in the history
…te/list block combinations (#1569)

fix issue from #1507

---------

Co-authored-by: Johannes Obermair <[email protected]>
  • Loading branch information
nsams and johnnyomair authored Jan 23, 2024
1 parent 3ee4ce0 commit 76f85ab
Show file tree
Hide file tree
Showing 14 changed files with 214 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/odd-fishes-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@comet/blocks-admin": patch
---

Fix linking from block preview to block admin for non-trivial composite/list block combinations
2 changes: 2 additions & 0 deletions demo/admin/src/pages/PageContentBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as React from "react";
import { ColumnsBlock } from "./blocks/ColumnsBlock";
import { FullWidthImageBlock } from "./blocks/FullWidthImageBlock";
import { MediaBlock } from "./blocks/MediaBlock";
import { TeaserBlock } from "./blocks/TeaserBlock";
import { TwoListsBlock } from "./blocks/TwoListsBlock";
import { VideoBlock } from "./blocks/VideoBlock";

Expand All @@ -32,6 +33,7 @@ export const PageContentBlock = createBlocksBlock({
anchor: AnchorBlock,
twoLists: TwoListsBlock,
media: MediaBlock,
teaser: TeaserBlock,
},
additionalItemFields: {
...userGroupAdditionalItemFields,
Expand Down
43 changes: 43 additions & 0 deletions demo/admin/src/pages/blocks/TeaserBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { BlockCategory, createCompositeBlock } from "@comet/blocks-admin";
import { DamImageBlock } from "@comet/cms-admin";
import { HeadlineBlock } from "@src/common/blocks/HeadlineBlock";
import { LinkListBlock } from "@src/common/blocks/LinkListBlock";
import React from "react";
import { FormattedMessage } from "react-intl";

const TeaserBlock = createCompositeBlock(
{
name: "Teaser",
displayName: <FormattedMessage id="blocks.teaser" defaultMessage="Teaser" />,
blocks: {
// Normal
headline: {
block: HeadlineBlock,
title: <FormattedMessage id="blocks.teaser.headline" defaultMessage="Headline" />,
},
// Nested
image: {
block: DamImageBlock,
title: <FormattedMessage id="blocks.teaser.image" defaultMessage="Image" />,
nested: true,
},
// Subroutes
links: {
block: LinkListBlock,
title: <FormattedMessage id="blocks.teaser.links" defaultMessage="Links" />,
},
// Nested inner subroutes
buttons: {
block: LinkListBlock,
title: <FormattedMessage id="blocks.teaser.buttons" defaultMessage="Buttons" />,
nested: true,
},
},
},
(block) => {
block.category = BlockCategory.Teaser;
return block;
},
);

export { TeaserBlock };
61 changes: 59 additions & 2 deletions demo/api/block-meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,8 @@
"columns": "Columns",
"anchor": "Anchor",
"twoLists": "TwoLists",
"media": "Media"
"media": "Media",
"teaser": "Teaser"
},
"nullable": false
},
Expand Down Expand Up @@ -1130,7 +1131,8 @@
"columns": "Columns",
"anchor": "Anchor",
"twoLists": "TwoLists",
"media": "Media"
"media": "Media",
"teaser": "Teaser"
},
"nullable": false
},
Expand Down Expand Up @@ -1737,6 +1739,61 @@
}
]
},
{
"name": "Teaser",
"fields": [
{
"name": "headline",
"kind": "Block",
"block": "Headline",
"nullable": false
},
{
"name": "image",
"kind": "Block",
"block": "DamImage",
"nullable": false
},
{
"name": "links",
"kind": "Block",
"block": "LinkList",
"nullable": false
},
{
"name": "buttons",
"kind": "Block",
"block": "LinkList",
"nullable": false
}
],
"inputFields": [
{
"name": "headline",
"kind": "Block",
"block": "Headline",
"nullable": false
},
{
"name": "image",
"kind": "Block",
"block": "DamImage",
"nullable": false
},
{
"name": "links",
"kind": "Block",
"block": "LinkList",
"nullable": false
},
{
"name": "buttons",
"kind": "Block",
"block": "LinkList",
"nullable": false
}
]
},
{
"name": "TextImage",
"fields": [
Expand Down
2 changes: 2 additions & 0 deletions demo/api/src/pages/blocks/PageContentBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ColumnsBlock } from "./columns.block";
import { FullWidthImageBlock } from "./full-width-image.block";
import { HeadlineBlock } from "./headline.block";
import { MediaBlock } from "./media.block";
import { TeaserBlock } from "./teaser.block";
import { TextImageBlock } from "./TextImageBlock";
import { TwoListsBlock } from "./two-lists.block";
import { VideoBlock } from "./video.block";
Expand All @@ -28,6 +29,7 @@ const supportedBlocks = {
anchor: AnchorBlock,
twoLists: TwoListsBlock,
media: MediaBlock,
teaser: TeaserBlock,
};

class BlocksBlockItemData extends BaseBlocksBlockItemData(supportedBlocks) {
Expand Down
51 changes: 51 additions & 0 deletions demo/api/src/pages/blocks/teaser.block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
BlockData,
BlockDataInterface,
BlockInput,
ChildBlock,
ChildBlockInput,
createBlock,
ExtractBlockData,
ExtractBlockInput,
inputToData,
} from "@comet/blocks-api";
import { DamImageBlock } from "@comet/cms-api";
import { LinkListBlock } from "@src/common/blocks/link-list.block";

import { HeadlineBlock } from "./headline.block";

class TeaserBlockData extends BlockData {
@ChildBlock(HeadlineBlock)
headline: ExtractBlockData<typeof HeadlineBlock>;

@ChildBlock(DamImageBlock)
image: ExtractBlockData<typeof DamImageBlock>;

@ChildBlock(LinkListBlock)
links: ExtractBlockData<typeof LinkListBlock>;

@ChildBlock(LinkListBlock)
buttons: ExtractBlockData<typeof LinkListBlock>;
}

class TeaserBlockInput extends BlockInput {
@ChildBlockInput(HeadlineBlock)
headline: ExtractBlockInput<typeof HeadlineBlock>;

@ChildBlockInput(DamImageBlock)
image: ExtractBlockInput<typeof DamImageBlock>;

@ChildBlockInput(LinkListBlock)
links: ExtractBlockInput<typeof LinkListBlock>;

@ChildBlockInput(LinkListBlock)
buttons: ExtractBlockInput<typeof LinkListBlock>;

transformToBlockData(): BlockDataInterface {
return inputToData(TeaserBlockData, this);
}
}

const TeaserBlock = createBlock(TeaserBlockData, TeaserBlockInput, "Teaser");

export { TeaserBlock };
2 changes: 2 additions & 0 deletions demo/site/src/blocks/PageContentBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BlocksBlock, PropsWithData, SupportedBlocks, YouTubeVideoBlock } from "@comet/cms-site";
import { PageContentBlockData } from "@src/blocks.generated";
import { TeaserBlock } from "@src/documents/pages/blocks/TeaserBlock";
import * as React from "react";

import { AnchorBlock } from "./AnchorBlock";
Expand Down Expand Up @@ -29,6 +30,7 @@ const supportedBlocks: SupportedBlocks = {
anchor: (props) => <AnchorBlock data={props} />,
media: (props) => <MediaBlock data={props} />,
twoLists: (props) => <TwoListsBlock data={props} />,
teaser: (props) => <TeaserBlock data={props} />,
};

export const PageContentBlock: React.FC<PropsWithData<PageContentBlockData>> = ({ data }) => {
Expand Down
29 changes: 29 additions & 0 deletions demo/site/src/documents/pages/blocks/TeaserBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { PropsWithData, withPreview } from "@comet/cms-site";
import { TeaserBlockData } from "@src/blocks.generated";
import { DamImageBlock } from "@src/blocks/DamImageBlock";
import { HeadlineBlock } from "@src/blocks/HeadlineBlock";
import { LinkListBlock } from "@src/blocks/LinkListBlock";
import styled from "styled-components";

const TeaserBlock = withPreview(
({ data: { headline, image, links, buttons } }: PropsWithData<TeaserBlockData>) => {
return (
<Root>
<HeadlineBlock data={headline} />
<DamImageBlock data={image} />
<LinkListBlock data={links} />
<LinkListBlock data={buttons} />
</Root>
);
},
{ label: "Teaser" },
);

const Root = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
`;

export { TeaserBlock };
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export function createBlocksBlock<AdditionalItemFields extends Record<string, un
blocks: state.blocks
.filter((child) => (previewCtx.showVisibleOnly ? child.visible : true)) // depending on context show all blocks or only visible blocks
.map((child) => {
const blockAdminRoute = `${previewCtx.parentUrl}/${child.key}/blocks`;
const blockAdminRoute = `${previewCtx.parentUrlSubRoute ?? previewCtx.parentUrl}/${child.key}/blocks`;
const block = blockForType(child.type);
if (!block) {
throw new Error(`No Block found for type ${child.type}`); // for TS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export function createColumnsBlock<T extends BlockInterface>({
columns: state.columns
.filter((c) => (previewContext.showVisibleOnly ? c.visible : true)) // depending on context show all blocks or only visible blocks
.map((column) => {
const blockAdminRoute = `${previewContext.parentUrl}/${column.key}/edit`;
const blockAdminRoute = `${previewContext.parentUrlSubRoute ?? previewContext.parentUrl}/${column.key}/edit`;

return {
key: column.key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,16 @@ export const createCompositeBlock = <Options extends CreateCompositeBlockOptions
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(blockPreviewState as any)[attr] = extractedBlock.createPreviewState(blockState, {
...previewContext,
parentUrl: `${previewContext.parentUrl}/${attr}/${attr}`,
parentUrl: `${previewContext.parentUrlSubRoute ?? previewContext.parentUrl}/${attr}/${attr}`,
});
} else if ((block.nested == null || !block.nested) && isBlockInterface(extractedBlock)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const blockState: any = (state as any)[attr];

const embeddedBlockState = extractedBlock.createPreviewState(blockState, {
...previewContext,
parentUrl: `${previewContext.parentUrl}/${attr}`,
parentUrlSubRoute: `${previewContext.parentUrl}/${attr}`,
parentUrl: `${previewContext.parentUrl}`,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(blockPreviewState as any)[attr] = { ...embeddedBlockState, adminMeta: { route: `${previewContext.parentUrl}#${attr}` } };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export function createListBlock<T extends BlockInterface, AdditionalItemFields e
blocks: state.blocks
.filter((child) => (previewCtx.showVisibleOnly ? child.visible : true)) // depending on context show all blocks or only visible blocks
.map((child) => {
const blockAdminRoute = `${previewCtx.parentUrl}/${child.key}/edit`;
const blockAdminRoute = `${previewCtx.parentUrlSubRoute ?? previewCtx.parentUrl}/${child.key}/edit`;

return {
key: child.key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,20 @@ export function composeBlocks<C extends CompositeBlocksConfig>(compositeBlocks:
{ flatten: true },
),

createPreviewState: (s, previewCtx) =>
applyToCompositeBlocks(
compositeBlocks,
([block, options], attr) => {
const extractedState = extractData([block, options], attr, s);
return block.createPreviewState(extractedState, previewCtx);
},
{ flatten: true },
),

createPreviewState: (s, previewCtx) => {
return {
adminRoute: previewCtx.parentUrl,
adminMeta: { route: previewCtx.parentUrl },
...applyToCompositeBlocks(
compositeBlocks,
([block, options], attr) => {
const extractedState = extractData([block, options], attr, s);
return block.createPreviewState(extractedState, previewCtx);
},
{ flatten: true },
),
};
},
isValid: async (state) => {
const isValidPromises: Promise<boolean>[] = Object.values(
applyToCompositeBlocks(compositeBlocks, ([block, options], attr) => {
Expand Down
1 change: 1 addition & 0 deletions packages/admin/blocks-admin/src/blocks/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type DispatchSetStateAction<S> = (setStateAction: SetStateAction<S>) => v
export interface IPreviewContext {
showVisibleOnly?: boolean;
parentUrl: string;
parentUrlSubRoute?: string;
}

interface AdminMetaInterface {
Expand Down

0 comments on commit 76f85ab

Please sign in to comment.