import {useTheme} from '@emotion/react'; import moment from 'moment-timezone'; import ChartZoom from 'sentry/components/charts/chartZoom'; import ErrorPanel from 'sentry/components/charts/errorPanel'; import {LineChart} from 'sentry/components/charts/lineChart'; import ReleaseSeries from 'sentry/components/charts/releaseSeries'; import {ChartContainer, HeaderTitleLegend} from 'sentry/components/charts/styles'; import TransitionChart from 'sentry/components/charts/transitionChart'; import TransparentLoadingMask from 'sentry/components/charts/transparentLoadingMask'; import Panel from 'sentry/components/panels/panel'; import QuestionTooltip from 'sentry/components/questionTooltip'; import {IconWarning} from 'sentry/icons'; import {t} from 'sentry/locale'; import type {DateString} from 'sentry/types/core'; import type {Series} from 'sentry/types/echarts'; import type {MetricsApiResponse} from 'sentry/types/metrics'; import {browserHistory} from 'sentry/utils/browserHistory'; import type {WebVital} from 'sentry/utils/fields'; import getDynamicText from 'sentry/utils/getDynamicText'; import {useLocation} from 'sentry/utils/useLocation'; import useRouter from 'sentry/utils/useRouter'; import {replaceSeriesName, transformEventStatsSmoothed} from '../trends/utils'; import type {ViewProps} from '../types'; import {getMaxOfSeries, getVitalChartDefinitions, getVitalChartTitle} from './utils'; type Props = Omit & { end: DateString | null; errored: boolean; field: string; loading: boolean; reloading: boolean; response: MetricsApiResponse | null; start: DateString | null; vital: WebVital; }; function VitalChartMetrics({ reloading, loading, response, errored, statsPeriod, start, end, project, environment, field, vital, }: Props) { const location = useLocation(); const router = useRouter(); const theme = useTheme(); const {utc, legend, vitalPoor, markLines, chartOptions} = getVitalChartDefinitions({ theme, location, vital, yAxis: field, }); function handleLegendSelectChanged(legendChange: { name: string; selected: Record; type: string; }) { const {selected} = legendChange; const unselected = Object.keys(selected).filter(key => !selected[key]); const to = { ...location, query: { ...location.query, unselectedSeries: unselected, }, }; browserHistory.push(to); } return ( {getVitalChartTitle(vital)} {zoomRenderProps => { if (errored) { return ( ); } const data = response?.groups.map(group => ({ seriesName: field, data: response.intervals.map((intervalValue, intervalIndex) => ({ name: moment(intervalValue).valueOf(), value: group.series ? group.series[field][intervalIndex] : 0, })), })) as Series[] | undefined; const colors = (data && theme.charts.getColorPalette(data.length - 2)) || []; const {smoothedResults} = transformEventStatsSmoothed(data); const smoothedSeries = smoothedResults ? smoothedResults.map(({seriesName, ...rest}, i: number) => { return { seriesName: replaceSeriesName(seriesName) || 'p75', ...rest, color: colors[i], lineStyle: { opacity: 1, width: 2, }, }; }) : []; const seriesMax = getMaxOfSeries(smoothedSeries); const yAxisMax = Math.max(seriesMax, vitalPoor); chartOptions.yAxis!.max = yAxisMax * 1.1; return ( {({releaseSeries}) => ( {getDynamicText({ value: ( ), fixed: 'Web Vitals Chart', })} )} ); }} ); } export default VitalChartMetrics;