2026-04-29 12:24:44 +08:00
|
|
|
//! MNOTE 文档页面组件 (SSR)
|
|
|
|
|
//!
|
|
|
|
|
//! 提供文档编辑器的服务器端渲染壳。
|
|
|
|
|
//! 外部手写 `<body>` 包装和 `<script>` 数据嵌入由路由 handler 处理。
|
|
|
|
|
|
|
|
|
|
use crate::ssr::pages::layout::PageLayout;
|
2026-04-29 14:36:24 +08:00
|
|
|
use leptos::prelude::*;
|
2026-04-29 12:24:44 +08:00
|
|
|
|
|
|
|
|
/// MNOTE 文档页面
|
|
|
|
|
///
|
|
|
|
|
/// 渲染文档编辑器的 SSR 壳结构:
|
|
|
|
|
/// - `<PageLayout current_nav="documents">`
|
|
|
|
|
/// - 标题区域
|
|
|
|
|
/// - 页面聚合快照标记
|
|
|
|
|
/// - 编辑器占位区
|
|
|
|
|
#[component]
|
|
|
|
|
pub fn DocumentPage(
|
|
|
|
|
/// 文档标题
|
|
|
|
|
title: String,
|
2026-04-29 14:36:24 +08:00
|
|
|
/// 文档 id
|
|
|
|
|
document_id: String,
|
2026-04-30 05:46:36 +08:00
|
|
|
/// 工作区 id
|
|
|
|
|
workspace_id: String,
|
2026-04-29 12:24:44 +08:00
|
|
|
/// 侧栏页面树 HTML(可选)
|
|
|
|
|
#[prop(optional)]
|
|
|
|
|
sidebar_tree_html: Option<String>,
|
|
|
|
|
/// 工作区名称(可选)
|
|
|
|
|
#[prop(optional)]
|
|
|
|
|
workspace_name: Option<String>,
|
2026-04-29 14:36:24 +08:00
|
|
|
/// workspace shell 侧栏 sections HTML(可选)
|
|
|
|
|
#[prop(optional)]
|
|
|
|
|
workspace_sidebar_html: Option<String>,
|
|
|
|
|
/// Page Aggregate 子树 JSON(可选)
|
|
|
|
|
#[prop(optional)]
|
|
|
|
|
page_subtree_json: Option<String>,
|
2026-04-29 12:24:44 +08:00
|
|
|
) -> impl IntoView {
|
2026-04-29 14:36:24 +08:00
|
|
|
let has_page_subtree = page_subtree_json
|
|
|
|
|
.as_deref()
|
|
|
|
|
.map(str::trim)
|
|
|
|
|
.filter(|value| !value.is_empty() && *value != "null")
|
|
|
|
|
.is_some();
|
2026-04-29 16:23:49 +08:00
|
|
|
let workspace_label = workspace_name
|
|
|
|
|
.clone()
|
|
|
|
|
.map(|value| value.trim().to_string())
|
|
|
|
|
.filter(|value| !value.is_empty())
|
|
|
|
|
.unwrap_or_else(|| "个人空间".to_string());
|
2026-04-29 12:24:44 +08:00
|
|
|
view! {
|
2026-04-29 14:36:24 +08:00
|
|
|
<PageLayout current_nav="documents" sidebar_tree_html={sidebar_tree_html.unwrap_or_default()} workspace_name={workspace_name.unwrap_or_default()} workspace_sidebar_html={workspace_sidebar_html.unwrap_or_default()} topbar_title={title.clone()}>
|
2026-04-30 05:46:36 +08:00
|
|
|
<main class="document-shell" data-editor-host="leptos_tiptap_island" data-document-id={document_id.clone()} data-workspace-id={workspace_id.clone()}>
|
2026-04-29 12:24:44 +08:00
|
|
|
<header class="document-shell-header">
|
2026-04-30 05:46:36 +08:00
|
|
|
<div class="document-page-icon" aria-hidden="true">
|
|
|
|
|
<svg class="mnote-symbol mnote-symbol--document" data-icon="home" viewBox="0 0 24 24" focusable="false">
|
|
|
|
|
<path d="M4 10.5 12 3l8 7.5"></path>
|
|
|
|
|
<path d="M6.5 9.5V21h11V9.5"></path>
|
|
|
|
|
<path d="M9.5 21v-6h5v6"></path>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<h1 class="document-title-heading">
|
|
|
|
|
<textarea
|
|
|
|
|
id="mnote-page-title-input"
|
|
|
|
|
class="document-title-input"
|
|
|
|
|
aria-label="页面标题"
|
|
|
|
|
data-page-title-input="true"
|
|
|
|
|
data-document-id={document_id.clone()}
|
|
|
|
|
data-workspace-id={workspace_id.clone()}
|
|
|
|
|
data-title-endpoint="/api/documents/title"
|
|
|
|
|
rows="1"
|
|
|
|
|
>{title.clone()}</textarea>
|
|
|
|
|
</h1>
|
2026-04-29 16:23:49 +08:00
|
|
|
<div class="document-shell-meta" aria-label="页面元信息">
|
|
|
|
|
<span><span aria-hidden="true">"◌"</span>{workspace_label}</span>
|
|
|
|
|
<span><span aria-hidden="true">"▣"</span>"已同步"</span>
|
|
|
|
|
</div>
|
2026-04-29 12:24:44 +08:00
|
|
|
</header>
|
|
|
|
|
<section data-page-aggregate-snapshot="mnote.page_aggregate.v1"></section>
|
2026-04-29 14:36:24 +08:00
|
|
|
<section
|
|
|
|
|
data-testid="mnote-page-subtree"
|
|
|
|
|
data-page-tree-source="page_aggregate.tree.pageSubtree"
|
|
|
|
|
data-page-subtree-present={has_page_subtree.to_string()}
|
|
|
|
|
></section>
|
|
|
|
|
<section id="mnote-editor-island" data-editor-host="leptos_tiptap_island">
|
|
|
|
|
<div
|
|
|
|
|
id="mnote-leptos-tiptap-island-editor-root"
|
|
|
|
|
data-testid="mnote-leptos-tiptap-island-editor-root"
|
|
|
|
|
data-editor-host-kind="leptos_tiptap_island"
|
|
|
|
|
data-runtime-editor-status="booting"
|
|
|
|
|
></div>
|
|
|
|
|
<div
|
|
|
|
|
class="sr-only"
|
|
|
|
|
data-editor-host-observability="rust-web-inline-island"
|
|
|
|
|
data-editor-host-active="leptos_tiptap_island"
|
|
|
|
|
data-editor-host-requested="leptos_tiptap_island"
|
|
|
|
|
data-editor-host-status="booting"
|
|
|
|
|
></div>
|
|
|
|
|
</section>
|
2026-04-29 12:24:44 +08:00
|
|
|
</main>
|
|
|
|
|
</PageLayout>
|
|
|
|
|
}
|
|
|
|
|
}
|