Files
Nick Richmond 29fa6dfc8d ExploreMetrics: Add toggle to enable routing to externalized Explore Metrics app plugin (#99481)
* feat: toggle for explore metrics app plugin

* chore: put app navigation settings behind feature toggle

* chore: require restart

* feat: context-driven applinks toggling

* fix: toggle ownership

* docs: note restart requirement

* refactor: prefer global feature toggle check

* chore: undo rm newlines

* fix: minimize changes

* fix: app id, `chromeless`, sidebar ordering
2025-02-03 15:46:54 -05:00

62 lines
2.2 KiB
TypeScript

import { NavModelItem } from '@grafana/data';
import { RouteDescriptor } from 'app/core/navigation/types';
import { getRootSectionForNode } from 'app/core/selectors/navModel';
import AppRootPage from 'app/features/plugins/components/AppRootPage';
import { getState } from 'app/store/store';
const isPluginNavModelItem = (model: NavModelItem): model is PluginNavModelItem => 'pluginId' in model && 'id' in model;
const isStandalonePluginPage = (id: string) => id.startsWith('standalone-plugin-page-/');
function getPathForNavItem(navItem: PluginNavModelItem) {
const pluginNavSection = getRootSectionForNode(navItem);
const appPluginUrl = `/a/${navItem.pluginId}`;
const path = isStandalonePluginPage(navItem.id) ? navItem.url || appPluginUrl : appPluginUrl; // Only standalone pages can use core URLs, otherwise we fall back to "/a/:pluginId"
const isSensitive = isStandalonePluginPage(navItem.id) && !navItem.url?.startsWith('/a/'); // Have case-sensitive URLs only for standalone pages that have custom URLs
return {
path: `${path}/*`,
sensitive: isSensitive,
component: () => <AppRootPage pluginId={navItem.pluginId} pluginNavSection={pluginNavSection} />,
};
}
export function getAppPluginRoutes(): RouteDescriptor[] {
const state = getState();
const { navIndex } = state;
const explicitAppPluginRoutes = Object.values(navIndex)
.filter<PluginNavModelItem>(isPluginNavModelItem)
.map(getPathForNavItem);
return [
...explicitAppPluginRoutes,
// Fallback route for plugins that don't have any pages under includes
{
path: '/a/:pluginId/*',
component: () => <AppRootPage pluginNavSection={navIndex.home} />,
},
];
}
export function getRouteForAppPlugin(pluginId: string): RouteDescriptor {
const state = getState();
const { navIndex } = state;
const navItem = Object.values(navIndex)
.filter<PluginNavModelItem>(isPluginNavModelItem)
.find((navItem) => navItem.pluginId === pluginId);
if (!navItem) {
return {
path: '/a/:pluginId/*',
component: () => <AppRootPage pluginNavSection={navIndex.home} />,
};
}
return getPathForNavItem(navItem);
}
interface PluginNavModelItem extends Omit<NavModelItem, 'pluginId' | 'id'> {
pluginId: string;
id: string;
}