index.tsx 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import {RouteComponentProps} from 'react-router';
  2. import Feature from 'sentry/components/acl/feature';
  3. import * as Layout from 'sentry/components/layouts/thirds';
  4. import NoProjectMessage from 'sentry/components/noProjectMessage';
  5. import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
  6. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  7. import {t} from 'sentry/locale';
  8. import {defined} from 'sentry/utils';
  9. import {decodeScalar} from 'sentry/utils/queryString';
  10. import useOrganization from 'sentry/utils/useOrganization';
  11. import useProjects from 'sentry/utils/useProjects';
  12. import {getTransactionName} from '../../../utils';
  13. import {NoAccess, redirectToPerformanceHomepage} from '../../pageLayout';
  14. import {generateSpansEventView, parseSpanSlug} from '../utils';
  15. import SpanDetailsContent from './content';
  16. type Props = Pick<RouteComponentProps<{spanSlug: string}, {}>, 'location' | 'params'>;
  17. export default function SpanDetails(props: Props) {
  18. const {location, params} = props;
  19. const transactionName = getTransactionName(location);
  20. const spanSlug = parseSpanSlug(params.spanSlug);
  21. const organization = useOrganization();
  22. const {projects} = useProjects();
  23. const projectId = decodeScalar(location.query.project);
  24. if (!defined(projectId) || !defined(transactionName) || !defined(spanSlug)) {
  25. redirectToPerformanceHomepage(organization, location);
  26. return null;
  27. }
  28. const project = projects.find(p => p.id === projectId);
  29. const eventView = generateSpansEventView({
  30. location,
  31. transactionName,
  32. });
  33. return (
  34. <SentryDocumentTitle
  35. title={getDocumentTitle(transactionName)}
  36. orgSlug={organization.slug}
  37. projectSlug={project?.slug}
  38. >
  39. <Feature
  40. features={['performance-view']}
  41. organization={organization}
  42. renderDisabled={NoAccess}
  43. >
  44. <PageFiltersContainer
  45. shouldForceProject={defined(project)}
  46. forceProject={project}
  47. specificProjectSlugs={defined(project) ? [project.slug] : []}
  48. >
  49. <Layout.Page>
  50. <NoProjectMessage organization={organization}>
  51. <SpanDetailsContent
  52. location={location}
  53. organization={organization}
  54. eventView={eventView}
  55. project={project}
  56. transactionName={transactionName}
  57. spanSlug={spanSlug}
  58. />
  59. </NoProjectMessage>
  60. </Layout.Page>
  61. </PageFiltersContainer>
  62. </Feature>
  63. </SentryDocumentTitle>
  64. );
  65. }
  66. function getDocumentTitle(transactionName: string): string {
  67. const hasTransactionName =
  68. typeof transactionName === 'string' && String(transactionName).trim().length > 0;
  69. if (hasTransactionName) {
  70. return [String(transactionName).trim(), t('Performance')].join(' - ');
  71. }
  72. return [t('Summary'), t('Performance')].join(' - ');
  73. }