Skip to content

Commit

Permalink
Domain management: allow bulk-selecting domains (Automattic#80826)
Browse files Browse the repository at this point in the history
* Add the ability to select domains

* Add DomainsTableRow unit tests

* Add DomainsTable unit tests

* Revert test data param change

* Remove DomainsTableRow tests covered by DomainsTable

* Add accessible labels to checkboxes

* Remove display flex from table header on desktop

* Use a set instead of an array to store the selected domains

* Only remove dangling domains from the bulk selection

* Fix type errors on domain header tests

* Revert code style changes on domains-table/style.scss

---------

Co-authored-by: Philip Jackson <p-jackson@live.com>
  • Loading branch information
zaguiini and p-jackson authored Aug 21, 2023
1 parent 96d47d7 commit ae58cbe
Show file tree
Hide file tree
Showing 8 changed files with 328 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import React from 'react';
import { renderWithProvider } from '../../test-utils';
import { DomainsTableColumn, DomainsTableHeader } from '../index';

const noop = jest.fn();

const render = ( el ) =>
renderWithProvider( el, {
wrapper: ( { children } ) => <table>{ children }</table>,
Expand Down Expand Up @@ -33,6 +35,8 @@ test( 'domain columns are rendered in the header', () => {
activeSortKey="domain"
activeSortDirection="asc"
onChangeSortOrder={ jest.fn() }
bulkSelectionStatus="no-domains"
onBulkSelectionChange={ noop }
/>
);

Expand All @@ -56,6 +60,8 @@ test( 'renders custom header component', () => {
activeSortKey="domain"
activeSortDirection="asc"
onChangeSortOrder={ jest.fn() }
bulkSelectionStatus="no-domains"
onBulkSelectionChange={ noop }
/>
);

Expand All @@ -70,6 +76,8 @@ test( 'renders a chevron next to sortable columns', () => {
activeSortKey="domain"
activeSortDirection="asc"
onChangeSortOrder={ jest.fn() }
bulkSelectionStatus="no-domains"
onBulkSelectionChange={ noop }
/>
);

Expand All @@ -87,6 +95,8 @@ test( 'columns that are not sortable do not renders a chevron', () => {
activeSortKey="domain"
activeSortDirection="asc"
onChangeSortOrder={ jest.fn() }
bulkSelectionStatus="no-domains"
onBulkSelectionChange={ noop }
/>
);

Expand Down
19 changes: 18 additions & 1 deletion packages/domains-table/src/domains-table-header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Button } from '@automattic/components';
import { DomainData } from '@automattic/data-stores';
import { Icon } from '@wordpress/components';
import { CheckboxControl, Icon } from '@wordpress/components';
import { chevronDown, chevronUp } from '@wordpress/icons';
import { useI18n } from '@wordpress/react-i18n';
import classNames from 'classnames';
import './style.scss';

export type DomainsTableBulkSelectionStatus = 'no-domains' | 'some-domains' | 'all-domains';

export type DomainsTableColumn =
| {
name: string;
Expand All @@ -30,16 +33,21 @@ type DomainsTableHeaderProps = {
activeSortKey: string;
activeSortDirection: 'asc' | 'desc';
onChangeSortOrder: ( selectedColumn: DomainsTableColumn ) => void;
bulkSelectionStatus: DomainsTableBulkSelectionStatus;
onBulkSelectionChange(): void;
headerClasses?: string;
};

export const DomainsTableHeader = ( {
columns,
activeSortKey,
activeSortDirection,
bulkSelectionStatus,
onBulkSelectionChange,
onChangeSortOrder,
headerClasses,
}: DomainsTableHeaderProps ) => {
const { __ } = useI18n();
const listHeaderClasses = classNames(
'domains-table-header',
'domains-table-header__desktop',
Expand All @@ -64,6 +72,15 @@ export const DomainsTableHeader = ( {
return (
<thead className={ listHeaderClasses }>
<tr>
<th className="domains-table__bulk-action-container">
<CheckboxControl
__nextHasNoMarginBottom
onChange={ onBulkSelectionChange }
indeterminate={ bulkSelectionStatus === 'some-domains' }
checked={ bulkSelectionStatus === 'all-domains' }
aria-label={ __( 'Select all tick boxes for domains in table', __i18n_text_domain__ ) }
/>
</th>
{ columns.map( ( column ) => (
<th key={ column.name }>
<Button
Expand Down
8 changes: 0 additions & 8 deletions packages/domains-table/src/domains-table-header/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
@import "@wordpress/base-styles/colors";

.domains-table-header {
display: flex;
justify-content: space-between;
padding: 8px 0 16px;
font-size: $font-body-small;
font-weight: 500;
Expand All @@ -31,9 +29,6 @@
}
}

&.domains-table-header__desktop {
display: none;
}
&.domains-table-header__mobile {
display: flex;
padding: 16px;
Expand All @@ -50,9 +45,6 @@
}

@include break-large {
&.domains-table-header__desktop {
display: flex;
}
&.domains-table-header__mobile {
display: none;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import React from 'react';
import { renderWithProvider, testDomain, testPartialDomain } from '../../test-utils';
import { DomainsTableRow } from '../domains-table-row';

const noop = jest.fn();

const render = ( el ) =>
renderWithProvider( el, {
wrapper: ( { children } ) => (
Expand All @@ -17,7 +19,12 @@ const render = ( el ) =>

test( 'domain name is rendered in the row', () => {
render(
<DomainsTableRow domain={ testPartialDomain( { domain: 'example1.com' } ) } isAllSitesView />
<DomainsTableRow
domain={ testPartialDomain( { domain: 'example1.com' } ) }
isAllSitesView
isSelected={ false }
onSelect={ noop }
/>
);

expect( screen.queryByText( 'example1.com' ) ).toBeInTheDocument();
Expand All @@ -40,6 +47,8 @@ test( 'wpcom domains do not link to management interface', async () => {
domain={ partialDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView
isSelected={ false }
onSelect={ noop }
/>
);

Expand All @@ -62,6 +71,8 @@ test( 'domain name links to management interface', async () => {
domain={ partialDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView
isSelected={ false }
onSelect={ noop }
/>
);

Expand All @@ -88,6 +99,8 @@ test( 'domain name links to management interface', async () => {
domain={ partialDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView={ false }
isSelected={ false }
onSelect={ noop }
/>
);

Expand Down Expand Up @@ -118,6 +131,8 @@ test( 'non primary domain uses the primary domain as the site slug in its link U
domain={ partialDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView
isSelected={ false }
onSelect={ noop }
/>
);

Expand All @@ -136,6 +151,8 @@ test( 'non primary domain uses the primary domain as the site slug in its link U
domain={ partialDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView={ false }
isSelected={ false }
onSelect={ noop }
/>
);

Expand Down Expand Up @@ -170,6 +187,8 @@ test( 'redirect links use the unmapped domain for the site slug', async () => {
domain={ partialRedirectDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView
isSelected={ false }
onSelect={ noop }
/>
);

Expand All @@ -188,6 +207,8 @@ test( 'redirect links use the unmapped domain for the site slug', async () => {
domain={ partialRedirectDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView={ false }
isSelected={ false }
onSelect={ noop }
/>
);

Expand Down Expand Up @@ -215,6 +236,8 @@ test( 'transfer links use the unmapped domain for the site slug', async () => {
domain={ partialDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView
isSelected={ false }
onSelect={ noop }
/>
);

Expand All @@ -233,6 +256,8 @@ test( 'transfer links use the unmapped domain for the site slug', async () => {
domain={ partialDomain }
fetchSiteDomains={ fetchSiteDomains }
isAllSitesView={ false }
isSelected={ false }
onSelect={ noop }
/>
);

Expand Down
Loading

0 comments on commit ae58cbe

Please sign in to comment.