From 0ead87792b9c7a793a3d221e3184df9f97f038c3 Mon Sep 17 00:00:00 2001 From: Thomas Metzger Date: Mon, 2 Jun 2025 12:16:34 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8(frontend)=20embed-block:=20added?= =?UTF-8?q?=20url=20embed=20block?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../doc-editor/components/BlockNoteEditor.tsx | 3 +- .../components/BlockNoteSuggestionMenu.tsx | 2 + .../components/custom-blocks/EmbedBlock.tsx | 159 ++++++++++++++++++ .../components/custom-blocks/index.ts | 1 + .../doc-export/blocks-mapping/embedDocx.tsx | 8 + .../doc-export/blocks-mapping/embedPDF.tsx | 8 + .../features/docs/doc-export/mappingDocx.tsx | 2 + .../features/docs/doc-export/mappingPDF.tsx | 2 + 8 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/EmbedBlock.tsx create mode 100644 src/frontend/apps/impress/src/features/docs/doc-export/blocks-mapping/embedDocx.tsx create mode 100644 src/frontend/apps/impress/src/features/docs/doc-export/blocks-mapping/embedPDF.tsx diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx index 9a486b5864..0c874fd5ab 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx @@ -27,7 +27,7 @@ import { randomColor } from '../utils'; import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu'; import { BlockNoteToolbar } from './BlockNoteToolBar/BlockNoteToolbar'; -import { CalloutBlock, DividerBlock } from './custom-blocks'; +import { CalloutBlock, DividerBlock, ReactEmbedBlock } from './custom-blocks'; export const blockNoteSchema = withPageBreak( BlockNoteSchema.create({ @@ -35,6 +35,7 @@ export const blockNoteSchema = withPageBreak( ...defaultBlockSpecs, callout: CalloutBlock, divider: DividerBlock, + embed: ReactEmbedBlock, }, }), ); diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx index 3122b1c175..138d3f772d 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteSuggestionMenu.tsx @@ -14,6 +14,7 @@ import { DocsBlockSchema } from '../types'; import { getCalloutReactSlashMenuItems, getDividerReactSlashMenuItems, + getEmbedReactSlashMenuItems, } from './custom-blocks'; export const BlockNoteSuggestionMenu = () => { @@ -30,6 +31,7 @@ export const BlockNoteSuggestionMenu = () => { getPageBreakReactSlashMenuItems(editor), getCalloutReactSlashMenuItems(editor, t, basicBlocksName), getDividerReactSlashMenuItems(editor, t, basicBlocksName), + getEmbedReactSlashMenuItems(editor, t, basicBlocksName), ), query, ), diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/EmbedBlock.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/EmbedBlock.tsx new file mode 100644 index 0000000000..14d94cb587 --- /dev/null +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-blocks/EmbedBlock.tsx @@ -0,0 +1,159 @@ +import { + FileBlockConfig, + InlineContentSchema, + PropSchema, + StyleSchema, + insertOrUpdateBlock, +} from '@blocknote/core'; +import { + BlockTypeSelectItem, + ReactCustomBlockRenderProps, + ResizableFileBlockWrapper, + createReactBlockSpec, +} from '@blocknote/react'; +import { TFunction } from 'i18next'; +import React, { useState } from 'react'; +import { css } from 'styled-components'; + +import { Box, Icon } from '@/components'; + +import { DocsBlockNoteEditor } from '../../types'; + +export const iframePropSchema: PropSchema & { + caption: { + default: ''; + }; + name: { + default: ''; + }; +} = { + url: { default: '' }, + caption: { default: '' }, + name: { default: '' }, + showPreview: { default: true }, + previewWidth: { type: 'number', default: undefined }, +}; + +export const iframeBlockConfig = { + type: 'embed' as const, + propSchema: iframePropSchema, + content: 'none', + isFileBlock: true, + fileBlockAccept: ['image/png'], +} satisfies FileBlockConfig; + +export const IFrameViewer = ( + props: ReactCustomBlockRenderProps< + typeof iframeBlockConfig, + InlineContentSchema, + StyleSchema + >, +) => { + const url = props.block.props.url; + + const [iframeError, setIframeError] = useState(false); + if (!url) { + return No URL provided for embed.; + } + + return !iframeError ? ( +