From 1bf654b6c7f794d598fc6980789185924168ee2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= <583546+oandregal@users.noreply.github.com> Date: Wed, 15 Nov 2023 15:18:04 +0100 Subject: [PATCH] DataViews: allow users to add filters dynamically (#55992) --- .../src/components/dataviews/README.md | 5 +- .../src/components/dataviews/add-filter.js | 111 ++++++++++++++++++ .../src/components/dataviews/filters.js | 66 ++++++----- .../src/components/dataviews/in-filter.js | 14 +-- .../src/components/dataviews/reset-filters.js | 34 +++--- .../src/components/dataviews/search.js | 1 + .../sidebar-dataviews/default-views.js | 1 - 7 files changed, 171 insertions(+), 61 deletions(-) create mode 100644 packages/edit-site/src/components/dataviews/add-filter.js diff --git a/packages/edit-site/src/components/dataviews/README.md b/packages/edit-site/src/components/dataviews/README.md index 5502165f0cfdc5..8f1349044d6cf5 100644 --- a/packages/edit-site/src/components/dataviews/README.md +++ b/packages/edit-site/src/components/dataviews/README.md @@ -47,7 +47,6 @@ Example: { field: 'author', operator: 'in', value: 2 }, { field: 'status', operator: 'in', value: 'publish,draft' } ], - visibleFilters: [ 'author', 'status' ], hiddenFields: [ 'date', 'featured-image' ], layout: {}, } @@ -62,8 +61,7 @@ Example: - `filters`: the filters applied to the dataset. Each item describes: - `field`: which field this filter is bound to. - `operator`: which type of filter it is. Only `in` available at the moment. - - `vaule`: the actual value selected by the user. -- `visibleFilters`: the `id` of the filters that are visible in the UI. + - `value`: the actual value selected by the user. - `hiddenFields`: the `id` of the fields that are hidden in the UI. - `layout`: ... @@ -88,7 +86,6 @@ function MyCustomPageList() { { field: 'author', operator: 'in', value: 2 }, { field: 'status', operator: 'in', value: 'publish,draft' } ], - visibleFilters: [ 'author', 'status' ], hiddenFields: [ 'date', 'featured-image' ], layout: {}, } ); diff --git a/packages/edit-site/src/components/dataviews/add-filter.js b/packages/edit-site/src/components/dataviews/add-filter.js new file mode 100644 index 00000000000000..2cc0051f0f2d49 --- /dev/null +++ b/packages/edit-site/src/components/dataviews/add-filter.js @@ -0,0 +1,111 @@ +/** + * WordPress dependencies + */ +import { + privateApis as componentsPrivateApis, + Button, + Icon, +} from '@wordpress/components'; +import { chevronRightSmall, plus } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; +import { OPERATOR_IN } from './in-filter'; + +const { + DropdownMenuV2, + DropdownSubMenuV2, + DropdownSubMenuTriggerV2, + DropdownMenuItemV2, +} = unlock( componentsPrivateApis ); + +const VALID_OPERATORS = [ OPERATOR_IN ]; + +export default function AddFilter( { fields, view, onChangeView } ) { + const filters = []; + fields.forEach( ( field ) => { + if ( ! field.filters ) { + return; + } + + field.filters.forEach( ( filter ) => { + if ( VALID_OPERATORS.some( ( operator ) => operator === filter ) ) { + filters.push( { + field: field.id, + name: field.header, + operator: filter, + elements: field.elements || [], + isVisible: view.filters.some( + ( f ) => f.field === field.id && f.operator === filter + ), + } ); + } + } ); + } ); + + if ( filters.length === 0 ) { + return null; + } + + return ( + + { __( 'Add filter' ) } + + } + > + { filters.map( ( filter ) => { + if ( filter.isVisible ) { + return null; + } + + return ( + } + > + { filter.name } + + } + > + { filter.elements.map( ( element ) => ( + { + onChangeView( ( currentView ) => ( { + ...currentView, + page: 1, + filters: [ + ...currentView.filters, + { + field: filter.field, + operator: 'in', + value: element.value, + }, + ], + } ) ); + } } + role="menuitemcheckbox" + > + { element.label } + + ) ) } + + ); + } ) } + + ); +} diff --git a/packages/edit-site/src/components/dataviews/filters.js b/packages/edit-site/src/components/dataviews/filters.js index e34ba84040a95d..dc268845df5c0e 100644 --- a/packages/edit-site/src/components/dataviews/filters.js +++ b/packages/edit-site/src/components/dataviews/filters.js @@ -7,12 +7,13 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import { default as InFilter, OPERATOR_IN } from './in-filter'; +import AddFilter from './add-filter'; import ResetFilters from './reset-filters'; const VALID_OPERATORS = [ OPERATOR_IN ]; export default function Filters( { fields, view, onChangeView } ) { - const filtersRegistered = []; + const filters = []; fields.forEach( ( field ) => { if ( ! field.filters ) { return; @@ -20,7 +21,7 @@ export default function Filters( { fields, view, onChangeView } ) { field.filters.forEach( ( filter ) => { if ( VALID_OPERATORS.some( ( operator ) => operator === filter ) ) { - filtersRegistered.push( { + filters.push( { field: field.id, name: field.header, operator: filter, @@ -31,46 +32,47 @@ export default function Filters( { fields, view, onChangeView } ) { }, ...( field.elements || [] ), ], + isVisible: view.filters.some( + ( f ) => f.field === field.id && f.operator === filter + ), } ); } } ); } ); - const visibleFilters = view.visibleFilters - ?.map( ( fieldName ) => { - const visibleFiltersForField = filtersRegistered.filter( - ( f ) => f.field === fieldName + const filterComponents = filters?.map( ( filter ) => { + if ( ! filter.isVisible ) { + return null; + } + + if ( OPERATOR_IN === filter.operator ) { + return ( + ); + } - if ( visibleFiltersForField.length === 0 ) { - return null; - } + return null; + } ); - return visibleFiltersForField.map( ( filter ) => { - if ( OPERATOR_IN === filter.operator ) { - return ( - - ); - } - return null; - } ); - } ) - .filter( Boolean ); + filterComponents.push( + + ); - if ( visibleFilters?.length > 0 ) { - visibleFilters.push( - + if ( filterComponents.length > 1 ) { + filterComponents.push( + ); } - return visibleFilters; + return filterComponents; } diff --git a/packages/edit-site/src/components/dataviews/in-filter.js b/packages/edit-site/src/components/dataviews/in-filter.js index 9642169335aafa..4154e0576101c1 100644 --- a/packages/edit-site/src/components/dataviews/in-filter.js +++ b/packages/edit-site/src/components/dataviews/in-filter.js @@ -24,6 +24,7 @@ export default ( { filter, view, onChangeView } ) => { return ( { ( f ) => f.field !== filter.field || f.operator !== OPERATOR_IN ); - if ( value !== '' ) { - filters.push( { - field: filter.field, - operator: OPERATOR_IN, - value, - } ); - } + + filters.push( { + field: filter.field, + operator: OPERATOR_IN, + value, + } ); onChangeView( ( currentView ) => ( { ...currentView, diff --git a/packages/edit-site/src/components/dataviews/reset-filters.js b/packages/edit-site/src/components/dataviews/reset-filters.js index 68b5c17590c977..d78c06624087a7 100644 --- a/packages/edit-site/src/components/dataviews/reset-filters.js +++ b/packages/edit-site/src/components/dataviews/reset-filters.js @@ -1,26 +1,26 @@ /** * WordPress dependencies */ -import { BaseControl, Button } from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; export default ( { view, onChangeView } ) => { return ( - - - + ); }; diff --git a/packages/edit-site/src/components/dataviews/search.js b/packages/edit-site/src/components/dataviews/search.js index 3ade147922ac99..17a882637a7183 100644 --- a/packages/edit-site/src/components/dataviews/search.js +++ b/packages/edit-site/src/components/dataviews/search.js @@ -31,6 +31,7 @@ export default function Search( { label, view, onChangeView } ) { const searchLabel = label || __( 'Filter list' ); return (