content.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import {InjectedRouter} from 'react-router';
  2. import {Theme} from '@emotion/react';
  3. import {Query} from 'history';
  4. import ChartZoom from 'sentry/components/charts/chartZoom';
  5. import ErrorPanel from 'sentry/components/charts/errorPanel';
  6. import {LineChart, LineChartProps} from 'sentry/components/charts/lineChart';
  7. import ReleaseSeries from 'sentry/components/charts/releaseSeries';
  8. import TransitionChart from 'sentry/components/charts/transitionChart';
  9. import TransparentLoadingMask from 'sentry/components/charts/transparentLoadingMask';
  10. import Placeholder from 'sentry/components/placeholder';
  11. import {IconWarning} from 'sentry/icons';
  12. import {t} from 'sentry/locale';
  13. import {Series} from 'sentry/types/echarts';
  14. import {
  15. axisLabelFormatter,
  16. getDurationUnit,
  17. tooltipFormatter,
  18. } from 'sentry/utils/discover/charts';
  19. import getDynamicText from 'sentry/utils/getDynamicText';
  20. import {NormalizedTrendsTransaction} from 'sentry/views/performance/trends/types';
  21. import {getIntervalLine} from 'sentry/views/performance/utils';
  22. import {transformEventStatsSmoothed} from '../../../trends/utils';
  23. type Props = {
  24. errored: boolean;
  25. loading: boolean;
  26. queryExtra: Query;
  27. reloading: boolean;
  28. router: InjectedRouter;
  29. theme: Theme;
  30. series?: Series[];
  31. timeFrame?: {
  32. end: number;
  33. start: number;
  34. };
  35. transaction?: NormalizedTrendsTransaction;
  36. withBreakpoint?: boolean;
  37. } & Omit<React.ComponentProps<typeof ReleaseSeries>, 'children' | 'queryExtra'> &
  38. Pick<LineChartProps, 'onLegendSelectChanged' | 'legend'>;
  39. function Content({
  40. errored,
  41. theme,
  42. series: data,
  43. timeFrame,
  44. start,
  45. end,
  46. period,
  47. projects,
  48. environments,
  49. loading,
  50. reloading,
  51. legend,
  52. utc,
  53. queryExtra,
  54. router,
  55. withBreakpoint,
  56. transaction,
  57. onLegendSelectChanged,
  58. }: Props) {
  59. if (errored) {
  60. return (
  61. <ErrorPanel>
  62. <IconWarning color="gray500" size="lg" />
  63. </ErrorPanel>
  64. );
  65. }
  66. const series = data
  67. ? data
  68. .map(values => {
  69. return {
  70. ...values,
  71. color: theme.purple300,
  72. lineStyle: {
  73. opacity: 0.75,
  74. width: 1,
  75. },
  76. };
  77. })
  78. .reverse()
  79. : [];
  80. const needsLabel = false;
  81. const breakpointSeries = withBreakpoint
  82. ? getIntervalLine(theme, data || [], 0.5, needsLabel, transaction)
  83. : [];
  84. const durationUnit = getDurationUnit(series, legend);
  85. const chartOptions: Omit<LineChartProps, 'series'> = {
  86. grid: {
  87. left: '10px',
  88. right: '10px',
  89. top: '40px',
  90. bottom: '0px',
  91. },
  92. seriesOptions: {
  93. showSymbol: false,
  94. },
  95. tooltip: {
  96. valueFormatter: (value: number | null) => tooltipFormatter(value, 'duration'),
  97. },
  98. xAxis: timeFrame
  99. ? {
  100. min: timeFrame.start,
  101. max: timeFrame.end,
  102. }
  103. : undefined,
  104. yAxis: {
  105. min: 0,
  106. minInterval: durationUnit,
  107. axisLabel: {
  108. color: theme.chartLabel,
  109. formatter: (value: number) =>
  110. axisLabelFormatter(value, 'duration', undefined, durationUnit),
  111. },
  112. },
  113. };
  114. const {smoothedResults} = transformEventStatsSmoothed(data, t('Smoothed'));
  115. const smoothedSeries = smoothedResults
  116. ? smoothedResults.map(values => {
  117. return {
  118. ...values,
  119. color: theme.purple300,
  120. lineStyle: {
  121. opacity: 1,
  122. },
  123. };
  124. })
  125. : [];
  126. return (
  127. <ChartZoom router={router} period={period} start={start} end={end} utc={utc}>
  128. {zoomRenderProps => (
  129. <ReleaseSeries
  130. start={start}
  131. end={end}
  132. queryExtra={queryExtra}
  133. period={period}
  134. utc={utc}
  135. projects={projects}
  136. environments={environments}
  137. >
  138. {({releaseSeries}) => (
  139. <TransitionChart loading={loading} reloading={reloading}>
  140. <TransparentLoadingMask visible={reloading} />
  141. {getDynamicText({
  142. value: (
  143. <LineChart
  144. {...zoomRenderProps}
  145. {...chartOptions}
  146. legend={legend}
  147. onLegendSelectChanged={onLegendSelectChanged}
  148. series={[
  149. ...series,
  150. ...smoothedSeries,
  151. ...releaseSeries,
  152. ...breakpointSeries,
  153. ]}
  154. />
  155. ),
  156. fixed: <Placeholder height="200px" testId="skeleton-ui" />,
  157. })}
  158. </TransitionChart>
  159. )}
  160. </ReleaseSeries>
  161. )}
  162. </ChartZoom>
  163. );
  164. }
  165. export default Content;