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

Add SelectColumns and DatagridConfigurable #8274

Merged
merged 28 commits into from
Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c88933e
Proof of concept
fzaninotto Oct 17, 2022
35eace9
Add ability to omit columns by default
fzaninotto Oct 17, 2022
cc49be2
Add inspector title
fzaninotto Oct 17, 2022
f2b203c
simplify story
fzaninotto Oct 17, 2022
dfa9546
Use DatagridConfigurable in PostList
fzaninotto Oct 17, 2022
740d35c
More robust CSS targeting
fzaninotto Oct 17, 2022
a9a4231
throw error when using optimized prop
fzaninotto Oct 18, 2022
9608a4f
Add hide all / show all buttons
fzaninotto Oct 18, 2022
9c90cd0
Lest DatagridConfigurable accept columns in any order
fzaninotto Oct 18, 2022
639bd50
Add ColumnsButton
fzaninotto Oct 18, 2022
f3528d5
Fix reselect column in DatagridEditor
fzaninotto Oct 18, 2022
c4511f7
Fix ColumnsButton doesn't honor omit prop
fzaninotto Oct 18, 2022
d5989ee
Allow to show/hide fields without source
fzaninotto Oct 18, 2022
2d97915
Add DatagridConfigurable test
fzaninotto Oct 18, 2022
7f41b22
Document DatagridConfigurable
fzaninotto Oct 18, 2022
3d645f4
Rename ColumnsButton to SelectColumnsButton
fzaninotto Oct 18, 2022
af07b21
document preferenceKey
fzaninotto Oct 18, 2022
cc0a8f0
Add tests for omit and preferenceKey props
fzaninotto Oct 19, 2022
efe8921
Add SelectColumnsButton story
fzaninotto Oct 19, 2022
4ce3d7b
Add unit tests for SelectColumnsButton
fzaninotto Oct 19, 2022
274b417
Document SelectColumnsButton
fzaninotto Oct 19, 2022
022a31e
Add index entry for SelectColumnsButton
fzaninotto Oct 19, 2022
c5dc165
Add column selector to orders list
fzaninotto Oct 19, 2022
b938bab
Review
fzaninotto Oct 20, 2022
05ec504
Fix problem with persistent storage of available columns
fzaninotto Oct 20, 2022
34d8557
Update packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurab…
fzaninotto Oct 20, 2022
0a661d7
Review
fzaninotto Oct 21, 2022
dfdc23c
Fix bad copy/paste
fzaninotto Oct 21, 2022
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
100 changes: 100 additions & 0 deletions docs/Datagrid.md
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,7 @@ The `<Datagrid>` component accepts the usual `className` prop. You can also over

