news 2026/9/10 13:37:56

Metabase Embedding SDK 编程式创建仪表盘:CreateDashboardValues 类型全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Metabase Embedding SDK 编程式创建仪表盘:CreateDashboardValues 类型全解析

Metabase Embedding SDK 编程式创建仪表盘:CreateDashboardValues 类型全解析

【免费下载链接】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

CreateDashboardValues是 Metabase Embedding SDK 中描述"创建新仪表盘所需参数"的核心类型,它同时服务于useCreateDashboardApiHook 与底层POST /api/dashboard接口。本文将以该类型为骨架,逐一拆解namedescriptioncollectionId三个字段的含义、取值规则与底层解析逻辑,并给出可直接落地的 TypeScript 实战示例,帮助你在嵌入应用中用几行代码动态生成仪表盘。

CreateDashboardValues:编程式建盘的参数契约

在 Embedding SDK 中,当你需要在宿主应用中"以代码方式"新建一个仪表盘(例如根据用户操作动态生成报表容器)时,传入的参数对象就是CreateDashboardValues。它的完整定义如下:

export type CreateDashboardValues = Omit< CreateDashboardProperties, "collection_id" > & { /** * Collection in which to create a new dashboard. * You can use predefined system values like `root` or `personal`. */ collectionId: SdkCollectionId; };

该定义位于 frontend/src/embedding-sdk-bundle/types/dashboard.ts,其核心手法是:从核心应用的表单属性CreateDashboardProperties中剔除内部字段collection_id,再替换为面向 SDK 使用者的collectionId(类型为SdkCollectionId)。这意味着你在 SDK 侧永远不需要关心后端真实的数值型集合 ID,只需给出语义化的引用即可。

CreateDashboardProperties本身定义于 frontend/src/metabase/common/CreateDashboard/CreateDashboardForm.tsx,是 Metabase 核心产品"新建仪表盘"表单同款的数据结构,保证了嵌入式场景与原生界面的行为一致。

属性一览

CreateDashboardValues共包含三个属性,其中namecollectionId必填,description可空:

属性类型说明
collectionIdSdkCollectionId新仪表盘将被创建到哪个集合(Collection)中。可使用预定义的系统值,如rootpersonal
descriptionstring \| null仪表盘描述。
namestring仪表盘标题。

name:仪表盘标题

name是必填字段,对应创建后仪表盘显示的名称。在表单校验层(CreateDashboardForm.tsx 中的 Yup schema),它被定义为:

name: Yup.string() .required(Errors.required) .max(DASHBOARD_NAME_MAX_LENGTH, Errors.maxLength) .default(""),

即:必填、不允许为空字符串,且最大长度受DASHBOARD_NAME_MAX_LENGTH约束。该常量定义于 frontend/src/metabase/common/utils/dashboard.ts:

export const DASHBOARD_NAME_MAX_LENGTH = 254; export const DASHBOARD_DESCRIPTION_MAX_LENGTH = 1500;

因此标题最长 254 个字符,描述最长 1500 个字符。超出长度时,SDK 侧的表单组件与后端校验都会拒绝创建。

description:仪表盘描述

description类型为string | null,即允许显式传入null表示无描述。在 Yup schema 中:

description: Yup.string() .nullable() .max(DASHBOARD_DESCRIPTION_MAX_LENGTH, Errors.maxLength) .default(null),

如果不传,SDK 会以null作为默认值提交。后端接口同样将description定义为可选({:optional true} [:maybe :string]),并在存储时原样保留。

collectionId:决定仪表盘的归属集合

collectionId是三个属性中最具 SDK 特色、也最值得展开讲解的一个。它不要求你提供后端数据库里的原始数值 ID,而是接受一组"集合引用",包括:

  • 预定义系统值:"personal"(当前用户个人集合)、"root"(根集合)、"tenant"(租户集合);
  • 普通数值 ID:某个具体集合的数据库 ID;
  • 字符串实体 ID:集合的entity_idSdkEntityId类型)。

其类型定义同时出现在 SdkCollectionId.md 与 frontend/src/embedding-sdk-bundle/types/collection.ts:

export type SdkCollectionId = | number | "personal" | "root" | "tenant" | SdkEntityId;

其中SdkEntityId是一个品牌化字符串类型(type SdkEntityId = string & {}),用于在类型层面与普通字符串区分,详见 SdkEntityId.md。需要说明的是,该类型刻意不包含核心应用CollectionId中的"users""trash"等值——SDK 的公开 API 不支持这些内部集合,源码注释对此有明确说明。

