grafana_bak/public/app/features/explore/RawPrometheus/RawPrometheusContainer.tsx
2025-04-01 10:38:02 +09:00

163 lines
5.4 KiB
TypeScript

import { css } from '@emotion/css';
import { PureComponent } from 'react';
import { connect, ConnectedProps } from 'react-redux';
import { applyFieldOverrides, DataFrame, SelectableValue, SplitOpen } from '@grafana/data';
import { getTemplateSrv, reportInteraction } from '@grafana/runtime';
import { TimeZone } from '@grafana/schema';
import { RadioButtonGroup, Table, AdHocFilterItem, PanelChrome } from '@grafana/ui';
import { config } from 'app/core/config';
import { PANEL_BORDER } from 'app/core/constants';
import { StoreState, TABLE_RESULTS_STYLE } from 'app/types';
import { ExploreItemState, TABLE_RESULTS_STYLES, TableResultsStyle } from 'app/types/explore';
import { MetaInfoText } from '../MetaInfoText';
import RawListContainer from '../PrometheusListView/RawListContainer';
import { exploreDataLinkPostProcessorFactory } from '../utils/links';
interface RawPrometheusContainerProps {
ariaLabel?: string;
exploreId: string;
width: number;
timeZone: TimeZone;
onCellFilterAdded?: (filter: AdHocFilterItem) => void;
showRawPrometheus?: boolean;
splitOpenFn: SplitOpen;
}
interface PrometheusContainerState {
resultsStyle: TableResultsStyle;
}
function mapStateToProps(state: StoreState, { exploreId }: RawPrometheusContainerProps) {
const explore = state.explore;
const item: ExploreItemState = explore.panes[exploreId]!;
const { tableResult, rawPrometheusResult, range, queryResponse } = item;
const rawPrometheusFrame: DataFrame[] = rawPrometheusResult ? [rawPrometheusResult] : [];
const result = (tableResult?.length ?? 0) > 0 && rawPrometheusResult ? tableResult : rawPrometheusFrame;
const loading = queryResponse.state;
return { loading, tableResult: result, range };
}
const connector = connect(mapStateToProps, {});
type Props = RawPrometheusContainerProps & ConnectedProps<typeof connector>;
export class RawPrometheusContainer extends PureComponent<Props, PrometheusContainerState> {
constructor(props: Props) {
super(props);
// If resultsStyle is undefined we won't render the toggle, and the default table will be rendered
if (props.showRawPrometheus) {
this.state = {
resultsStyle: TABLE_RESULTS_STYLE.raw,
};
}
}
onChangeResultsStyle = (resultsStyle: TableResultsStyle) => {
this.setState({ resultsStyle });
};
getTableHeight() {
const { tableResult } = this.props;
if (!tableResult || tableResult.length === 0) {
return 200;
}
// tries to estimate table height
return Math.max(Math.min(600, tableResult[0].length * 35) + 35);
}
renderLabel = () => {
const spacing = css({
display: 'flex',
justifyContent: 'space-between',
flex: '1',
});
const ALL_GRAPH_STYLE_OPTIONS: Array<SelectableValue<TableResultsStyle>> = TABLE_RESULTS_STYLES.map((style) => ({
value: style,
// capital-case it and switch `_` to ` `
label: style[0].toUpperCase() + style.slice(1).replace(/_/, ' '),
}));
return (
<div className={spacing}>
<RadioButtonGroup
onClick={() => {
const props = {
state:
this.state.resultsStyle === TABLE_RESULTS_STYLE.table
? TABLE_RESULTS_STYLE.raw
: TABLE_RESULTS_STYLE.table,
};
reportInteraction('grafana_explore_prometheus_instant_query_ui_toggle_clicked', props);
}}
size="sm"
options={ALL_GRAPH_STYLE_OPTIONS}
value={this.state?.resultsStyle}
onChange={this.onChangeResultsStyle}
/>
</div>
);
};
render() {
const { loading, onCellFilterAdded, tableResult, width, splitOpenFn, range, ariaLabel, timeZone } = this.props;
const height = this.getTableHeight();
const tableWidth = width - config.theme.panelPadding * 2 - PANEL_BORDER;
let dataFrames = tableResult;
const dataLinkPostProcessor = exploreDataLinkPostProcessorFactory(splitOpenFn, range);
if (dataFrames?.length) {
dataFrames = applyFieldOverrides({
data: dataFrames,
timeZone,
theme: config.theme2,
replaceVariables: getTemplateSrv().replace.bind(getTemplateSrv()),
fieldConfig: {
defaults: {},
overrides: [],
},
dataLinkPostProcessor,
});
}
const frames = dataFrames?.filter(
(frame: DataFrame | undefined): frame is DataFrame => !!frame && frame.length !== 0
);
const title = this.state.resultsStyle === TABLE_RESULTS_STYLE.raw ? 'Raw' : 'Table';
const label = this.state?.resultsStyle !== undefined ? this.renderLabel() : 'Table';
// Render table as default if resultsStyle is not set.
const renderTable = !this.state?.resultsStyle || this.state?.resultsStyle === TABLE_RESULTS_STYLE.table;
return (
<PanelChrome title={title} actions={label} loadingState={loading}>
{frames?.length && (
<>
{renderTable && (
<Table
ariaLabel={ariaLabel}
data={frames[0]}
width={tableWidth}
height={height}
onCellFilterAdded={onCellFilterAdded}
/>
)}
{this.state?.resultsStyle === TABLE_RESULTS_STYLE.raw && <RawListContainer tableResult={frames[0]} />}
</>
)}
{!frames?.length && <MetaInfoText metaItems={[{ value: '0 series returned' }]} />}
</PanelChrome>
);
}
}
export default connector(RawPrometheusContainer);