groupDetailsLayout.tsx 3.9 KB

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