Skip to content

Commit

Permalink
use label prop with two types
Browse files Browse the repository at this point in the history
  • Loading branch information
ntsekouras committed May 28, 2024
1 parent 927bc95 commit 871c894
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 53 deletions.
3 changes: 2 additions & 1 deletion packages/dataviews/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
### Internal

- Remove some unused dependencies ([#62010](https://github.com/WordPress/gutenberg/pull/62010)).

### Enhancement

- Add `getLabel` prop in Actions API to support labels that use information from the selected items. ([#61942](https://github.com/WordPress/gutenberg/pull/61942)).
- `label` prop in Actions API can be either a `sting` value or a `function`, in case we want to use information from the selected items. ([#61942](https://github.com/WordPress/gutenberg/pull/61942)).

## 1.2.0 (2024-05-16)

Expand Down
64 changes: 33 additions & 31 deletions packages/dataviews/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ npm install @wordpress/dataviews --save

```jsx
const Example = () => {

// Declare data, fields, etc.

return (
Expand All @@ -27,7 +26,7 @@ const Example = () => {
paginationInfo={ paginationInfo }
/>
);
}
};
```

## Properties
Expand All @@ -42,12 +41,14 @@ Example:
const data = [
{
id: 1,
title: "Title",
author: "Admin",
date: "2012-04-23T18:25:43.511Z"
title: 'Title',
author: 'Admin',
date: '2012-04-23T18:25:43.511Z',
},
{ /* ... */ }
]
{
/* ... */
},
];
```

By default, dataviews would use each record's `id` as an unique identifier. If it's not, the consumer should provide a `getItemId` function that returns one.
Expand Down Expand Up @@ -125,8 +126,8 @@ Each field is an object with the following properties:
- `enableSorting`: whether the data can be sorted by the given field. True by default.
- `enableHiding`: whether the field can be hidden. True by default.
- `filterBy`: configuration for the filters.
- `operators`: the list of operators supported by the field.
- `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter.
- `operators`: the list of operators supported by the field.
- `isPrimary`: whether it is a primary filter. A primary filter is always visible and is not listed in the "Add filter" component, except for the list layout where it behaves like a secondary filter.

### `view`: `object`

Expand All @@ -140,7 +141,7 @@ const view = {
search: '',
filters: [
{ field: 'author', operator: 'is', value: 2 },
{ field: 'status', operator: 'isAny', value: [ 'publish', 'draft'] }
{ field: 'status', operator: 'isAny', value: [ 'publish', 'draft' ] },
],
page: 1,
perPage: 5,
Expand All @@ -150,7 +151,7 @@ const view = {
},
hiddenFields: [ 'date', 'featured-image' ],
layout: {},
}
};
```

Properties:
Expand All @@ -164,8 +165,8 @@ Properties:
- `perPage`: number of records to show per page.
- `page`: the page that is visible.
- `sort`:
- `field`: the field used for sorting the dataset.
- `direction`: the direction to use for sorting, one of `asc` or `desc`.
- `field`: the field used for sorting the dataset.
- `direction`: the direction to use for sorting, one of `asc` or `desc`.
- `hiddenFields`: the `id` of the fields that are hidden in the UI.
- `layout`: config that is specific to a particular layout type.
- `mediaField`: used by the `grid` and `list` layouts. The `id` of the field to be used for rendering each card's media.
Expand All @@ -192,7 +193,11 @@ function MyCustomPageTable() {
search: '',
filters: [
{ field: 'author', operator: 'is', value: 2 },
{ field: 'status', operator: 'isAny', value: [ 'publish', 'draft' ] }
{
field: 'status',
operator: 'isAny',
value: [ 'publish', 'draft' ],
},
],
hiddenFields: [ 'date', 'featured-image' ],
layout: {},
Expand All @@ -219,9 +224,7 @@ function MyCustomPageTable() {
};
}, [ view ] );

const {
records
} = useEntityRecords( 'postType', 'page', queryArgs );
const { records } = useEntityRecords( 'postType', 'page', queryArgs );

return (
<DataViews
Expand All @@ -241,8 +244,7 @@ Collection of operations that can be performed upon each record.
Each action is an object with the following properties:

- `id`: string, required. Unique identifier of the action. For example, `move-to-trash`.
- `label`: string, optional. User facing description of the action. For example, `Move to Trash`.
- `getLabel` function, optional. Accepts the selected records as input and returns the user facing description of the action. It takes precedence over the `label` prop.
- `label`: string|function, required. User facing description of the action. For example, `Move to Trash`. In case we want to adjust the label based on the selected items, a getter function which accepts the selected records as input can be provided. The getter function should always return a `string` value.
- `isPrimary`: boolean, optional. Whether the action should be listed inline (primary) or in hidden in the more actions menu (secondary).
- `icon`: icon to show for primary actions. It's required for a primary action, otherwise the action would be considered secondary.
- `isEligible`: function, optional. Whether the action can be performed for a given record. If not present, the action is considered to be eligible for all items. It takes the given record as input.
Expand All @@ -253,8 +255,8 @@ Each action is an object with the following properties:

### `paginationInfo`: `Object`

- `totalItems`: the total number of items in the datasets.
- `totalPages`: the total number of pages, taking into account the total items in the dataset and the number of items per page provided by the user.
- `totalItems`: the total number of items in the datasets.
- `totalPages`: the total number of pages, taking into account the total items in the dataset and the number of items per page provided by the user.

### `search`: `boolean`

Expand Down Expand Up @@ -284,9 +286,9 @@ Callback that signals the user selected one of more items, and takes them as par

### Layouts

- `table`: the view uses a table layout.
- `grid`: the view uses a grid layout.
- `list`: the view uses a list layout.
- `table`: the view uses a table layout.
- `grid`: the view uses a grid layout.
- `list`: the view uses a list layout.

### Fields

Expand All @@ -296,13 +298,13 @@ Callback that signals the user selected one of more items, and takes them as par

Allowed operators:

| Operator | Selection | Description | Example |
| --- | --- | --- | --- |
| `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin |
| `isNot` | Single item | `NOT EQUAL TO`. The item's field is not equal to a single value. | Author is not Admin |
| `isAny` | Multiple items | `OR`. The item's field is present in a list of values. | Author is any: Admin, Editor |
| `isNone` | Multiple items | `NOT OR`. The item's field is not present in a list of values. | Author is none: Admin, Editor |
| `isAll` | Multiple items | `AND`. The item's field has all of the values in the list. | Category is all: Book, Review, Science Fiction |
| Operator | Selection | Description | Example |
| ---------- | -------------- | ----------------------------------------------------------------------- | -------------------------------------------------- |
| `is` | Single item | `EQUAL TO`. The item's field is equal to a single value. | Author is Admin |
| `isNot` | Single item | `NOT EQUAL TO`. The item's field is not equal to a single value. | Author is not Admin |
| `isAny` | Multiple items | `OR`. The item's field is present in a list of values. | Author is any: Admin, Editor |
| `isNone` | Multiple items | `NOT OR`. The item's field is not present in a list of values. | Author is none: Admin, Editor |
| `isAll` | Multiple items | `AND`. The item's field has all of the values in the list. | Category is all: Book, Review, Science Fiction |
| `isNotAll` | Multiple items | `NOT AND`. The item's field doesn't have all of the values in the list. | Category is not all: Book, Review, Science Fiction |

`is` and `isNot` are single-selection operators, while `isAny`, `isNone`, `isAll`, and `isNotALl` are multi-selection. By default, a filter with no operators declared will support the `isAny` and `isNone` multi-selection operators. A filter cannot mix single-selection & multi-selection operators; if a single-selection operator is present in the list of valid operators, the multi-selection ones will be discarded and the filter won't allow selecting more than one item.
Expand Down
4 changes: 3 additions & 1 deletion packages/dataviews/src/bulk-actions-toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@ function ActionTrigger< Item extends AnyItem >( {
isBusy,
items,
}: ActionTriggerProps< Item > ) {
const label =
typeof action.label === 'string' ? action.label : action.label( items );
return (
<ToolbarButton
disabled={ isBusy }
label={ action.getLabel?.( items ) || action.label }
label={ label }
icon={ action.icon }
isDestructive={ action.isDestructive }
size="compact"
Expand Down
6 changes: 5 additions & 1 deletion packages/dataviews/src/bulk-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,13 @@ function ActionWithModal< Item extends AnyItem >( {
const onCloseModal = useCallback( () => {
setActionWithModal( undefined );
}, [ setActionWithModal ] );
const label =
typeof action.label === 'string'
? action.label
: action.label( selectedItems );
return (
<Modal
title={ ! hideModalHeader ? action.label : undefined }
title={ ! hideModalHeader ? label : undefined }
__experimentalHideHeader={ !! hideModalHeader }
onRequestClose={ onCloseModal }
overlayClassName="dataviews-action-modal"
Expand Down
14 changes: 9 additions & 5 deletions packages/dataviews/src/item-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ function ButtonTrigger< Item extends AnyItem >( {
onClick,
items,
}: ActionTriggerProps< Item > ) {
const label =
typeof action.label === 'string' ? action.label : action.label( items );
return (
<Button
label={ action.getLabel?.( items ) || action.label }
label={ label }
icon={ action.icon }
isDestructive={ action.isDestructive }
size="compact"
Expand All @@ -86,14 +88,14 @@ function DropdownMenuItemTrigger< Item extends AnyItem >( {
onClick,
items,
}: ActionTriggerProps< Item > ) {
const label =
typeof action.label === 'string' ? action.label : action.label( items );
return (
<DropdownMenuItem
onClick={ onClick }
hideOnClick={ ! ( 'RenderModal' in action ) }
>
<DropdownMenuItemLabel>
{ action.getLabel?.( items ) || action.label }
</DropdownMenuItemLabel>
<DropdownMenuItemLabel>{ label }</DropdownMenuItemLabel>
</DropdownMenuItem>
);
}
Expand All @@ -103,9 +105,11 @@ export function ActionModal< Item extends AnyItem >( {
items,
closeModal,
}: ActionModalProps< Item > ) {
const label =
typeof action.label === 'string' ? action.label : action.label( items );
return (
<Modal
title={ action.modalHeader || action.label }
title={ action.modalHeader || label }
__experimentalHideHeader={ !! action.hideModalHeader }
onRequestClose={ closeModal ?? ( () => {} ) }
overlayClassName={ `dataviews-action-modal dataviews-action-modal__${ kebabCase(
Expand Down
11 changes: 3 additions & 8 deletions packages/dataviews/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,17 +285,12 @@ interface ActionBase< Item extends AnyItem > {
*/
id: string;

/**
* Getter function to return the label of the action in case
* we want to adjust the label based on the selected items.
* It takes precedence over the `label` prop.
*/
getLabel?: ( items: Item[] ) => string;

/**
* The label of the action.
* In case we want to adjust the label based on the selected items,
* a function can be provided.
*/
label?: string;
label: string | ( ( items: Item[] ) => string );

/**
* The icon of the action. (Either a string or an SVG element)
Expand Down
9 changes: 7 additions & 2 deletions packages/dataviews/src/view-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ function ListItem< Item extends AnyItem >( {
}, [ actions, item ] );

const [ isModalOpen, setIsModalOpen ] = useState( false );
const primaryActionLabel =
primaryAction &&
( typeof primaryAction.label === 'string'
? primaryAction.label
: primaryAction.label( [ item ] ) );

return (
<CompositeRow
Expand Down Expand Up @@ -193,7 +198,7 @@ function ListItem< Item extends AnyItem >( {
store={ store }
render={
<Button
label={ primaryAction.label }
label={ primaryActionLabel }
icon={ primaryAction.icon }
isDestructive={
primaryAction.isDestructive
Expand Down Expand Up @@ -224,7 +229,7 @@ function ListItem< Item extends AnyItem >( {
store={ store }
render={
<Button
label={ primaryAction.label }
label={ primaryActionLabel }
icon={ primaryAction.icon }
isDestructive={
primaryAction.isDestructive
Expand Down
2 changes: 1 addition & 1 deletion packages/editor/src/components/post-actions/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ const viewPostAction = {

const postRevisionsAction = {
id: 'view-post-revisions',
getLabel( items ) {
label( items ) {
const revisionsCount =
items[ 0 ]._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0;
return sprintf(
Expand Down
6 changes: 3 additions & 3 deletions packages/editor/src/components/post-actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ export default function PostActions( { onActionPerformed, buttonProps } ) {

// Copied as is from packages/dataviews/src/item-actions.js
function DropdownMenuItemTrigger( { action, onClick, items } ) {
const label =
typeof action.label === 'string' ? action.label : action.label( items );
return (
<DropdownMenuItem
onClick={ onClick }
hideOnClick={ ! action.RenderModal }
>
<DropdownMenuItemLabel>
{ action.getLabel?.( items ) || action.label }
</DropdownMenuItemLabel>
<DropdownMenuItemLabel>{ label }</DropdownMenuItemLabel>
</DropdownMenuItem>
);
}
Expand Down

0 comments on commit 871c894

Please sign in to comment.