diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.story.tsx b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.story.tsx index d6f4b3d0493..994756175e4 100644 --- a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.story.tsx +++ b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.story.tsx @@ -93,34 +93,33 @@ export const Examples = () => { - {renderPanel('Error status', { + {renderPanel('Has statusMessage', { title: 'Default title', - status: { - message: 'Error text', - onClick: action('ErrorIndicator: onClick fired'), - }, + statusMessage: 'Error text', + statusMessageOnClick: action('ErrorIndicator: onClick fired'), })} - {renderPanel('No padding, error loadingState', { + {renderPanel('No padding, has statusMessage', { padding: 'none', title: 'Default title', + statusMessage: 'Error text', + statusMessageOnClick: action('ErrorIndicator: onClick fired'), + })} + {renderPanel('No title, loadingState is Error, no statusMessage', { loadingState: LoadingState.Error, })} - {renderPanel('No title, error loadingState', { - loadingState: LoadingState.Error, - })} - {renderPanel('Streaming loadingState', { + {renderPanel('loadingState is Streaming', { title: 'Default title', loadingState: LoadingState.Streaming, })} - {renderPanel('Loading loadingState', { + {renderPanel('loadingState is Loading', { title: 'Default title', loadingState: LoadingState.Loading, })} {renderPanel('Default panel: no non-required props')} - {renderPanel('No padding, no title', { + {renderPanel('No padding', { padding: 'none', })} {renderPanel('Very long title', { @@ -137,28 +136,27 @@ export const Examples = () => { {renderPanel('Error status, menu', { title: 'Default title', menu, - status: { - message: 'Error text', - onClick: action('ErrorIndicator: onClick fired'), - }, + statusMessage: 'Error text', + statusMessageOnClick: action('ErrorIndicator: onClick fired'), })} - {renderPanel('No padding, error loadingState, menu', { + {renderPanel('No padding; has statusMessage, menu', { padding: 'none', title: 'Default title', menu, - loadingState: LoadingState.Error, + statusMessage: 'Error text', + statusMessageOnClick: action('ErrorIndicator: onClick fired'), })} - {renderPanel('No title, error loadingState, menu', { + {renderPanel('No title, loadingState is Error, no statusMessage, menu', { menu, loadingState: LoadingState.Error, })} - {renderPanel('Streaming loadingState, menu', { + {renderPanel('loadingState is Streaming, menu', { title: 'Default title', menu, loadingState: LoadingState.Streaming, })} - {renderPanel('Loading loadingState, menu', { + {renderPanel('loadingState is Loading, menu', { title: 'Default title', menu, loadingState: LoadingState.Loading, diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx index d2f2b3716a6..e91d3297633 100644 --- a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx +++ b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx @@ -1,6 +1,5 @@ import { css, cx } from '@emotion/css'; -import { isEmpty } from 'lodash'; -import React, { CSSProperties, ReactNode, ReactElement } from 'react'; +import React, { CSSProperties, ReactElement, ReactNode } from 'react'; import { GrafanaTheme2, LoadingState } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; @@ -15,11 +14,6 @@ import { Tooltip } from '../Tooltip'; import { PanelDescription } from './PanelDescription'; import { PanelStatus } from './PanelStatus'; -interface Status { - message?: string; - onClick?: (e: React.SyntheticEvent) => void; -} - /** * @internal */ @@ -36,7 +30,14 @@ export interface PanelChromeProps { // dragClass?: string; hoverHeader?: boolean; loadingState?: LoadingState; - status?: Status; + /** + * Used to display status message (used for panel errors currently) + */ + statusMessage?: string; + /** + * Handle opening error details view (like inspect / error tab) + */ + statusMessageOnClick?: (e: React.SyntheticEvent) => void; /** @deprecated in favor of props * status for errors and loadingState for loading and streaming * which will serve the same purpose @@ -65,8 +66,9 @@ export function PanelChrome({ // dragClass, hoverHeader = false, loadingState, - status, - leftItems = [], + statusMessage, + statusMessageOnClick, + leftItems, }: PanelChromeProps) { const theme = useTheme2(); const styles = useStyles2(getStyles); @@ -82,7 +84,7 @@ export function PanelChrome({ titleItems.length > 0 || description !== '' || loadingState === LoadingState.Streaming || - leftItems.length > 0); + (leftItems?.length ?? 0) > 0); const headerHeight = getHeaderHeight(theme, hasHeader); const { contentStyle, innerWidth, innerHeight } = getContentStyle(padding, theme, width, headerHeight, height); @@ -97,29 +99,12 @@ export function PanelChrome({ }; const containerStyles: CSSProperties = { width, height }; - - const isUsingDeprecatedLeftItems = isEmpty(status) && !loadingState; - const showLoading = loadingState === LoadingState.Loading && !isUsingDeprecatedLeftItems; - const showStreaming = loadingState === LoadingState.Streaming && !isUsingDeprecatedLeftItems; - - const renderStatus = () => { - const showError = loadingState === LoadingState.Error || status?.message; - if (!isUsingDeprecatedLeftItems && showError) { - return ( -
- -
- ); - } else { - return null; - } - }; - const ariaLabel = title ? selectors.components.Panels.Panel.containerByTitle(title) : 'Panel'; + return (
- {showLoading ? : null} + {loadingState === LoadingState.Loading ? : null}
@@ -131,13 +116,13 @@ export function PanelChrome({ - {titleItems && ( + {titleItems.length > 0 && (
{titleItems.map((item) => item)}
)} - {showStreaming && ( + {loadingState === LoadingState.Streaming && (
@@ -159,11 +144,16 @@ export function PanelChrome({ )} - {isUsingDeprecatedLeftItems &&
{itemsRenderer(leftItems, (item) => item)}
} + {leftItems &&
{itemsRenderer(leftItems, (item) => item)}
}
- {renderStatus()} + {statusMessage && ( +
+ +
+ )}
+
{children(innerWidth, innerHeight)}
@@ -180,6 +170,7 @@ const getHeaderHeight = (theme: GrafanaTheme2, hasHeader: boolean) => { if (hasHeader) { return theme.spacing.gridSize * theme.components.panel.headerHeight; } + return 0; }; diff --git a/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx b/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx index 0a0c3df1643..b7e2a8daeda 100644 --- a/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx +++ b/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx @@ -592,10 +592,11 @@ export class PanelStateWrapper extends PureComponent { e.stopPropagation(); locationService.partial({ inspect: this.props.panel.id, inspectTab: tab }); }; - onOpenErrorInspect(e: React.SyntheticEvent, tab: string) { + + onOpenErrorInspect = (e: React.SyntheticEvent) => { e.stopPropagation(); - locationService.partial({ inspect: this.props.panel.id, inspectTab: tab }); - } + locationService.partial({ inspect: this.props.panel.id, inspectTab: InspectTab.Error }); + }; render() { const { dashboard, panel, isViewing, isEditing, width, height, plugin } = this.props; @@ -648,10 +649,8 @@ export class PanelStateWrapper extends PureComponent { height={height} title={title} loadingState={data.state} - status={{ - message: errorMessage, - onClick: (e: React.SyntheticEvent) => this.onOpenErrorInspect(e, InspectTab.Error), - }} + statusMessage={errorMessage} + statusMessageOnClick={this.onOpenErrorInspect} description={!!panel.description ? this.onShowPanelDescription : undefined} titleItems={titleItems} menu={menu}