feat: 收口 mindmap Phase 6 Leptos UI shell
This commit is contained in:
@@ -25,6 +25,14 @@ export async function GET(
|
||||
{ params }: { params: Promise<{ docId: string; mindmapId: string }> },
|
||||
) {
|
||||
const { docId, mindmapId } = await params;
|
||||
const url = new URL(request.url);
|
||||
const view = url.searchParams.get("view");
|
||||
const queryName =
|
||||
view === "simple_mind_map_scene" || url.searchParams.get("queryName") === "mindmap.simple_mind_map_scene.get"
|
||||
? "mindmap.simple_mind_map_scene.get"
|
||||
: view === "editor_scene"
|
||||
? "mindmap.editor_scene.get"
|
||||
: "mindmaps.get";
|
||||
|
||||
if (isConvexEnabled()) {
|
||||
const { auth, client } = await getAuthedConvexClient();
|
||||
@@ -43,11 +51,12 @@ export async function GET(
|
||||
},
|
||||
});
|
||||
const envelope = buildDocumentQueryEnvelope({
|
||||
name: "mindmaps.get",
|
||||
name: queryName,
|
||||
payload: {
|
||||
documentId: docId,
|
||||
mindmapId,
|
||||
workspaceId: null,
|
||||
rootNodeId: url.searchParams.get("rootNodeId"),
|
||||
},
|
||||
});
|
||||
const plan = await resolveRustBridgeQueryPlan({ context, envelope });
|
||||
@@ -65,6 +74,9 @@ export async function GET(
|
||||
client,
|
||||
plan,
|
||||
});
|
||||
if (queryName === "mindmap.simple_mind_map_scene.get" || queryName === "mindmap.editor_scene.get") {
|
||||
return NextResponse.json(res);
|
||||
}
|
||||
return NextResponse.json({
|
||||
data: res?.data ?? defaultMindmapData,
|
||||
source: "convex",
|
||||
@@ -97,9 +109,12 @@ export async function POST(
|
||||
|
||||
if (isConvexEnabled()) {
|
||||
const { auth, client } = await getAuthedConvexClient();
|
||||
const { data, createOnly } = (await request.json().catch(() => ({ data: null }))) as {
|
||||
const { data, createOnly, commandName, commands, projectionRevision } = (await request.json().catch(() => ({ data: null }))) as {
|
||||
data?: unknown;
|
||||
createOnly?: boolean;
|
||||
commandName?: string;
|
||||
commands?: unknown[];
|
||||
projectionRevision?: number | null;
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -116,22 +131,31 @@ export async function POST(
|
||||
client: "wolai-frontend",
|
||||
},
|
||||
});
|
||||
const isCommandApply = commandName === "mindmap.command.apply";
|
||||
const envelope = buildDocumentCommandEnvelope({
|
||||
name: "mindmaps.put",
|
||||
payload: {
|
||||
documentId: docId,
|
||||
mindmapId,
|
||||
data: data ?? defaultMindmapData,
|
||||
createOnly: typeof createOnly === "boolean" ? createOnly : false,
|
||||
},
|
||||
name: isCommandApply ? "mindmap.command.apply" : "mindmaps.put",
|
||||
payload: isCommandApply
|
||||
? {
|
||||
documentId: docId,
|
||||
mindmapId,
|
||||
workspaceId: null,
|
||||
commands: Array.isArray(commands) ? commands : [],
|
||||
projectionRevision: typeof projectionRevision === "number" ? projectionRevision : null,
|
||||
}
|
||||
: {
|
||||
documentId: docId,
|
||||
mindmapId,
|
||||
data: data ?? defaultMindmapData,
|
||||
createOnly: typeof createOnly === "boolean" ? createOnly : false,
|
||||
},
|
||||
context,
|
||||
target: {
|
||||
workspaceId: null,
|
||||
pageId: docId,
|
||||
blockId: mindmapId,
|
||||
},
|
||||
reason: "mindmap-route:put",
|
||||
refs: ["task-032", "mindmap-route"],
|
||||
reason: isCommandApply ? "mindmap-route:command-apply" : "mindmap-route:put",
|
||||
refs: isCommandApply ? ["task-166", "mindmap-command-bridge"] : ["task-032", "mindmap-route"],
|
||||
});
|
||||
const plan = await resolveRustBridgeCommandPlan({ context, envelope });
|
||||
const result = await executeRustBridgeMutationTransport<{
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { MindmapBlockView, defaultMindmapData } from "@/components/editor/blocks/MindmapBlock";
|
||||
import type { BlockNoteEditor } from "@blocknote/core";
|
||||
import type { CustomBlockSchema } from "@/components/editor/schema";
|
||||
|
||||
const stubBlock = {
|
||||
id: "dev-mindmap",
|
||||
type: "mindmap",
|
||||
props: {
|
||||
docId: "dev",
|
||||
data: defaultMindmapData,
|
||||
},
|
||||
content: [],
|
||||
children: [],
|
||||
} as any;
|
||||
|
||||
const editorStub = {
|
||||
updateBlock: () => {
|
||||
/* 开发沙盒中跳过持久化 */
|
||||
},
|
||||
} as unknown as BlockNoteEditor<CustomBlockSchema>;
|
||||
|
||||
export default function MindmapDevPage() {
|
||||
return (
|
||||
<div className="fixed inset-0 bg-white">
|
||||
<MindmapBlockView block={stubBlock} editor={editorStub} fullscreen />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -7,31 +7,41 @@ import {
|
||||
buildMindmapProjection,
|
||||
defaultMindmapData,
|
||||
type MindmapProjection,
|
||||
type MindmapSimpleMindMapScene,
|
||||
} from "@/lib/mindmap/mindmap-projection";
|
||||
import MindmapPageClient from "./mindmap-page-client";
|
||||
|
||||
type MindmapRouteQueryResult = {
|
||||
data?: unknown;
|
||||
meta?: unknown;
|
||||
};
|
||||
|
||||
export const MINDMAP_PAGE_LEGACY_COMPAT_CONTRACT = {
|
||||
shellOwner: "mnote-web",
|
||||
runtimeRole: "legacy_compat_island",
|
||||
island: "mindmap_runtime",
|
||||
runtimeRole: "simple_mind_map_adapter",
|
||||
island: "leptos_mindmap_adapter",
|
||||
projectionQueryName: "mindmap.simple_mind_map_scene.get",
|
||||
commandName: "mindmap.command.apply",
|
||||
} as const;
|
||||
|
||||
async function fetchMindmapProjectionOnServer(input: {
|
||||
async function fetchMindmapAdapterProjectionOnServer(input: {
|
||||
docId: string;
|
||||
mindmapId: string;
|
||||
}): Promise<MindmapProjection | null> {
|
||||
}): Promise<MindmapSimpleMindMapScene | null> {
|
||||
if (!isConvexEnabled()) {
|
||||
return buildMindmapProjection({
|
||||
return {
|
||||
schema: "mnote.mindmap.simple_mind_map_scene.v1",
|
||||
runtime: "simple-mind-map",
|
||||
documentId: input.docId,
|
||||
mindmapId: input.mindmapId,
|
||||
data: defaultMindmapData,
|
||||
rootNodeId: null,
|
||||
root: defaultMindmapData,
|
||||
layout: "logicalStructure",
|
||||
theme: "classic",
|
||||
themeConfig: {},
|
||||
view: {},
|
||||
config: {},
|
||||
compatPayload: { source: "compat-blob", mindmapId: input.mindmapId },
|
||||
kernelRevision: 1,
|
||||
source: "compat-blob",
|
||||
owner: "rust-kernel",
|
||||
meta: null,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -63,7 +73,7 @@ async function fetchMindmapProjectionOnServer(input: {
|
||||
workspaceId: null,
|
||||
});
|
||||
const envelope = buildDocumentQueryEnvelope({
|
||||
name: "mindmaps.get",
|
||||
name: MINDMAP_PAGE_LEGACY_COMPAT_CONTRACT.projectionQueryName,
|
||||
payload: {
|
||||
documentId: input.docId,
|
||||
mindmapId: input.mindmapId,
|
||||
@@ -74,43 +84,70 @@ async function fetchMindmapProjectionOnServer(input: {
|
||||
context,
|
||||
envelope,
|
||||
});
|
||||
const result = await executeRustBridgeQueryTransport<MindmapRouteQueryResult | null>({
|
||||
const result = await executeRustBridgeQueryTransport<MindmapSimpleMindMapScene | null>({
|
||||
client,
|
||||
plan,
|
||||
});
|
||||
|
||||
return buildMindmapProjection({
|
||||
documentId: input.docId,
|
||||
mindmapId: input.mindmapId,
|
||||
data: result?.data ?? defaultMindmapData,
|
||||
meta: result?.meta ?? {
|
||||
requestId: context.requestId,
|
||||
traceId: context.traceId,
|
||||
workspaceId: context.workspaceId,
|
||||
documentId: input.docId,
|
||||
pageId: input.docId,
|
||||
mindmapId: input.mindmapId,
|
||||
attachmentId: input.mindmapId,
|
||||
},
|
||||
});
|
||||
return result
|
||||
? {
|
||||
...result,
|
||||
source: result.source ?? "compat-blob",
|
||||
owner: result.owner ?? "rust-kernel",
|
||||
meta: result.meta ?? {
|
||||
requestId: context.requestId,
|
||||
traceId: context.traceId,
|
||||
workspaceId: context.workspaceId,
|
||||
documentId: input.docId,
|
||||
pageId: input.docId,
|
||||
mindmapId: input.mindmapId,
|
||||
attachmentId: input.mindmapId,
|
||||
},
|
||||
}
|
||||
: null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function buildStandaloneProjectionFromAdapter(input: {
|
||||
docId: string;
|
||||
mindmapId: string;
|
||||
adapterProjection: MindmapSimpleMindMapScene | null;
|
||||
}): MindmapProjection | null {
|
||||
if (!input.adapterProjection) return null;
|
||||
return buildMindmapProjection({
|
||||
documentId: input.docId,
|
||||
mindmapId: input.mindmapId,
|
||||
data: input.adapterProjection.root ?? defaultMindmapData,
|
||||
source: input.adapterProjection.source ?? "compat-blob",
|
||||
owner: input.adapterProjection.owner ?? "rust-kernel",
|
||||
meta: input.adapterProjection.meta,
|
||||
});
|
||||
}
|
||||
|
||||
export default async function MindmapFullscreenPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ docId: string; mindmapId: string }>;
|
||||
}) {
|
||||
const { docId, mindmapId } = await params;
|
||||
const initialProjection = await fetchMindmapProjectionOnServer({ docId, mindmapId });
|
||||
const initialAdapterProjection = await fetchMindmapAdapterProjectionOnServer({ docId, mindmapId });
|
||||
const initialProjection = buildStandaloneProjectionFromAdapter({
|
||||
docId,
|
||||
mindmapId,
|
||||
adapterProjection: initialAdapterProjection,
|
||||
});
|
||||
|
||||
return (
|
||||
<main
|
||||
data-react-island={MINDMAP_PAGE_LEGACY_COMPAT_CONTRACT.island}
|
||||
data-leptos-mindmap-island={MINDMAP_PAGE_LEGACY_COMPAT_CONTRACT.island}
|
||||
data-runtime-role={MINDMAP_PAGE_LEGACY_COMPAT_CONTRACT.runtimeRole}
|
||||
data-shell-owner={MINDMAP_PAGE_LEGACY_COMPAT_CONTRACT.shellOwner}
|
||||
data-projection-query={MINDMAP_PAGE_LEGACY_COMPAT_CONTRACT.projectionQueryName}
|
||||
data-command-name={MINDMAP_PAGE_LEGACY_COMPAT_CONTRACT.commandName}
|
||||
data-adapter-source={initialAdapterProjection?.source ?? "compat-blob"}
|
||||
data-kernel-revision={initialAdapterProjection?.kernelRevision ?? 1}
|
||||
>
|
||||
<MindmapPageClient
|
||||
docId={docId}
|
||||
|
||||
Reference in New Issue
Block a user