Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref(js): Convert TrendChart to functional component #29165

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {Component, Fragment} from 'react';
import {Fragment} from 'react';
import {browserHistory, withRouter, WithRouterProps} from 'react-router';
import {withTheme} from '@emotion/react';
import {useTheme} from '@emotion/react';
import {Location, Query} from 'history';

import {Client} from 'app/api';
import ChartZoom from 'app/components/charts/chartZoom';
import ErrorPanel from 'app/components/charts/errorPanel';
import EventsRequest from 'app/components/charts/eventsRequest';
Expand All @@ -23,8 +22,7 @@ import {getUtcToLocalDateObject} from 'app/utils/dates';
import {axisLabelFormatter, tooltipFormatter} from 'app/utils/discover/charts';
import EventView from 'app/utils/discover/eventView';
import getDynamicText from 'app/utils/getDynamicText';
import {Theme} from 'app/utils/theme';
import withApi from 'app/utils/withApi';
import useApi from 'app/utils/useApi';

import {transformEventStatsSmoothed} from '../../trends/utils';

Expand All @@ -41,18 +39,31 @@ type ViewProps = Pick<EventView, typeof QUERY_KEYS[number]>;

type Props = WithRouterProps &
ViewProps & {
theme: Theme;
api: Client;
location: Location;
organization: OrganizationSummary;
queryExtra: Query;
trendDisplay: string;
withoutZerofill: boolean;
};

