ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Metabase 嵌入 SDK 之 DashCardMenuItem 完全指南:自定义仪表盘卡片菜单项的字段、用法与源码实现

Metabase 嵌入 SDK 之 DashCardMenuItem 完全指南:自定义仪表盘卡片菜单项的字段、用法与源码实现 Metabase 嵌入 SDK 之 DashCardMenuItem 完全指南自定义仪表盘卡片菜单项的字段、用法与源码实现【免费下载链接】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/metabaseDashCardMenuItem是 Metabase Embedding SDKmetabase/embedding-sdk-react中用于自定义仪表盘Dashboard卡片右键菜单/溢出菜单项的核心类型。本文以 DashCardMenuItem.md 为骨架结合仓库内 类型源码、菜单渲染实现 与官方插件示例逐字段讲解该类型的含义、默认行为与底层工作方式并给出可直接复用的实战代码。读完本文你将能通过plugins.dashboard.dashboardCardMenu配置为自己的嵌入仪表盘追加自定义菜单项、控制下载/编辑等默认项并理解这些菜单项最终如何被映射为 MantineMenu.Item渲染出来。一、类型定义速览DashCardMenuItem描述了一条仪表盘卡片菜单项包含图标、文本标签、点击回调以及若干可选修饰字段。其完整定义如下与 源码 plugins.ts 一一对应type DashCardMenuItem { children?: ReactNode; closeMenuOnClick?: boolean; color?: MantineColor; disabled?: boolean; iconName: IconName; label: string; leftSection?: ReactNode; onClick: () void; rightSection?: ReactNode; };其中iconName、label、onClick为必填项其余字段均为可选。该类型是仪表盘卡片菜单定制体系的基础构件被以下类型直接引用CustomDashboardCardMenuItem—— 接收{ question }参数、返回DashCardMenuItem的函数用于根据当前卡片所对应的问题动态生成菜单项见 CustomDashboardCardMenuItem.mdDashboardCardCustomMenuItem—— 通过customItems数组承载若干DashCardMenuItem | CustomDashboardCardMenuItem并附带withDownloads/withEditLink两个开关见 DashboardCardCustomMenuItem.mdDashboardCardMenu—— 上面两个配置形态的联合类型见 DashboardCardMenu.mdMetabaseDashboardPluginsConfig.dashboardCardMenu—— 仪表盘插件配置的入口字段见 MetabaseDashboardPluginsConfig.md。二、属性逐项详解下表完整列出DashCardMenuItem的九个属性随后对每个属性做深入说明。属性类型说明children?ReactNode菜单项的子内容closeMenuOnClick?boolean点击该项后是否关闭菜单会覆盖Menu组件上的closeOnItemClick属性color?MantineColortheme.colors的键或任意合法的 CSS 颜色值disabled?boolean禁用该项iconNameIconName图标名称labelstring菜单项标签文本leftSection?ReactNode显示在标签左侧的区域onClick() void点击回调rightSection?ReactNode显示在标签右侧的区域1.iconName必填图标名称iconName决定菜单项左侧展示的图标其类型是 SDK 内置的 IconName 联合类型涵盖 Metabase 全部内置图标。常见取值包括通用操作download、pencil、trash、copy、share、export、external、expand方向与箭头chevronright、chevronleft、chevrondown、chevronup、arrow_right、arrow_left、arrow_up、arrow_down数据与内容类型dashboard、question、model、table、collection、database、sql、metric图表类型bar、line、pie、area、funnel、map、gauge、pivot_table状态与反馈check、check_filled、info、info_outline、warning、ban、eye、eye_crossed_out常用工具settings、gear、clock、calendar、filter、sort、search、bookmark、pin、refresh、external。完整的取值清单超过 300 个可在 IconName.md 中查阅。需要注意iconName必须使用字符串字面量TypeScript 会在编译期校验拼写因此写错图标名会直接报类型错误而非运行时报错。2.label必填菜单项文本label是显示在菜单项上的文本。在 DashCardMenuItems.tsx 的渲染实现中它同时被用作菜单项可见文本渲染在Menu.Item内aria-label无障碍标签自定义项去重key的来源见下文源码实现原理一节。Menu.Item key{key} leftSection{Icon name{iconName} aria-hidden /} aria-label{item.label} {item.label} /Menu.Item3.onClick必填点击回调onClick在用户点击该菜单项时触发无参数、无返回值。典型用法是触发自定义业务逻辑{ iconName: chevronright, label: Custom action, onClick: () { alert(Custom action clicked); }, }4.closeMenuOnClick?点击后是否关闭菜单该字段控制点击菜单项后整个下拉菜单是否收起优先级高于Menu组件自身的closeOnItemClick属性。当需要执行较长的异步流程如数据下载、文件导出或希望用户在点击后继续在菜单内操作时应设为false。从源码可以印证这一字段的实际用途内置的下载结果菜单项正是通过closeMenuOnClick: false保持菜单展开、并在下载完成后由组件主动关闭菜单见 DashCardMenuItems.tsxif (withDownloads canDownloadResults(result)) { items.push({ key: MB_DOWNLOAD_RESULTS, iconName: download, label: isDownloadingData ? tDownloading… : tDownload results, onClick: onDownload, disabled: isDownloadingData, closeMenuOnClick: false, }); }5.color?文字/图标着色color接受MantineColor即theme.colors的键如red、brand、success、error或任意合法 CSS 颜色如#e4572e。常用于强调危险操作或状态色例如删除类操作可设为red。由于该类型来自 Mantine 的MantineColor自定义主题色键同样有效。6.disabled?禁用态disabled: true会使菜单项置灰且不可点击。典型场景权限不足时禁用操作、异步进行中禁用重复提交。内置的下载项在下载进行中正是同时设置了disabled: isDownloadingData与closeMenuOnClick: false见上文代码。7.children?子内容children允许向菜单项内部注入任意 React 节点用于比纯文本更丰富的展示例如自定义富文本、徽标或图标组合。8.leftSection?/rightSection?标签两侧的辅助区域leftSection渲染在标签左侧可放置快捷键提示、状态小图标、色块等rightSection渲染在标签右侧常用于放置次级图标如展开箭头chevronright、快捷按键文本或额外指示器。两者类型均为ReactNode可自由组合。注意iconName本身会被 SDK 渲染为左侧图标若同时指定leftSection视觉上两者都会出现在左侧建议按需二选一。三、在插件配置中的位置从入口到菜单项DashCardMenuItem不是独立使用的组件而是通过MetabaseProvider的plugins配置注入。完整的配置链路如下MetabasePluginsConfig └── dashboard?: MetabaseDashboardPluginsConfig └── dashboardCardMenu?: DashboardCardMenu ├── DashboardCardMenuCustomElement (question) ReactNode // 完全自定义整个菜单 └── DashboardCardCustomMenuItem { withDownloads?, withEditLink?, customItems? } └── customItems?: (DashCardMenuItem | CustomDashboardCardMenuItem)[]引用关系可在 MetabaseDashboardPluginsConfig.md、DashboardCardMenu.md 与 DashboardCardCustomMenuItem.md 中逐一核对源码层面见 plugins.ts。最简单的接入方式——保留默认下载/编辑项仅追加自定义项import { InteractiveDashboard } from metabase/embedding-sdk-react; const dashboardId 1; const plugins { dashboard: { dashboardCardMenu: { withDownloads: true, // 保留下载结果 withEditLink: true, // 保留编辑问题/可视化 customItems: [], }, }, }; export default () ( InteractiveDashboard dashboardId{dashboardId} plugins{plugins} / );该示例同样收录在 docs/embedding/sdk/snippets/dashboards/plugins.tsx 的example-base-2片段中。四、实战向仪表盘卡片菜单追加自定义项4.1 追加静态自定义项在customItems数组中直接放置DashCardMenuItem对象字面量即可const plugins { dashboard: { dashboardCardMenu: { customItems: [ { iconName: chevronright, label: Custom action, onClick: () { alert(Custom action clicked); }, }, ], }, }, };对应官方示例见 plugins.tsx 的example-custom-actions片段。4.2 追加动态自定义项函数式如果菜单项需要访问当前卡片对应的问题信息可将元素替换为CustomDashboardCardMenuItem函数。该函数接收{ question }类型为 MetabaseQuestion返回一个DashCardMenuItem。question可能为undefined如查询未加载完成时需做好空值处理const plugins { dashboard: { dashboardCardMenu: { customItems: [ // 静态项 { iconName: chevronright, label: Custom action, onClick: () { alert(Custom action clicked); }, }, // 动态项依赖当前卡片的问题名称 ({ question }) { return { iconName: chevronright, label: Custom action, onClick: () { alert(Custom action clicked ${question?.name}); }, }; }, ], }, }, };动态项的函数签名定义见 CustomDashboardCardMenuItem.md在源码中这一调用发生在 DashCardMenuItems.tsxitems.push( ...customItems.map((item) { const customItem typeof item function ? item({ question: transformSdkQuestion(question) }) : item; return { ...customItem, key: MB_CUSTOM_${customItem.label}, }; }), );4.3 隐藏默认项DashboardCardCustomMenuItem还提供两个开关withDownloads: false隐藏下载结果、withEditLink: false隐藏编辑问题/编辑可视化见 DashCardMenuItems.tsx 中二者的默认值均为trueconst plugins { dashboard: { dashboardCardMenu: { withDownloads: false, withEditLink: false, customItems: [], }, }, };当三个字段分别为false、false、空数组时菜单被判定为空菜单而完全隐藏——这一逻辑位于 DashCardMenu.tsx 的isDashCardMenuEmpty函数中function isDashCardMenuEmpty(dashcardMenu) { if (typeof dashcardMenu ! object) { return false; } return ( dashcardMenu?.withDownloads false dashcardMenu?.withEditLink false !dashcardMenu?.customItems?.length ); }4.4 完全接管菜单自定义元素若连菜单的外壳都要自定义可将dashboardCardMenu直接设为一个接收{ question }、返回ReactNode的函数类型为 DashboardCardMenuCustomElement此时DashCardMenuItem不再参与渲染const plugins { dashboard: { dashboardCardMenu: ({ question }) ( button onClick{() console.log(question.name)}Click me/button ), }, };对应 plugins.tsx 的example-custom-actions-menu片段。SDK 判定该分支后会直接把函数返回值作为菜单内容渲染见 DashCardMenu.tsxif (typeof dashcardMenu function) { return dashcardMenu({ question: transformSdkQuestion(question), dashcard, result, downloadsEnabled, }); }五、源码实现原理DashCardMenuItem 如何被渲染理解渲染链路有助于预判自定义项的行为边界。整个流程分为三步配置下发dashboardCardMenu配置经由useDashboardContext注入见 context.tsx最终由DashCardMenu组件消费。菜单项组装在 DashCardMenuItems.tsx 中useMemo将内置项与自定义项统一合并为一个DashCardMenuItem数组内置编辑项按问题类型question/model/metric生成分别使用pencil图标与MB_EDIT_QUESTION/MB_EDIT_MODEL/MB_EDIT_METRIC作为 key内置下载项使用download图标key 为MB_DOWNLOAD_RESULTS并设置closeMenuOnClick: false自定义项统一使用MB_CUSTOM_${label}作为 key同一 label 的重复项会产生重复 key实践中应保证 label 唯一。映射为 Menu.Item最终每个DashCardMenuItem被展开为 Mantine 的Menu.Item其中iconName被转换为leftSection中的Icon name{iconName} /key被剥离其余字段color、disabled、onClick、closeMenuOnClick、children、leftSection、rightSection原样透传见 DashCardMenuItems.tsx。因此DashCardMenuItem本质上是对 MantineMenu.Item属性的裁剪与约束iconName让图标类型受限于 IconName 联合类型closeMenuOnClick直接对应 Mantine 菜单的行为控制其余字段则与 MantineMenu.Item的 Props 对齐。六、实践建议与常见陷阱iconName拼写由类型系统兜底赋值非法图标名会在编译期报错建议在写自定义项时从 IconName.md 的清单中复制取值。动态项中question可能为undefinedCustomDashboardCardMenuItem的入参类型是{ question?: MetabaseQuestion }构建onClick闭包时使用可选链question?.name最稳妥。需要菜单在点击后保持打开显式设置closeMenuOnClick: false否则会受Menu组件closeOnItemClick默认行为影响。异步操作记得同时设置disabled参照内置下载项用disabled防止重复触发并配合closeMenuOnClick: false让用户看到进度反馈。leftSection与iconName的视觉叠加iconName已被 SDK 渲染为左侧图标再传leftSection会导致左侧出现两个元素按需二选一。空菜单自动隐藏若withDownloads、withEditLink均为false且customItems为空DashCardMenu会返回null卡片上不再显示菜单入口这是预期行为而非 bug。菜单渲染的准入条件DashCardMenu.shouldRender要求卡片存在、菜单配置非null且至少满足可编辑可下载存在下钻子项三者之一见 DashCardMenu.tsx。配置了customItems但卡片本身既不可编辑也不可下载时自定义项同样不会出现。七、相关类型与文档索引围绕DashCardMenuItem完整的类型家族与文档如下便于对照查阅IconName.md —— 全部可用图标名联合类型CustomDashboardCardMenuItem.md —— 函数式自定义项接收question返回DashCardMenuItemDashboardCardCustomMenuItem.md —— 自定义项容器customItemswithDownloadswithEditLinkDashboardCardMenu.md —— 菜单配置的两种形态函数 / 对象DashboardCardMenuCustomElement.md —— 完全自定义菜单元素MetabaseDashboardPluginsConfig.md —— 仪表盘插件配置入口MetabaseQuestion.md —— 动态项入参中的问题对象源码级参考frontend/src/metabase/embedding-sdk/types/plugins.ts#L41-L86 ——DashCardMenuItem类型定义frontend/src/metabase/dashboard/components/DashCard/DashCardMenu/DashCardMenuItems.tsx —— 菜单项组装与渲染frontend/src/metabase/dashboard/components/DashCard/DashCardMenu/DashCardMenu.tsx —— 菜单整体渲染与空菜单判定docs/embedding/sdk/snippets/dashboards/plugins.tsx —— 可直接运行的完整示例掌握DashCardMenuItem的九个字段及其在 SDK 渲染管线中的位置后你就能在嵌入仪表盘上自由定制卡片菜单追加静态或依赖问题的动态操作项、按需隐藏下载与编辑入口甚至完全替换为自定义 React 元素将仪表盘无缝融入宿主应用的产品交互。【免费下载链接】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),仅供参考
返回列表