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 (