2022-09-05 07:56:08 -05:00
|
|
|
import { Location as HistoryLocation } from 'history';
|
|
|
|
|
|
|
|
import { GrafanaPlugin, NavIndex, NavModel, NavModelItem, PanelPluginMeta, PluginType } from '@grafana/data';
|
|
|
|
import { config } from '@grafana/runtime';
|
2022-10-10 05:47:04 -05:00
|
|
|
import { HOME_NAV_ID } from 'app/core/reducers/navModel';
|
2022-10-07 09:33:36 -05:00
|
|
|
import { getRootSectionForNode } from 'app/core/selectors/navModel';
|
2022-04-22 08:33:13 -05:00
|
|
|
|
|
|
|
import { importPanelPluginFromMeta } from './importPanelPlugin';
|
2021-11-19 06:42:26 -06:00
|
|
|
import { getPluginSettings } from './pluginSettings';
|
|
|
|
import { importAppPlugin, importDataSourcePlugin } from './plugin_loader';
|
|
|
|
|
|
|
|
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);
|
2022-02-02 06:02:32 -06:00
|
|
|
result = panelPlugin as unknown as GrafanaPlugin;
|
2021-11-19 06:42:26 -06:00
|
|
|
}
|
|
|
|
if (info.type === PluginType.renderer) {
|
|
|
|
result = { meta: info } as GrafanaPlugin;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
throw new Error('Unknown Plugin type: ' + info.type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2022-09-05 07:56:08 -05:00
|
|
|
|
2022-09-28 01:29:35 -05:00
|
|
|
export function buildPluginSectionNav(
|
|
|
|
location: HistoryLocation,
|
|
|
|
pluginNav: NavModel | null,
|
|
|
|
navIndex: NavIndex,
|
|
|
|
pluginId: string
|
2022-09-29 06:27:51 -05:00
|
|
|
): NavModel | undefined {
|
2022-09-05 07:56:08 -05:00
|
|
|
// When topnav is disabled we only just show pluginNav like before
|
|
|
|
if (!config.featureToggles.topnav) {
|
2022-09-29 06:27:51 -05:00
|
|
|
return pluginNav ?? undefined;
|
2022-09-05 07:56:08 -05:00
|
|
|
}
|
|
|
|
|
2022-09-29 06:27:51 -05:00
|
|
|
let section = getPluginSection(location, navIndex, pluginId);
|
|
|
|
if (!section) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
// shallow clone as we set active flag
|
|
|
|
section = { ...section };
|
2022-09-05 07:56:08 -05:00
|
|
|
|
|
|
|
// If we have plugin nav don't set active page in section as it will cause double breadcrumbs
|
|
|
|
const currentUrl = config.appSubUrl + location.pathname + location.search;
|
|
|
|
let activePage: NavModelItem | undefined;
|
|
|
|
|
2022-09-29 06:27:51 -05:00
|
|
|
function setPageToActive(page: NavModelItem, currentUrl: string): NavModelItem {
|
|
|
|
if (!currentUrl.startsWith(page.url ?? '')) {
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (activePage && (activePage.url?.length ?? 0) > (page.url?.length ?? 0)) {
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (activePage) {
|
|
|
|
activePage.active = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
activePage = { ...page, active: true };
|
|
|
|
return activePage;
|
|
|
|
}
|
|
|
|
|
2022-09-28 01:29:35 -05:00
|
|
|
// Find and set active page
|
2022-09-05 07:56:08 -05:00
|
|
|
section.children = (section?.children ?? []).map((child) => {
|
|
|
|
if (child.children) {
|
|
|
|
return {
|
2022-10-05 04:46:27 -05:00
|
|
|
...setPageToActive(child, currentUrl),
|
2022-09-29 06:27:51 -05:00
|
|
|
children: child.children.map((pluginPage) => setPageToActive(pluginPage, currentUrl)),
|
2022-09-05 07:56:08 -05:00
|
|
|
};
|
|
|
|
}
|
2022-09-29 06:27:51 -05:00
|
|
|
|
|
|
|
return setPageToActive(child, currentUrl);
|
2022-09-05 07:56:08 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
return { main: section, node: activePage ?? section };
|
|
|
|
}
|
2022-09-28 01:29:35 -05:00
|
|
|
|
|
|
|
// TODO make work for sub pages
|
|
|
|
export function getPluginSection(location: HistoryLocation, navIndex: NavIndex, pluginId: string): NavModelItem {
|
|
|
|
// First check if this page exist in navIndex using path, some plugin pages are not under their own section
|
|
|
|
const byPath = navIndex[`standalone-plugin-page-${location.pathname}`];
|
|
|
|
if (byPath) {
|
2022-10-07 09:33:36 -05:00
|
|
|
return getRootSectionForNode(byPath);
|
2022-09-28 01:29:35 -05:00
|
|
|
}
|
|
|
|
|
2022-09-29 06:27:51 -05:00
|
|
|
// Some plugins like cloud home don't have any precense in the navtree so we need to allow those
|
2022-09-28 01:29:35 -05:00
|
|
|
const navTreeNodeForPlugin = navIndex[`plugin-page-${pluginId}`];
|
|
|
|
if (!navTreeNodeForPlugin) {
|
2022-10-10 05:47:04 -05:00
|
|
|
return navIndex[HOME_NAV_ID];
|
2022-09-28 01:29:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!navTreeNodeForPlugin.parentItem) {
|
|
|
|
throw new Error('Could not find plugin section');
|
|
|
|
}
|
|
|
|
|
|
|
|
return navTreeNodeForPlugin.parentItem;
|
|
|
|
}
|