From fc5a2fc9421a71691d3ea199d33f5d99c48625b6 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Tue, 26 Mar 2024 10:57:25 -0400 Subject: [PATCH 1/4] feat: notification user profile link --- src/__mocks__/mockedData.ts | 22 ++++++++++++++++++++++ src/components/NotificationRow.tsx | 13 ++++++++++++- src/typesGithub.ts | 2 ++ src/utils/helpers.ts | 1 + src/utils/subject.ts | 13 ++++++++++--- 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/__mocks__/mockedData.ts b/src/__mocks__/mockedData.ts index 987b26c71..0d74f5190 100644 --- a/src/__mocks__/mockedData.ts +++ b/src/__mocks__/mockedData.ts @@ -299,6 +299,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-20T18:33:39Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [], @@ -309,6 +310,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-21T03:30:42Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [], @@ -319,6 +321,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-21T18:26:27Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [ @@ -327,6 +330,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-23T00:57:58Z', author: { login: 'reply-user', + url: 'https://github.com/reply-user', }, }, ], @@ -337,6 +341,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-23T00:57:49Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [], @@ -347,6 +352,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-27T01:22:20Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [ @@ -355,6 +361,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-05T17:43:52Z', author: { login: 'reply-user', + url: 'https://github.com/reply-user', }, }, ], @@ -365,6 +372,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-04T20:39:44Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [ @@ -373,6 +381,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-05T17:41:04Z', author: { login: 'reply-user', + url: 'https://github.com/reply-user', }, }, ], @@ -383,6 +392,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-05T11:05:42Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [ @@ -391,6 +401,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-05T17:41:44Z', author: { login: 'reply-user', + url: 'https://github.com/reply-user', }, }, ], @@ -412,6 +423,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-20T18:33:39Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [], @@ -422,6 +434,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-21T03:30:42Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [], @@ -432,6 +445,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-21T18:26:27Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [ @@ -440,6 +454,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-23T00:57:58Z', author: { login: 'reply-user', + url: 'https://github.com/reply-user', }, }, ], @@ -450,6 +465,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-23T00:57:49Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [], @@ -460,6 +476,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-02-27T01:22:20Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [ @@ -468,6 +485,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-05T17:43:52Z', author: { login: 'reply-user', + url: 'https://github.com/reply-user', }, }, ], @@ -478,6 +496,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-04T20:39:44Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [ @@ -486,6 +505,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-05T17:41:04Z', author: { login: 'reply-user', + url: 'https://github.com/reply-user', }, }, ], @@ -496,6 +516,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-05T11:05:42Z', author: { login: 'comment-user', + url: 'https://github.com/comment-user', }, replies: { nodes: [ @@ -504,6 +525,7 @@ export const mockedGraphQLResponse: GraphQLSearch = { createdAt: '2022-03-05T17:41:44Z', author: { login: 'reply-user', + url: 'https://github.com/reply-user', }, }, ], diff --git a/src/components/NotificationRow.tsx b/src/components/NotificationRow.tsx index 54a42474d..ae9d19ba0 100644 --- a/src/components/NotificationRow.tsx +++ b/src/components/NotificationRow.tsx @@ -10,6 +10,7 @@ import { import { formatForDisplay, openInBrowser } from '../utils/helpers'; import { Notification } from '../typesGithub'; import { AppContext } from '../context/App'; +import { openExternalLink } from '../utils/comms'; interface IProps { hostname: string; @@ -93,7 +94,17 @@ export const NotificationRow: React.FC = ({
{reason.type} -{' '} - {updatedLabel} + + Updated {updatedAt} + + openExternalLink(notification.subject.user.html_url) + } + > + {updatedBy} + +
diff --git a/src/typesGithub.ts b/src/typesGithub.ts index 2c640ef86..7d9997feb 100644 --- a/src/typesGithub.ts +++ b/src/typesGithub.ts @@ -137,10 +137,12 @@ export interface User { export interface SubjectUser { login: string; + html_url: string; } export interface DiscussionAuthor { login: string; + url: string; } export interface Repository { diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 91d1dd9f3..99a9af042 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -160,6 +160,7 @@ export async function fetchDiscussion( createdAt author { login + url } } diff --git a/src/utils/subject.ts b/src/utils/subject.ts index e651c1c14..bd3377041 100644 --- a/src/utils/subject.ts +++ b/src/utils/subject.ts @@ -10,6 +10,7 @@ import { PullRequest, PullRequestStateType, ReleaseComments, + SubjectUser, User, WorkflowRunAttributes, } from '../typesGithub'; @@ -110,14 +111,17 @@ async function getGitifySubjectForDiscussion( const latestDiscussionComment = getLatestDiscussionComment( discussion.comments.nodes, ); - let discussionUser = null; + let discussionUser: SubjectUser = null; if (latestDiscussionComment) { - discussionUser = latestDiscussionComment.author; + discussionUser = { + login: latestDiscussionComment.author.login, + html_url: latestDiscussionComment.author.url, + }; } return { state: discussionState, - user: discussionUser ?? null, + user: discussionUser, }; } @@ -135,6 +139,7 @@ async function getGitifySubjectForIssue( state: issue.state_reason ?? issue.state, user: { login: issueCommentUser?.login ?? issue.user.login, + html_url: issueCommentUser?.html_url ?? issue.user.html_url, }, }; } @@ -160,6 +165,7 @@ async function getGitifySubjectForPullRequest( state: prState, user: { login: prCommentUser?.login ?? pr.user.login, + html_url: prCommentUser?.html_url ?? pr.user.html_url, }, }; } @@ -174,6 +180,7 @@ async function getGitifySubjectForRelease( state: null, user: { login: releaseCommentUser.login, + html_url: releaseCommentUser.html_url, }, }; } From 91f774c16619c6e0883071f1d04bb6c1fab3d5f6 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 27 Mar 2024 05:30:18 -0400 Subject: [PATCH 2/4] feat: notification user profile link --- src/components/NotificationRow.tsx | 32 ++++++++------- .../NotificationRow.test.tsx.snap | 9 ++-- src/hooks/useNotifications.test.ts | 41 ++++++++++++++++--- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/components/NotificationRow.tsx b/src/components/NotificationRow.tsx index ae9d19ba0..021387c91 100644 --- a/src/components/NotificationRow.tsx +++ b/src/components/NotificationRow.tsx @@ -80,13 +80,11 @@ export const NotificationRow: React.FC = ({ -
pressTitle()} - role="main" - > +
pressTitle()} + role="main" title={notification.subject.title} > {notification.subject.title} @@ -96,14 +94,20 @@ export const NotificationRow: React.FC = ({ {reason.type} -{' '} Updated {updatedAt} - - openExternalLink(notification.subject.user.html_url) - } - > - {updatedBy} - + {notification.subject.user && ( + <> + {' '} + by{' '} + + openExternalLink(notification.subject.user.html_url) + } + > + {notification.subject.user.login} + + + )}
diff --git a/src/components/__snapshots__/NotificationRow.test.tsx.snap b/src/components/__snapshots__/NotificationRow.test.tsx.snap index b671daa41..219fe1bbf 100644 --- a/src/components/__snapshots__/NotificationRow.test.tsx.snap +++ b/src/components/__snapshots__/NotificationRow.test.tsx.snap @@ -36,11 +36,11 @@ exports[`components/NotificationRow.tsx should render itself & its children 1`]
I am a robot and this is a test! @@ -58,7 +58,8 @@ exports[`components/NotificationRow.tsx should render itself & its children 1`] - Updated in over 3 years + Updated + in over 3 years
diff --git a/src/hooks/useNotifications.test.ts b/src/hooks/useNotifications.test.ts index 516b49be4..326df03d7 100644 --- a/src/hooks/useNotifications.test.ts +++ b/src/hooks/useNotifications.test.ts @@ -287,19 +287,50 @@ describe('hooks/useNotifications.ts', () => { nock('https://api.github.com') .get('/3') - .reply(200, { state: 'closed', merged: true }); + .reply(200, { + state: 'closed', + merged: true, + user: { + login: 'some-user', + html_url: 'https://github.com/some-user', + }, + }); nock('https://api.github.com') .get('/3/comments') - .reply(200, { user: { login: 'some-user' } }); + .reply(200, { + user: { + login: 'some-commenter', + html_url: 'https://github.com/some-commenter', + }, + }); nock('https://api.github.com') .get('/4') - .reply(200, { state: 'closed', merged: false }); + .reply(200, { + state: 'closed', + merged: false, + user: { + login: 'some-user', + html_url: 'https://github.com/some-user', + }, + }); nock('https://api.github.com') .get('/4/comments') - .reply(200, { user: { login: 'some-user' } }); + .reply(200, { + user: { + login: 'some-commenter', + html_url: 'https://github.com/some-commenter', + }, + }); nock('https://api.github.com') .get('/5') - .reply(200, { state: 'open', draft: false }); + .reply(200, { + state: 'open', + draft: false, + user: { + login: 'some-commenter', + html_url: 'https://github.com/some-commenter', + }, + }); const { result } = renderHook(() => useNotifications(true)); From 3f7f2b2e8954d1f165159d9f4905fe7d62c95f06 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 27 Mar 2024 05:43:36 -0400 Subject: [PATCH 3/4] feat: notification user profile link --- src/hooks/useNotifications.test.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/hooks/useNotifications.test.ts b/src/hooks/useNotifications.test.ts index 326df03d7..64dbebc9a 100644 --- a/src/hooks/useNotifications.test.ts +++ b/src/hooks/useNotifications.test.ts @@ -321,16 +321,6 @@ describe('hooks/useNotifications.ts', () => { html_url: 'https://github.com/some-commenter', }, }); - nock('https://api.github.com') - .get('/5') - .reply(200, { - state: 'open', - draft: false, - user: { - login: 'some-commenter', - html_url: 'https://github.com/some-commenter', - }, - }); const { result } = renderHook(() => useNotifications(true)); From 844ca458db0f9caaa13d3aa4e2fded20a817d2b9 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Wed, 27 Mar 2024 07:09:14 -0400 Subject: [PATCH 4/4] feat: notification user profile link --- src/components/NotificationRow.test.tsx | 31 +++++++++++++++++++++++++ src/components/NotificationRow.tsx | 3 ++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/components/NotificationRow.test.tsx b/src/components/NotificationRow.test.tsx index 035a77220..047919ee7 100644 --- a/src/components/NotificationRow.test.tsx +++ b/src/components/NotificationRow.test.tsx @@ -8,6 +8,7 @@ import { AppContext } from '../context/App'; import { mockedSingleNotification } from '../__mocks__/mockedData'; import { NotificationRow } from './NotificationRow'; import { mockAccounts, mockSettings } from '../__mocks__/mock-state'; +import { shell } from 'electron'; describe('components/NotificationRow.tsx', () => { beforeEach(() => { @@ -148,4 +149,34 @@ describe('components/NotificationRow.tsx', () => { fireEvent.click(getByLabelText('Unsubscribe')); expect(unsubscribeNotification).toHaveBeenCalledTimes(1); }); + + it('should open notification user profile', () => { + const props = { + notification: { + ...mockedSingleNotification, + subject: { + ...mockedSingleNotification.subject, + user: { + login: 'some-user', + html_url: 'https://github.com/some-user', + }, + }, + }, + hostname: 'github.com', + }; + + const { getByTitle } = render( + + + , + ); + + fireEvent.click(getByTitle('View User Profile')); + expect(shell.openExternal).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/components/NotificationRow.tsx b/src/components/NotificationRow.tsx index 021387c91..d26a31d38 100644 --- a/src/components/NotificationRow.tsx +++ b/src/components/NotificationRow.tsx @@ -83,8 +83,8 @@ export const NotificationRow: React.FC = ({
pressTitle()} role="main" + onClick={() => pressTitle()} title={notification.subject.title} > {notification.subject.title} @@ -100,6 +100,7 @@ export const NotificationRow: React.FC = ({ by{' '} openExternalLink(notification.subject.user.html_url) }