Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 3 additions & 38 deletions src/components/NotificationRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
CommentIcon,
FeedPersonIcon,
IssueClosedIcon,
MarkGithubIcon,
MilestoneIcon,
ReadIcon,
TagIcon,
Expand All @@ -29,16 +28,13 @@ import {
getNotificationTypeIconColor,
getPullRequestReviewIcon,
} from '../utils/icons';
import {
openNotification,
openRepository,
openUserProfile,
} from '../utils/links';
import { openNotification, openUserProfile } from '../utils/links';
import { formatReason } from '../utils/reason';
import { HoverGroup } from './HoverGroup';
import { InteractionButton } from './buttons/InteractionButton';
import { PillButton } from './buttons/PillButton';
import { AvatarIcon } from './icons/AvatarIcon';
import { NotificationHeader } from './notification/NotificationHeader';

interface INotificationRow {
notification: Notification;
Expand Down Expand Up @@ -108,9 +104,6 @@ export const NotificationRow: FC<INotificationRow> = ({
notification.subject.linkedIssues?.length > 1 ? 'issues' : 'issue'
} ${notification.subject?.linkedIssues?.join(', ')}`;

const repoAvatarUrl = notification.repository.owner.avatar_url;
const repoSlug = notification.repository.full_name;

const groupByDate = settings.groupBy === 'DATE';

return (
Expand All @@ -137,35 +130,7 @@ export const NotificationRow: FC<INotificationRow> = ({
className="flex-1 overflow-hidden overflow-ellipsis whitespace-nowrap cursor-pointer"
onClick={() => handleNotification()}
>
{groupByDate && (
<div
className={cn(
'mb-1 flex items-center gap-1 text-xs font-medium',
Opacity.MEDIUM,
)}
title={repoSlug}
>
<span>
<AvatarIcon
title={repoSlug}
url={repoAvatarUrl}
size={Size.SMALL}
defaultIcon={MarkGithubIcon}
/>
</span>
<span
title={repoSlug}
className="cursor-pointer truncate opacity-90"
onClick={(event: MouseEvent<HTMLElement>) => {
// Don't trigger onClick of parent element.
event.stopPropagation();
openRepository(notification.repository);
}}
>
{repoSlug}
</span>
</div>
)}
<NotificationHeader notification={notification} />

<div
className="mb-1 truncate text-sm"
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions src/components/__snapshots__/NotificationRow.test.tsx.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions src/components/notification/NotificationHeader.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { mockSettings } from '../../__mocks__/state-mocks';
import { AppContext } from '../../context/App';
import { GroupBy } from '../../types';
import { mockSingleNotification } from '../../utils/api/__mocks__/response-mocks';
import * as comms from '../../utils/comms';
import { NotificationHeader } from './NotificationHeader';

describe('components/notification/NotificationHeader.tsx', () => {
it('should render itself & its children - group by repositories', async () => {
const props = {
notification: mockSingleNotification,
};

const tree = render(
<AppContext.Provider
value={{ settings: { ...mockSettings, groupBy: GroupBy.REPOSITORY } }}
>
<NotificationHeader {...props} />
</AppContext.Provider>,
);
expect(tree).toMatchSnapshot();
});

it('should render itself & its children - group by date', async () => {
const props = {
notification: mockSingleNotification,
};

const tree = render(
<AppContext.Provider
value={{ settings: { ...mockSettings, groupBy: GroupBy.DATE } }}
>
<NotificationHeader {...props} />
</AppContext.Provider>,
);
expect(tree).toMatchSnapshot();
});

it('should open notification user profile - group by date', () => {
const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink');

const props = {
notification: mockSingleNotification,
};

render(
<AppContext.Provider
value={{ settings: { ...mockSettings, groupBy: GroupBy.DATE } }}
>
<NotificationHeader {...props} />
</AppContext.Provider>,
);

fireEvent.click(screen.getByTitle(props.notification.repository.full_name));
expect(openExternalLinkMock).toHaveBeenCalledTimes(1);
expect(openExternalLinkMock).toHaveBeenCalledWith(
props.notification.repository.html_url,
);
});
});
54 changes: 54 additions & 0 deletions src/components/notification/NotificationHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { MarkGithubIcon } from '@primer/octicons-react';
import { type FC, type MouseEvent, useContext } from 'react';
import { AppContext } from '../../context/App';
import { Opacity, Size } from '../../types';
import type { Notification } from '../../typesGitHub';
import { cn } from '../../utils/cn';
import { openRepository } from '../../utils/links';
import { AvatarIcon } from '../icons/AvatarIcon';

interface INotificationHeader {
notification: Notification;
}

export const NotificationHeader: FC<INotificationHeader> = ({
notification,
}: INotificationHeader) => {
const { settings } = useContext(AppContext);

const repoAvatarUrl = notification.repository.owner.avatar_url;
const repoSlug = notification.repository.full_name;

const groupByDate = settings.groupBy === 'DATE';

return (
groupByDate && (
<div
className={cn(
'mb-1 flex items-center gap-1 text-xs font-medium',
Opacity.MEDIUM,
)}
>
<span>
<AvatarIcon
title={repoSlug}
url={repoAvatarUrl}
size={Size.SMALL}
defaultIcon={MarkGithubIcon}
/>
</span>
<span
title={repoSlug}
className="cursor-pointer truncate opacity-90"
onClick={(event: MouseEvent<HTMLElement>) => {
// Don't trigger onClick of parent element.
event.stopPropagation();
openRepository(notification.repository);
}}
>
{repoSlug}
</span>
</div>
)
);
};
Loading