content.tsx 4.6 KB

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