Skip to content

Commit 4328c7f

Browse files
authored
feat: color coding for PRs and issues (#565)
1 parent a37814a commit 4328c7f

File tree

14 files changed

+255
-27
lines changed

14 files changed

+255
-27
lines changed

src/__mocks__/mock-state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ export const mockSettings: SettingsState = {
1919
markOnClick: false,
2020
openAtStartup: false,
2121
appearance: Appearance.SYSTEM,
22+
colors: false,
2223
};

src/__mocks__/mockedData.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const mockedSingleNotification: Notification = {
2626
url: 'https://api.github.com/repos/manosim/notifications-test/issues/1',
2727
latest_comment_url: 'https://api.github.com/repos/manosim/notifications-test/issues/comments/302888448',
2828
type: 'Issue',
29+
state: 'open',
2930
},
3031
repository: {
3132
id: 57216596,

src/components/NotificationRow.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import React, { useCallback, useContext } from 'react';
22
import { formatDistanceToNow, parseISO } from 'date-fns';
33
import { CheckIcon, MuteIcon } from '@primer/octicons-react';
44

5-
import { formatReason, getNotificationTypeIcon } from '../utils/github-api';
5+
import {
6+
formatReason,
7+
getNotificationTypeIcon,
8+
getNotificationTypeIconColor,
9+
} from '../utils/github-api';
610
import { openInBrowser } from '../utils/helpers';
711
import { Notification } from '../typesGithub';
812
import { AppContext } from '../context/App';
@@ -41,13 +45,17 @@ export const NotificationRow: React.FC<IProps> = ({
4145

4246
const reason = formatReason(notification.reason);
4347
const NotificationIcon = getNotificationTypeIcon(notification.subject.type);
48+
const iconColor = getNotificationTypeIconColor(notification.subject.state);
49+
const realIconColor = settings
50+
? (settings.colors && iconColor) || ''
51+
: iconColor;
4452
const updatedAt = formatDistanceToNow(parseISO(notification.updated_at), {
4553
addSuffix: true,
4654
});
4755

4856
return (
4957
<div className="flex space-x-2 p-2 bg-white dark:bg-gray-dark dark:text-white hover:bg-gray-100 dark:hover:bg-gray-darker border-b border-gray-100 dark:border-gray-darker">
50-
<div className="flex justify-center items-center w-8">
58+
<div className={`flex justify-center items-center w-8 ${realIconColor}`}>
5159
<NotificationIcon size={18} aria-label={notification.subject.type} />
5260
</div>
5361

src/components/__snapshots__/NotificationRow.test.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ exports[`components/Notification.js should render itself & its children 1`] = `
55
className="flex space-x-2 p-2 bg-white dark:bg-gray-dark dark:text-white hover:bg-gray-100 dark:hover:bg-gray-darker border-b border-gray-100 dark:border-gray-darker"
66
>
77
<div
8-
className="flex justify-center items-center w-8"
8+
className="flex justify-center items-center w-8 text-green-500"
99
>
1010
<svg
1111
aria-hidden="false"

src/context/App.test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ describe('context/App.tsx', () => {
253253
participating: true,
254254
playSound: true,
255255
showNotifications: true,
256+
colors: true,
256257
}
257258
);
258259
});
@@ -289,6 +290,7 @@ describe('context/App.tsx', () => {
289290
participating: false,
290291
playSound: true,
291292
showNotifications: true,
293+
colors: true,
292294
}
293295
);
294296
});

src/context/App.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const defaultSettings: SettingsState = {
3737
markOnClick: false,
3838
openAtStartup: false,
3939
appearance: Appearance.SYSTEM,
40+
colors: true,
4041
};
4142

4243
interface AppContextState {
@@ -72,7 +73,7 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
7273
markNotification,
7374
unsubscribeNotification,
7475
markRepoNotifications,
75-
} = useNotifications();
76+
} = useNotifications(settings.colors);
7677

7778
useEffect(() => {
7879
restoreSettings();
@@ -161,6 +162,7 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => {
161162

162163
if (existing.settings) {
163164
setSettings({ ...defaultSettings, ...existing.settings });
165+
return existing.settings;
164166
}
165167
}, []);
166168

src/hooks/useNotifications.test.ts

Lines changed: 107 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe('hooks/useNotifications.ts', () => {
2929
.reply(200, notifications);
3030

3131
const { result, waitForNextUpdate } = renderHook(() =>
32-
useNotifications()
32+
useNotifications(false)
3333
);
3434

3535
act(() => {
@@ -59,7 +59,7 @@ describe('hooks/useNotifications.ts', () => {
5959
.reply(400, { message });
6060

6161
const { result, waitForNextUpdate } = renderHook(() =>
62-
useNotifications()
62+
useNotifications(false)
6363
);
6464

6565
act(() => {
@@ -92,7 +92,7 @@ describe('hooks/useNotifications.ts', () => {
9292
.reply(200, notifications);
9393

9494
const { result, waitForNextUpdate } = renderHook(() =>
95-
useNotifications()
95+
useNotifications(false)
9696
);
9797

9898
act(() => {
@@ -118,7 +118,7 @@ describe('hooks/useNotifications.ts', () => {
118118
.reply(400, { message: 'Oops! Something went wrong.' });
119119

120120
const { result, waitForNextUpdate } = renderHook(() =>
121-
useNotifications()
121+
useNotifications(false)
122122
);
123123

124124
act(() => {
@@ -149,7 +149,7 @@ describe('hooks/useNotifications.ts', () => {
149149
.reply(200, notifications);
150150

151151
const { result, waitForNextUpdate } = renderHook(() =>
152-
useNotifications()
152+
useNotifications(false)
153153
);
154154

155155
act(() => {
@@ -173,7 +173,7 @@ describe('hooks/useNotifications.ts', () => {
173173
.reply(400, { message: 'Oops! Something went wrong.' });
174174

175175
const { result, waitForNextUpdate } = renderHook(() =>
176-
useNotifications()
176+
useNotifications(false)
177177
);
178178

179179
act(() => {
@@ -185,6 +185,95 @@ describe('hooks/useNotifications.ts', () => {
185185
expect(result.current.requestFailed).toBe(true);
186186
});
187187
});
188+
189+
describe('with colors', () => {
190+
it('should fetch notifications with success - with colors', async () => {
191+
const accounts: AuthState = {
192+
...mockAccounts,
193+
enterpriseAccounts: [],
194+
user: mockedUser,
195+
};
196+
197+
const notifications = [
198+
{
199+
id: 1,
200+
title: 'This is a notification.',
201+
subject: { type: 'Issue', url: 'https://api.github.com/1' },
202+
},
203+
{
204+
id: 2,
205+
title: 'A merged PR.',
206+
subject: { type: 'PullRequest', url: 'https://api.github.com/2' },
207+
},
208+
{
209+
id: 3,
210+
title: 'A closed PR.',
211+
subject: { type: 'PullRequest', url: 'https://api.github.com/3' },
212+
},
213+
{
214+
id: 4,
215+
title: 'A draft PR.',
216+
subject: { type: 'PullRequest', url: 'https://api.github.com/4' },
217+
},
218+
{
219+
id: 5,
220+
title: 'A draft PR.',
221+
subject: { type: 'PullRequest', url: 'https://api.github.com/5' },
222+
},
223+
];
224+
225+
nock('https://api.github.com')
226+
.get('/notifications?participating=false')
227+
.reply(200, notifications);
228+
229+
nock('https://api.github.com').get('/1').reply(200, { state: 'open' });
230+
nock('https://api.github.com')
231+
.get('/2')
232+
.reply(200, { state: 'closed', merged: true });
233+
nock('https://api.github.com')
234+
.get('/3')
235+
.reply(200, { state: 'closed', merged: false });
236+
nock('https://api.github.com')
237+
.get('/4')
238+
.reply(200, { state: 'open', draft: false });
239+
nock('https://api.github.com')
240+
.get('/5')
241+
.reply(200, { state: 'open', draft: true });
242+
243+
const { result, waitForNextUpdate } = renderHook(() =>
244+
useNotifications(true)
245+
);
246+
247+
act(() => {
248+
result.current.fetchNotifications(accounts, {
249+
...mockSettings,
250+
colors: true,
251+
});
252+
});
253+
254+
expect(result.current.isFetching).toBe(true);
255+
256+
await waitForNextUpdate();
257+
258+
expect(result.current.notifications[0].hostname).toBe('github.com');
259+
expect(result.current.notifications[0].notifications.length).toBe(5);
260+
expect(
261+
result.current.notifications[0].notifications[0].subject.state
262+
).toBe('open');
263+
expect(
264+
result.current.notifications[0].notifications[1].subject.state
265+
).toBe('merged');
266+
expect(
267+
result.current.notifications[0].notifications[2].subject.state
268+
).toBe('closed');
269+
expect(
270+
result.current.notifications[0].notifications[3].subject.state
271+
).toBe('open');
272+
expect(
273+
result.current.notifications[0].notifications[4].subject.state
274+
).toBe('draft');
275+
});
276+
});
188277
});
189278

190279
describe('markNotification', () => {
@@ -200,7 +289,7 @@ describe('hooks/useNotifications.ts', () => {
200289
.reply(200);
201290

202291
const { result, waitForNextUpdate } = renderHook(() =>
203-
useNotifications()
292+
useNotifications(false)
204293
);
205294

206295
act(() => {
@@ -218,7 +307,7 @@ describe('hooks/useNotifications.ts', () => {
218307
.reply(400);
219308

220309
const { result, waitForNextUpdate } = renderHook(() =>
221-
useNotifications()
310+
useNotifications(false)
222311
);
223312

224313
act(() => {
@@ -241,7 +330,7 @@ describe('hooks/useNotifications.ts', () => {
241330
.reply(200);
242331

243332
const { result, waitForNextUpdate } = renderHook(() =>
244-
useNotifications()
333+
useNotifications(false)
245334
);
246335

247336
act(() => {
@@ -259,7 +348,7 @@ describe('hooks/useNotifications.ts', () => {
259348
.reply(400);
260349

261350
const { result, waitForNextUpdate } = renderHook(() =>
262-
useNotifications()
351+
useNotifications(false)
263352
);
264353

265354
act(() => {
@@ -292,7 +381,7 @@ describe('hooks/useNotifications.ts', () => {
292381
.reply(200);
293382

294383
const { result, waitForValueToChange } = renderHook(() =>
295-
useNotifications()
384+
useNotifications(false)
296385
);
297386

298387
act(() => {
@@ -318,7 +407,7 @@ describe('hooks/useNotifications.ts', () => {
318407
.reply(400);
319408

320409
const { result, waitForValueToChange } = renderHook(() =>
321-
useNotifications()
410+
useNotifications(false)
322411
);
323412

324413
act(() => {
@@ -349,7 +438,7 @@ describe('hooks/useNotifications.ts', () => {
349438
.reply(200);
350439

351440
const { result, waitForValueToChange } = renderHook(() =>
352-
useNotifications()
441+
useNotifications(false)
353442
);
354443

355444
act(() => {
@@ -375,7 +464,7 @@ describe('hooks/useNotifications.ts', () => {
375464
.reply(400);
376465

377466
const { result, waitForValueToChange } = renderHook(() =>
378-
useNotifications()
467+
useNotifications(false)
379468
);
380469

381470
act(() => {
@@ -404,7 +493,7 @@ describe('hooks/useNotifications.ts', () => {
404493
.reply(200);
405494

406495
const { result, waitForNextUpdate } = renderHook(() =>
407-
useNotifications()
496+
useNotifications(false)
408497
);
409498

410499
act(() => {
@@ -422,7 +511,7 @@ describe('hooks/useNotifications.ts', () => {
422511
.reply(400);
423512

424513
const { result, waitForNextUpdate } = renderHook(() =>
425-
useNotifications()
514+
useNotifications(false)
426515
);
427516

428517
act(() => {
@@ -445,7 +534,7 @@ describe('hooks/useNotifications.ts', () => {
445534
.reply(200);
446535

447536
const { result, waitForNextUpdate } = renderHook(() =>
448-
useNotifications()
537+
useNotifications(false)
449538
);
450539

451540
act(() => {
@@ -463,7 +552,7 @@ describe('hooks/useNotifications.ts', () => {
463552
.reply(400);
464553

465554
const { result, waitForNextUpdate } = renderHook(() =>
466-
useNotifications()
555+
useNotifications(false)
467556
);
468557

469558
act(() => {

0 commit comments

Comments
 (0)