details.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import {Fragment} from 'react';
  2. import DetailedError from 'sentry/components/errors/detailedError';
  3. import NotFound from 'sentry/components/errors/notFound';
  4. import {
  5. Provider as ReplayContextProvider,
  6. useReplayContext,
  7. } from 'sentry/components/replays/replayContext';
  8. import {t} from 'sentry/locale';
  9. import {PageContent} from 'sentry/styles/organization';
  10. import useReplayData from 'sentry/utils/replays/hooks/useReplayData';
  11. import useUrlParam from 'sentry/utils/replays/hooks/useUrlParams';
  12. import {useRouteContext} from 'sentry/utils/useRouteContext';
  13. import Layout from 'sentry/views/replays/detail/layout';
  14. import Page from 'sentry/views/replays/detail/page';
  15. const LAYOUT_NAMES = ['topbar', 'sidebar_right', 'sidebar_left'];
  16. function ReplayDetails() {
  17. const {
  18. location,
  19. params: {eventSlug, orgId},
  20. } = useRouteContext();
  21. const {
  22. t: initialTimeOffset, // Time, in seconds, where the video should start
  23. } = location.query;
  24. const {fetching, onRetry, replay} = useReplayData({
  25. eventSlug,
  26. orgId,
  27. });
  28. if (!fetching && !replay) {
  29. return (
  30. <Page orgId={orgId}>
  31. <PageContent>
  32. <NotFound />
  33. </PageContent>
  34. </Page>
  35. );
  36. }
  37. if (!fetching && replay && replay.getRRWebEvents().length < 2) {
  38. return (
  39. <Page orgId={orgId} event={replay.getEvent()}>
  40. <DetailedError
  41. onRetry={onRetry}
  42. hideSupportLinks
  43. heading={t('Expected two or more replay events')}
  44. message={
  45. <Fragment>
  46. <p>{t('This Replay may not have captured any user actions.')}</p>
  47. <p>
  48. {t(
  49. 'Or there may be an issue loading the actions from the server, click to try loading the Replay again.'
  50. )}
  51. </p>
  52. </Fragment>
  53. }
  54. />
  55. </Page>
  56. );
  57. }
  58. return (
  59. <ReplayContextProvider replay={replay} initialTimeOffset={initialTimeOffset}>
  60. <LoadedDetails orgId={orgId} />
  61. </ReplayContextProvider>
  62. );
  63. }
  64. function LoadedDetails({orgId}: {orgId: string}) {
  65. const {getParamValue} = useUrlParam('l_page', 'topbar');
  66. const {duration, replay} = useReplayContext();
  67. return (
  68. <Page
  69. orgId={orgId}
  70. crumbs={replay?.getRawCrumbs()}
  71. duration={duration}
  72. event={replay?.getEvent()}
  73. >
  74. <Layout
  75. layout={
  76. // TODO(replay): If we end up keeping this, we'll fix up the typing
  77. LAYOUT_NAMES.includes(getParamValue()) ? (getParamValue() as any) : 'topbar'
  78. }
  79. />
  80. </Page>
  81. );
  82. }
  83. export default ReplayDetails;