import * as React from 'react'; import {RouteComponentProps} from 'react-router'; import styled from '@emotion/styled'; import * as Sentry from '@sentry/react'; import NotFound from 'app/components/errors/notFound'; import LoadingError from 'app/components/loadingError'; import LoadingIndicator from 'app/components/loadingIndicator'; import NoProjectMessage from 'app/components/noProjectMessage'; import SentryDocumentTitle from 'app/components/sentryDocumentTitle'; import {t} from 'app/locale'; import {PageContent} from 'app/styles/organization'; import {Organization} from 'app/types'; import withOrganization from 'app/utils/withOrganization'; import TransactionComparisonContent from './content'; import FetchEvent, {ChildrenProps} from './fetchEvent'; type ComparedEventSlugs = { baselineEventSlug: string | undefined; regressionEventSlug: string | undefined; }; type Props = RouteComponentProps< {baselineEventSlug: string; regressionEventSlug: string}, {} > & { organization: Organization; }; class TransactionComparisonPage extends React.PureComponent { getEventSlugs(): ComparedEventSlugs { const {baselineEventSlug, regressionEventSlug} = this.props.params; const validatedBaselineEventSlug = typeof baselineEventSlug === 'string' ? baselineEventSlug.trim() : undefined; const validatedRegressionEventSlug = typeof regressionEventSlug === 'string' ? regressionEventSlug.trim() : undefined; return { baselineEventSlug: validatedBaselineEventSlug, regressionEventSlug: validatedRegressionEventSlug, }; } fetchEvent( eventSlug: string | undefined, renderFunc: (props: ChildrenProps) => React.ReactNode ) { if (!eventSlug) { return ; } const {organization} = this.props; return ( {renderFunc} ); } renderComparison({ baselineEventSlug, regressionEventSlug, }: ComparedEventSlugs): React.ReactNode { return this.fetchEvent(baselineEventSlug, baselineEventResults => { return this.fetchEvent(regressionEventSlug, regressionEventResults => { if (baselineEventResults.isLoading || regressionEventResults.isLoading) { return ; } if (baselineEventResults.error || regressionEventResults.error) { if (baselineEventResults.error) { Sentry.captureException(baselineEventResults.error); } if (regressionEventResults.error) { Sentry.captureException(regressionEventResults.error); } return ; } if (!baselineEventResults.event || !regressionEventResults.event) { return ; } const {organization, location, params} = this.props; return ( ); }); }); } getDocumentTitle({baselineEventSlug, regressionEventSlug}: ComparedEventSlugs): string { if ( typeof baselineEventSlug === 'string' && typeof regressionEventSlug === 'string' ) { const title = t('Comparing %s to %s', baselineEventSlug, regressionEventSlug); return [title, t('Performance')].join(' - '); } return [t('Transaction Comparison'), t('Performance')].join(' - '); } render() { const {organization} = this.props; const {baselineEventSlug, regressionEventSlug} = this.getEventSlugs(); return ( {this.renderComparison({baselineEventSlug, regressionEventSlug})} ); } } const StyledPageContent = styled(PageContent)` padding: 0; `; export default withOrganization(TransactionComparisonPage);