Skip to content

Commit dd1eb7a

Browse files
authored
feat(filters): add catch-all other filter value to all sections (#3354)
* feat(filters): add catch-all `other` filter value to all sections Signed-off-by: Adam Setch <adam.setch@outlook.com> * test(visual): refresh filters baselines for catch-all 'other' option --------- Signed-off-by: Adam Setch <adam.setch@outlook.com>
1 parent 3cbc13d commit dd1eb7a

26 files changed

Lines changed: 1005 additions & 69 deletions
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { renderWithProviders } from '../../__helpers__/test-utils';
2+
import { mockMultipleAccountNotifications } from '../../__mocks__/notifications-mocks';
3+
import { mockAuth } from '../../__mocks__/state-mocks';
4+
5+
import { AccountFilter } from './AccountFilter';
6+
7+
describe('renderer/components/filters/AccountFilter.tsx', () => {
8+
it('should count notifications from the current filtered list per account', () => {
9+
const tree = renderWithProviders(<AccountFilter />, {
10+
accounts: mockAuth.accounts,
11+
notifications: mockMultipleAccountNotifications,
12+
});
13+
14+
const counters = Array.from(
15+
tree.container.querySelectorAll('span.text-gitify-counter-text'),
16+
).map((el) => Number.parseInt(el.textContent ?? '0', 10));
17+
18+
expect(counters.reduce((sum, value) => sum + value, 0)).toBe(
19+
mockMultipleAccountNotifications.reduce(
20+
(sum, account) => sum + account.notifications.length,
21+
0,
22+
),
23+
);
24+
});
25+
});

‎src/renderer/components/filters/FilterSection.test.tsx‎

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import userEvent from '@testing-library/user-event';
44
import { MarkGithubIcon } from '@primer/octicons-react';
55

66
import { renderWithProviders } from '../../__helpers__/test-utils';
7-
import { mockMultipleAccountNotifications } from '../../__mocks__/notifications-mocks';
7+
import {
8+
mockMultipleAccountNotifications,
9+
mockPartialGitifyNotification,
10+
} from '../../__mocks__/notifications-mocks';
811
import { mockSettings } from '../../__mocks__/state-mocks';
912

1013
import { useFiltersStore } from '../../stores';
@@ -116,4 +119,79 @@ describe('renderer/components/filters/FilterSection.tsx', () => {
116119

117120
expect(updateFilterSpy).toHaveBeenCalledWith(mockFilterSetting, 'closed', true);
118121
});
122+
123+
it('should count notifications from the currently filtered list', () => {
124+
const filteredNotifications = [
125+
mockPartialGitifyNotification({ state: 'OPEN' }),
126+
mockPartialGitifyNotification({ state: 'CLOSED' }),
127+
mockPartialGitifyNotification({ state: 'MERGED' }),
128+
].map((notification) => ({
129+
account: notification.account,
130+
notifications: [notification],
131+
error: null,
132+
}));
133+
134+
renderWithProviders(
135+
<FilterSection
136+
filter={mockFilter}
137+
filterSetting={mockFilterSetting}
138+
icon={MarkGithubIcon}
139+
id={'FilterSectionTest'}
140+
title={'FilterSectionTitle'}
141+
/>,
142+
{
143+
settings: {
144+
...mockSettings,
145+
detailedNotifications: true,
146+
},
147+
notifications: filteredNotifications,
148+
},
149+
);
150+
151+
const counters = getCounterValues();
152+
expect(counters.reduce((sum, value) => sum + value, 0)).toBe(3);
153+
});
154+
155+
it('should rescale counts when a filter in another section is toggled', () => {
156+
renderWithProviders(
157+
<FilterSection
158+
filter={mockFilter}
159+
filterSetting={mockFilterSetting}
160+
icon={MarkGithubIcon}
161+
id={'FilterSectionTest'}
162+
title={'FilterSectionTitle'}
163+
/>,
164+
{
165+
settings: {
166+
...mockSettings,
167+
detailedNotifications: true,
168+
},
169+
notifications: [
170+
mockPartialGitifyNotification({ state: 'OPEN' }),
171+
mockPartialGitifyNotification({ state: 'CLOSED' }),
172+
mockPartialGitifyNotification({ state: 'MERGED' }),
173+
].map((notification) => ({
174+
account: notification.account,
175+
notifications: [notification],
176+
error: null,
177+
})),
178+
},
179+
);
180+
181+
const before = getCounterValues();
182+
expect(before.reduce((sum, value) => sum + value, 0)).toBe(3);
183+
184+
act(() => {
185+
useFiltersStore.getState().updateFilter('reasons', 'mention', true);
186+
});
187+
188+
const after = getCounterValues();
189+
expect(after).toEqual(before);
190+
});
191+
192+
function getCounterValues(): number[] {
193+
return Array.from(document.querySelectorAll('span.text-gitify-counter-text')).map((el) =>
194+
Number.parseInt(el.textContent ?? '0', 10),
195+
);
196+
}
119197
});

