
Metabase Embedding SDK 的 CreateDashboardModal 组件从 Props 解析到仪表盘创建全流程实战【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabaseMetabase Embedding SDK嵌入式分析 SDK为宿主应用提供了一系列开箱即用的 React 组件CreateDashboardModal是其中专门用于“在宿主页面内让最终用户创建新仪表盘”的模式框Modal组件。本文以 SDK 公开的类型文档 CreateDashboardModalProps.md 为骨架结合仓库内该组件的真实实现、Schema 校验、Storybook 示例与单元测试完整梳理其全部 Props 的含义、默认值与底层行为并给出可直接复用的集成代码。读完本文你将掌握如何在自己的应用中嵌入创建仪表盘流程、如何控制集合归属个人/根/指定集合、如何接管创建成功与关闭事件以及该组件背后的 API 调用链。一、组件定位与函数签名CreateDashboardModal是 Metabase Embedding SDK 导出的公开组件之一在 SDK 统一导出入口 sdk-bundle-exports.ts 中以sdkBundleExports的一部分对外发布组件定义位于 CreateDashboardModal.tsx。其函数签名见 CreateDashboardModal.md为function CreateDashboardModal(props: CreateDashboardModalProps): Element;参数单个props对象类型即CreateDashboardModalProps返回值一个 React 元素Element在宿主应用中以CreateDashboardModal ... /的形式使用。从源码结构看该组件是一个受控型模式框它并不维护自身的打开状态而是通过isOpen属性由外部决定显示/隐藏创建成功或取消关闭时通过回调把控制权交还给宿主应用。二、Props 全览CreateDashboardModalProps共包含 5 个属性其中仅onCreate为必填其余均可选。原文档属性表整理并补充默认值如下属性类型说明默认值来自源码initialCollectionId?SdkCollectionId打开模式框时集合选择器所在的初始集合。可使用root、personal等预定义系统值personal当前用户的个人收藏isOpen?boolean模式框是否打开trueonClose?() void关闭模式框的回调处理器—onCreate(dashboard:MetabaseDashboard) void仪表盘创建成功后的回调接收新创建的仪表盘对象必填无默认值targetCollection?SdkCollectionId仪表盘保存到的目标集合。传入后保存模式框内的集合选择器将被隐藏—其中initialCollectionId与targetCollection均使用SdkCollectionId类型onCreate是唯一必填属性这在组件的 Schema 校验中也有强制约束见下文第四节。三、SdkCollectionId 与集合引用解析SdkCollectionId是 SDK 对“集合 ID”的公共抽象其类型定义位于 types/collection.tsexport type SdkCollectionId | number | personal | root | tenant | SdkEntityId;也就是说你可以传入数字 ID如42对应 Metabase 数据库中集合的主键personal预定义系统值指向当前登录用户的个人收藏root预定义系统值指向“根集合”所有集合的顶层tenant预定义系统值指向当前用户的租户集合Enterprise 多租户场景SdkEntityId字符串形式的实体 IDentity_id。从源码注释看collection.ts核心应用中的CollectionId还包含users、trash等值但 SDK 公共 API 刻意排除了它们以保证宿主应用只接触受支持的集合引用。引用如何被解析为真实 IDCreateDashboardModal内部通过 store/collections.ts 中的选择器把符号化引用转换为 API 可用的值getCollectionIdValueFromReferenceL21-L54负责把personal解析为当前用户的personal_collection_id、tenant解析为tenant_collection_id、root解析为null因为创建仪表盘时根集合在 API 层就是用null表示、数字/字符串 ID 原样透传getCollectionIdSlugFromReferenceL69-L100负责解析出/api/collection/{id}所需的 slug根集合在这里是root而非null用于前置加载集合信息。需要注意的是当传入tenant而当前用户并非租户成员时选择器会抛出错误当personal无法解析例如 API Key 认证的用户没有个人收藏时slug 解析结果为null/undefined组件会通过skipToken跳过集合请求避免产生/api/collection/undefined或/api/collection/null的 404 请求见 CreateDashboardModal.tsx。四、逐个 Props 深入解析1.initialCollectionId?—— 初始集合类型SdkCollectionId默认值personal该属性决定模式框打开时集合选择器定位在哪个集合。源码中显式解构了默认值initialCollectionId personalCreateDashboardModal.tsx并通过useGetCollectionQuery预取该集合的名称用于展示。单元测试 CreateDashboardModal.unit.spec.tsx 验证了两种行为不传initialCollectionId时集合选择器按钮显示当前用户的Personal collection传入某个集合的数字 ID 时选择器按钮显示该集合名称。2.targetCollection?—— 固定目标集合隐藏选择器类型SdkCollectionId默认值无不传则让用户在模式框内自由选择targetCollection是“直接指定保存位置”的属性一旦传入保存模式框内的集合选择器将被隐藏用户只能填写仪表盘名称与描述无法更改保存位置。源码中通过resolvedTargetCollection选择器将其解析为真实集合 ID 后传给核心创建表单CreateDashboardModal.tsx。测试用例 L181-L228 明确验证了两个关键行为targetCollection优先级高于initialCollectionId同时传入两者时创建请求的collection_id使用targetCollection的值传入后集合选择器按钮不渲染queryByTestId(collection-picker-button)为空。此外L230-L268 验证了传targetCollection: root时POST/api/dashboard请求体中的collection_id为null—— 这正是根集合在创建 API 中的表示方式。3.isOpen?—— 受控开合类型boolean默认值trueisOpen控制模式框是否渲染。源码将其透传给核心组件的opened属性CreateDashboardModal.tsx。测试 L130-L144 验证了传入isOpen{false}时模式框不显示重新渲染为isOpen默认 true后出现 “New dashboard” 标题。实际使用中通常将isOpen与宿主应用的状态绑定例如用 React 的useState控制“新建仪表盘”按钮的开关。4.onClose?—— 关闭回调类型() void默认值无可选用户点击遮罩、取消按钮等关闭模式框时触发用于让宿主应用同步更新自己的状态例如把isOpen置为false。源码中通过onClose{() onClose?.()}透传给核心组件CreateDashboardModal.tsx。5.onCreate—— 创建成功回调必填类型(dashboard: MetabaseDashboard) void必填是仪表盘创建成功后触发参数为新建的仪表盘对象。MetabaseDashboard的类型定义位于 types/dashboard.ts包含以下字段type MetabaseDashboard { id: SdkDashboardId; // 数字 ID 或 entity_id entity_id: SdkEntityId; created_at: string; updated_at: string; collection?: MetabaseCollection | null; name: string; description: string | null; last-edit-info: { id: number; email: string; first_name: string; last_name: string; timestamp: string; }; };拿到这个对象后宿主应用常见的做法是跳转到新建仪表盘例如配合EditableDashboard进入编辑态或刷新自己的仪表盘列表。五、底层工作流程从 Props 到 POST /api/dashboard结合 CreateDashboardModal.tsx 的完整实现一次仪表盘创建请求的流程如下挂载分析组件通过useTrackSdkComponentMount(CreateDashboardModal, null, {})记录组件挂载事件L79用于使用情况审计本地化就绪useLocale()判断 SDK 的语言资源是否加载完成未完成时组件返回null不渲染避免闪烁L56-L57集合信息加载解析initialCollectionId得到 slug 后请求GET /api/collection/{id}获取集合元数据名称等加载期间同样不渲染L72-L82渲染核心表单将opened、onCreate、onClose、collectionId、targetCollection透传给核心应用的CreateDashboardModalCore来自metabase/common/CreateDashboard/CreateDashboardModalL85-L93提交创建用户填写名称必填、描述并点击 Create 后核心表单发起POST /api/dashboard请求体形如{ name, collection_id }回调与收尾创建成功后调用onCreate并传入 API 返回的MetabaseDashboard测试断言其被调用恰好 1 次且参数为 mock 的响应对象unit.spec.tsx L125-L127。另外值得注意的是该组件通过withPublicComponentWrapper包装并显式声明supportsGuestEmbed: falseCreateDashboardModal.tsx L96-L100—— 即CreateDashboardModal不支持访客guest嵌入模式宿主应用需要以已登录用户身份使用。Schema 校验SDK 的公共组件会附带一份基于 Yup 的运行时校验 Schema用于在开发期校验宿主传入的 Props。CreateDashboardModal的 Schema 位于 CreateDashboardModal.schema.tsconst propsSchema: Yup.SchemaOfCreateDashboardModalProps Yup.object({ initialCollectionId: Yup.mixed().optional(), targetCollection: Yup.mixed().optional(), isOpen: Yup.mixed().optional(), onClose: Yup.mixed().optional(), onCreate: Yup.object().required(), // 唯一必填项 }).noUnknown(); // 不允许未知属性onCreate被标记为required()与类型定义中的必填声明一致.noUnknown()意味着传入任何未在 Props 中声明的属性都会触发校验警告这能帮助宿主应用尽早发现拼写错误或误传的 Props。六、完整集成示例基础用法import { useState } from react; import { CreateDashboardModal } from metabase/embedding-sdk-react; export function NewDashboardButton() { const [open, setOpen] useState(false); return ( button onClick{() setOpen(true)}新建仪表盘/button {open ( CreateDashboardModal isOpen{open} initialCollectionIdpersonal // 默认值可省略 onClose{() setOpen(false)} onCreate{(dashboard) { console.log(创建成功, dashboard.id, dashboard.name); setOpen(false); }} / )} / ); }固定保存位置隐藏集合选择器CreateDashboardModal isOpen{open} targetCollectionroot // 保存到根集合选择器被隐藏 // 或 targetCollection{42} // 保存到指定集合 // 或 targetCollectionpersonal onClose{() setOpen(false)} onCreate{(dashboard) { // 用 entity_id 或数字 id 做后续跳转 console.log(dashboard.entity_id); }} /创建后无缝进入编辑态完整流程示例仓库自带的 Storybook 示例 CreateDashboardModal.stories.tsx 展示了一个典型的完整工作流先弹出创建模式框用户创建成功后立即切换到该仪表盘的编辑组件EditableDashboardimport { useState } from react; import { CreateDashboardModal, EditableDashboard } from metabase/embedding-sdk-react; import type { MetabaseDashboard } from metabase/embedding-sdk-react; function FullWorkflowExample() { const [dashboard, setDashboard] useStateMetabaseDashboard | null(null); if (dashboard) { return EditableDashboard dashboardId{dashboard.id} /; } return ( CreateDashboardModal onClose{() {}} onCreate{setDashboard} / ); }该示例同时印证了两点onCreate的返回值可以直接setState保存MetabaseDashboard.id可直接作为EditableDashboard的dashboardId使用。七、测试覆盖与行为保证组件的行为由 CreateDashboardModal.unit.spec.tsx 全面锁定可视为一份“行为契约”测试场景断言要点本地化加载中不渲染 “New dashboard” 标题避免闪现正常渲染显示标题、Description 输入框、集合选择器表单提交创建触发一次POST /api/dashboard请求体含name与collection_idonCreate以 API 响应为参数调用一次isOpen切换false时不渲染重新置为true后渲染默认initialCollectionId选择器显示当前用户的 Personal collection自定义initialCollectionId选择器显示对应集合名称targetCollection隐藏集合选择器优先于initialCollectionId请求体collection_id为目标集合targetCollection: root请求体collection_id为null八、相关资源与延伸阅读组件实现CreateDashboardModal.tsx函数签名文档CreateDashboardModal.md类型定义SdkCollectionId见 types/collection.tsMetabaseDashboard见 types/dashboard.ts集合引用解析store/collections.tsSDK 导出入口sdk-bundle-exports.ts如果需要进一步控制仪表盘的编辑与展示可继续阅读 SDK 文档中关于EditableDashboard、InteractiveDashboard的公开 Props 文档见 docs/embedding/sdk/api/snippets/EditableDashboardProps.md、docs/embedding/sdk/api/snippets/InteractiveDashboardProps.md组合出“创建 → 编辑 → 展示”的完整嵌入式分析链路。【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考