ExploreGraphPanel.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import React, { PureComponent } from 'react';
  2. import { css, cx } from 'emotion';
  3. import { TimeZone, AbsoluteTimeRange, GraphSeriesXY, dateTimeForTimeZone } from '@grafana/data';
  4. import {
  5. GrafanaTheme,
  6. selectThemeVariant,
  7. Themeable,
  8. GraphWithLegend,
  9. LegendDisplayMode,
  10. withTheme,
  11. Collapse,
  12. GraphSeriesToggler,
  13. GraphSeriesTogglerAPI,
  14. } from '@grafana/ui';
  15. const MAX_NUMBER_OF_TIME_SERIES = 20;
  16. const getStyles = (theme: GrafanaTheme) => ({
  17. timeSeriesDisclaimer: css`
  18. label: time-series-disclaimer;
  19. width: 300px;
  20. margin: ${theme.spacing.sm} auto;
  21. padding: 10px 0;
  22. border-radius: ${theme.border.radius.md};
  23. text-align: center;
  24. background-color: ${selectThemeVariant({ light: theme.colors.white, dark: theme.colors.dark4 }, theme.type)};
  25. `,
  26. disclaimerIcon: css`
  27. label: disclaimer-icon;
  28. color: ${theme.colors.yellow};
  29. margin-right: ${theme.spacing.xs};
  30. `,
  31. showAllTimeSeries: css`
  32. label: show-all-time-series;
  33. cursor: pointer;
  34. color: ${theme.colors.linkExternal};
  35. `,
  36. });
  37. interface Props extends Themeable {
  38. series: GraphSeriesXY[];
  39. width: number;
  40. absoluteRange: AbsoluteTimeRange;
  41. loading: boolean;
  42. showPanel: boolean;
  43. showBars: boolean;
  44. showLines: boolean;
  45. isStacked: boolean;
  46. showingGraph: boolean;
  47. showingTable: boolean;
  48. timeZone: TimeZone;
  49. onUpdateTimeRange: (absoluteRange: AbsoluteTimeRange) => void;
  50. onToggleGraph?: (showingGraph: boolean) => void;
  51. onHiddenSeriesChanged?: (hiddenSeries: string[]) => void;
  52. }
  53. interface State {
  54. hiddenSeries: string[];
  55. showAllTimeSeries: boolean;
  56. }
  57. class UnThemedExploreGraphPanel extends PureComponent<Props, State> {
  58. state: State = {
  59. hiddenSeries: [],
  60. showAllTimeSeries: false,
  61. };
  62. onShowAllTimeSeries = () => {
  63. this.setState({
  64. showAllTimeSeries: true,
  65. });
  66. };
  67. onClickGraphButton = () => {
  68. const { onToggleGraph, showingGraph } = this.props;
  69. if (onToggleGraph) {
  70. onToggleGraph(showingGraph);
  71. }
  72. };
  73. onChangeTime = (from: number, to: number) => {
  74. const { onUpdateTimeRange } = this.props;
  75. onUpdateTimeRange({ from, to });
  76. };
  77. renderGraph = () => {
  78. const {
  79. width,
  80. series,
  81. onHiddenSeriesChanged,
  82. timeZone,
  83. absoluteRange,
  84. showPanel,
  85. showingGraph,
  86. showingTable,
  87. showBars,
  88. showLines,
  89. isStacked,
  90. } = this.props;
  91. const { showAllTimeSeries } = this.state;
  92. if (!series) {
  93. return null;
  94. }
  95. const timeRange = {
  96. from: dateTimeForTimeZone(timeZone, absoluteRange.from),
  97. to: dateTimeForTimeZone(timeZone, absoluteRange.to),
  98. raw: {
  99. from: dateTimeForTimeZone(timeZone, absoluteRange.from),
  100. to: dateTimeForTimeZone(timeZone, absoluteRange.to),
  101. },
  102. };
  103. const height = showPanel === false ? 100 : showingGraph && showingTable ? 200 : 400;
  104. const lineWidth = showLines ? 1 : 5;
  105. const seriesToShow = showAllTimeSeries ? series : series.slice(0, MAX_NUMBER_OF_TIME_SERIES);
  106. return (
  107. <GraphSeriesToggler series={seriesToShow} onHiddenSeriesChanged={onHiddenSeriesChanged}>
  108. {({ onSeriesToggle, toggledSeries }: GraphSeriesTogglerAPI) => {
  109. return (
  110. <GraphWithLegend
  111. displayMode={LegendDisplayMode.List}
  112. height={height}
  113. isLegendVisible={true}
  114. placement={'under'}
  115. width={width}
  116. timeRange={timeRange}
  117. timeZone={timeZone}
  118. showBars={showBars}
  119. showLines={showLines}
  120. showPoints={false}
  121. onToggleSort={() => {}}
  122. series={toggledSeries}
  123. isStacked={isStacked}
  124. lineWidth={lineWidth}
  125. onSeriesToggle={onSeriesToggle}
  126. onHorizontalRegionSelected={this.onChangeTime}
  127. />
  128. );
  129. }}
  130. </GraphSeriesToggler>
  131. );
  132. };
  133. render() {
  134. const { series, showPanel, showingGraph, loading, theme } = this.props;
  135. const { showAllTimeSeries } = this.state;
  136. const style = getStyles(theme);
  137. return (
  138. <>
  139. {series && series.length > MAX_NUMBER_OF_TIME_SERIES && !showAllTimeSeries && (
  140. <div className={cx([style.timeSeriesDisclaimer])}>
  141. <i className={cx(['fa fa-fw fa-warning', style.disclaimerIcon])} />
  142. {`Showing only ${MAX_NUMBER_OF_TIME_SERIES} time series. `}
  143. <span className={cx([style.showAllTimeSeries])} onClick={this.onShowAllTimeSeries}>{`Show all ${
  144. series.length
  145. }`}</span>
  146. </div>
  147. )}
  148. {showPanel && (
  149. <Collapse
  150. label="Graph"
  151. collapsible
  152. isOpen={showingGraph}
  153. loading={loading}
  154. onToggle={this.onClickGraphButton}
  155. >
  156. {this.renderGraph()}
  157. </Collapse>
  158. )}
  159. {!showPanel && this.renderGraph()}
  160. </>
  161. );
  162. }
  163. }
  164. export const ExploreGraphPanel = withTheme(UnThemedExploreGraphPanel);
  165. ExploreGraphPanel.displayName = 'ExploreGraphPanel';