Panel Inspect: allow plugins to add custom actions to the panel inspect popup (#34086)

This commit is contained in:
Ryan McKinley 2021-05-18 13:55:35 -07:00 committed by GitHub
parent e799257637
commit 855da80542
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 99 additions and 3 deletions

View File

@ -13,6 +13,7 @@ import { InspectDataTab } from 'app/features/inspector/InspectDataTab';
import { InspectTab } from 'app/features/inspector/types';
import { DashboardModel, PanelModel } from '../../state';
import { GetDataOptions } from '../../../query/state/PanelQueryRunner';
import { InspectActionsTab } from './PanelInspectActions';
interface Props {
dashboard: DashboardModel;
@ -97,6 +98,7 @@ export const InspectContent: React.FC<Props> = ({
{data && activeTab === InspectTab.Query && (
<QueryInspector panel={panel} data={data.series} onRefreshQuery={() => panel.refresh()} />
)}
{activeTab === InspectTab.Actions && <InspectActionsTab panel={panel} data={data} />}
</TabContent>
</CustomScrollbar>
</Drawer>

View File

@ -0,0 +1,84 @@
import { PanelModel } from '../../state';
export interface PanelInspectActionProps {
panel: PanelModel;
data?: PanelData;
}
export interface PanelInspectAction {
title: string;
description: string;
component: ComponentType<PanelInspectActionProps>;
}
export interface PanelInspectActionSupplier {
getActions: (panel: PanelModel) => PanelInspectAction[] | null;
}
// const dummySupplier: PanelInspectActionSupplier = {
// getActions: (panel: PanelModel) => {
// return [
// {
// title: 'Do something',
// description: 'that thingy',
// // eslint-disable-next-line react/display-name
// component: ({ panel }) => {
// return (
// <div>
// DO THING ONE. Panel: <pre>{JSON.stringify(panel.targets)}</pre>
// </div>
// );
// },
// },
// {
// title: 'Do something else',
// description: 'another thing',
// // eslint-disable-next-line react/display-name
// component: ({ panel }) => {
// return (
// <div>
// DO THING TWO. Panel: <pre>{JSON.stringify(panel.targets)}</pre>
// </div>
// );
// },
// },
// ];
// },
// };
// In Grafana 8.1, this can be improved and moved to `@grafana/runtime`
// NOTE: This is an internal/experimental API/hack and will change!
// (window as any).grafanaPanelInspectActionSupplier = dummySupplier;
import React, { ComponentType } from 'react';
import { PanelData } from '@grafana/data';
interface InspectActionsTabProps {
panel: PanelModel;
data?: PanelData;
}
export const InspectActionsTab: React.FC<InspectActionsTabProps> = ({ panel, data }) => {
const supplier = (window as any).grafanaPanelInspectActionSupplier as PanelInspectActionSupplier;
if (!supplier) {
return <div>Missing actions</div>;
}
const actions = supplier.getActions(panel);
if (!actions?.length) {
return <div>No actions avaliable</div>;
}
return (
<div>
{actions.map((a, idx) => (
<div key={idx}>
<h2>{a.title}</h2>
<span>{a.description}</span>
<a.component panel={panel} data={data} />
</div>
))}
</div>
);
};

View File

@ -31,7 +31,7 @@ const PanelInspectorUnconnected: React.FC<Props> = ({ panel, dashboard, plugin }
const location = useLocation();
const { data, isLoading, error } = usePanelLatestData(panel, dataOptions, true);
const metaDs = useDatasourceMetadata(data);
const tabs = useInspectTabs(dashboard, plugin, error, metaDs);
const tabs = useInspectTabs(panel, dashboard, plugin, error, metaDs);
const defaultTab = new URLSearchParams(location.search).get('inspectTab') as InspectTab;
const onClose = () => {

View File

@ -1,10 +1,11 @@
import { DataQueryError, DataSourceApi, PanelData, PanelPlugin } from '@grafana/data';
import useAsync from 'react-use/lib/useAsync';
import { getDataSourceSrv } from '@grafana/runtime';
import { DashboardModel } from 'app/features/dashboard/state';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { useMemo } from 'react';
import { supportsDataQuery } from '../PanelEditor/utils';
import { InspectTab } from 'app/features/inspector/types';
import { PanelInspectActionSupplier } from './PanelInspectActions';
/**
* Given PanelData return first data source supporting metadata inspector
@ -34,6 +35,7 @@ export const useDatasourceMetadata = (data?: PanelData) => {
* Configures tabs for PanelInspector
*/
export const useInspectTabs = (
panel: PanelModel,
dashboard: DashboardModel,
plugin: PanelPlugin | undefined | null,
error?: DataQueryError,
@ -56,9 +58,16 @@ export const useInspectTabs = (
tabs.push({ label: 'Error', value: InspectTab.Error });
}
// This is a quick internal hack to allow custom actions in inspect
// For 8.1, something like this should be exposed through grafana/runtime
const supplier = (window as any).grafanaPanelInspectActionSupplier as PanelInspectActionSupplier;
if (supplier && supplier.getActions(panel)) {
tabs.push({ label: 'Actions', value: InspectTab.Actions });
}
if (dashboard.meta.canEdit && supportsDataQuery(plugin)) {
tabs.push({ label: 'Query', value: InspectTab.Query });
}
return tabs;
}, [plugin, metaDs, dashboard, error]);
}, [panel, plugin, metaDs, dashboard, error]);
};

View File

@ -5,4 +5,5 @@ export enum InspectTab {
Stats = 'stats',
JSON = 'json',
Query = 'query',
Actions = 'actions', // ALPHA!
}