‎src/renderer/components/filters/FilterSection.tsx‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,19 @@ const FilterSectionComponent = <K extends keyof FiltersState>({
6666

6767
<Stack direction={layout} gap={layout === 'horizontal' ? 'normal' : 'condensed'}>
6868
{(Object.keys(filter.FILTER_TYPES) as FiltersState[K][number][])
69-
.sort((a, b) =>
70-
filter
69+
.sort((a, b) => {
70+
// Always pin the catch-all 'other' option to the end of the list.
71+
if ((a as string) === 'other') {
72+
return 1;
73+
}
74+
if ((b as string) === 'other') {
75+
return -1;
76+
}
77+
return filter
7178
.getTypeDetails(a)
7279
.title.toLowerCase()
73-
.localeCompare(filter.getTypeDetails(b).title.toLowerCase(), 'en'),
74-
)
80+
.localeCompare(filter.getTypeDetails(b).title.toLowerCase(), 'en');
81+
})
7582
.map((type) => {
7683
const typeDetails = filter.getTypeDetails(type);
7784
const typeTitle = typeDetails.title;

‎src/renderer/components/filters/ReviewRequestTypeFilter.tsx‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { FC } from 'react';
22

33
import { GitPullRequestIcon } from '@primer/octicons-react';
4-
import { Text } from '@primer/react';
4+
import { Stack, Text } from '@primer/react';
55

66
import { reviewRequestTypeFilter } from '../../utils/notifications/filters';
77
import { FilterSection } from './FilterSection';
@@ -15,9 +15,16 @@ export const ReviewRequestTypeFilter: FC = () => {
1515
id="filter-review-request-types"
1616
title="Review Request Type"
1717
tooltip={
18-
<Text>
19-
Filter review requests by whether you were directly requested or requested via a team.
20-
</Text>
18+
<Stack direction="vertical" gap="condensed">
19+
<Text>
20+
Filter review requests by whether you were directly requested or requested via a team.
21+
Selecting an option shows only matching review requests.
22+
</Text>
23+
<Text>
24+
Other shows all notifications that are not a review request, such as mentions, comments,
25+
and assigned issues.
26+
</Text>
27+
</Stack>
2128
}
2229
/>
2330
);

‎src/renderer/components/filters/UserTypeFilter.tsx‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ export const UserTypeFilter: FC = () => {
2020
filterSetting="userTypes"
2121
icon={FeedPersonIcon}
2222
id="filter-user-types"
23-
layout="horizontal"
2423
title="User Type"
2524
tooltip={
2625
<Stack direction="vertical" gap="condensed">
@@ -39,8 +38,15 @@ export const UserTypeFilter: FC = () => {
3938
<OrganizationIcon size={Size.SMALL} />
4039
{userTypeFilter.FILTER_TYPES.Organization.title}
4140
</Stack>
41+
<Stack direction="horizontal" gap="condensed">
42+
<PersonIcon size={Size.SMALL} />
43+
{userTypeFilter.FILTER_TYPES.other.title}
44+
</Stack>
4245
</Stack>
4346
</div>
47+
<Text>
48+
Other covers notifications with no author or a non-human, non-organization author.
49+
</Text>
4450
</Stack>
4551
}
4652
/>

‎src/renderer/components/filters/__snapshots__/ReasonFilter.test.tsx.snap‎

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/renderer/components/filters/__snapshots__/ReviewRequestTypeFilter.test.tsx.snap‎

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/renderer/components/filters/__snapshots__/SubjectTypeFilter.test.tsx.snap‎

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)