Files
grafana/public/app/features/explore/Graph/GraphContainer.tsx
Piotr Jamróz 58285e37a2 Explore: Pass the dataframes along with the time range of the data (#90259)
* Use data time range for rendering instead of selected range from the picker

* Update CustomContainer to use data time range

* Update test
2024-07-17 11:05:09 +02:00

146 lines
4.1 KiB
TypeScript

import { css } from '@emotion/css';
import { useCallback, useMemo, useState } from 'react';
import { useToggle } from 'react-use';
import {
DataFrame,
EventBus,
AbsoluteTimeRange,
TimeZone,
SplitOpen,
LoadingState,
ThresholdsConfig,
GrafanaTheme2,
TimeRange,
} from '@grafana/data';
import {
GraphThresholdsStyleConfig,
PanelChrome,
PanelChromeProps,
Icon,
Button,
useStyles2,
Tooltip,
} from '@grafana/ui';
import { t, Trans } from 'app/core/internationalization';
import { ExploreGraphStyle } from 'app/types';
import { storeGraphStyle } from '../state/utils';
import { ExploreGraph } from './ExploreGraph';
import { ExploreGraphLabel } from './ExploreGraphLabel';
import { loadGraphStyle } from './utils';
const MAX_NUMBER_OF_TIME_SERIES = 20;
interface Props extends Pick<PanelChromeProps, 'statusMessage'> {
width: number;
height: number;
data: DataFrame[];
annotations?: DataFrame[];
eventBus: EventBus;
timeRange: TimeRange;
timeZone: TimeZone;
onChangeTime: (absoluteRange: AbsoluteTimeRange) => void;
splitOpenFn: SplitOpen;
loadingState: LoadingState;
thresholdsConfig?: ThresholdsConfig;
thresholdsStyle?: GraphThresholdsStyleConfig;
}
export const GraphContainer = ({
data,
eventBus,
height,
width,
timeRange,
timeZone,
annotations,
onChangeTime,
splitOpenFn,
thresholdsConfig,
thresholdsStyle,
loadingState,
statusMessage,
}: Props) => {
const [showAllSeries, toggleShowAllSeries] = useToggle(false);
const [graphStyle, setGraphStyle] = useState(loadGraphStyle);
const styles = useStyles2(getStyles);
const onGraphStyleChange = useCallback((graphStyle: ExploreGraphStyle) => {
storeGraphStyle(graphStyle);
setGraphStyle(graphStyle);
}, []);
const slicedData = useMemo(() => {
return showAllSeries ? data : data.slice(0, MAX_NUMBER_OF_TIME_SERIES);
}, [data, showAllSeries]);
return (
<PanelChrome
title={t('graph.container.title', 'Graph')}
titleItems={[
!showAllSeries && MAX_NUMBER_OF_TIME_SERIES < data.length && (
<div key="disclaimer" className={styles.timeSeriesDisclaimer}>
<span className={styles.warningMessage}>
<Icon name="exclamation-triangle" aria-hidden="true" />
<Trans i18nKey={'graph.container.show-only-series'}>
Showing only {{ MAX_NUMBER_OF_TIME_SERIES }} series
</Trans>
</span>
<Tooltip
content={t(
'graph.container.content',
'Rendering too many series in a single panel may impact performance and make data harder to read. Consider refining your queries.'
)}
>
<Button variant="secondary" size="sm" onClick={toggleShowAllSeries}>
<Trans i18nKey={'graph.container.show-all-series'}>Show all {{ length: data.length }}</Trans>
</Button>
</Tooltip>
</div>
),
].filter(Boolean)}
width={width}
height={height}
loadingState={loadingState}
statusMessage={statusMessage}
actions={<ExploreGraphLabel graphStyle={graphStyle} onChangeGraphStyle={onGraphStyleChange} />}
>
{(innerWidth, innerHeight) => (
<ExploreGraph
graphStyle={graphStyle}
data={slicedData}
height={innerHeight}
width={innerWidth}
timeRange={timeRange}
onChangeTime={onChangeTime}
timeZone={timeZone}
annotations={annotations}
splitOpenFn={splitOpenFn}
loadingState={loadingState}
thresholdsConfig={thresholdsConfig}
thresholdsStyle={thresholdsStyle}
eventBus={eventBus}
/>
)}
</PanelChrome>
);
};
const getStyles = (theme: GrafanaTheme2) => ({
timeSeriesDisclaimer: css({
label: 'time-series-disclaimer',
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
}),
warningMessage: css({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(0.5),
color: theme.colors.warning.main,
fontSize: theme.typography.bodySmall.fontSize,
}),
});