@wordpress/dataviews 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +48 -15
- package/build/add-filter.js +0 -2
- package/build/add-filter.js.map +1 -1
- package/build/bulk-actions.js +41 -3
- package/build/bulk-actions.js.map +1 -1
- package/build/constants.js +28 -7
- package/build/constants.js.map +1 -1
- package/build/dataviews.js +34 -21
- package/build/dataviews.js.map +1 -1
- package/build/filter-summary.js +33 -12
- package/build/filter-summary.js.map +1 -1
- package/build/filters.js +10 -2
- package/build/filters.js.map +1 -1
- package/build/item-actions.js +20 -39
- package/build/item-actions.js.map +1 -1
- package/build/pagination.js +4 -3
- package/build/pagination.js.map +1 -1
- package/build/reset-filters.js +2 -1
- package/build/reset-filters.js.map +1 -1
- package/build/search-widget.js +117 -8
- package/build/search-widget.js.map +1 -1
- package/build/single-selection-checkbox.js +7 -2
- package/build/single-selection-checkbox.js.map +1 -1
- package/build/utils.js +24 -2
- package/build/utils.js.map +1 -1
- package/build/view-actions.js.map +1 -1
- package/build/view-grid.js +12 -13
- package/build/view-grid.js.map +1 -1
- package/build/view-list.js +1 -1
- package/build/view-list.js.map +1 -1
- package/build/view-table.js +111 -47
- package/build/view-table.js.map +1 -1
- package/build-module/add-filter.js +0 -2
- package/build-module/add-filter.js.map +1 -1
- package/build-module/bulk-actions.js +40 -4
- package/build-module/bulk-actions.js.map +1 -1
- package/build-module/constants.js +27 -6
- package/build-module/constants.js.map +1 -1
- package/build-module/dataviews.js +35 -22
- package/build-module/dataviews.js.map +1 -1
- package/build-module/filter-summary.js +34 -13
- package/build-module/filter-summary.js.map +1 -1
- package/build-module/filters.js +11 -3
- package/build-module/filters.js.map +1 -1
- package/build-module/item-actions.js +20 -39
- package/build-module/item-actions.js.map +1 -1
- package/build-module/pagination.js +4 -3
- package/build-module/pagination.js.map +1 -1
- package/build-module/reset-filters.js +2 -1
- package/build-module/reset-filters.js.map +1 -1
- package/build-module/search-widget.js +120 -11
- package/build-module/search-widget.js.map +1 -1
- package/build-module/single-selection-checkbox.js +7 -2
- package/build-module/single-selection-checkbox.js.map +1 -1
- package/build-module/utils.js +25 -3
- package/build-module/utils.js.map +1 -1
- package/build-module/view-actions.js.map +1 -1
- package/build-module/view-grid.js +13 -14
- package/build-module/view-grid.js.map +1 -1
- package/build-module/view-list.js +2 -2
- package/build-module/view-list.js.map +1 -1
- package/build-module/view-table.js +113 -49
- package/build-module/view-table.js.map +1 -1
- package/build-style/style-rtl.css +76 -46
- package/build-style/style.css +76 -46
- package/package.json +11 -11
- package/src/add-filter.js +0 -2
- package/src/bulk-actions.js +54 -4
- package/src/constants.js +35 -6
- package/src/dataviews.js +66 -49
- package/src/filter-summary.js +76 -23
- package/src/filters.js +16 -5
- package/src/item-actions.js +19 -55
- package/src/pagination.js +8 -3
- package/src/reset-filters.js +2 -1
- package/src/search-widget.js +182 -15
- package/src/single-selection-checkbox.js +7 -1
- package/src/stories/fixtures.js +12 -1
- package/src/stories/index.story.js +43 -4
- package/src/style.scss +108 -73
- package/src/utils.js +38 -4
- package/src/view-actions.js +1 -1
- package/src/view-grid.js +13 -12
- package/src/view-list.js +2 -1
- package/src/view-table.js +162 -81
package/src/bulk-actions.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
Modal,
|
|
8
8
|
} from '@wordpress/components';
|
|
9
9
|
import { __, sprintf, _n } from '@wordpress/i18n';
|
|
10
|
-
import { useMemo, useState, useCallback } from '@wordpress/element';
|
|
10
|
+
import { useMemo, useState, useCallback, useEffect } from '@wordpress/element';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Internal dependencies
|
|
@@ -21,6 +21,24 @@ const {
|
|
|
21
21
|
DropdownMenuSeparatorV2: DropdownMenuSeparator,
|
|
22
22
|
} = unlock( componentsPrivateApis );
|
|
23
23
|
|
|
24
|
+
export function useHasAPossibleBulkAction( actions, item ) {
|
|
25
|
+
return useMemo( () => {
|
|
26
|
+
return actions.some( ( action ) => {
|
|
27
|
+
return action.supportsBulk && action.isEligible( item );
|
|
28
|
+
} );
|
|
29
|
+
}, [ actions, item ] );
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function useSomeItemHasAPossibleBulkAction( actions, data ) {
|
|
33
|
+
return useMemo( () => {
|
|
34
|
+
return data.some( ( item ) => {
|
|
35
|
+
return actions.some( ( action ) => {
|
|
36
|
+
return action.supportsBulk && action.isEligible( item );
|
|
37
|
+
} );
|
|
38
|
+
} );
|
|
39
|
+
}, [ actions, data ] );
|
|
40
|
+
}
|
|
41
|
+
|
|
24
42
|
function ActionWithModal( {
|
|
25
43
|
action,
|
|
26
44
|
selectedItems,
|
|
@@ -107,15 +125,47 @@ export default function BulkActions( {
|
|
|
107
125
|
() => actions.filter( ( action ) => action.supportsBulk ),
|
|
108
126
|
[ actions ]
|
|
109
127
|
);
|
|
110
|
-
const areAllSelected = selection && selection.length === data.length;
|
|
111
128
|
const [ isMenuOpen, onMenuOpenChange ] = useState( false );
|
|
112
129
|
const [ actionWithModal, setActionWithModal ] = useState();
|
|
130
|
+
const selectableItems = useMemo( () => {
|
|
131
|
+
return data.filter( ( item ) => {
|
|
132
|
+
return bulkActions.some( ( action ) => action.isEligible( item ) );
|
|
133
|
+
} );
|
|
134
|
+
}, [ data, bulkActions ] );
|
|
135
|
+
|
|
136
|
+
const numberSelectableItems = selectableItems.length;
|
|
137
|
+
const areAllSelected =
|
|
138
|
+
selection && selection.length === numberSelectableItems;
|
|
139
|
+
|
|
113
140
|
const selectedItems = useMemo( () => {
|
|
114
141
|
return data.filter( ( item ) =>
|
|
115
142
|
selection.includes( getItemId( item ) )
|
|
116
143
|
);
|
|
117
144
|
}, [ selection, data, getItemId ] );
|
|
118
145
|
|
|
146
|
+
const hasNonSelectableItemSelected = useMemo( () => {
|
|
147
|
+
return selectedItems.some( ( item ) => {
|
|
148
|
+
return ! selectableItems.includes( item );
|
|
149
|
+
} );
|
|
150
|
+
}, [ selectedItems, selectableItems ] );
|
|
151
|
+
useEffect( () => {
|
|
152
|
+
if ( hasNonSelectableItemSelected ) {
|
|
153
|
+
onSelectionChange(
|
|
154
|
+
selectedItems.filter( ( selectedItem ) => {
|
|
155
|
+
return selectableItems.some( ( item ) => {
|
|
156
|
+
return getItemId( selectedItem ) === getItemId( item );
|
|
157
|
+
} );
|
|
158
|
+
} )
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}, [
|
|
162
|
+
hasNonSelectableItemSelected,
|
|
163
|
+
selectedItems,
|
|
164
|
+
selectableItems,
|
|
165
|
+
getItemId,
|
|
166
|
+
onSelectionChange,
|
|
167
|
+
] );
|
|
168
|
+
|
|
119
169
|
if ( bulkActions.length === 0 ) {
|
|
120
170
|
return null;
|
|
121
171
|
}
|
|
@@ -157,9 +207,9 @@ export default function BulkActions( {
|
|
|
157
207
|
disabled={ areAllSelected }
|
|
158
208
|
hideOnClick={ false }
|
|
159
209
|
onClick={ () => {
|
|
160
|
-
onSelectionChange(
|
|
210
|
+
onSelectionChange( selectableItems );
|
|
161
211
|
} }
|
|
162
|
-
suffix={
|
|
212
|
+
suffix={ numberSelectableItems }
|
|
163
213
|
>
|
|
164
214
|
{ __( 'Select all' ) }
|
|
165
215
|
</DropdownMenuItem>
|
package/src/constants.js
CHANGED
|
@@ -20,17 +20,46 @@ import ViewList from './view-list';
|
|
|
20
20
|
export const ENUMERATION_TYPE = 'enumeration';
|
|
21
21
|
|
|
22
22
|
// Filter operators.
|
|
23
|
-
export const
|
|
24
|
-
export const
|
|
23
|
+
export const OPERATOR_IS = 'is';
|
|
24
|
+
export const OPERATOR_IS_NOT = 'isNot';
|
|
25
|
+
export const OPERATOR_IS_ANY = 'isAny';
|
|
26
|
+
export const OPERATOR_IS_NONE = 'isNone';
|
|
27
|
+
export const OPERATOR_IS_ALL = 'isAll';
|
|
28
|
+
export const OPERATOR_IS_NOT_ALL = 'isNotAll';
|
|
29
|
+
|
|
30
|
+
export const ALL_OPERATORS = [
|
|
31
|
+
OPERATOR_IS,
|
|
32
|
+
OPERATOR_IS_NOT,
|
|
33
|
+
OPERATOR_IS_ANY,
|
|
34
|
+
OPERATOR_IS_NONE,
|
|
35
|
+
OPERATOR_IS_ALL,
|
|
36
|
+
OPERATOR_IS_NOT_ALL,
|
|
37
|
+
];
|
|
25
38
|
export const OPERATORS = {
|
|
26
|
-
[
|
|
27
|
-
key: '
|
|
39
|
+
[ OPERATOR_IS ]: {
|
|
40
|
+
key: 'is-filter',
|
|
28
41
|
label: __( 'Is' ),
|
|
29
42
|
},
|
|
30
|
-
[
|
|
31
|
-
key: 'not-
|
|
43
|
+
[ OPERATOR_IS_NOT ]: {
|
|
44
|
+
key: 'is-not-filter',
|
|
32
45
|
label: __( 'Is not' ),
|
|
33
46
|
},
|
|
47
|
+
[ OPERATOR_IS_ANY ]: {
|
|
48
|
+
key: 'is-any-filter',
|
|
49
|
+
label: __( 'Is any' ),
|
|
50
|
+
},
|
|
51
|
+
[ OPERATOR_IS_NONE ]: {
|
|
52
|
+
key: 'is-none-filter',
|
|
53
|
+
label: __( 'Is none' ),
|
|
54
|
+
},
|
|
55
|
+
[ OPERATOR_IS_ALL ]: {
|
|
56
|
+
key: 'is-all-filter',
|
|
57
|
+
label: __( 'Is all' ),
|
|
58
|
+
},
|
|
59
|
+
[ OPERATOR_IS_NOT_ALL ]: {
|
|
60
|
+
key: 'is-not-all-filter',
|
|
61
|
+
label: __( 'Is not all' ),
|
|
62
|
+
},
|
|
34
63
|
};
|
|
35
64
|
|
|
36
65
|
// Sorting
|
package/src/dataviews.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
__experimentalVStack as VStack,
|
|
6
|
-
__experimentalHStack as HStack,
|
|
7
|
-
} from '@wordpress/components';
|
|
4
|
+
import { __experimentalHStack as HStack } from '@wordpress/components';
|
|
8
5
|
import { useMemo, useState, useCallback, useEffect } from '@wordpress/element';
|
|
9
6
|
|
|
10
7
|
/**
|
|
@@ -20,13 +17,23 @@ import BulkActions from './bulk-actions';
|
|
|
20
17
|
const defaultGetItemId = ( item ) => item.id;
|
|
21
18
|
const defaultOnSelectionChange = () => {};
|
|
22
19
|
|
|
20
|
+
function useSomeItemHasAPossibleBulkAction( actions, data ) {
|
|
21
|
+
return useMemo( () => {
|
|
22
|
+
return data.some( ( item ) => {
|
|
23
|
+
return actions.some( ( action ) => {
|
|
24
|
+
return action.supportsBulk && action.isEligible( item );
|
|
25
|
+
} );
|
|
26
|
+
} );
|
|
27
|
+
}, [ actions, data ] );
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
export default function DataViews( {
|
|
24
31
|
view,
|
|
25
32
|
onChangeView,
|
|
26
33
|
fields,
|
|
27
34
|
search = true,
|
|
28
35
|
searchLabel = undefined,
|
|
29
|
-
actions,
|
|
36
|
+
actions = [],
|
|
30
37
|
data,
|
|
31
38
|
getItemId = defaultGetItemId,
|
|
32
39
|
isLoading = false,
|
|
@@ -70,18 +77,33 @@ export default function DataViews( {
|
|
|
70
77
|
( v ) => v.type === view.type
|
|
71
78
|
).component;
|
|
72
79
|
const _fields = useMemo( () => {
|
|
73
|
-
return fields.map( ( field ) =>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
return fields.map( ( field ) => {
|
|
81
|
+
const getValue =
|
|
82
|
+
field.getValue || ( ( { item } ) => item[ field.id ] );
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
...field,
|
|
86
|
+
getValue,
|
|
87
|
+
render: field.render || getValue,
|
|
88
|
+
};
|
|
89
|
+
} );
|
|
77
90
|
}, [ fields ] );
|
|
91
|
+
|
|
92
|
+
const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction(
|
|
93
|
+
actions,
|
|
94
|
+
data
|
|
95
|
+
);
|
|
78
96
|
return (
|
|
79
97
|
<div className="dataviews-wrapper">
|
|
80
|
-
<
|
|
98
|
+
<HStack
|
|
99
|
+
alignment="top"
|
|
100
|
+
justify="start"
|
|
101
|
+
className="dataviews-filters__view-actions"
|
|
102
|
+
>
|
|
81
103
|
<HStack
|
|
82
|
-
alignment="flex-start"
|
|
83
104
|
justify="start"
|
|
84
|
-
className="dataviews-
|
|
105
|
+
className="dataviews-filters__container"
|
|
106
|
+
wrap
|
|
85
107
|
>
|
|
86
108
|
{ search && (
|
|
87
109
|
<Search
|
|
@@ -90,27 +112,6 @@ export default function DataViews( {
|
|
|
90
112
|
onChangeView={ onChangeView }
|
|
91
113
|
/>
|
|
92
114
|
) }
|
|
93
|
-
{ [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) && (
|
|
94
|
-
<BulkActions
|
|
95
|
-
actions={ actions }
|
|
96
|
-
data={ data }
|
|
97
|
-
onSelectionChange={ onSetSelection }
|
|
98
|
-
selection={ selection }
|
|
99
|
-
getItemId={ getItemId }
|
|
100
|
-
/>
|
|
101
|
-
) }
|
|
102
|
-
<ViewActions
|
|
103
|
-
fields={ _fields }
|
|
104
|
-
view={ view }
|
|
105
|
-
onChangeView={ onChangeView }
|
|
106
|
-
supportedLayouts={ supportedLayouts }
|
|
107
|
-
/>
|
|
108
|
-
</HStack>
|
|
109
|
-
<HStack
|
|
110
|
-
justify="start"
|
|
111
|
-
className="dataviews-filters__container"
|
|
112
|
-
wrap
|
|
113
|
-
>
|
|
114
115
|
<Filters
|
|
115
116
|
fields={ _fields }
|
|
116
117
|
view={ view }
|
|
@@ -119,26 +120,42 @@ export default function DataViews( {
|
|
|
119
120
|
setOpenedFilter={ setOpenedFilter }
|
|
120
121
|
/>
|
|
121
122
|
</HStack>
|
|
122
|
-
|
|
123
|
+
{ [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) &&
|
|
124
|
+
hasPossibleBulkAction && (
|
|
125
|
+
<BulkActions
|
|
126
|
+
actions={ actions }
|
|
127
|
+
data={ data }
|
|
128
|
+
onSelectionChange={ onSetSelection }
|
|
129
|
+
selection={ selection }
|
|
130
|
+
getItemId={ getItemId }
|
|
131
|
+
/>
|
|
132
|
+
) }
|
|
133
|
+
<ViewActions
|
|
123
134
|
fields={ _fields }
|
|
124
135
|
view={ view }
|
|
125
136
|
onChangeView={ onChangeView }
|
|
126
|
-
|
|
127
|
-
data={ data }
|
|
128
|
-
getItemId={ getItemId }
|
|
129
|
-
isLoading={ isLoading }
|
|
130
|
-
onSelectionChange={ onSetSelection }
|
|
131
|
-
onDetailsChange={ onDetailsChange }
|
|
132
|
-
selection={ selection }
|
|
133
|
-
deferredRendering={ deferredRendering }
|
|
134
|
-
setOpenedFilter={ setOpenedFilter }
|
|
135
|
-
/>
|
|
136
|
-
<Pagination
|
|
137
|
-
view={ view }
|
|
138
|
-
onChangeView={ onChangeView }
|
|
139
|
-
paginationInfo={ paginationInfo }
|
|
137
|
+
supportedLayouts={ supportedLayouts }
|
|
140
138
|
/>
|
|
141
|
-
</
|
|
139
|
+
</HStack>
|
|
140
|
+
<ViewComponent
|
|
141
|
+
fields={ _fields }
|
|
142
|
+
view={ view }
|
|
143
|
+
onChangeView={ onChangeView }
|
|
144
|
+
actions={ actions }
|
|
145
|
+
data={ data }
|
|
146
|
+
getItemId={ getItemId }
|
|
147
|
+
isLoading={ isLoading }
|
|
148
|
+
onSelectionChange={ onSetSelection }
|
|
149
|
+
onDetailsChange={ onDetailsChange }
|
|
150
|
+
selection={ selection }
|
|
151
|
+
deferredRendering={ deferredRendering }
|
|
152
|
+
setOpenedFilter={ setOpenedFilter }
|
|
153
|
+
/>
|
|
154
|
+
<Pagination
|
|
155
|
+
view={ view }
|
|
156
|
+
onChangeView={ onChangeView }
|
|
157
|
+
paginationInfo={ paginationInfo }
|
|
158
|
+
/>
|
|
142
159
|
</div>
|
|
143
160
|
);
|
|
144
161
|
}
|
package/src/filter-summary.js
CHANGED
|
@@ -24,43 +24,93 @@ import { ENTER, SPACE } from '@wordpress/keycodes';
|
|
|
24
24
|
* Internal dependencies
|
|
25
25
|
*/
|
|
26
26
|
import SearchWidget from './search-widget';
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
OPERATORS,
|
|
29
|
+
OPERATOR_IS,
|
|
30
|
+
OPERATOR_IS_NOT,
|
|
31
|
+
OPERATOR_IS_ANY,
|
|
32
|
+
OPERATOR_IS_NONE,
|
|
33
|
+
OPERATOR_IS_ALL,
|
|
34
|
+
OPERATOR_IS_NOT_ALL,
|
|
35
|
+
} from './constants';
|
|
28
36
|
|
|
29
|
-
const FilterText = ( {
|
|
30
|
-
if (
|
|
37
|
+
const FilterText = ( { activeElements, filterInView, filter } ) => {
|
|
38
|
+
if ( activeElements === undefined || activeElements.length === 0 ) {
|
|
31
39
|
return filter.name;
|
|
32
40
|
}
|
|
33
41
|
|
|
34
42
|
const filterTextWrappers = {
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
Name: <span className="dataviews-filter-summary__filter-text-name" />,
|
|
44
|
+
Value: <span className="dataviews-filter-summary__filter-text-value" />,
|
|
37
45
|
};
|
|
38
46
|
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
if ( filterInView?.operator === OPERATOR_IS_ANY ) {
|
|
48
|
+
return createInterpolateElement(
|
|
49
|
+
sprintf(
|
|
50
|
+
/* translators: 1: Filter name. 3: Filter value. e.g.: "Author is any: Admin, Editor". */
|
|
51
|
+
__( '<Name>%1$s is any: </Name><Value>%2$s</Value>' ),
|
|
52
|
+
filter.name,
|
|
53
|
+
activeElements.map( ( element ) => element.label ).join( ', ' )
|
|
54
|
+
),
|
|
55
|
+
filterTextWrappers
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if ( filterInView?.operator === OPERATOR_IS_NONE ) {
|
|
60
|
+
return createInterpolateElement(
|
|
61
|
+
sprintf(
|
|
62
|
+
/* translators: 1: Filter name. 3: Filter value. e.g.: "Author is none: Admin, Editor". */
|
|
63
|
+
__( '<Name>%1$s is none: </Name><Value>%2$s</Value>' ),
|
|
64
|
+
filter.name,
|
|
65
|
+
activeElements.map( ( element ) => element.label ).join( ', ' )
|
|
66
|
+
),
|
|
67
|
+
filterTextWrappers
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if ( filterInView?.operator === OPERATOR_IS_ALL ) {
|
|
43
72
|
return createInterpolateElement(
|
|
44
73
|
sprintf(
|
|
45
|
-
/* translators: 1: Filter name.
|
|
46
|
-
__( '<
|
|
74
|
+
/* translators: 1: Filter name. 3: Filter value. e.g.: "Author is all: Admin, Editor". */
|
|
75
|
+
__( '<Name>%1$s is all: </Name><Value>%2$s</Value>' ),
|
|
47
76
|
filter.name,
|
|
48
|
-
|
|
77
|
+
activeElements.map( ( element ) => element.label ).join( ', ' )
|
|
49
78
|
),
|
|
50
79
|
filterTextWrappers
|
|
51
80
|
);
|
|
52
81
|
}
|
|
53
82
|
|
|
54
|
-
if (
|
|
55
|
-
activeElement !== undefined &&
|
|
56
|
-
filterInView?.operator === OPERATOR_NOT_IN
|
|
57
|
-
) {
|
|
83
|
+
if ( filterInView?.operator === OPERATOR_IS_NOT_ALL ) {
|
|
58
84
|
return createInterpolateElement(
|
|
59
85
|
sprintf(
|
|
60
|
-
/* translators: 1: Filter name.
|
|
61
|
-
__( '<
|
|
86
|
+
/* translators: 1: Filter name. 3: Filter value. e.g.: "Author is not all: Admin, Editor". */
|
|
87
|
+
__( '<Name>%1$s is not all: </Name><Value>%2$s</Value>' ),
|
|
62
88
|
filter.name,
|
|
63
|
-
|
|
89
|
+
activeElements.map( ( element ) => element.label ).join( ', ' )
|
|
90
|
+
),
|
|
91
|
+
filterTextWrappers
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if ( filterInView?.operator === OPERATOR_IS ) {
|
|
96
|
+
return createInterpolateElement(
|
|
97
|
+
sprintf(
|
|
98
|
+
/* translators: 1: Filter name. 3: Filter value. e.g.: "Author is: Admin". */
|
|
99
|
+
__( '<Name>%1$s is: </Name><Value>%2$s</Value>' ),
|
|
100
|
+
filter.name,
|
|
101
|
+
activeElements[ 0 ].label
|
|
102
|
+
),
|
|
103
|
+
filterTextWrappers
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if ( filterInView?.operator === OPERATOR_IS_NOT ) {
|
|
108
|
+
return createInterpolateElement(
|
|
109
|
+
sprintf(
|
|
110
|
+
/* translators: 1: Filter name. 3: Filter value. e.g.: "Author is not: Admin". */
|
|
111
|
+
__( '<Name>%1$s is not: </Name><Value>%2$s</Value>' ),
|
|
112
|
+
filter.name,
|
|
113
|
+
activeElements[ 0 ].label
|
|
64
114
|
),
|
|
65
115
|
filterTextWrappers
|
|
66
116
|
);
|
|
@@ -140,9 +190,12 @@ export default function FilterSummary( {
|
|
|
140
190
|
const toggleRef = useRef();
|
|
141
191
|
const { filter, view, onChangeView } = commonProps;
|
|
142
192
|
const filterInView = view.filters.find( ( f ) => f.field === filter.field );
|
|
143
|
-
const
|
|
144
|
-
(
|
|
145
|
-
|
|
193
|
+
const activeElements = filter.elements.filter( ( element ) => {
|
|
194
|
+
if ( filter.singleSelection ) {
|
|
195
|
+
return element.value === filterInView?.value;
|
|
196
|
+
}
|
|
197
|
+
return filterInView?.value?.includes( element.value );
|
|
198
|
+
} );
|
|
146
199
|
const isPrimary = filter.isPrimary;
|
|
147
200
|
const hasValues = filterInView?.value !== undefined;
|
|
148
201
|
const canResetOrRemove = ! isPrimary || hasValues;
|
|
@@ -188,7 +241,7 @@ export default function FilterSummary( {
|
|
|
188
241
|
ref={ toggleRef }
|
|
189
242
|
>
|
|
190
243
|
<FilterText
|
|
191
|
-
|
|
244
|
+
activeElements={ activeElements }
|
|
192
245
|
filterInView={ filterInView }
|
|
193
246
|
filter={ filter }
|
|
194
247
|
/>
|
package/src/filters.js
CHANGED
|
@@ -10,7 +10,13 @@ import FilterSummary from './filter-summary';
|
|
|
10
10
|
import AddFilter from './add-filter';
|
|
11
11
|
import ResetFilters from './reset-filters';
|
|
12
12
|
import { sanitizeOperators } from './utils';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
ENUMERATION_TYPE,
|
|
15
|
+
ALL_OPERATORS,
|
|
16
|
+
OPERATOR_IS,
|
|
17
|
+
OPERATOR_IS_NOT,
|
|
18
|
+
} from './constants';
|
|
19
|
+
import { __experimentalHStack as HStack } from '@wordpress/components';
|
|
14
20
|
|
|
15
21
|
const Filters = memo( function Filters( {
|
|
16
22
|
fields,
|
|
@@ -42,15 +48,16 @@ const Filters = memo( function Filters( {
|
|
|
42
48
|
field: field.id,
|
|
43
49
|
name: field.header,
|
|
44
50
|
elements: field.elements,
|
|
51
|
+
singleSelection: operators.some( ( op ) =>
|
|
52
|
+
[ OPERATOR_IS, OPERATOR_IS_NOT ].includes( op )
|
|
53
|
+
),
|
|
45
54
|
operators,
|
|
46
55
|
isVisible:
|
|
47
56
|
isPrimary ||
|
|
48
57
|
view.filters.some(
|
|
49
58
|
( f ) =>
|
|
50
59
|
f.field === field.id &&
|
|
51
|
-
|
|
52
|
-
f.operator
|
|
53
|
-
)
|
|
60
|
+
ALL_OPERATORS.includes( f.operator )
|
|
54
61
|
),
|
|
55
62
|
isPrimary,
|
|
56
63
|
} );
|
|
@@ -108,7 +115,11 @@ const Filters = memo( function Filters( {
|
|
|
108
115
|
);
|
|
109
116
|
}
|
|
110
117
|
|
|
111
|
-
return
|
|
118
|
+
return (
|
|
119
|
+
<HStack justify="flex-start" style={ { width: 'fit-content' } } wrap>
|
|
120
|
+
{ filterComponents }
|
|
121
|
+
</HStack>
|
|
122
|
+
);
|
|
112
123
|
} );
|
|
113
124
|
|
|
114
125
|
export default Filters;
|
package/src/item-actions.js
CHANGED
|
@@ -105,37 +105,28 @@ function ActionsDropdownMenuGroup( { actions, item } ) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
export default function ItemActions( { item, actions, isCompact } ) {
|
|
108
|
-
const { primaryActions,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if ( action.isPrimary && !! action.icon ) {
|
|
117
|
-
accumulator.primaryActions.push( action );
|
|
118
|
-
} else {
|
|
119
|
-
accumulator.secondaryActions.push( action );
|
|
120
|
-
}
|
|
121
|
-
return accumulator;
|
|
122
|
-
},
|
|
123
|
-
{ primaryActions: [], secondaryActions: [] }
|
|
108
|
+
const { primaryActions, eligibleActions } = useMemo( () => {
|
|
109
|
+
// If an action is eligible for all items, doesn't need
|
|
110
|
+
// to provide the `isEligible` function.
|
|
111
|
+
const _eligibleActions = actions.filter(
|
|
112
|
+
( action ) => ! action.isEligible || action.isEligible( item )
|
|
113
|
+
);
|
|
114
|
+
const _primaryActions = _eligibleActions.filter(
|
|
115
|
+
( action ) => action.isPrimary && !! action.icon
|
|
124
116
|
);
|
|
117
|
+
return {
|
|
118
|
+
primaryActions: _primaryActions,
|
|
119
|
+
eligibleActions: _eligibleActions,
|
|
120
|
+
};
|
|
125
121
|
}, [ actions, item ] );
|
|
126
122
|
if ( isCompact ) {
|
|
127
|
-
return
|
|
128
|
-
<CompactItemActions
|
|
129
|
-
item={ item }
|
|
130
|
-
primaryActions={ primaryActions }
|
|
131
|
-
secondaryActions={ secondaryActions }
|
|
132
|
-
/>
|
|
133
|
-
);
|
|
123
|
+
return <CompactItemActions item={ item } actions={ eligibleActions } />;
|
|
134
124
|
}
|
|
135
125
|
return (
|
|
136
126
|
<HStack
|
|
137
127
|
spacing={ 1 }
|
|
138
128
|
justify="flex-end"
|
|
129
|
+
className="dataviews-item-actions"
|
|
139
130
|
style={ {
|
|
140
131
|
flexShrink: '0',
|
|
141
132
|
width: 'auto',
|
|
@@ -161,27 +152,12 @@ export default function ItemActions( { item, actions, isCompact } ) {
|
|
|
161
152
|
/>
|
|
162
153
|
);
|
|
163
154
|
} ) }
|
|
164
|
-
<
|
|
165
|
-
trigger={
|
|
166
|
-
<Button
|
|
167
|
-
size="compact"
|
|
168
|
-
icon={ moreVertical }
|
|
169
|
-
label={ __( 'Actions' ) }
|
|
170
|
-
disabled={ ! secondaryActions.length }
|
|
171
|
-
/>
|
|
172
|
-
}
|
|
173
|
-
placement="bottom-end"
|
|
174
|
-
>
|
|
175
|
-
<ActionsDropdownMenuGroup
|
|
176
|
-
actions={ secondaryActions }
|
|
177
|
-
item={ item }
|
|
178
|
-
/>
|
|
179
|
-
</DropdownMenu>
|
|
155
|
+
<CompactItemActions item={ item } actions={ eligibleActions } />
|
|
180
156
|
</HStack>
|
|
181
157
|
);
|
|
182
158
|
}
|
|
183
159
|
|
|
184
|
-
function CompactItemActions( { item,
|
|
160
|
+
function CompactItemActions( { item, actions } ) {
|
|
185
161
|
return (
|
|
186
162
|
<DropdownMenu
|
|
187
163
|
trigger={
|
|
@@ -189,25 +165,13 @@ function CompactItemActions( { item, primaryActions, secondaryActions } ) {
|
|
|
189
165
|
size="compact"
|
|
190
166
|
icon={ moreVertical }
|
|
191
167
|
label={ __( 'Actions' ) }
|
|
192
|
-
disabled={
|
|
193
|
-
|
|
194
|
-
}
|
|
168
|
+
disabled={ ! actions.length }
|
|
169
|
+
className="dataviews-all-actions-button"
|
|
195
170
|
/>
|
|
196
171
|
}
|
|
197
172
|
placement="bottom-end"
|
|
198
173
|
>
|
|
199
|
-
{
|
|
200
|
-
<ActionsDropdownMenuGroup
|
|
201
|
-
actions={ primaryActions }
|
|
202
|
-
item={ item }
|
|
203
|
-
/>
|
|
204
|
-
) }
|
|
205
|
-
{ !! secondaryActions.length && (
|
|
206
|
-
<ActionsDropdownMenuGroup
|
|
207
|
-
actions={ secondaryActions }
|
|
208
|
-
item={ item }
|
|
209
|
-
/>
|
|
210
|
-
) }
|
|
174
|
+
<ActionsDropdownMenuGroup actions={ actions } item={ item } />
|
|
211
175
|
</DropdownMenu>
|
|
212
176
|
);
|
|
213
177
|
}
|
package/src/pagination.js
CHANGED
|
@@ -27,15 +27,20 @@ const Pagination = memo( function Pagination( {
|
|
|
27
27
|
justify="end"
|
|
28
28
|
className="dataviews-pagination"
|
|
29
29
|
>
|
|
30
|
-
<HStack
|
|
30
|
+
<HStack
|
|
31
|
+
justify="flex-start"
|
|
32
|
+
expanded={ false }
|
|
33
|
+
spacing={ 2 }
|
|
34
|
+
className="dataviews-pagination__page-selection"
|
|
35
|
+
>
|
|
31
36
|
{ createInterpolateElement(
|
|
32
37
|
sprintf(
|
|
33
38
|
// translators: %s: Total number of pages.
|
|
34
|
-
_x( 'Page <
|
|
39
|
+
_x( 'Page <CurrentPageControl /> of %s', 'paging' ),
|
|
35
40
|
totalPages
|
|
36
41
|
),
|
|
37
42
|
{
|
|
38
|
-
|
|
43
|
+
CurrentPageControl: (
|
|
39
44
|
<SelectControl
|
|
40
45
|
aria-label={ __( 'Current page' ) }
|
|
41
46
|
value={ view.page }
|
package/src/reset-filters.js
CHANGED
|
@@ -21,6 +21,7 @@ export default function ResetFilter( { filters, view, onChangeView } ) {
|
|
|
21
21
|
__experimentalIsFocusable
|
|
22
22
|
size="compact"
|
|
23
23
|
variant="tertiary"
|
|
24
|
+
className="dataviews-filters__reset-button"
|
|
24
25
|
onClick={ () => {
|
|
25
26
|
onChangeView( {
|
|
26
27
|
...view,
|
|
@@ -30,7 +31,7 @@ export default function ResetFilter( { filters, view, onChangeView } ) {
|
|
|
30
31
|
} );
|
|
31
32
|
} }
|
|
32
33
|
>
|
|
33
|
-
{ __( 'Reset
|
|
34
|
+
{ __( 'Reset' ) }
|
|
34
35
|
</Button>
|
|
35
36
|
);
|
|
36
37
|
}
|