groupDetailsLayout.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import * as Layout from 'sentry/components/layouts/thirds';
  4. import {space} from 'sentry/styles/space';
  5. import type {Event} from 'sentry/types/event';
  6. import type {Group} from 'sentry/types/group';
  7. import type {Project} from 'sentry/types/project';
  8. import {getConfigForIssueType} from 'sentry/utils/issueTypeConfig';
  9. import theme from 'sentry/utils/theme';
  10. import useMedia from 'sentry/utils/useMedia';
  11. import {useSyncedLocalStorageState} from 'sentry/utils/useSyncedLocalStorageState';
  12. import {EventDetailsHeader} from 'sentry/views/issueDetails/streamline/eventDetailsHeader';
  13. import {IssueEventNavigation} from 'sentry/views/issueDetails/streamline/eventNavigation';
  14. import {useEventQuery} from 'sentry/views/issueDetails/streamline/eventSearch';
  15. import StreamlinedGroupHeader from 'sentry/views/issueDetails/streamline/header';
  16. import StreamlinedSidebar from 'sentry/views/issueDetails/streamline/sidebar';
  17. import {ToggleSidebar} from 'sentry/views/issueDetails/streamline/toggleSidebar';
  18. import type {ReprocessingStatus} from 'sentry/views/issueDetails/utils';
  19. interface GroupDetailsLayoutProps {
  20. children: React.ReactNode;
  21. event: Event | undefined;
  22. group: Group;
  23. groupReprocessingStatus: ReprocessingStatus;
  24. project: Project;
  25. }
  26. export function GroupDetailsLayout({
  27. group,
  28. event,
  29. project,
  30. groupReprocessingStatus,
  31. children,
  32. }: GroupDetailsLayoutProps) {
  33. const searchQuery = useEventQuery({group});
  34. const [sidebarOpen] = useSyncedLocalStorageState('issue-details-sidebar-open', true);
  35. const isScreenSmall = useMedia(`(max-width: ${theme.breakpoints.large})`);
  36. const shouldDisplaySidebar = sidebarOpen || isScreenSmall;
  37. const issueTypeConfig = getConfigForIssueType(group, group.project);
  38. return (
  39. <Fragment>
  40. <StreamlinedGroupHeader
  41. group={group}
  42. event={event ?? null}
  43. project={project}
  44. groupReprocessingStatus={groupReprocessingStatus}
  45. />
  46. <StyledLayoutBody data-test-id="group-event-details" sidebarOpen={sidebarOpen}>
  47. <div>
  48. <EventDetailsHeader event={event} group={group} project={project} />
  49. <GroupContent>
  50. <NavigationSidebarWrapper
  51. hasToggleSidebar={!issueTypeConfig.filterAndSearchHeader.enabled}
  52. >
  53. <IssueEventNavigation event={event} group={group} query={searchQuery} />
  54. {/* Since the event details header is disabled, display the sidebar toggle here */}
  55. {!issueTypeConfig.filterAndSearchHeader.enabled && (
  56. <ToggleSidebar size="sm" />
  57. )}
  58. </NavigationSidebarWrapper>
  59. <ContentPadding>{children}</ContentPadding>
  60. </GroupContent>
  61. </div>
  62. {shouldDisplaySidebar ? (
  63. <StreamlinedSidebar group={group} event={event} project={project} />
  64. ) : null}
  65. </StyledLayoutBody>
  66. </Fragment>
  67. );
  68. }
  69. const StyledLayoutBody = styled(Layout.Body)<{
  70. sidebarOpen: boolean;
  71. }>`
  72. padding: 0 !important;
  73. gap: 0 !important;
  74. @media (min-width: ${p => p.theme.breakpoints.large}) {
  75. align-content: stretch;
  76. grid-template-columns: minmax(100px, auto) ${p => (p.sidebarOpen ? '325px' : '0px')};
  77. }
  78. `;
  79. const GroupContent = styled('section')`
  80. background: ${p => p.theme.backgroundSecondary};
  81. display: flex;
  82. flex-direction: column;
  83. @media (min-width: ${p => p.theme.breakpoints.large}) {
  84. border-right: 1px solid ${p => p.theme.translucentBorder};
  85. }
  86. @media (max-width: ${p => p.theme.breakpoints.large}) {
  87. border-bottom-width: 1px solid ${p => p.theme.translucentBorder};
  88. }
  89. `;
  90. const NavigationSidebarWrapper = styled('div')<{
  91. hasToggleSidebar: boolean;
  92. }>`
  93. position: relative;
  94. display: flex;
  95. padding: ${p =>
  96. p.hasToggleSidebar
  97. ? `${space(1)} 0 ${space(0.5)} ${space(1.5)}`
  98. : `10px ${space(1.5)} ${space(0.25)} ${space(1.5)}`};
  99. `;
  100. const ContentPadding = styled('div')`
  101. min-height: 100vh;
  102. padding: 0 ${space(1.5)} ${space(1.5)} ${space(1.5)};
  103. `;