跳到主要内容

注册扩展

一个扩展是插件定义的链接或 React 组件,可以在 Grafana 核心 UI 或其他应用插件中渲染。

暴露组件相比,它们明确注册到一个或多个扩展点 ID。这对于扩展 Grafana 核心 UI,或者当您需要更精细地控制哪些内容可以使用您的插件扩展时,更为适用。

关键概念下阅读更多关于扩展的信息。

类型描述
链接链接有一个 pathonClick() 属性。

何时使用?
如果您希望插件能够为您的 UI 的一部分定义自定义用户操作,请使用链接。这些操作可以是插件之间的交叉链接,或者使用 onClick() 方法通过模态框实现更具交互性的页面体验。

API 参考
- addLink() - 从插件注册链接
- usePluginLinks() - 获取为扩展点注册的链接
组件组件是 React 组件,可用于渲染自定义用户体验。

何时使用?
如果您希望插件有更多自由来扩展您的 UI,例如使用自定义部分扩展配置表单,请使用组件。

API 参考
- addComponent() - 从插件注册组件
- usePluginComponents() - 获取为扩展点注册的组件
警告

您必须更新您的 plugin.json 元数据,以列出所有已注册的扩展。

您可以为链接添加扩展。例如

import { PluginExtensionPoints } from '@grafana/data';
import pluginJson from './plugin.json';

export const plugin = new AppPlugin().addLink({
title: '...', // This appears as the label for the link
description: '...',
targets: [PluginExtensionPoints.DashboardPanelMenu], // Show it in the panel menu
path: `/a/${pluginJson.id}/foo`, // Path can only point somewhere under the plugin
});

您可以在扩展点隐藏链接。例如

import { PluginExtensionPoints } from '@grafana/data';

export const plugin = new AppPlugin().addLink({
title: '...',
description: '...',
targets: [PluginExtensionPoints.DashboardPanelMenu],
path: `/a/${pluginJson.id}/foo`,
// The `context` is coming from the extension point.
// (Passed in to the `usePluginLinks({ context })` hook.)
configure: (context) => {
// Returning `undefined` will hide the link at the extension point.
// (In this example we are NOT showing the link for "timeseries" panels.)
if (context?.pluginId === 'timeseries') {
return undefined;
}

// Returning an empty object meanst that we don't update the link properties.
return {};
},
});

根据上下文更新路径

import { PluginExtensionPoints } from '@grafana/data';

export const plugin = new AppPlugin().addLink({
title: '...',
description: '...',
targets: [PluginExtensionPoints.DashboardPanelMenu],
path: `/a/${pluginJson.id}/foo`,
configure: (context) => {
if (context?.pluginId === 'timeseries') {
// We render a different link for "timeseries" panels.
//
// Heads up! Only the following properties can be updated from the `configure()` function:
// - title
// - description
// - path
// - icon
// - category
return {
path: `/a/${pluginJson.id}/foo/timeseries`,
};
}

// Returning an empty object means no updates to any of the properties.
return {};
},
});

通过 onClick() 打开模态框

import { PluginExtensionPoints } from '@grafana/data';
import { Button, Modal } from '@grafana/ui';

export const plugin = new AppPlugin().addLink({
title: '...',
description: '...',
targets: [PluginExtensionPoints.DashboardPanelMenu],
// `event` - the `React.MouseEvent` from the click event
// `context` - the `context` object shared with the extensions
onClick: (event, { openModal, context }) =>
openModal({
title: 'My modal',
width: 500, // (Optional) - width of the modal in pixels
height: 500, // (Optional) - height of the modal in pixels

// Calling `onDismiss()` closes the modal
body: ({ onDismiss }) => (
<div>
<div>This is our modal.</div>

<Modal.ButtonRow>
<Button variant="secondary" fill="outline" onClick={onDismiss}>
Cancel
</Button>
<Button onClick={onDismiss}>Ok</Button>
</Modal.ButtonRow>
</div>
),
}),
});

组件

添加组件的最佳实践

  • 使用 props - 检查扩展点传递给组件的 props,并使用它们来实现更定制化的体验。
  • 用 providers 包装您的组件 - 如果您想在组件中访问任何插件特定的状态,请确保使用必要的 React 上下文 providers (例如 Redux) 将其包装起来。
  • 使用 Grafana 扩展点 ID 的枚举 - 如果您将组件注册到可用的 Grafana 扩展点之一,请确保使用 @grafana/data 包暴露的 PluginExtensionPoints 枚举

