mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PanelChrome: Simplify props and code a bit (#61595)
* PanelChrome: Simplify props and code a bit * Don't set a default empty array for leftItems so we can know user has set it * fix 'this' is undefined * add storybook examples of statusMessage; remove SB examples of loadingState === Error; simplify loadingState checks in PanelChrome; Co-authored-by: polinaboneva <polina.boneva@grafana.com>
This commit is contained in:
parent
54fd1b634f
commit
c1d3b59643
@ -93,34 +93,33 @@ export const Examples = () => {
|
||||
<DashboardStoryCanvas>
|
||||
<HorizontalGroup spacing="md" align="flex-start">
|
||||
<VerticalGroup spacing="md">
|
||||
{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,
|
||||
})}
|
||||
</VerticalGroup>
|
||||
<VerticalGroup spacing="md">
|
||||
{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,
|
||||
|
@ -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 (
|
||||
<div className={styles.errorContainer}>
|
||||
<PanelStatus message={status?.message} onClick={status?.onClick} />
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const ariaLabel = title ? selectors.components.Panels.Panel.containerByTitle(title) : 'Panel';
|
||||
|
||||
return (
|
||||
<div className={styles.container} style={containerStyles} aria-label={ariaLabel}>
|
||||
<div className={styles.loadingBarContainer}>
|
||||
{showLoading ? <LoadingBar width={'28%'} height={'2px'} /> : null}
|
||||
{loadingState === LoadingState.Loading ? <LoadingBar width={'28%'} height={'2px'} /> : null}
|
||||
</div>
|
||||
|
||||
<div className={styles.headerContainer} style={headerStyles} data-testid="header-container">
|
||||
@ -131,13 +116,13 @@ export function PanelChrome({
|
||||
|
||||
<PanelDescription description={description} />
|
||||
|
||||
{titleItems && (
|
||||
{titleItems.length > 0 && (
|
||||
<div className={styles.titleItems} data-testid="title-items-container">
|
||||
{titleItems.map((item) => item)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showStreaming && (
|
||||
{loadingState === LoadingState.Streaming && (
|
||||
<div className={styles.item} style={itemStyles}>
|
||||
<Tooltip content="Streaming">
|
||||
<Icon name="circle-mono" size="sm" className={styles.streaming} />
|
||||
@ -159,11 +144,16 @@ export function PanelChrome({
|
||||
</Dropdown>
|
||||
)}
|
||||
|
||||
{isUsingDeprecatedLeftItems && <div className={styles.items}>{itemsRenderer(leftItems, (item) => item)}</div>}
|
||||
{leftItems && <div className={styles.items}>{itemsRenderer(leftItems, (item) => item)}</div>}
|
||||
</div>
|
||||
|
||||
{renderStatus()}
|
||||
{statusMessage && (
|
||||
<div className={styles.errorContainer}>
|
||||
<PanelStatus message={statusMessage} onClick={statusMessageOnClick} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.content} style={contentStyle}>
|
||||
{children(innerWidth, innerHeight)}
|
||||
</div>
|
||||
@ -180,6 +170,7 @@ const getHeaderHeight = (theme: GrafanaTheme2, hasHeader: boolean) => {
|
||||
if (hasHeader) {
|
||||
return theme.spacing.gridSize * theme.components.panel.headerHeight;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
@ -592,10 +592,11 @@ export class PanelStateWrapper extends PureComponent<Props, State> {
|
||||
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<Props, State> {
|
||||
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}
|
||||
|
Loading…
Reference in New Issue
Block a user