| Rule name | Description |
| ------------------------------ |--------------------------------------------------|
| `& .RaDatagrid-root` | Applied to the root div element |
| `& .RaDatagrid-tableWrapper` | Applied to the div that wraps table element |
| `& .RaDatagrid-table` | Applied to the table element |
| `& .RaDatagrid-thead` | Applied to the table header |
Expand Down Expand Up @@ -797,6 +798,105 @@ const PostList = () => (
```
{% endraw %}

## Showing / Hiding Columns

The [`<SelectColumnsButton>`](./SelectColumnsButton.md) lets users hide or show datagrid columns.

![SelectColumnsButton](./img/SelectColumnsButton.gif)

```jsx
import {
DatagridConfigurable,
List,
SelectColumnsButton,
TextField,
TopToolbar,
} from "react-admin";

const PostListActions = () => (
<TopToolbar>
<SelectColumnsButton />
</TopToolbar>
);

const PostList = () => (
<List actions={<PostListActions />}>
<DatagridConfigurable>
<TextField source="id" />
<TextField source="title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
</List>
);
```

`<SelectColumnsButton>` must be used in conjunction with `<DatagridConfigurable>`, the configurable version of `<Datagrid>`, described in the next section.

## Configurable

You can let end users customize the fields displayed in the `<Datagrid>` by using the `<DatagridConfigurable>` component instead.

![DatagridConfigurable](./img/DatagridConfigurable.gif)

```diff
import {
List,
- Datagrid,
+ DatagridConfigurable,
TextField,
} from 'react-admin';

const PostList = () => (
<List>
- <Datagrid>
+ <DatagridConfigurable>
<TextField source="id" />
<TextField source="title" />
<TextField source="author" />
<TextField source="year" />
- </Datagrid>
+ </DatagridConfigurable>
</List>
);
```

When users enter the configuration mode and select the `<Datagrid>`, they can show / hide datagrid columns. They can also use the [`<SelectColumnsButton>`](./SelectColumnsButton.md)

By default, `<DatagridConfigurable>` renders all child fields. But you can also omit some of them by passing an `omit` prop containing an array of field sources:

```jsx
// by default, hide the id and author columns
// users can choose to show them in configuration mode
const PostList = () => (
<List>
<DatagridConfigurable omit={['id', 'author']}>
<TextField source="id" />
<TextField source="title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
</List>
);
```

If you render more than one `<DatagridConfigurable>` in the same page, you must pass a unique `preferenceKey` prop to each one:

```jsx
const PostList = () => (
<List>
<DatagridConfigurable preferenceKey="posts.datagrid">
<TextField source="id" />
<TextField source="title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
</List>
);
```

`<DatagridConfigurable>` accepts the same props as `<Datagrid>`.

## Customizing Column Sort

![Sort Column Header](./img/sort-column-header.gif)
Expand Down
2 changes: 1 addition & 1 deletion docs/Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ title: "Reference"
* [`<Search>`](https://marmelab.com/ra-enterprise/modules/ra-search#the-search-component)<img class="icon" src="./img/premium.svg" />
* [`<SearchInput>`](./FilteringTutorial.md#searchinput)
* [`<SelectArrayInput>`](./SelectArrayInput.md)
* [`<SelectColumnsButton>`](https://marmelab.com/ra-enterprise/modules/ra-preferences#selectcolumnsbutton-store-datagrid-columns-in-preferences)<img class="icon" src="./img/premium.svg" />
* [`<SelectColumnsButton>`](./SelectColumnsButton.md)
* [`<SelectField>`](./SelectField.md)
* [`<SelectInput>`](./SelectInput.md)
* [`<Show>`](./Show.md#show)
Expand Down
83 changes: 83 additions & 0 deletions docs/SelectColumnsButton.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
layout: default
title: "The SelectColumnsButton Component"
---

# `<SelectColumnsButton>`

This button lets users show or hide columns in a Datagrid. It must be used in conjunction with [`<DatagridConfigurable>`](./Datagrid.md#configurable).

![SelectColumnsButton](./img/SelectColumnsButton.gif)

```jsx
import {
DatagridConfigurable,
List,
SelectColumnsButton,
TextField,
TopToolbar,
} from "react-admin";

const PostListActions = () => (
<TopToolbar>
<SelectColumnsButton />
</TopToolbar>
);

const PostList = () => (
<List actions={<PostListActions />}>
<DatagridConfigurable>
<TextField source="id" />
<TextField source="title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
</List>
);
```

**Note**: `<SelectColumnsButton>` doesn't work with `<Datagrid>` - you must use `<DatagridConfigurable>` instead.

If you want to add the `<SelectColumnsButton>` to the usual List Actions, use the following snippet:

```jsx
const ListActions = () => (
<TopToolbar>
<SelectColumnsButton />
<FilterButton />
<CreateButton />
<ExportButton />
</TopToolbar>
);
```

## `preferenceKey`

If you include `<SelectColumnsButton>` in a page that has more than one `<DatagridConfigurable>` (e.g. in a dasboard), you have to link the two components by giving them the same `preferenceKey`:

```jsx
const BookList = () => {
const { data, total, isLoading } = useGetList('books', {
pagination: { page: 1, perPage: 10 },
sort,
});
return (
<div>
<SelectColumnsButton preferenceKey="postList1" />
<DatagridConfigurable
preferenceKey="postList1"
data={data}
total={total}
isLoading={isLoading}
sort={sort}
bulkActionButtons={false}
>
<TextField source="id" />
<TextField source="title" />
<TextField source="author" />
<TextField source="year" />
</DatagridConfigurable>
</div>
);
};
```
Binary file added docs/img/DatagridConfigurable.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/SelectColumnsButton.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
<li {% if page.path == 'SavedQueriesList.md' %} class="active" {% endif %}><a class="nav-link" href="./SavedQueriesList.html"><code>&lt;SavedQueriesList&gt;</code></a></li>
<li {% if page.path == 'Pagination.md' %} class="active" {% endif %}><a class="nav-link" href="./Pagination.html"><code>&lt;Pagination&gt;</code></a></li>
<li {% if page.path == 'SortButton.md' %} class="active" {% endif %}><a class="nav-link" href="./SortButton.html"><code>&lt;SortButton&gt;</code></a></li>
<li {% if page.path == 'SelectColumnsButton.md' %} class="active" {% endif %}><a class="nav-link" href="./SelectColumnsButton.html"><code>&lt;SelectColumnsButton&gt;</code></a></li>
<li {% if page.path == 'useList.md' %} class="active" {% endif %}><a class="nav-link" href="./useList.html"><code>useList</code></a></li>
fzaninotto marked this conversation as resolved.
Show resolved Hide resolved
<li {% if page.path == 'useListContext.md' %} class="active" {% endif %}><a class="nav-link" href="./useListContext.html"><code>useListContext</code></a></li>
<li {% if page.path == 'useListController.md' %} class="active" {% endif %}><a class="nav-link" href="./useListController.html"><code>useListController</code></a></li>
Expand Down
103 changes: 92 additions & 11 deletions examples/demo/src/orders/OrderList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Fragment, useCallback } from 'react';
import {
AutocompleteInput,
BooleanField,
Datagrid,
DatagridConfigurable,
DateField,
DateInput,
List,
Expand All @@ -16,6 +16,10 @@ import {
TextInput,
useGetList,
useListContext,
TopToolbar,
SelectColumnsButton,
FilterButton,
ExportButton,
} from 'react-admin';
import { useMediaQuery, Divider, Tabs, Tab, Theme } from '@mui/material';

Expand All @@ -25,12 +29,21 @@ import AddressField from '../visitors/AddressField';
import MobileGrid from './MobileGrid';
import { Customer } from '../types';

const ListActions = () => (
<TopToolbar>
<SelectColumnsButton />
<FilterButton />
<ExportButton />
</TopToolbar>
);

const OrderList = () => (
<List
filterDefaultValues={{ status: 'ordered' }}
sort={{ field: 'date', order: 'DESC' }}
perPage={25}
filters={orderFilters}
actions={<ListActions />}
>
<TabbedDatagrid />
</List>
Expand Down Expand Up @@ -130,7 +143,10 @@ const TabbedDatagrid = () => {
) : (
<>
{filterValues.status === 'ordered' && (
<Datagrid optimized rowClick="edit">
<DatagridConfigurable
rowClick="edit"
omit={['total_ex_taxes', 'delivery_fees', 'taxes']}
>
<DateField source="date" showTime />
<TextField source="reference" />
<CustomerReferenceField />
Expand All @@ -143,6 +159,27 @@ const TabbedDatagrid = () => {
<AddressField />
</ReferenceField>
<NbItemsField />
<NumberField
source="total_ex_taxes"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="delivery_fees"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="taxes"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="total"
options={{
Expand All @@ -151,10 +188,13 @@ const TabbedDatagrid = () => {
}}
sx={{ fontWeight: 'bold' }}
/>
</Datagrid>
</DatagridConfigurable>
)}
{filterValues.status === 'delivered' && (
<Datagrid rowClick="edit">
<DatagridConfigurable
rowClick="edit"
omit={['total_ex_taxes', 'delivery_fees', 'taxes']}
>
<DateField source="date" showTime />
<TextField source="reference" />
<CustomerReferenceField />
Expand All @@ -167,6 +207,27 @@ const TabbedDatagrid = () => {
<AddressField />
</ReferenceField>
<NbItemsField />
<NumberField
source="total_ex_taxes"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="delivery_fees"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="taxes"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="total"
options={{
Expand All @@ -179,10 +240,13 @@ const TabbedDatagrid = () => {
source="returned"
sx={{ mt: -0.5, mb: -0.5 }}
/>
</Datagrid>
</DatagridConfigurable>
)}
{filterValues.status === 'cancelled' && (
<Datagrid rowClick="edit">
<DatagridConfigurable
rowClick="edit"
omit={['total_ex_taxes', 'delivery_fees', 'taxes']}
>
<DateField source="date" showTime />
<TextField source="reference" />
<CustomerReferenceField />
Expand All @@ -195,6 +259,27 @@ const TabbedDatagrid = () => {
<AddressField />
</ReferenceField>
<NbItemsField />
<NumberField
source="total_ex_taxes"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="delivery_fees"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="taxes"
options={{
style: 'currency',
currency: 'USD',
}}
/>
<NumberField
source="total"
options={{
Expand All @@ -203,11 +288,7 @@ const TabbedDatagrid = () => {
}}
sx={{ fontWeight: 'bold' }}
/>
<BooleanField
source="returned"
sx={{ mt: -0.5, mb: -0.5 }}
/>
</Datagrid>
</DatagridConfigurable>
)}
</>
)}
Expand Down
Loading