注册组件

import { PluginExtensionPoints } from '@grafana/data';

export const plugin = new AppPlugin().addComponent({
title: 'User profile tab',
description: '...',
targets: [PluginExtensionPoints.UserProfileTab],
component: () => <div>This is a new tab on the user profile page.</div>,
});

在组件中访问插件元数据

您可以使用 usePluginContext() hook 在组件内部访问任何插件特定的元信息。该 hook 返回一个 PluginMeta 对象。这非常有用,因为您从插件注册的组件不会在插件的 React 树下渲染,而是在 UI 中的其他位置渲染。

import { usePluginContext, PluginExtensionPoints } from '@grafana/data';

export const plugin = new AppPlugin().addComponent({
title: 'User profile tab',
description: '...',
targets: [PluginExtensionPoints.UserProfileTab],
component: () => {
const { meta } = usePluginContext();

// The `jsonData` property is an object that your plugin can manage
// using the Grafana Rest APIs
return <div>Plugin specific setting: {meta.jsonData.foo}</div>;
},
});

在组件中访问插件状态

import { PluginExtensionPoints } from '@grafana/data';
import { MyCustomDataProvider } from './MyCustomDataProvider';

export const plugin = new AppPlugin().addComponent({
title: 'User profile tab',
description: '...',
targets: [PluginExtensionPoints.UserProfileTab],
component: () => (
<MyCustomDataProvider>
<div>Plugin specific setting: {meta.jsonData.foo}</div>
</MyCustomDataProvider>
),
});

在特定条件下隐藏组件

只需从您的组件中返回 null,这样就不会渲染任何内容,从而隐藏组件。

import { usePluginContext, PluginExtensionPoints } from '@grafana/data';

export const plugin = new AppPlugin().addComponent({
title: 'User profile tab',
description: '...',
targets: [PluginExtensionPoints.UserProfileTab],
component: () => {
const { meta } = usePluginContext();

// For the sake of the example this condition is relying on a `jsonData` property
// that is managed by your plugin
if (!meta.jsonData.isExtensionEnabled) {
return null;
}

return <div>Plugin specific setting: {meta.jsonData.foo}</div>;
},
});

更新 plugin.json 元数据

一旦您定义了要注册到扩展点的链接或组件扩展,就必须更新您的 plugin.json 元数据。

例如

"extensions": [
{
"extensionPointId": "grafana/dashboard/panel/menu/v1",
"type": "link"
"title": "My app",
"description": "Link to my app"
}
]

更多信息,请参阅 plugin.json 参考

故障排除

  1. 检查控制台日志 - 您的链接很有可能是因为某些验证错误而没有出现。在这种情况下,您应该在浏览器的控制台中看到相关的日志。
  2. 检查 targets - 确保您使用了正确的扩展点 ID(对于 Grafana 扩展点,请始终使用 PluginExtensionPoints 枚举)
  3. 检查链接的 configure() 函数 - 如果您的链接有 configure() 函数,在某些条件下它可能会返回 undefined,从而隐藏链接。
  4. 检查是否注册了过多的链接 - 某些扩展点限制了每个插件允许的链接数量,如果您的插件为同一扩展点注册了多个链接,则其中一些可能会被过滤掉。
  5. 检查 Grafana 版本 - 链接和组件扩展仅在 Grafana 版本 >=10.1.0 之后支持,而 addLink() 仅在版本 >=11.1.0 中支持。

我的组件没有出现

  1. 检查控制台日志 - 您的组件很有可能是因为某些验证错误而没有出现。在这种情况下,您应该在浏览器的控制台中看到相关的日志。
  2. 检查 targets - 确保您使用了正确的扩展点 ID(对于 Grafana 扩展点,请始终使用 PluginExtensionPoints 枚举)
  3. 检查您的组件实现 - 如果您的组件在某些条件下返回 null,那么它将不会在扩展点渲染。
  4. 检查是否注册了过多的组件 - 某些扩展点限制了每个插件允许的组件数量,如果您的插件为同一扩展点注册了多个组件,则其中一些可能会被过滤掉。
  5. 检查 Grafana 版本 - 链接和组件扩展仅在 Grafana 版本 >=10.1.0 之后支持,而 addComponent() 仅在版本 >=11.1.0 中支持。