集合引用的底层解析规则

当你把collectionId传给 SDK 后,真正发生转换的地方是 frontend/src/embedding-sdk-bundle/store/collections.ts 中的getCollectionIdValueFromReference(一个基于 Redux 状态的createSelector)。它依据传入的引用类型进行分支匹配:

传入值解析结果说明
"personal"当前用户的个人集合 IDgetUserPersonalCollectionId派生
"tenant"当前用户的租户集合 ID(tenant_collection_id若用户不属于任何租户,会抛出"You must be a tenant member to access the tenant collection."错误
"root"null关键细节:根集合在后端 API 中就是用null表示的
数值 / 字符串原样透传数值作为真实集合 ID;字符串按实体 ID 处理
其他抛错抛出"Invalid collection id, expected number \| string \| 'root' \| 'personal' \| 'tenant'"

这段逻辑(collections.ts)同时揭示了两个易踩的坑:

  1. "root"会被转换为null提交。这是因为后端POST /api/dashboard端点用collection_id = null表示根集合,而非字面量字符串"root"
  2. "tenant"依赖当前用户的租户成员身份,非租户成员直接抛出异常,调用前应做好容错(如try/catch或先判断当前用户)。

实战:通过 useCreateDashboardApi 创建仪表盘

CreateDashboardValues最典型的使用场景是配合useCreateDashboardApiHook。其签名定义于 useCreateDashboardApi.md:

function useCreateDashboardApi(): { createDashboard: ( params: CreateDashboardValues, ) => Promise<MetabaseDashboard>; } | null;

注意返回值为null或对象:在 SDK 完全加载并初始化完成之前,该 Hook 返回null,因此调用前必须先判空。一个完整的实战示例:

import { useCreateDashboardApi } from "@metabase/embedding-sdk-react"; function CreateDashboardButton() { const { createDashboard } = useCreateDashboardApi() ?? {}; const handleCreate = async () => { if (!createDashboard) { // SDK 尚未就绪,此时 createDashboard 不可用 return; } try { const dashboard = await createDashboard({ name: "Q3 销售周报", // 必填,仪表盘标题(≤ 254 字符) description: "由嵌入应用动态生成", // 可选,可传 null collectionId: "personal", // 可选但强烈建议显式指定; // 不传时 SDK 默认使用 "personal" }); console.log("创建成功,仪表盘 ID:", dashboard.id); console.log("实体 ID:", dashboard.entity_id); } catch (error) { // 处理权限不足、名称超长、租户集合不可达等异常 } }; return <button onClick={handleCreate}>新建仪表盘</button>; }

一个值得注意的默认值细节:SDK 的createDashboard实现(frontend/src/embedding-sdk-bundle/lib/create-dashboard.ts)在解构参数时为collectionId提供了默认值"personal"

export const createDashboard = (reduxStore: SdkStore) => async ({ collectionId = "personal", ...rest }: CreateDashboardValues) => { const realCollectionId = getCollectionIdValueFromReference( reduxStore.getState(), collectionId, ); const action = createDashboardMutation.initiate({ ...rest, collection_id: realCollectionId, }); return reduxStore.dispatch(action).unwrap(); };

即:即使你在类型层面按必填声明了collectionId,运行时也可以省略它,仪表盘会被创建到当前用户的个人集合中。解析后的真实集合 ID 被映射为collection_id字段,连同其余参数一起交给 RTK Query 的createDashboardmutation(定义于 frontend/src/metabase/api/dashboard.ts),最终发出POST /api/dashboard请求。

创建成功后的返回值:MetabaseDashboard

createDashboard返回Promise<MetabaseDashboard>,即创建成功的完整仪表盘实体,其结构见 MetabaseDashboard.md,对应源码定义在 dashboard.ts:

export type MetabaseDashboard = { id: SdkDashboardId; 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; }; };

其中idSdkDashboardId(数值 ID、字符串 ID 或实体 ID 的联合类型)。拿到返回值后,你可以直接将其id传入InteractiveDashboard/StaticDashboard等组件立即渲染刚创建的仪表盘,形成"创建即展示"的闭环。

另一种方式:CreateDashboardModal 组件

如果你的产品更希望复用 Metabase 自带的新建界面(而不是自绘表单),可以使用CreateDashboardModal组件,其声明见 CreateDashboardModal.md,入参类型为 CreateDashboardModalProps.md:

属性类型说明
initialCollectionId?SdkCollectionId初始选中的集合,可使用rootpersonal等系统值
isOpen?boolean弹窗是否打开
onClose?() => void关闭弹窗的处理函数
onCreate(dashboard: MetabaseDashboard) => void创建成功后的回调,参数即新建的仪表盘
targetCollection?SdkCollectionId固定保存到指定集合;设置后保存弹窗中的集合选择器会被隐藏

该组件的属性同样建立在SdkCollectionId之上,因此initialCollectionIdtargetCollection支持与CreateDashboardValues.collectionId完全相同的取值集合。两种方式对比:useCreateDashboardApi适合完全自定义 UI 与流程(例如静默创建、批量创建);CreateDashboardModal适合快速交付,直接复用官方弹窗交互。

底层调用链:从前端 SDK 到后端接口

为便于排查问题,这里梳理创建仪表盘的完整链路(均可从仓库源码验证):

  1. SDK 入口:create-dashboard.ts 接收CreateDashboardValues,用getCollectionIdValueFromReference解析collectionId
  2. RTK Query 层:dashboard.ts 的createDashboardmutation 组装POST /api/dashboard请求体,请求体类型CreateDashboardRequestnamedescription?parameters?cache_ttl?collection_id?等字段;
  3. 后端端点:src/metabase/dashboards_rest/api.clj 中POST /端点接收并校验请求,schema 要求nameNonBlankString(非空白字符串),descriptioncache_ttlcollection_idcollection_position均可选;
  4. 权限与落库:后端先执行api/create-check :model/Dashboard(确认当前用户对目标集合具备建盘权限),随后在事务中调用insert-dashboard!写入,并发布:event/dashboard-create事件、上报 Snowplow 分析事件(见 api.clj);
  5. 响应:后端返回补齐了last-edit-info、根集合信息等详情的仪表盘对象,即MetabaseDashboard

这条链路意味着:CreateDashboardValues中的name/description直接映射为后端同名字段,而collectionId经过"引用 → 真实 ID →collection_id"的两步转换,最终决定新仪表盘挂在哪个集合下——这也是创建请求在权限校验时依据的目标集合。

常见错误与排查要点

  • useCreateDashboardApi()返回null:SDK 尚未初始化完成,需等待MetabaseProvider加载后再调用,代码中务必判空;
  • "You must be a tenant member to access the tenant collection.":使用了"tenant"引用但当前用户无租户集合,改用"personal""root"或具体集合 ID;
  • "Invalid collection id...":传入了类型允许之外的值(例如"all"——该值仅存在于SdkBrowserCollectionId,属于集合浏览器的虚拟顶层,不能用于创建仪表盘);
  • 名称/描述超长name超过 254、description超过 1500 字符会被表单校验或后端拒绝,建议在 UI 侧先做长度提示;
  • 权限不足:目标集合无创建权限时后端create-check会拒绝请求,可先确认当前嵌入用户的集合权限配置。

综上,CreateDashboardValues虽只有三个字段,却是打通"嵌入应用 → SDK → Metabase 后端"创建链路的关键契约。理解SdkCollectionId的引用语义与默认值行为,即可在嵌入场景中稳定、可预期地动态创建仪表盘。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 13:37:20

Sim 集成工具开发规范:从服务 API 到注册表全流程实战指南

Sim 集成工具开发规范&#xff1a;从服务 API 到注册表全流程实战指南 【免费下载链接】sim Sim is the collaborative workspace to build, deploy, and monitor AI agents and workflows. Used by 100,000 builders. 项目地址: https://gitcode.com/GitHub_Trending/sim16/…

作者头像 李华
网站建设 2026/9/10 13:35:49

CANN/ge变量查询接口

GetVariables 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前…

作者头像 李华
网站建设 2026/9/10 13:32:53

2026材料信息学MI落地指南:破解新材料开发试错低效、成本超高难题

新材料开发的核心困境并非研发人员技术能力不足&#xff0c;而是传统试错式研发模式存在结构性缺陷。依托材料信息学&#xff08;MI&#xff09;结合AI基础模型&#xff0c;可彻底革新传统研发逻辑&#xff0c;大幅压缩研发周期、削减巨额试错成本&#xff0c;同时突破人工经验…

作者头像 李华