mirror of
https://github.com/docmost/docmost.git
synced 2026-07-25 23:54:43 +10:00
feat(base): inline base embed — node registration, slash command, and renderer view
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
import { NodeViewWrapper, NodeViewProps } from '@tiptap/react';
|
||||||
|
import { Box, Text } from '@mantine/core';
|
||||||
|
import { BaseTable } from '@/features/base/components/base-table';
|
||||||
|
import { useBaseQuery } from '@/features/base/queries/base-query';
|
||||||
|
|
||||||
|
export function BaseEmbedView({ node }: NodeViewProps) {
|
||||||
|
const pageId = node.attrs.pageId as string | null;
|
||||||
|
|
||||||
|
if (!pageId) {
|
||||||
|
return (
|
||||||
|
<NodeViewWrapper>
|
||||||
|
<Box p="md">
|
||||||
|
<Text c="red">Invalid base embed (missing page id)</Text>
|
||||||
|
</Box>
|
||||||
|
</NodeViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { isLoading, isError } = useBaseQuery(pageId);
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<NodeViewWrapper>
|
||||||
|
<Box p="md">
|
||||||
|
<Text c="dimmed">Loading...</Text>
|
||||||
|
</Box>
|
||||||
|
</NodeViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
return (
|
||||||
|
<NodeViewWrapper>
|
||||||
|
<Box p="md" bg="gray.0" style={{ borderRadius: 8 }}>
|
||||||
|
<Text c="dimmed">You don't have access to this database.</Text>
|
||||||
|
</Box>
|
||||||
|
</NodeViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NodeViewWrapper>
|
||||||
|
<Box style={{ minHeight: 200 }}>
|
||||||
|
<BaseTable pageId={pageId} />
|
||||||
|
</Box>
|
||||||
|
</NodeViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -52,6 +52,7 @@ import {
|
|||||||
VimeoIcon,
|
VimeoIcon,
|
||||||
YoutubeIcon,
|
YoutubeIcon,
|
||||||
} from "@/components/icons";
|
} from "@/components/icons";
|
||||||
|
import api from "@/lib/api-client";
|
||||||
|
|
||||||
const CommandGroups: SlashMenuGroupedItemsType = {
|
const CommandGroups: SlashMenuGroupedItemsType = {
|
||||||
basic: [
|
basic: [
|
||||||
@@ -477,6 +478,25 @@ const CommandGroups: SlashMenuGroupedItemsType = {
|
|||||||
editor.chain().focus().deleteRange(range).insertSubpages().run();
|
editor.chain().focus().deleteRange(range).insertSubpages().run();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Database",
|
||||||
|
description: "Insert an inline database on this page",
|
||||||
|
searchTerms: ["database", "base", "table", "grid", "spreadsheet"],
|
||||||
|
icon: IconTable,
|
||||||
|
command: async ({ editor, range }: CommandProps) => {
|
||||||
|
// @ts-ignore
|
||||||
|
const parentPageId = editor.storage?.pageId as string | undefined;
|
||||||
|
if (!parentPageId) return;
|
||||||
|
|
||||||
|
editor.chain().focus().deleteRange(range).run();
|
||||||
|
|
||||||
|
const res = await api.post<{ id: string }>("/bases/inline-embed", {
|
||||||
|
parentPageId,
|
||||||
|
});
|
||||||
|
|
||||||
|
editor.commands.insertBaseEmbed({ pageId: res.data.id });
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "2 Columns",
|
title: "2 Columns",
|
||||||
description: "Split content into two columns.",
|
description: "Split content into two columns.",
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import {
|
|||||||
Columns,
|
Columns,
|
||||||
Column,
|
Column,
|
||||||
Status,
|
Status,
|
||||||
|
BaseEmbed as BaseEmbedNode,
|
||||||
} from "@docmost/editor-ext";
|
} from "@docmost/editor-ext";
|
||||||
import {
|
import {
|
||||||
randomElement,
|
randomElement,
|
||||||
@@ -80,6 +81,7 @@ import ExcalidrawView from "@/features/editor/components/excalidraw/excalidraw-v
|
|||||||
import EmbedView from "@/features/editor/components/embed/embed-view.tsx";
|
import EmbedView from "@/features/editor/components/embed/embed-view.tsx";
|
||||||
import PdfView from "@/features/editor/components/pdf/pdf-view.tsx";
|
import PdfView from "@/features/editor/components/pdf/pdf-view.tsx";
|
||||||
import SubpagesView from "@/features/editor/components/subpages/subpages-view.tsx";
|
import SubpagesView from "@/features/editor/components/subpages/subpages-view.tsx";
|
||||||
|
import { BaseEmbedView } from "@/features/editor/components/base-embed/base-embed-view.tsx";
|
||||||
import { common, createLowlight } from "lowlight";
|
import { common, createLowlight } from "lowlight";
|
||||||
import plaintext from "highlight.js/lib/languages/plaintext";
|
import plaintext from "highlight.js/lib/languages/plaintext";
|
||||||
import powershell from "highlight.js/lib/languages/powershell";
|
import powershell from "highlight.js/lib/languages/powershell";
|
||||||
@@ -351,6 +353,11 @@ export const mainExtensions = [
|
|||||||
Status.configure({
|
Status.configure({
|
||||||
view: StatusView,
|
view: StatusView,
|
||||||
}),
|
}),
|
||||||
|
BaseEmbedNode.extend({
|
||||||
|
addNodeView() {
|
||||||
|
return ReactNodeViewRenderer(BaseEmbedView);
|
||||||
|
},
|
||||||
|
}),
|
||||||
MarkdownClipboard.configure({
|
MarkdownClipboard.configure({
|
||||||
transformPastedText: true,
|
transformPastedText: true,
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user