sidebar.tsx 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import {Fragment, useMemo} from 'react';
  2. import styled from '@emotion/styled';
  3. import ErrorBoundary from 'sentry/components/errorBoundary';
  4. import {StreamlinedExternalIssueList} from 'sentry/components/group/externalIssuesList/streamlinedExternalIssueList';
  5. import * as Layout from 'sentry/components/layouts/thirds';
  6. import * as SidebarSection from 'sentry/components/sidebarSection';
  7. import {space} from 'sentry/styles/space';
  8. import type {Event} from 'sentry/types/event';
  9. import type {Group, TeamParticipant, UserParticipant} from 'sentry/types/group';
  10. import type {Project} from 'sentry/types/project';
  11. import {useUser} from 'sentry/utils/useUser';
  12. import StreamlinedActivitySection from 'sentry/views/issueDetails/streamline/activitySection';
  13. import FirstLastSeenSection from 'sentry/views/issueDetails/streamline/firstLastSeenSection';
  14. import PeopleSection from 'sentry/views/issueDetails/streamline/peopleSection';
  15. import {MergedIssuesSidebarSection} from 'sentry/views/issueDetails/streamline/sidebar/mergedSidebarSection';
  16. import {SimilarIssuesSidebarSection} from 'sentry/views/issueDetails/streamline/sidebar/similarIssuesSidebarSection';
  17. import SolutionsSection from 'sentry/views/issueDetails/streamline/solutionsSection';
  18. type Props = {
  19. group: Group;
  20. project: Project;
  21. event?: Event;
  22. };
  23. export default function StreamlinedSidebar({group, event, project}: Props) {
  24. const activeUser = useUser();
  25. const {userParticipants, teamParticipants, viewers} = useMemo(() => {
  26. return {
  27. userParticipants: group.participants.filter(
  28. (p): p is UserParticipant => p.type === 'user'
  29. ),
  30. teamParticipants: group.participants.filter(
  31. (p): p is TeamParticipant => p.type === 'team'
  32. ),
  33. viewers: group.seenBy.filter(user => activeUser.id !== user.id),
  34. };
  35. }, [group, activeUser.id]);
  36. const showPeopleSection = group.participants.length > 0 || viewers.length > 0;
  37. return (
  38. <Side>
  39. <SolutionsSection group={group} project={project} event={event} />
  40. <StyledBreak />
  41. <FirstLastSeenSection group={group} />
  42. <StyledBreak />
  43. {event && (
  44. <ErrorBoundary mini>
  45. <StreamlinedExternalIssueList group={group} event={event} project={project} />
  46. <StyledBreak style={{marginBottom: space(0.5)}} />
  47. </ErrorBoundary>
  48. )}
  49. <StreamlinedActivitySection group={group} />
  50. {showPeopleSection && (
  51. <Fragment>
  52. <StyledBreak />
  53. <PeopleSection
  54. userParticipants={userParticipants}
  55. teamParticipants={teamParticipants}
  56. viewers={viewers}
  57. />
  58. </Fragment>
  59. )}
  60. <StyledBreak />
  61. <SimilarIssuesSidebarSection />
  62. <StyledBreak />
  63. <MergedIssuesSidebarSection />
  64. </Side>
  65. );
  66. }
  67. const StyledBreak = styled('hr')`
  68. margin-top: ${space(1.5)};
  69. margin-bottom: ${space(1.5)};
  70. border-color: ${p => p.theme.border};
  71. `;
  72. export const SidebarSectionTitle = styled(SidebarSection.Title)`
  73. margin-bottom: ${space(1)};
  74. color: ${p => p.theme.headingColor};
  75. `;
  76. const Side = styled(Layout.Side)`
  77. position: relative;
  78. padding: ${space(1.5)} ${space(2)};
  79. `;