Skip to content

Commit

Permalink
feat(issue-details): Add people section to sidebar (#79609)
Browse files Browse the repository at this point in the history
this pr removes participants/viewers from the header and moves them into
their own section in the sidebar
![Screenshot 2024-10-23 at 9 50
05 AM](https://github.com/user-attachments/assets/6737bd6c-4450-4cc4-920a-7c89629f62f8)
  • Loading branch information
roggenkemper authored Oct 23, 2024
1 parent c5ee901 commit 5355d93
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 61 deletions.
33 changes: 1 addition & 32 deletions static/app/views/issueDetails/streamline/header.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import {OrganizationFixture} from 'sentry-fixture/organization';
import {ProjectFixture} from 'sentry-fixture/project';
import {RouterFixture} from 'sentry-fixture/routerFixture';
import {TeamFixture} from 'sentry-fixture/team';
import {UserFixture} from 'sentry-fixture/user';

import {render, screen} from 'sentry-test/reactTestingLibrary';

import type {TeamParticipant, UserParticipant} from 'sentry/types/group';
import {IssueCategory} from 'sentry/types/group';
import {formatAbbreviatedNumber} from 'sentry/utils/formatters';
import StreamlinedGroupHeader from 'sentry/views/issueDetails/streamline/header';
Expand Down Expand Up @@ -56,36 +54,10 @@ describe('StreamlinedGroupHeader', () => {
});

it('shows all elements of header', async () => {
const teams: TeamParticipant[] = [{...TeamFixture(), type: 'team'}];
const users: UserParticipant[] = [
{
...UserFixture({
id: '2',
name: 'John Smith',
email: '[email protected]',
}),
type: 'user',
},
{
...UserFixture({
id: '3',
name: 'Sohn Jmith',
email: '[email protected]',
}),
type: 'user',
},
];

const participantGroup = {
...group,
participants: [...teams, ...users],
seenBy: users,
};

render(
<StreamlinedGroupHeader
{...defaultProps}
group={participantGroup}
group={group}
project={project}
event={null}
/>,
Expand All @@ -110,9 +82,6 @@ describe('StreamlinedGroupHeader', () => {
screen.getByRole('button', {name: 'Modify issue assignee'})
).toBeInTheDocument();

expect(screen.getByText('Participants')).toBeInTheDocument();
expect(screen.getByText('Viewers')).toBeInTheDocument();

expect(
screen.queryByRole('button', {name: 'Switch to the old issue experience'})
).not.toBeInTheDocument();
Expand Down
31 changes: 2 additions & 29 deletions static/app/views/issueDetails/streamline/header.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Fragment, useMemo} from 'react';
import {Fragment} from 'react';
import styled from '@emotion/styled';
import Color from 'color';

Expand All @@ -8,20 +8,18 @@ import {Flex} from 'sentry/components/container/flex';
import Count from 'sentry/components/count';
import ErrorLevel from 'sentry/components/events/errorLevel';
import UnhandledTag from 'sentry/components/group/inboxBadges/unhandledTag';
import ParticipantList from 'sentry/components/group/streamlinedParticipantList';
import Link from 'sentry/components/links/link';
import {Tooltip} from 'sentry/components/tooltip';
import {IconChevron, IconPanel} from 'sentry/icons';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {Event} from 'sentry/types/event';
import type {Group, TeamParticipant, UserParticipant} from 'sentry/types/group';
import type {Group} from 'sentry/types/group';
import type {Project} from 'sentry/types/project';
import {getMessage, getTitle} from 'sentry/utils/events';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import {useSyncedLocalStorageState} from 'sentry/utils/useSyncedLocalStorageState';
import {useUser} from 'sentry/utils/useUser';
import GroupActions from 'sentry/views/issueDetails/actions/index';
import {NewIssueExperienceButton} from 'sentry/views/issueDetails/actions/newIssueExperienceButton';
import {Divider} from 'sentry/views/issueDetails/divider';
Expand All @@ -47,7 +45,6 @@ export default function StreamlinedGroupHeader({
groupReprocessingStatus,
project,
}: GroupHeaderProps) {
const activeUser = useUser();
const location = useLocation();
const organization = useOrganization();
const {baseUrl} = useGroupDetailsRoute();
Expand All @@ -65,18 +62,6 @@ export default function StreamlinedGroupHeader({
true
);

const {userParticipants, teamParticipants, displayUsers} = useMemo(() => {
return {
userParticipants: group.participants.filter(
(p): p is UserParticipant => p.type === 'user'
),
teamParticipants: group.participants.filter(
(p): p is TeamParticipant => p.type === 'team'
),
displayUsers: group.seenBy.filter(user => activeUser.id !== user.id),
};
}, [group, activeUser.id]);

return (
<Fragment>
<Header>
Expand Down Expand Up @@ -163,18 +148,6 @@ export default function StreamlinedGroupHeader({
{t('Assignee')}
<GroupHeaderAssigneeSelector group={group} project={project} event={event} />
</Workflow>
{group.participants.length > 0 && (
<Workflow>
{t('Participants')}
<ParticipantList users={userParticipants} teams={teamParticipants} />
</Workflow>
)}
{displayUsers.length > 0 && (
<Workflow>
{t('Viewers')}
<ParticipantList users={displayUsers} />
</Workflow>
)}
<SidebarButton
icon={
sidebarOpen ? (
Expand Down
52 changes: 52 additions & 0 deletions static/app/views/issueDetails/streamline/peopleSection.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {GroupFixture} from 'sentry-fixture/group';
import {TeamFixture} from 'sentry-fixture/team';
import {UserFixture} from 'sentry-fixture/user';

import {render, screen} from 'sentry-test/reactTestingLibrary';

import type {TeamParticipant, UserParticipant} from 'sentry/types/group';
import PeopleSection from 'sentry/views/issueDetails/streamline/peopleSection';

describe('PeopleSection', () => {
const group = GroupFixture();

it('displays participants and viewers', async () => {
const teams: TeamParticipant[] = [{...TeamFixture(), type: 'team'}];
const users: UserParticipant[] = [
{
...UserFixture({
id: '2',
name: 'John Smith',
email: '[email protected]',
}),
type: 'user',
},
{
...UserFixture({
id: '3',
name: 'Sohn Jmith',
email: '[email protected]',
}),
type: 'user',
},
];

const participantGroup = {
...group,
participants: [...teams, ...users],
seenBy: users,
};

render(<PeopleSection group={participantGroup} />);

expect(await screen.findByText('participating')).toBeInTheDocument();
expect(await screen.findByText('viewed')).toBeInTheDocument();
});

it('does not display anything if there are no participants or viewers', () => {
render(<PeopleSection group={group} />);

expect(screen.queryByText('participating')).not.toBeInTheDocument();
expect(screen.queryByText('viewed')).not.toBeInTheDocument();
});
});
49 changes: 49 additions & 0 deletions static/app/views/issueDetails/streamline/peopleSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {useMemo} from 'react';

import {Flex} from 'sentry/components/container/flex';
import ParticipantList from 'sentry/components/group/streamlinedParticipantList';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {Group, TeamParticipant, UserParticipant} from 'sentry/types/group';
import {useUser} from 'sentry/utils/useUser';
import {SidebarSectionTitle} from 'sentry/views/issueDetails/streamline/sidebar';

export default function PeopleSection({group}: {group: Group}) {
const activeUser = useUser();
const {userParticipants, teamParticipants, viewers} = useMemo(() => {
return {
userParticipants: group.participants.filter(
(p): p is UserParticipant => p.type === 'user'
),
teamParticipants: group.participants.filter(
(p): p is TeamParticipant => p.type === 'team'
),
viewers: group.seenBy.filter(user => activeUser.id !== user.id),
};
}, [group, activeUser.id]);

const hasParticipants = group.participants.length > 0;
const hasViewers = viewers.length > 0;

if (!hasParticipants && !hasViewers) {
return null;
}

return (
<div>
<SidebarSectionTitle>{t('People')}</SidebarSectionTitle>
{hasParticipants && (
<Flex gap={space(0.5)} align="center">
<ParticipantList users={userParticipants} teams={teamParticipants} />
{t('participating')}
</Flex>
)}
{hasViewers && (
<Flex gap={space(0.5)} align="center">
<ParticipantList users={viewers} />
{t('viewed')}
</Flex>
)}
</div>
);
}
9 changes: 9 additions & 0 deletions static/app/views/issueDetails/streamline/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import styled from '@emotion/styled';

import ErrorBoundary from 'sentry/components/errorBoundary';
import {StreamlinedExternalIssueList} from 'sentry/components/group/externalIssuesList/streamlinedExternalIssueList';
import * as SidebarSection from 'sentry/components/sidebarSection';
import {space} from 'sentry/styles/space';
import type {Event} from 'sentry/types/event';
import type {Group} from 'sentry/types/group';
import type {Project} from 'sentry/types/project';
import StreamlinedActivitySection from 'sentry/views/issueDetails/streamline/activitySection';
import FirstLastSeenSection from 'sentry/views/issueDetails/streamline/firstLastSeenSection';
import PeopleSection from 'sentry/views/issueDetails/streamline/peopleSection';

type Props = {
group: Group;
Expand All @@ -27,6 +29,8 @@ export default function StreamlinedSidebar({group, event, project}: Props) {
</ErrorBoundary>
)}
<StreamlinedActivitySection group={group} />
<StyledBreak />
<PeopleSection group={group} />
</div>
);
}
Expand All @@ -36,3 +40,8 @@ const StyledBreak = styled('hr')`
margin-bottom: ${space(1.5)};
border-color: ${p => p.theme.border};
`;

export const SidebarSectionTitle = styled(SidebarSection.Title)`
margin-bottom: ${space(1)};
color: ${p => p.theme.headingColor};
`;

0 comments on commit 5355d93

Please sign in to comment.