Files
Hugo Häggmark 0f3edd3b5f Plugins: renames snake cased plugin files (#107862)
* Plugins: renames plugin_loader

* test(pluginloader): fix mock paths to pluginLoader

* chore: rename sandbox files

* Trigger build

* Trigger build

---------

Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
2025-07-09 13:18:44 +02:00

88 lines
2.8 KiB
TypeScript

import { GrafanaPlugin, NavModel, NavModelItem, PanelPluginMeta, PluginType } from '@grafana/data';
import { createMonitoringLogger } from '@grafana/runtime';
import { importPanelPluginFromMeta } from './importPanelPlugin';
import { importAppPlugin, importDataSourcePlugin } from './pluginLoader';
import { getPluginSettings } from './pluginSettings';
export async function loadPlugin(pluginId: string): Promise<GrafanaPlugin> {
const info = await getPluginSettings(pluginId);
let result: GrafanaPlugin | undefined;
if (info.type === PluginType.app) {
result = await importAppPlugin(info);
}
if (info.type === PluginType.datasource) {
result = await importDataSourcePlugin(info);
}
if (info.type === PluginType.panel) {
const panelPlugin = await importPanelPluginFromMeta(info as PanelPluginMeta);
result = panelPlugin as unknown as GrafanaPlugin;
}
if (info.type === PluginType.renderer) {
result = { meta: info } as GrafanaPlugin;
}
if (!result) {
throw new Error('Unknown Plugin type: ' + info.type);
}
return result;
}
export function buildPluginSectionNav(currentUrl: string, pluginNavSection?: NavModelItem): NavModel | undefined {
if (!pluginNavSection) {
return undefined;
}
// shallow clone as we set active flag
const MAX_RECURSION_DEPTH = 10;
let copiedPluginNavSection = { ...pluginNavSection };
let activePage: NavModelItem | undefined;
function setPageToActive(page: NavModelItem, currentUrl: string): NavModelItem {
if (!currentUrl.startsWith(page.url ?? '')) {
return page;
}
// Check if there is already an active page found with with a more specific url (possibly a child of the current page)
// (In this case we bail out early and don't mark the parent as active)
if (activePage && (activePage.url?.length ?? 0) > (page.url?.length ?? 0)) {
return page;
}
if (activePage) {
activePage.active = false;
}
activePage = { ...page, active: true };
return activePage;
}
function findAndSetActivePage(child: NavModelItem, depth = 0): NavModelItem {
if (depth > MAX_RECURSION_DEPTH) {
return child;
}
if (child.children) {
// Doing this here to make sure that first we check if any of the children is active
// (In case yes, then the check for the parent will not mark it as active)
const children = child.children.map((pluginPage) => findAndSetActivePage(pluginPage, depth + 1));
return {
...setPageToActive(child, currentUrl),
children,
};
}
return setPageToActive(child, currentUrl);
}
// Find and set active page
copiedPluginNavSection.children = (copiedPluginNavSection?.children ?? []).map(findAndSetActivePage);
return { main: copiedPluginNavSection, node: activePage ?? copiedPluginNavSection };
}
export const pluginsLogger = createMonitoringLogger('features.plugins');