mirror of
https://github.com/grafana/grafana.git
synced 2025-02-16 18:34:52 -06:00
* Fixed bug with event being forced. * Made onClick undefinable in the config as well. * Fixed some more type issues.
136 lines
4.0 KiB
TypeScript
136 lines
4.0 KiB
TypeScript
import {
|
|
type PluginExtension,
|
|
PluginExtensionTypes,
|
|
PluginExtensionLink,
|
|
PluginExtensionLinkConfig,
|
|
} from '@grafana/data';
|
|
|
|
import type { PluginExtensionRegistry } from './types';
|
|
import { isPluginExtensionLinkConfig, deepFreeze, logWarning, generateExtensionId, getEventHelpers } from './utils';
|
|
import { assertIsNotPromise, assertLinkPathIsValid, assertStringProps, isPromise } from './validators';
|
|
|
|
type GetExtensions = ({
|
|
context,
|
|
extensionPointId,
|
|
registry,
|
|
}: {
|
|
context?: object | Record<string | symbol, unknown>;
|
|
extensionPointId: string;
|
|
registry: PluginExtensionRegistry;
|
|
}) => { extensions: PluginExtension[] };
|
|
|
|
// Returns with a list of plugin extensions for the given extension point
|
|
export const getPluginExtensions: GetExtensions = ({ context, extensionPointId, registry }) => {
|
|
const frozenContext = context ? deepFreeze(context) : {};
|
|
const registryItems = registry[extensionPointId] ?? [];
|
|
// We don't return the extensions separated by type, because in that case it would be much harder to define a sort-order for them.
|
|
const extensions: PluginExtension[] = [];
|
|
|
|
for (const registryItem of registryItems) {
|
|
try {
|
|
const extensionConfig = registryItem.config;
|
|
|
|
if (isPluginExtensionLinkConfig(extensionConfig)) {
|
|
const overrides = getLinkExtensionOverrides(registryItem.pluginId, extensionConfig, frozenContext);
|
|
|
|
// Hide (configure() has returned `undefined`)
|
|
if (extensionConfig.configure && overrides === undefined) {
|
|
continue;
|
|
}
|
|
|
|
const extension: PluginExtensionLink = {
|
|
id: generateExtensionId(registryItem.pluginId, extensionConfig),
|
|
type: PluginExtensionTypes.link,
|
|
pluginId: registryItem.pluginId,
|
|
onClick: getLinkExtensionOnClick(extensionConfig, frozenContext),
|
|
|
|
// Configurable properties
|
|
title: overrides?.title || extensionConfig.title,
|
|
description: overrides?.description || extensionConfig.description,
|
|
path: overrides?.path || extensionConfig.path,
|
|
};
|
|
|
|
extensions.push(extension);
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
logWarning(error.message);
|
|
}
|
|
}
|
|
}
|
|
|
|
return { extensions };
|
|
};
|
|
|
|
function getLinkExtensionOverrides(pluginId: string, config: PluginExtensionLinkConfig, context?: object) {
|
|
try {
|
|
const overrides = config.configure?.(context);
|
|
|
|
// Hiding the extension
|
|
if (overrides === undefined) {
|
|
return undefined;
|
|
}
|
|
|
|
let { title = config.title, description = config.description, path = config.path, ...rest } = overrides;
|
|
|
|
assertIsNotPromise(
|
|
overrides,
|
|
`The configure() function for "${config.title}" returned a promise, skipping updates.`
|
|
);
|
|
|
|
path && assertLinkPathIsValid(pluginId, path);
|
|
assertStringProps({ title, description }, ['title', 'description']);
|
|
|
|
if (Object.keys(rest).length > 0) {
|
|
throw new Error(
|
|
`Invalid extension "${config.title}". Trying to override not-allowed properties: ${Object.keys(rest).join(
|
|
', '
|
|
)}`
|
|
);
|
|
}
|
|
|
|
return {
|
|
title,
|
|
description,
|
|
path,
|
|
};
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
logWarning(error.message);
|
|
}
|
|
|
|
// If there is an error, we hide the extension
|
|
// (This seems to be safest option in case the extension is doing something wrong.)
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
function getLinkExtensionOnClick(
|
|
config: PluginExtensionLinkConfig,
|
|
context?: object
|
|
): ((event?: React.MouseEvent) => void) | undefined {
|
|
const { onClick } = config;
|
|
|
|
if (!onClick) {
|
|
return;
|
|
}
|
|
|
|
return function onClickExtensionLink(event?: React.MouseEvent) {
|
|
try {
|
|
const result = onClick(event, getEventHelpers(context));
|
|
|
|
if (isPromise(result)) {
|
|
result.catch((e) => {
|
|
if (e instanceof Error) {
|
|
logWarning(e.message);
|
|
}
|
|
});
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
logWarning(error.message);
|
|
}
|
|
}
|
|
};
|
|
}
|