Skip to content

Commit 2f2abcb

Browse files
Add filter for deprecated domains (#880)
* Fix page filters styling, by aligning all items to flex-end instead of only the filters clear button being aligned so * Add an optional "mini" field to the page filter config that allows the filter to render in the minimum required size instead of being equally sized like the other page filters * Modify domain listing logic to filter out deleted and invalid domains * Add checkbox filter that shows deprecated domains when toggled
1 parent 1eaae36 commit 2f2abcb

13 files changed

+202
-31
lines changed

src/components/page-filters/page-filters-fields/page-filters-fields.styles.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ export const styled = {
1313
marginBottom: $theme.sizing.scale700,
1414
[$theme.mediaQuery.medium]: {
1515
flexDirection: 'row',
16+
alignItems: 'flex-end',
1617
},
1718
})
1819
),
19-
SearchFilterContainer: createStyled('div', {
20-
flexGrow: 2,
21-
flexBasis: 0,
22-
}),
20+
SearchFilterContainer: createStyled<'div', { $mini: boolean | undefined }>(
21+
'div',
22+
({ $mini }) => ({
23+
flexGrow: $mini ? 0 : 2,
24+
flexBasis: 'fit-content',
25+
})
26+
),
2327
};
2428

2529
export const overrides = {
@@ -31,8 +35,6 @@ export const overrides = {
3135
height: $theme.sizing.scale950,
3236
[$theme.mediaQuery.medium]: {
3337
flexGrow: 0,
34-
alignSelf: 'flex-end',
35-
marginTop: $theme.sizing.scale700,
3638
},
3739
}),
3840
},

