groupDetailsLayout.tsx 3.9 KB

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