From 14622450cf09ffb1ae466afd50a0a5a0369d965b Mon Sep 17 00:00:00 2001 From: DrMint <29893320+DrMint@users.noreply.github.com> Date: Fri, 15 Mar 2024 21:19:23 +0100 Subject: [PATCH] Added break block --- src/blocks/breakBlock.ts | 20 ++++++ src/blocks/sectionBlock.ts | 2 + src/collections/Pages/Pages.ts | 3 +- .../Pages/endpoints/getBySlugEndpoint.ts | 63 ++++++++++++++++--- src/constants.ts | 26 +++++--- src/sdk.ts | 2 + src/types/collections.ts | 10 +++ 7 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 src/blocks/breakBlock.ts diff --git a/src/blocks/breakBlock.ts b/src/blocks/breakBlock.ts new file mode 100644 index 0000000..7613c06 --- /dev/null +++ b/src/blocks/breakBlock.ts @@ -0,0 +1,20 @@ +import { Block } from "payload/types"; +import { BreakBlockType } from "../constants"; + +export const breakBlock: Block = { + slug: "breakBlock", + interfaceName: "BreakBlock", + labels: { singular: "Break", plural: "Breaks" }, + fields: [ + { + name: "type", + type: "radio", + required: true, + defaultValue: BreakBlockType.sceneBreak, + options: Object.entries(BreakBlockType).map(([_, value]) => ({ + label: value, + value: value, + })), + }, + ], +}; diff --git a/src/blocks/sectionBlock.ts b/src/blocks/sectionBlock.ts index ea0de05..2d7ecab 100644 --- a/src/blocks/sectionBlock.ts +++ b/src/blocks/sectionBlock.ts @@ -1,5 +1,6 @@ import { Block } from "payload/types"; import { createEditor } from "../utils/editor"; +import { breakBlock } from "./breakBlock"; import { transcriptBlock } from "./transcriptBlock"; const generateRecursiveSectionBlock = (depth = 1, maxDepth = 5): Block => ({ @@ -25,6 +26,7 @@ const generateRecursiveSectionBlock = (depth = 1, maxDepth = 5): Block => ({ blocks: [ ...(depth < maxDepth ? [generateRecursiveSectionBlock(depth + 1, maxDepth)] : []), transcriptBlock, + breakBlock ], }), }, diff --git a/src/collections/Pages/Pages.ts b/src/collections/Pages/Pages.ts index 1d1154b..2157382 100644 --- a/src/collections/Pages/Pages.ts +++ b/src/collections/Pages/Pages.ts @@ -1,4 +1,5 @@ import { Where } from "payload/types"; +import { breakBlock } from "../../blocks/breakBlock"; import { sectionBlock } from "../../blocks/sectionBlock"; import { transcriptBlock } from "../../blocks/transcriptBlock"; import { QuickFilters, publishStatusFilters } from "../../components/QuickFilters"; @@ -150,7 +151,7 @@ export const Pages = buildVersionedCollectionConfig({ images: true, inlines: true, alignment: true, - blocks: [sectionBlock, transcriptBlock], + blocks: [sectionBlock, transcriptBlock, breakBlock], links: true, lists: true, }), diff --git a/src/collections/Pages/endpoints/getBySlugEndpoint.ts b/src/collections/Pages/endpoints/getBySlugEndpoint.ts index 297406f..6d0dff6 100644 --- a/src/collections/Pages/endpoints/getBySlugEndpoint.ts +++ b/src/collections/Pages/endpoints/getBySlugEndpoint.ts @@ -1,7 +1,9 @@ import { + BreakBlockType, Collections, PageType, RichTextContent, + isBlockNodeBreakBlock, isBlockNodeSectionBlock, isNodeBlockNode, } from "../../../constants"; @@ -78,15 +80,58 @@ const handleContent = ( }; }; -const handleToc = (content: RichTextContent, parentPrefix = ""): TableOfContentEntry[] => - content.root.children - .filter(isNodeBlockNode) - .filter(isBlockNodeSectionBlock) - .map(({ fields }, index) => ({ - prefix: `${parentPrefix}${index + 1}.`, - title: fields.blockName ?? "", - children: handleToc(fields.content, `${index + 1}.`), - })); +const handleToc = (content: RichTextContent, parentPrefix = ""): TableOfContentEntry[] => { + let index = 0; + + return content.root.children.filter(isNodeBlockNode).flatMap((node) => { + if (isBlockNodeSectionBlock(node)) { + index++; + return [ + { + index, + prefix: `${parentPrefix}${index}.`, + title: node.fields.blockName ?? "", + type: "section", + children: handleToc(node.fields.content, `${index}.`), + }, + ]; + } else if (isBlockNodeBreakBlock(node)) { + switch (node.fields.type) { + case BreakBlockType.dottedLine: + case BreakBlockType.solidLine: { + index++; + return [ + { + index, + prefix: `${parentPrefix}${index}.`, + title: node.fields.blockName ?? "", + type: "break", + children: [], + }, + ]; + } + + case BreakBlockType.sceneBreak: { + index++; + return [ + { + index, + prefix: `${parentPrefix}${index}.`, + title: node.fields.blockName ?? "", + type: "sceneBreak", + children: [], + }, + ]; + } + + case BreakBlockType.space: + default: + return []; + } + } + return []; + }); +}; export const convertPageToPreview = ({ authors, diff --git a/src/constants.ts b/src/constants.ts index 970f5b7..61231f0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,8 +1,4 @@ -import type { - Image, - SectionBlock, - TranscriptBlock, -} from "./types/collections"; +import type { BreakBlock, Image, SectionBlock, TranscriptBlock } from "./types/collections"; // END MOCKING SECTION @@ -45,6 +41,13 @@ export enum LanguageCodes { "zh" = "Chinese", } +export enum BreakBlockType { + sceneBreak = "Scene break", + space = "Empty space", + solidLine = "Solid line", + dottedLine = "Dotted line", +} + export enum CollectibleBindingTypes { Paperback = "Paperback", Hardcover = "Hardcover", @@ -202,6 +205,10 @@ export interface RichTextTranscriptBlock extends RichTextBlockNode { fields: TranscriptBlock; } +export interface RichTextBreakBlock extends RichTextBlockNode { + fields: BreakBlock; +} + export const isNodeParagraphNode = (node: RichTextNode): node is RichTextParagraphNode => node.type === "paragraph"; @@ -251,19 +258,22 @@ export const isBlockNodeTranscriptBlock = ( node: RichTextBlockNode ): node is RichTextTranscriptBlock => node.fields.blockType === "transcriptBlock"; +export const isBlockNodeBreakBlock = (node: RichTextBlockNode): node is RichTextBreakBlock => + node.fields.blockType === "breakBlock"; + /* BLOCKS */ /* TODO: TO BE REMOVED WHEN https://github.com/payloadcms/payload/issues/5216 is closed */ export interface CueBlock { content: RichTextContent; - blockType: 'cueBlock'; + blockType: "cueBlock"; id?: string | null; blockName?: string | null; } export interface LineBlock { content: RichTextContent; - blockType: 'lineBlock'; + blockType: "lineBlock"; id?: string | null; blockName?: string | null; } @@ -278,4 +288,4 @@ export const isBlockCueBlock = (block: GenericBlock): block is CueBlock => block.blockType === "cueBlock"; export const isBlockLineBlock = (block: GenericBlock): block is LineBlock => - block.blockType === "lineBlock"; \ No newline at end of file + block.blockType === "lineBlock"; diff --git a/src/sdk.ts b/src/sdk.ts index 9b2bf91..7a34bbe 100644 --- a/src/sdk.ts +++ b/src/sdk.ts @@ -315,6 +315,8 @@ export type EndpointCollectible = EndpointCollectiblePreview & { export type TableOfContentEntry = { prefix: string; title: string; + type: "sceneBreak" | "break" | "section"; + index: number; children: TableOfContentEntry[]; }; diff --git a/src/types/collections.ts b/src/types/collections.ts index e4bdaff..3c3b607 100644 --- a/src/types/collections.ts +++ b/src/types/collections.ts @@ -805,6 +805,16 @@ export interface TranscriptBlock { blockName?: string | null; blockType: 'transcriptBlock'; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "BreakBlock". + */ +export interface BreakBlock { + type: 'Scene break' | 'Empty space' | 'Solid line' | 'Dotted line'; + id?: string | null; + blockName?: string | null; + blockType: 'breakBlock'; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "SectionBlock".