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

[RFR] Add Notification multiLine prop #6191

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
096e229
Upgrade MUI dependencies
Oct 5, 2021
ece6329
Update imports
Oct 5, 2021
26180df
Apply codemods
Oct 5, 2021
aeea05a
Migrate all makeStyles
Oct 5, 2021
ea5bc23
Fix popper usage
Oct 5, 2021
12927ad
Fix tests targetting user menu
Oct 5, 2021
58bd0ad
Ensure Login uses the theme only when inside a ThemeProvider
Oct 5, 2021
398713f
Temporarily disable loading state on SaveButton
Oct 5, 2021
14c701f
Migrate to new theme format and createTheme
Oct 5, 2021
ec419b1
Migrate auth components to new styling API
Oct 5, 2021
aa09a16
Migrate button components to new styling API
Oct 5, 2021
dc93163
Fix SkipNavigationButton
Oct 5, 2021
2bebe46
Migrate detail components to new styling API
Oct 5, 2021
815f826
Temporary richtextinput fix
Oct 6, 2021
2af0985
Migrate ra-no-code to fix build
Oct 6, 2021
3aea67a
Fix popperjs setup in jest to allow tests to run
Oct 6, 2021
4ed7de0
Restore useListController tests
Oct 6, 2021
4a22ed6
Migrate field components to new styling API
Oct 6, 2021
62f9659
Fix most button tests
Oct 6, 2021
e561c7a
Fix field tests
Oct 6, 2021
b3b91cb
Migrate form components to new styling API
Oct 6, 2021
f77221f
Fix ReferenceArrayField
Oct 7, 2021
fc454ad
Migrate layout components to new styling API
Oct 7, 2021
839916f
Migrate list filters components to new styling API
Oct 7, 2021
33ec296
Migrate list pagination components to new styling API
Oct 7, 2021
34a0f72
Migrate list datagrid components to new styling API
Oct 7, 2021
8a96953
Migrate list components to new styling API
Oct 7, 2021
d2f7d84
Migrate input components to new styling API
Oct 11, 2021
748786b
Cleanup menu
Oct 11, 2021
7c66b81
Fix popperjs related tests
Oct 11, 2021
ed29140
Fix many tests which needed the theme
Oct 11, 2021
553d155
Fix tests and warnings
Oct 11, 2021
cd054c7
Cleanup
Oct 11, 2021
3dfcb60
Migrate richtextinput to new style API
Oct 11, 2021
a72642c
Fix simple example vite config
Oct 11, 2021
b2970af
Fix ra-no-code
Oct 11, 2021
0e57a0a
Migrate simple example
Oct 11, 2021
fad0047
Fix simple example
Oct 11, 2021
bda15bd
Fix edit e2e test
Oct 12, 2021
f0f768e
Fix datagrid styles
Oct 12, 2021
2289437
Fix ecommerce demo
Oct 12, 2021
18c0ee5
Fix crm demo
Oct 12, 2021
5db255c
Merge pull request #6650 from marmelab/mui-upgrade
djhi Oct 12, 2021
5ebe0e6
Fix warning
Oct 12, 2021
dca0727
Just fix the onPageChange reference
Oct 12, 2021
a75ab2a
Merge pull request #6659 from WiXSL/fix-pagination-test
djhi Oct 12, 2021
edc1a0b
Add Notification multiLine prop
Apr 19, 2021
72aa9d5
Applied review
May 11, 2021
2c837fe
Improve docs
May 16, 2021
a4d6293
Allow a second signature of useNotify with two parameters
Sep 11, 2021
0a413a7
Applied prettier
Sep 11, 2021
9494221
Maintain `type` default value
Sep 11, 2021
6814feb
`type` must be optional
Sep 11, 2021
3e2275a
Added test
Sep 11, 2021
a532981
Added documentation and updated related examples with the new signatu…
Sep 11, 2021
94f3736
Fix NotificationProps type
Oct 12, 2021
866c535
Fix multiLine style
Oct 13, 2021
c31cfea
Add Notification multiLine prop
Apr 19, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
{
"paths": [
{
"name": "@material-ui/core",
"name": "@mui/material",
"importNames": ["makeStyles", "createMuiTheme"],
"message": "Please import from @material-ui/core/styles instead. See https://material-ui.com/guides/minimizing-bundle-size/#option-2 for more information"
"message": "Please import from @mui/material/styles instead. See https://material-ui.com/guides/minimizing-bundle-size/#option-2 for more information"
}
]
}
Expand Down
7 changes: 2 additions & 5 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,11 @@ Here's how to migrate the *Altering the Form Values before Submitting* example f
import * as React from 'react';
import { useCallback } from 'react';
import { useForm } from 'react-final-form';
import { SaveButton, Toolbar, useCreate, useRedirect, useNotify } from 'react-admin';
import { SaveButton, Toolbar, useCreate, useRedirect } from 'react-admin';

