Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataViews: implement multiple selection in filters #56468

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/edit-site/src/components/dataviews/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ Example:
- `enableSorting`: whether the data can be sorted by the given field. True by default.
- `enableHiding`: whether the field can be hidden. True by default.

TODO: how to disable multiselection?

## Actions

Array of operations that can be performed upon each record. Each action is an object with the following properties:
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-site/src/components/dataviews/add-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export default function AddFilter( { fields, view, onChangeView } ) {
{
field: filter.field,
operator: OPERATOR_IN,
value: element.value,
value: [ element.value ],
},
],
} ) );
Expand Down
54 changes: 35 additions & 19 deletions packages/edit-site/src/components/dataviews/in-filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,30 @@ const {

export default ( { filter, view, onChangeView } ) => {
const filterInView = view.filters.find( ( f ) => f.field === filter.field );
const activeElement = filter.elements.find(
( element ) => element.value === filterInView?.value
);
const activeElementLabels = filter.elements
.filter( ( element ) => filterInView?.value?.includes( element.value ) )
.map( ( element ) => element.label );

return (
<DropdownMenu
key={ filter.field }
trigger={
<Button variant="tertiary" size="compact" label={ filter.name }>
{ activeElement !== undefined
? sprintf(
/* translators: 1: Filter name. 2: filter value. e.g.: "Author is Admin". */
__( '%1$s is %2$s' ),
filter.name,
activeElement.label
)
: filter.name }
{ activeElementLabels.length === 0 && filter.name }
{ activeElementLabels.length === 1 &&
sprintf(
/* translators: 1: Filter name. 2: filter value. e.g.: "Author is Admin". */
__( '%1$s is %2$s' ),
filter.name,
activeElementLabels[ 0 ]
) }
{ activeElementLabels.length > 1 &&
sprintf(
/* translators: 1: Filter name. 2: filter value. e.g.: "Author in Admin, Editor". */
__( '%1$s in %2$s' ),
filter.name,
activeElementLabels.join( ',' )
) }
<Icon icon={ chevronDown } style={ { flexShrink: 0 } } />
</Button>
}
Expand All @@ -48,8 +55,11 @@ export default ( { filter, view, onChangeView } ) => {
<DropdownMenuCheckboxItem
key={ element.value }
value={ element.value }
checked={ activeElement?.value === element.value }
onSelect={ () =>
checked={ activeElementLabels.includes(
element.label
) }
onSelect={ ( event ) => {
event.preventDefault();
onChangeView( ( currentView ) => ( {
...currentView,
page: 1,
Expand All @@ -60,15 +70,21 @@ export default ( { filter, view, onChangeView } ) => {
{
field: filter.field,
operator: OPERATOR_IN,
value:
activeElement?.value ===
value: filterInView.value.includes(
element.value
? undefined
: element.value,
)
? filterInView.value.filter(
( value ) =>
value !== element.value
)
: [
...filterInView.value,
element.value,
],
},
],
} ) )
}
} ) );
} }
>
{ element.label }
</DropdownMenuCheckboxItem>
Expand Down
23 changes: 20 additions & 3 deletions packages/edit-site/src/components/dataviews/view-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,11 @@ function HeaderMenu( { dataView, header } ) {
Object.values( columnFilter )[ 0 ];
// Intentionally use loose comparison, so it does type conversion.
// This covers the case where a top-level filter for the same field converts a number into a string.
isActive = element.value == value; // eslint-disable-line eqeqeq
/* eslint-disable eqeqeq */
isActive = value.some(
( v ) => element.value == v
);
/* eslint-enable eqeqeq */
}

return (
Expand Down Expand Up @@ -193,14 +197,27 @@ function HeaderMenu( { dataView, header } ) {
);
}
);
const currentValues =
( columnFilter &&
Object.values(
columnFilter
)[ 0 ] ) ||
[];

dataView.setColumnFilters( [
...otherFilters,
{
[ filter.field + ':in' ]:
isActive
? undefined
: element.value,
? currentValues.filter(
( v ) =>
v !==
element.value
)
: [
...currentValues,
element.value,
],
},
] );
} }
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-site/src/components/page-pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export default function PagePages() {
filter.field === 'status' &&
filter.operator === OPERATOR_IN
) {
filters.status = filter.value;
filters.status = filter.value.join( ',' );
}
if (
filter.field === 'author' &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ const DEFAULT_VIEWS = {
view: {
...DEFAULT_PAGE_BASE,
filters: [
{ field: 'status', operator: OPERATOR_IN, value: 'draft' },
{
field: 'status',
operator: OPERATOR_IN,
value: [ 'draft' ],
},
],
},
},
Expand All @@ -49,7 +53,11 @@ const DEFAULT_VIEWS = {
view: {
...DEFAULT_PAGE_BASE,
filters: [
{ field: 'status', operator: OPERATOR_IN, value: 'trash' },
{
field: 'status',
operator: OPERATOR_IN,
value: [ 'trash' ],
},
],
},
},
Expand Down