diff --git a/public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx b/public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx index adb189673b2..b1d6ca570e1 100644 --- a/public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx +++ b/public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx @@ -5,15 +5,29 @@ import { RepeatRowSelect } from '../RepeatRowSelect/RepeatRowSelect'; import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor'; import { OptionsPaneCategoryDescriptor } from './OptionsPaneCategoryDescriptor'; import { OptionPaneRenderProps } from './types'; +import { isPanelModelLibraryPanel } from '../../../library-panels/guard'; +import { LibraryPanelInformation } from 'app/features/library-panels/components/LibraryPanelInfo/LibraryPanelInfo'; export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPaneCategoryDescriptor { - const { panel, onPanelConfigChange } = props; - - return new OptionsPaneCategoryDescriptor({ + const { panel, onPanelConfigChange, dashboard } = props; + const descriptor = new OptionsPaneCategoryDescriptor({ title: 'Panel options', id: 'Panel options', isOpenDefault: true, - }) + }); + + if (isPanelModelLibraryPanel(panel)) { + descriptor.addItem( + new OptionsPaneItemDescriptor({ + title: 'Global panel information', + render: function renderLibraryPanelInformation() { + return ; + }, + }) + ); + } + + return descriptor .addItem( new OptionsPaneItemDescriptor({ title: 'Title', diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index b5fd0b065da..7f910c48016 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -578,10 +578,6 @@ function getPluginVersion(plugin: PanelPlugin): string { return plugin && plugin.meta.info.version ? plugin.meta.info.version : config.buildInfo.version; } -export function isLibraryPanel(panel: PanelModel): panel is PanelModel & Required> { - return panel.libraryPanel !== undefined; -} - interface PanelOptionsCache { properties: any; fieldConfig: FieldConfigSource; diff --git a/public/app/features/library-panels/components/LibraryPanelInfo/LibraryPanelInfo.tsx b/public/app/features/library-panels/components/LibraryPanelInfo/LibraryPanelInfo.tsx index 39c0a0324f5..c422632521e 100644 --- a/public/app/features/library-panels/components/LibraryPanelInfo/LibraryPanelInfo.tsx +++ b/public/app/features/library-panels/components/LibraryPanelInfo/LibraryPanelInfo.tsx @@ -1,47 +1,50 @@ import { DateTimeInput, GrafanaTheme } from '@grafana/data'; -import { stylesFactory, useStyles } from '@grafana/ui'; -import { OptionsPaneCategory } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategory'; -import { PanelModel } from 'app/features/dashboard/state'; +import { useStyles } from '@grafana/ui'; import { css } from '@emotion/css'; import React from 'react'; +import { PanelModelWithLibraryPanel } from '../../types'; +import { isPanelModelLibraryPanel } from '../../guard'; interface Props { - panel: PanelModel & Required>; + panel: PanelModelWithLibraryPanel; formatDate?: (dateString: DateTimeInput, format?: string) => string; } export const LibraryPanelInformation: React.FC = ({ panel, formatDate }) => { const styles = useStyles(getStyles); + if (!isPanelModelLibraryPanel(panel)) { + return null; + } + return ( - - {panel.libraryPanel.uid && ( -

- {`Used on ${panel.libraryPanel.meta.connectedDashboards} `} - {panel.libraryPanel.meta.connectedDashboards === 1 ? 'dashboard' : 'dashboards'} -
- Last edited on {formatDate?.(panel.libraryPanel.meta.updated, 'L') ?? panel.libraryPanel.meta.updated} by - {panel.libraryPanel.meta.updatedBy.avatarUrl && ( - {`Avatar - )} - {panel.libraryPanel.meta.updatedBy.name} -

- )} -
+ <> +

+ {`Used on ${panel.libraryPanel.meta.connectedDashboards} `} + {panel.libraryPanel.meta.connectedDashboards === 1 ? 'dashboard' : 'dashboards'} +
+ Last edited on {formatDate?.(panel.libraryPanel.meta.updated, 'L') ?? panel.libraryPanel.meta.updated} by + {panel.libraryPanel.meta.updatedBy.avatarUrl && ( + {`Avatar + )} + {panel.libraryPanel.meta.updatedBy.name} +

+ ); }; -const getStyles = stylesFactory((theme: GrafanaTheme) => { +const getStyles = (theme: GrafanaTheme) => { return { libraryPanelInfo: css` color: ${theme.colors.textSemiWeak}; font-size: ${theme.typography.size.sm}; + margin-left: ${theme.spacing.xxs}; `, userAvatar: css` border-radius: 50%; @@ -52,4 +55,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => { padding-right: ${theme.spacing.sm}; `, }; -}); +};