Plugins: Add a new UI Extension type (#68600)

* feat: add a new UI extension type: component

* tests: add tests for checking if it is a react component

* fix: remove reference to not existing type

* chore: update betterer results

* review: remove unnecessary override function for components

* review: use a single type notation in import

* review: stop exporting `PluginExtensionBase`

* refactor: make extension config types more explicit

By using some repetition now these types are much easier to oversee.
This commit is contained in:
Levente Balogh
2023-05-31 09:26:37 +02:00
committed by GitHub
parent 82c770115e
commit a91033c025
14 changed files with 203 additions and 49 deletions
@@ -12,6 +12,8 @@ export * from './appEvents';
export {
setPluginExtensionGetter,
getPluginExtensions,
getPluginLinkExtensions,
getPluginComponentExtensions,
type GetPluginExtensions,
} from './pluginExtensions/getPluginExtensions';
export { isPluginExtensionLink } from './pluginExtensions/utils';
export { isPluginExtensionLink, isPluginExtensionComponent } from './pluginExtensions/utils';
@@ -1,13 +1,15 @@
import { PluginExtension } from '@grafana/data';
import type { PluginExtension, PluginExtensionLink, PluginExtensionComponent } from '@grafana/data';
export type GetPluginExtensions = ({
import { isPluginExtensionComponent, isPluginExtensionLink } from './utils';
export type GetPluginExtensions<T = PluginExtension> = ({
extensionPointId,
context,
}: {
extensionPointId: string;
context?: object | Record<string | symbol, unknown>;
}) => {
extensions: PluginExtension[];
extensions: T[];
};
let singleton: GetPluginExtensions | undefined;
@@ -28,3 +30,19 @@ function getPluginExtensionGetter(): GetPluginExtensions {
}
export const getPluginExtensions: GetPluginExtensions = (options) => getPluginExtensionGetter()(options);
export const getPluginLinkExtensions: GetPluginExtensions<PluginExtensionLink> = (options) => {
const { extensions } = getPluginExtensions(options);
return {
extensions: extensions.filter(isPluginExtensionLink),
};
};
export const getPluginComponentExtensions: GetPluginExtensions<PluginExtensionComponent> = (options) => {
const { extensions } = getPluginExtensions(options);
return {
extensions: extensions.filter(isPluginExtensionComponent),
};
};
@@ -1,4 +1,9 @@
import { PluginExtension, PluginExtensionLink, PluginExtensionTypes } from '@grafana/data';
import {
type PluginExtension,
type PluginExtensionComponent,
type PluginExtensionLink,
PluginExtensionTypes,
} from '@grafana/data';
export function isPluginExtensionLink(extension: PluginExtension | undefined): extension is PluginExtensionLink {
if (!extension) {
@@ -6,3 +11,12 @@ export function isPluginExtensionLink(extension: PluginExtension | undefined): e
}
return extension.type === PluginExtensionTypes.link && ('path' in extension || 'onClick' in extension);
}
export function isPluginExtensionComponent(
extension: PluginExtension | undefined
): extension is PluginExtensionComponent {
if (!extension) {
return false;
}
return extension.type === PluginExtensionTypes.component && 'component' in extension;
}