src/components/page-filters/page-filters-fields/page-filters-fields.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default function PageFiltersFields<P extends PageQueryParams>({
1818
<styled.SearchFiltersContainer>
1919
{pageFiltersConfig?.map((filter) => {
2020
return (
21-
<styled.SearchFilterContainer key={filter.id}>
21+
<styled.SearchFilterContainer key={filter.id} $mini={filter.mini}>
2222
<filter.component
2323
value={filter.getValue(queryParams)}
2424
setValue={(newValue) =>

src/components/page-filters/page-filters.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export type PageFilterConfig<
2525
keyof V extends string ? keyof V : never
2626
>;
2727
component: React.ComponentType<PageFilterComponentProps<V>>;
28+
mini?: boolean;
2829
};
2930

3031
export type Props<

src/views/domains-page/config/domains-page-filters.config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { type DomainsPageFilterConfig } from '../domains-page-filters/domains-page-filters.types';
22
import DomainsPageFiltersClusterName from '../domains-page-filters-cluster-name/domains-page-filters-cluster-name';
33
import { type DomainsPageFiltersClusterNameValue } from '../domains-page-filters-cluster-name/domains-page-filters-cluster-name.types';
4+
import DomainsPageFilterDeprecated from '../domains-page-filters-deprecated/domains-page-filters-deprecated';
5+
import { type DomainsPageFiltersDeprecatedValue } from '../domains-page-filters-deprecated/domains-page-filters-deprecated.types';
46

57
const domainsPageFiltersConfig: [
68
DomainsPageFilterConfig<DomainsPageFiltersClusterNameValue>,
9+
DomainsPageFilterConfig<DomainsPageFiltersDeprecatedValue>,
710
] = [
811
{
912
id: 'clusterName',
@@ -16,6 +19,21 @@ const domainsPageFiltersConfig: [
1619
formatValue: (v) => v,
1720
component: DomainsPageFiltersClusterName,
1821
},
22+
{
23+
id: 'showDeprecated',
24+
filterFunc: (domain, queryParams) =>
25+
queryParams.showDeprecated
26+
? true
27+
: domain.status === 'DOMAIN_STATUS_REGISTERED',
28+
getValue: (v) => ({ showDeprecated: v.showDeprecated }),
29+
formatValue: (v) => ({
30+
showDeprecated: v.showDeprecated
31+
? v.showDeprecated.toString()
32+
: undefined,
33+
}),
34+
component: DomainsPageFilterDeprecated,
35+
mini: true,
36+
},
1937
] as const;
2038

2139
export default domainsPageFiltersConfig;

src/views/domains-page/config/domains-page-query-params.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const domainsPageQueryParamsConfig: [
66
PageQueryParam<'clusterName', string | undefined>,
77
PageQueryParam<'sortColumn', string | undefined>,
88
PageQueryParam<'sortOrder', SortOrder | undefined>,
9+
PageQueryParam<'showDeprecated', boolean>,
910
] = [
1011
{
1112
key: 'searchText',
@@ -30,6 +31,12 @@ const domainsPageQueryParamsConfig: [
3031
return undefined;
3132
},
3233
},
34+
{
35+
key: 'showDeprecated',
36+
queryParamKey: 'd',
37+
defaultValue: false,
38+
parseValue: (value) => value === 'true',
39+
},
3340
] as const;
3441

3542
export default domainsPageQueryParamsConfig;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { render, screen, userEvent } from '@/test-utils/rtl';
2+
3+
import DomainsPageFilterDeprecated from '../domains-page-filters-deprecated';
4+
import { type DomainsPageFiltersDeprecatedValue } from '../domains-page-filters-deprecated.types';
5+
6+
describe('DomainsPageFilterDeprecated', () => {
7+
beforeEach(() => {
8+
jest.clearAllMocks();
9+
});
10+
11+
it('renders the checkbox with correct label', () => {
12+
setup({ showDeprecated: false });
13+
14+
expect(screen.getByText('Show deprecated domains')).toBeInTheDocument();
15+
});
16+
17+
it('renders checkbox in unchecked state when showDeprecated is false', () => {
18+
setup({ showDeprecated: false });
19+
20+
const checkbox = screen.getByRole('checkbox');
21+
expect(checkbox).not.toBeChecked();
22+
});
23+
24+
it('renders checkbox in checked state when showDeprecated is true', () => {
25+
setup({ showDeprecated: true });
26+
27+
const checkbox = screen.getByRole('checkbox');
28+
expect(checkbox).toBeChecked();
29+
});
30+
31+
it('calls setValue with true when checkbox is checked', async () => {
32+
const { user, mockSetValue } = setup({ showDeprecated: false });
33+
34+
const checkbox = screen.getByRole('checkbox');
35+
await user.click(checkbox);
36+
37+
expect(mockSetValue).toHaveBeenCalledWith({ showDeprecated: true });
38+
});
39+
40+
it('calls setValue with undefined when checkbox is unchecked', async () => {
41+
const { user, mockSetValue } = setup({ showDeprecated: true });
42+
43+
const checkbox = screen.getByRole('checkbox');
44+
await user.click(checkbox);
45+
46+
expect(mockSetValue).toHaveBeenCalledWith({ showDeprecated: undefined });
47+
});
48+
});
49+
50+
function setup(value: DomainsPageFiltersDeprecatedValue) {
51+
const user = userEvent.setup();
52+
const mockSetValue = jest.fn();
53+
54+
const renderResult = render(
55+
<DomainsPageFilterDeprecated value={value} setValue={mockSetValue} />
56+
);
57+
58+
return { ...renderResult, user, mockSetValue };
59+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { type Theme } from 'baseui';
2+
import { type CheckboxOverrides } from 'baseui/checkbox';
3+
import { type StyleObject } from 'styletron-react';
4+
5+
export const overrides = {
6+
checkbox: {
7+
Root: {
8+
style: ({ $theme }: { $theme: Theme }): StyleObject => ({
9+
alignItems: 'center',
10+
gap: $theme.sizing.scale500,
11+
paddingTop: $theme.sizing.scale400,
12+
paddingBottom: $theme.sizing.scale400,
13+
[$theme.mediaQuery.medium]: {
14+
paddingLeft: $theme.sizing.scale300,
15+
paddingRight: $theme.sizing.scale700,
16+
},
17+
}),
18+
},
19+
ToggleTrack: {
20+
style: {
21+
marginTop: 0,
22+
marginBottom: 0,
23+
marginLeft: 0,
24+
marginRight: 0,
25+
},
26+
},
27+
Label: {
28+
style: ({ $theme }: { $theme: Theme }): StyleObject => ({
29+
...$theme.typography.LabelXSmall,
30+
paddingLeft: 0,
31+
}),
32+
},
33+
} satisfies CheckboxOverrides,
34+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Checkbox, STYLE_TYPE, LABEL_PLACEMENT } from 'baseui/checkbox';
2+
3+
import { type PageFilterComponentProps } from '@/components/page-filters/page-filters.types';
4+
5+
import { overrides } from './domains-page-filters-deprecated.styles';
6+
import { type DomainsPageFiltersDeprecatedValue } from './domains-page-filters-deprecated.types';
7+
8+
export default function DomainsPageFilterDeprecated({
9+
value,
10+
setValue,
11+
}: PageFilterComponentProps<DomainsPageFiltersDeprecatedValue>) {
12+
return (
13+
<Checkbox
14+
checkmarkType={STYLE_TYPE.toggle}
15+
labelPlacement={LABEL_PLACEMENT.right}
16+
overrides={overrides.checkbox}
17+
checked={value.showDeprecated}
18+
onChange={(e) =>
19+
setValue({ showDeprecated: e.target.checked || undefined })
20+
}
21+
>
22+
Show deprecated domains
23+
</Checkbox>
24+
);
25+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type DomainsPageFiltersDeprecatedValue = {
2+
showDeprecated: boolean | undefined;
3+
};

src/views/domains-page/helpers/__tests__/filter-domains-irrelevant-to-cluster.test.ts renamed to src/views/domains-page/helpers/__tests__/filter-irrelevant-domains.test.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import { getDomainObj } from '../../__fixtures__/domains';
22
import type { DomainData } from '../../domains-page.types';
3-
import filterDomainsIrrelevantToCluster from '../filter-domains-irrelevant-to-cluster';
3+
import filterIrrelevantDomains from '../filter-irrelevant-domains';
44

5-
describe('filterDomainsIrrelevantToCluster', () => {
6-
it('should return domains relevant to the specified cluster', () => {
7-
// picking few domains data as clusters is the only required
5+
describe(filterIrrelevantDomains.name, () => {
6+
it('should filter out irrelevant domains', () => {
87
const domains = [
98
getDomainObj({
109
id: '1',
1110
name: '1',
1211
clusters: [{ clusterName: 'ClusterA' }],
1312
}),
13+
// Not relevant to the specified cluster
1414
getDomainObj({
1515
id: '1',
1616
name: '2',
@@ -21,14 +21,27 @@ describe('filterDomainsIrrelevantToCluster', () => {
2121
name: '3',
2222
clusters: [{ clusterName: 'ClusterA' }, { clusterName: 'ClusterC' }],
2323
}),
24+
// Deleted/Invalid domains
25+
getDomainObj({
26+
id: '4',
27+
name: '4',
28+
clusters: [{ clusterName: 'ClusterA' }, { clusterName: 'ClusterC' }],
29+
status: 'DOMAIN_STATUS_DELETED',
30+
}),
31+
getDomainObj({
32+
id: '5',
33+
name: '5',
34+
clusters: [{ clusterName: 'ClusterA' }, { clusterName: 'ClusterC' }],
35+
status: 'DOMAIN_STATUS_INVALID',
36+
}),
2437
];
2538

26-
const result = filterDomainsIrrelevantToCluster('ClusterA', domains);
39+
const result = filterIrrelevantDomains('ClusterA', domains);
2740

2841
expect(result).toEqual([domains[0], domains[2]]);
2942
});
3043

31-
it('should return an empty array if no domains are relevant to the specified cluster', () => {
44+
it('should return an empty array if no domains are relevant', () => {
3245
const domains = [
3346
getDomainObj({
3447
id: '1',
@@ -42,25 +55,25 @@ describe('filterDomainsIrrelevantToCluster', () => {
4255
}),
4356
];
4457

45-
const result = filterDomainsIrrelevantToCluster('ClusterA', domains);
58+
const result = filterIrrelevantDomains('ClusterA', domains);
4659

4760
expect(result).toEqual([]);
4861
});
4962

5063
it('should return an empty array if domains array is empty', () => {
5164
const domains: DomainData[] = [];
5265

53-
const result = filterDomainsIrrelevantToCluster('ClusterA', domains);
66+
const result = filterIrrelevantDomains('ClusterA', domains);
5467

5568
expect(result).toEqual([]);
5669
});
5770

5871
it('should handle null or undefined domains array gracefully', () => {
59-
//@ts-expect-error domains comes from backend so testing null behavior
60-
const resultWithNull = filterDomainsIrrelevantToCluster('ClusterA', null);
61-
const resultWithUndefined = filterDomainsIrrelevantToCluster(
72+
// @ts-expect-error domains come from backend so testing null behavior
73+
const resultWithNull = filterIrrelevantDomains('ClusterA', null);
74+
const resultWithUndefined = filterIrrelevantDomains(
6275
'ClusterA',
63-
//@ts-expect-error domains comes from backend so testing undefined behavior
76+
// @ts-expect-error domains come from backend so testing undefined behavior
6477
undefined
6578
);
6679

0 commit comments

Comments
 (0)