index.tsx 2.7 KB

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