const SaveWithNoteButton = ({ handleSubmit, handleSubmitWithRedirect, ...props }) => {
const [create] = useCreate('posts');
const redirectTo = useRedirect();
const notify = useNotify();
const { basePath, redirect } = props;

const form = useForm();
Expand Down Expand Up @@ -171,9 +170,7 @@ const SaveWithNoteButton = props => {
},
{
onSuccess: ({ data: newRecord }) => {
notify('ra.notification.created', 'info', {
smart_count: 1,
});
notify('ra.notification.created', { messageArgs: { smart_count: 1 } });
redirectTo(redirect, basePath, newRecord.id, newRecord);
},
}
Expand Down
15 changes: 15 additions & 0 deletions __mocks__/@popperjs/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const mock = () => {
const PopperJS = jest.requireActual('@popperjs/core');
return {
placements: PopperJS.placements,
destroy: () => {},
scheduleUpdate: () => {},
forceUpdate: () => {},
render: function (this: any) {
return this.$options._renderChildren;
},
};
};

export default mock;
export { mock as createPopper };
2 changes: 1 addition & 1 deletion cypress/support/CreatePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default url => ({
descInput: '.ql-editor',
tab: index => `.form-tab:nth-of-type(${index})`,
title: '#react-admin-title',
userMenu: 'button[title="Profile"]',
userMenu: 'button[aria-label="Profile"]',
logout: '.logout',
},

Expand Down
4 changes: 2 additions & 2 deletions cypress/support/EditPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default url => ({
return `.ra-input-${name} label`;
}
if (type === 'reference-array-input') {
return `.ra-input div[role=combobox]`;
return `.ra-input div[role=combobox] input`;
}
return `.edit-page [name='${name}']`;
},
Expand All @@ -22,7 +22,7 @@ export default url => ({
cloneButton: '.button-clone',
tab: index => `.form-tab:nth-of-type(${index})`,
title: '#react-admin-title',
userMenu: 'button[title="Profile"]',
userMenu: 'button[aria-label="Profile"]',
logout: '.logout',
},

Expand Down
2 changes: 1 addition & 1 deletion cypress/support/ListPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default url => ({
selectAll: '.select-all',
selectedItem: '.select-item input:checked',
selectItem: '.select-item input',
userMenu: 'button[title="Profile"]',
userMenu: 'button[aria-label="Profile"]',
title: '#react-admin-title',
headroomUnfixed: '.headroom--unfixed',
headroomUnpinned: '.headroom--unpinned',
Expand Down
2 changes: 1 addition & 1 deletion cypress/support/ShowPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default (url, initialField = 'title') => ({
snackbar: 'div[role="alertdialog"]',
tabs: `.show-tab`,
tab: index => `.show-tab:nth-of-type(${index})`,
userMenu: 'button[title="Profile"]',
userMenu: 'button[aria-label="Profile"]',
logout: '.logout',
},

Expand Down
36 changes: 24 additions & 12 deletions docs/Actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -641,16 +641,17 @@ const NotifyButton = () => {
};
```

The callback takes 5 arguments:
- the message to display
- the level of the notification (`info`, `success` or `warning` - the default is `info`)
- an `options` object to pass to the `translate` function (because notification messages are translated if your admin has an `i18nProvider`). It is useful for inserting variables into the translation.
- an `undoable` boolean. Set it to `true` if the notification should contain an "undo" button
- a `duration` number. Set it to `0` if the notification should not be dismissible.
The callback takes 6 arguments:
- The message to display
- The level of the notification (`info`, `success` or `warning` - the default is `info`)
- An `options` object to pass to the `translate` function (because notification messages are translated if your admin has an `i18nProvider`). It is useful for inserting variables into the translation.
- An `undoable` boolean. Set it to `true` if the notification should contain an "undo" button
- A `duration` number. Set it to `0` if the notification should not be dismissible.
- A `multiLine` boolean. Set it to `true` if the notification message should be shown in more than one line.

Here are more examples of `useNotify` calls:

```jsx
```js
// notify a warning
notify(`This is a warning`, 'warning');
// pass translation arguments
Expand All @@ -659,6 +660,17 @@ notify('item.created', 'info', { resource: 'post' });
notify('Element updated', 'info', undefined, true);
```

**Tip**: The callback also allows a signature with only 2 arguments, the message to display and an object with the rest of the arguments

```js
// notify an undoable success message, with translation arguments
notify('Element deleted', {
type: 'success',
undoable: true,
messageArgs: { resource: 'post' }
});
```

**Tip**: When using `useNotify` as a side effect for an `undoable` Edit form, you MUST set the fourth argument to `true`, otherwise the "undo" button will not appear, and the actual update will never occur.

```jsx
Expand All @@ -669,7 +681,7 @@ const PostEdit = props => {
const notify = useNotify();

const onSuccess = () => {
notify(`Changes saved`, undefined, undefined, true);
notify('Changes saved`', { undoable: true });
};

return (
Expand Down Expand Up @@ -841,7 +853,7 @@ const ApproveButton = ({ record }) => {
+ onSuccess: () => {
redirect('/comments');
- notify('Comment approved');
+ notify('Comment approved', 'info', {}, true);
+ notify('Comment approved', { undoable: true });
},
onFailure: (error) => notify(`Error: ${error.message}`, 'warning'),
}
Expand Down Expand Up @@ -870,7 +882,7 @@ const ApproveButton = ({ record }) => {
mutationMode: 'undoable',
onSuccess: () => {
redirect('/comments');
notify('Comment approved', 'info', {}, true);
notify('Comment approved', { undoable: true });
},
onFailure: (error) => notify(`Error: ${error.message}`, 'warning'),
}
Expand Down Expand Up @@ -905,7 +917,7 @@ const ApproveButton = ({ record }) => {
mutationMode: 'undoable',
onSuccess: ({ data }) => {
redirect('/comments');
notify('Comment approved', 'info', {}, true);
notify('Comment approved', { undoable: true });
},
onFailure: (error) => notify(`Error: ${error.message}`, 'warning'),
}
Expand Down Expand Up @@ -987,7 +999,7 @@ const ApproveButton = ({ record }) => {
const options = {
mutationMode: 'undoable',
onSuccess: ({ data }) => {
notify('Comment approved', 'info', {}, true);
notify('Comment approved', { undoable: true });
redirect('/comments');
},
onFailure: (error) => notify(`Error: ${error.message}`, 'warning'),
Expand Down
15 changes: 9 additions & 6 deletions docs/CreateEdit.md
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ const PostEdit = props => {
const redirect = useRedirect();

const onSuccess = () => {
notify(`Changes saved`)
notify(`Changes saved`);
redirect('/posts');
refresh();
};
Expand All @@ -423,13 +423,16 @@ The default `onSuccess` function is:
```jsx
// for the <Create> component:
() => {
notify('ra.notification.created', 'info', { smart_count: 1 });
notify('ra.notification.created', { messageArgs: { smart_count: 1 } });
redirect('edit', basePath, data.id, data);
}

// for the <Edit> component:
() => {
notify('ra.notification.updated', 'info', { smart_count: 1 }, mutationMode === 'undoable');
notify('ra.notification.created', {
messageArgs: { smart_count: 1 },
undoable: mutationMode === 'undoable'
});
redirect('list', basePath, data.id, data);
}
```
Expand All @@ -448,7 +451,7 @@ const PostEdit = props => {
const redirect = useRedirect();

const onSuccess = ({ data }) => {
notify(`Changes to post "${data.title}" saved`)
notify(`Changes to post "${data.title}" saved`);
redirect('/posts');
refresh();
};
Expand Down Expand Up @@ -483,7 +486,7 @@ const PostEdit = props => {
const redirect = useRedirect();

const onFailure = (error) => {
notify(`Could not edit post: ${error.message}`)
notify(`Could not edit post: ${error.message}`);
redirect('/posts');
refresh();
};
Expand Down Expand Up @@ -2225,7 +2228,7 @@ const PostEdit = props => {
if (error.code == 123) {
notify('Could not save changes: concurrent edition in progress', 'warning');
} else {
notify('ra.notification.http_error', 'warning')
notify('ra.notification.http_error', 'warning');
}
redirect('list', props.basePath);
}
Expand Down
2 changes: 1 addition & 1 deletion docs/List.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ const CustomResetViewsButton = ({ selectedIds }) => {
onSuccess: () => {
refresh();
- notify('Posts updated');
+ notify('Posts updated', 'info', '{}, true); // the last argument forces the display of 'undo' in the notification
+ notify('Posts updated', { undoable: true }); // the last argument forces the display of 'undo' in the notification
unselectAll('posts');
},
onFailure: error => notify('Error: posts not updated', 'warning'),
Expand Down
14 changes: 14 additions & 0 deletions docs/Theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,20 @@ export default MyNotification;

**Tip**: if you use the `showNotification` action, then you can define `autoHideDuration` per message as the third parameter of the `showNotification` action creator.

You can also decide to customize the displaing of the message in a single line or in multiple lines by using the `multiLine` prop.

```diff
// in src/MyNotification.js
import { Notification } from 'react-admin';

- const MyNotification = props => <Notification {...props} autoHideDuration={5000} />;
+ const MyNotification = props => <Notification {...props} autoHideDuration={5000} multiLine />;

export default MyNotification;
```

**Tip**: if you use the `showNotification` action, then you can define `multiLine` per message as the fourth parameter of the `showNotification` action creator.

To use this custom notification component, pass it to a custom Layout, as explained above:

```jsx
Expand Down
108 changes: 54 additions & 54 deletions examples/crm/package.json
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
{
"name": "react-admin-crm",
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^4.12.1",
"@material-ui/icons": "^4.11.2",
"@nivo/bar": "^0.67.0",
"@nivo/core": "^0.67.0",
"date-fns": "^2.19.0",
"faker": "~5.4.0",
"lodash": "~4.17.5",
"prop-types": "^15.7.2",
"ra-data-fakerest": "^3.13.4",
"react": "^17.0.0",
"react-admin": "^3.15.0",
"react-beautiful-dnd": "^13.0.0",
"react-dom": "^17.0.0",
"react-scripts": "^4.0.1"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/classnames": "^2.2.9",
"@types/faker": "^5.1.7",
"@types/jest": "^26.0.19",
"@types/lodash": "~4.14.168",
"@types/react": "^17.0.20",
"@types/react-beautiful-dnd": "^13.0.0",
"@types/react-dom": "^17.0.9",
"rewire": "^5.0.0",
"source-map-explorer": "^2.0.0",
"typescript": "^4.4.0",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "node ./build.js",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"homepage": ".",
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
"name": "react-admin-crm",
"version": "0.1.0",
"private": true,
"dependencies": {
"@mui/material": "^5.0.2",
"@mui/icons-material": "^5.0.1",
"@nivo/bar": "^0.67.0",
"@nivo/core": "^0.67.0",
"date-fns": "^2.19.0",
"faker": "~5.4.0",
"lodash": "~4.17.5",
"prop-types": "^15.7.2",
"ra-data-fakerest": "^3.13.4",
"react": "^17.0.0",
"react-admin": "^3.15.0",
"react-beautiful-dnd": "^13.0.0",
"react-dom": "^17.0.0",
"react-scripts": "^4.0.1"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/classnames": "^2.2.9",
"@types/faker": "^5.1.7",
"@types/jest": "^26.0.19",
"@types/lodash": "~4.14.168",
"@types/react": "^17.0.20",
"@types/react-beautiful-dnd": "^13.0.0",
"@types/react-dom": "^17.0.9",
"rewire": "^5.0.0",
"source-map-explorer": "^2.0.0",
"typescript": "^4.4.0",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "node ./build.js",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"homepage": ".",
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Loading