class TrendChart extends Component<Props> {
handleLegendSelectChanged = legendChange => {
const {location} = this.props;
function TrendChart({
project,
environment,
location,
organization,
query,
statsPeriod,
router,
trendDisplay,
queryExtra,
withoutZerofill,
start: propsStart,
end: propsEnd,
}: Props) {
const api = useApi();
const theme = useTheme();

const handleLegendSelectChanged = legendChange => {
const {selected} = legendChange;
const unselected = Object.keys(selected).filter(key => !selected[key]);

Expand All @@ -66,181 +77,164 @@ class TrendChart extends Component<Props> {
browserHistory.push(to);
};

render() {
const {
theme,
api,
project,
environment,
location,
organization,
query,
statsPeriod,
router,
trendDisplay,
queryExtra,
withoutZerofill,
} = this.props;

const start = this.props.start ? getUtcToLocalDateObject(this.props.start) : null;
const end = this.props.end ? getUtcToLocalDateObject(this.props.end) : null;
const {utc} = getParams(location.query);

const legend = {
right: 10,
top: 0,
selected: getSeriesSelection(location, 'trendsUnselectedSeries'),
};
const start = propsStart ? getUtcToLocalDateObject(propsStart) : null;
const end = propsEnd ? getUtcToLocalDateObject(propsEnd) : null;
const {utc} = getParams(location.query);

const datetimeSelection = {
start,
end,
period: statsPeriod,
};
const legend = {
right: 10,
top: 0,
selected: getSeriesSelection(location, 'trendsUnselectedSeries'),
};

return (
<Fragment>
<HeaderTitleLegend>
{t('Trend')}
<QuestionTooltip
size="sm"
position="top"
title={t(`Trends shows the smoothed value of an aggregate over time.`)}
/>
</HeaderTitleLegend>
<ChartZoom
router={router}
period={statsPeriod}
start={start}
end={end}
utc={utc === 'true'}
>
{zoomRenderProps => (
<EventsRequest
api={api}
organization={organization}
period={statsPeriod}
project={project}
environment={environment}
start={start}
end={end}
interval={getInterval(datetimeSelection, 'high')}
showLoading={false}
query={query}
includePrevious={false}
yAxis={trendDisplay}
currentSeriesName={trendDisplay}
partial
withoutZerofill={withoutZerofill}
referrer="api.performance.transaction-summary.trends-chart"
>
{({errored, loading, reloading, timeseriesData, timeframe}) => {
if (errored) {
return (
<ErrorPanel>
<IconWarning color="gray300" size="lg" />
</ErrorPanel>
);
}

const chartOptions = {
grid: {
left: '10px',
right: '10px',
top: '40px',
bottom: '0px',
},
seriesOptions: {
showSymbol: false,
},
tooltip: {
trigger: 'axis' as const,
valueFormatter: value => tooltipFormatter(value, 'p50()'),
},
xAxis: timeframe
? {
min: timeframe.start,
max: timeframe.end,
}
: undefined,
yAxis: {
min: 0,
axisLabel: {
color: theme.chartLabel,
// p50() coerces the axis to be time based
formatter: (value: number) => axisLabelFormatter(value, 'p50()'),
},
},
};

const series = timeseriesData
? timeseriesData
.map(values => {
return {
...values,
color: theme.purple300,
lineStyle: {
opacity: 0.75,
width: 1,
},
};
})
.reverse()
: [];

const {smoothedResults} = transformEventStatsSmoothed(
timeseriesData,
t('Smoothed')
const datetimeSelection = {
start,
end,
period: statsPeriod,
};

return (
<Fragment>
<HeaderTitleLegend>
{t('Trend')}
<QuestionTooltip
size="sm"
position="top"
title={t(`Trends shows the smoothed value of an aggregate over time.`)}
/>
</HeaderTitleLegend>
<ChartZoom
router={router}
period={statsPeriod}
start={start}
end={end}
utc={utc === 'true'}
>
{zoomRenderProps => (
<EventsRequest
api={api}
organization={organization}
period={statsPeriod}
project={project}
environment={environment}
start={start}
end={end}
interval={getInterval(datetimeSelection, 'high')}
showLoading={false}
query={query}
includePrevious={false}
yAxis={trendDisplay}
currentSeriesName={trendDisplay}
partial
withoutZerofill={withoutZerofill}
referrer="api.performance.transaction-summary.trends-chart"
>
{({errored, loading, reloading, timeseriesData, timeframe}) => {
if (errored) {
return (
<ErrorPanel>
<IconWarning color="gray300" size="lg" />
</ErrorPanel>
);
}

const chartOptions = {
grid: {
left: '10px',
right: '10px',
top: '40px',
bottom: '0px',
},
seriesOptions: {
showSymbol: false,
},
tooltip: {
trigger: 'axis' as const,
valueFormatter: value => tooltipFormatter(value, 'p50()'),
},
xAxis: timeframe
? {
min: timeframe.start,
max: timeframe.end,
}
: undefined,
yAxis: {
min: 0,
axisLabel: {
color: theme.chartLabel,
// p50() coerces the axis to be time based
formatter: (value: number) => axisLabelFormatter(value, 'p50()'),
},
},
};

const smoothedSeries = smoothedResults
? smoothedResults.map(values => {
const series = timeseriesData
? timeseriesData
.map(values => {
return {
...values,
color: theme.purple300,
lineStyle: {
opacity: 1,
opacity: 0.75,
width: 1,
},
};
})
: [];

return (
<ReleaseSeries
start={start}
end={end}
queryExtra={queryExtra}
period={statsPeriod}
utc={utc === 'true'}
projects={project}
environments={environment}
>
{({releaseSeries}) => (
<TransitionChart loading={loading} reloading={reloading}>
<TransparentLoadingMask visible={reloading} />
{getDynamicText({
value: (
<LineChart
{...zoomRenderProps}
{...chartOptions}
legend={legend}
onLegendSelectChanged={this.handleLegendSelectChanged}
series={[...series, ...smoothedSeries, ...releaseSeries]}
/>
),
fixed: <Placeholder height="200px" testId="skeleton-ui" />,
})}
</TransitionChart>
)}
</ReleaseSeries>
);
}}
</EventsRequest>
)}
</ChartZoom>
</Fragment>
);
}
.reverse()
: [];

const {smoothedResults} = transformEventStatsSmoothed(
timeseriesData,
t('Smoothed')
);

const smoothedSeries = smoothedResults
? smoothedResults.map(values => {
return {
...values,
color: theme.purple300,
lineStyle: {
opacity: 1,
},
};
})
: [];

return (
<ReleaseSeries
start={start}
end={end}
queryExtra={queryExtra}
period={statsPeriod}
utc={utc === 'true'}
projects={project}
environments={environment}
>
{({releaseSeries}) => (
<TransitionChart loading={loading} reloading={reloading}>
<TransparentLoadingMask visible={reloading} />
{getDynamicText({
value: (
<LineChart
{...zoomRenderProps}
{...chartOptions}
legend={legend}
onLegendSelectChanged={handleLegendSelectChanged}
series={[...series, ...smoothedSeries, ...releaseSeries]}
/>
),
fixed: <Placeholder height="200px" testId="skeleton-ui" />,
})}
</TransitionChart>
)}
</ReleaseSeries>
);
}}
</EventsRequest>
)}
</ChartZoom>
</Fragment>
);
}

export default withApi(withTheme(withRouter(TrendChart)));
export default withRouter(TrendChart);