Skip to content

Commit 0622e8c

Browse files
authored
Merge pull request #745 from marmelab/next
Prepare 1.2.0
2 parents d214df7 + 83a5f7e commit 0622e8c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+1799
-596
lines changed

CHANGELOG.md

+22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
# Changelog
22

3+
## v1.2.0
4+
5+
* Add ability to override redirect behavior on save for `<Create>` and `<Edit>` views ([wesley6j](https://github.com/wesley6j))
6+
* Add refresh button to `<Show>` view ([djhi](https://github.com/djhi))
7+
* Add asterisk to label on required `Input` ([djhi](https://github.com/djhi))
8+
* Add `<FileInput>` ([djhi](https://github.com/djhi))
9+
* Add sort feature to `<ReferenceManyField>` ([wesley6j](https://github.com/wesley6j))
10+
* Add ability to use custom history in `<Admin>` ([fzaninotto](https://github.com/fzaninotto))
11+
* Add `<TabbedShowLayout>` to mirror `<TabbedForm>` ([remi13131](https://github.com/remi13131))
12+
* Add `options` prop to `<BooleanInput>` and pass them to mui `<Toggle>` ([djhi](https://github.com/djhi))
13+
* Add `AOR/` prefix to Redux actions ([ThieryMichel](https://github.com/ThieryMichel))
14+
* Add deep path support for `optionText` and `optionValue` props the `Input` components used as `Reference` children ([mtakayuki](https://github.com/mtakayuki))
15+
* Add ability to override `<SimpleShowLayout>` container styles ([djhi](https://github.com/djhi))
16+
* Add `<MenuItemLink>` to fix bad click handling of menu on mobile ([djhi](https://github.com/djhi))
17+
* Add `aor-firebase-client` to the list of REST clients ([sidferreira](https://github.com/sidferreira))
18+
* Update redux-saga to 0.15.3 ([dervos](https://github.com/dervos))
19+
* Fix filter in `<ReferenceInput>` not taken into account when `<AutocompleteInput>` is filled ([djhi](https://github.com/djhi))
20+
* Fix `<ReferenceArrayField>` when ids is null ([wesley6j](https://github.com/wesley6j))
21+
* Fix missing translation helper in `<Show>` view ([djhi](https://github.com/djhi))
22+
* Fix code highlighting on REAMDE ([diegohaz](https://github.com/diegohaz))
23+
* Fix custom REST client list format for better readability ([fzaninotto](https://github.com/fzaninotto))
24+
325
## v1.1.2
426

527
* Fix a typo in tutorial ([calebhaye](https://github.com/calebhaye))

docs/Actions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,10 @@ function* commentApproveFailure({ error }) {
234234
}
235235

236236
export default function* commentSaga() {
237-
yield [
237+
yield all([
238238
takeEvery('COMMENT_APPROVE_SUCCESS', commentApproveSuccess),
239239
takeEvery('COMMENT_APPROVE_FAILURE', commentApproveFailure),
240-
];
240+
]);
241241
}
242242
```
243243

docs/Admin.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,20 @@ If you want to add or remove menu items, for instance to link to non-resources p
118118
```jsx
119119
// in src/Menu.js
120120
import React from 'react';
121-
import MenuItem from 'material-ui/MenuItem';
122-
import { Link } from 'react-router-dom';
121+
import { MenuItemLink } from 'admin-on-rest';
123122

124123
export default ({ resources, onMenuTap, logout }) => (
125124
<div>
126-
<MenuItem containerElement={<Link to="/posts" />} primaryText="Posts" onTouchTap={onMenuTap} />
127-
<MenuItem containerElement={<Link to="/comments" />} primaryText="Comments" onTouchTap={onMenuTap} />
128-
<MenuItem containerElement={<Link to="/custom-route" />} primaryText="Miscellaneous" onTouchTap={onMenuTap} />
125+
<MenuItemLink to="/posts" primaryText="Posts" onTouchTap={onMenuTap} />
126+
<MenuItemLink to="/comments" primaryText="Comments" onTouchTap={onMenuTap} />
127+
<MenuItemLink to="/custom-route" primaryText="Miscellaneous" onTouchTap={onMenuTap} />
129128
{logout}
130129
</div>
131130
);
132131
```
133132

133+
**Tip**: Note the `MenuItemLink` component. It must be used to avoid unwanted side effects in mobile views.
134+
134135
Then, pass it to the `<Admin>` component as the `menu` prop:
135136

136137
```jsx

docs/CreateEdit.md

+82-7
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ Here are all the props accepted by the `<SimpleForm>` component:
157157

158158
* [`defautValue`](#default-values)
159159
* [`validation`](#validation)
160+
* [`submitOnEnter`](#submit-on-enter)
161+
* [`redirect`](#redirection-after-submission)
162+
* [`toolbar`](#toolbar)
160163

161164
```jsx
162165
export const PostCreate = (props) => (
@@ -183,6 +186,9 @@ Here are all the props accepted by the `<TabbedForm>` component:
183186

184187
* [`defautValue`](#default-values)
185188
* [`validation`](#validation)
189+
* [`submitOnEnter`](#submit-on-enter)
190+
* [`redirect`](#redirection-after-submission)
191+
* [`toolbar`](#toolbar)
186192

187193
{% raw %}
188194
```jsx
@@ -336,7 +342,7 @@ Input validation functions receive the current field value, and the values of al
336342
**Tip**: Validator functions receive the form `props` as third parameter, including the `translate` function. This lets you build internationalized validators:
337343

338344
```jsx
339-
const required = (value, _, props) => value ? undefined : props.translate('myroot.validation.required');
345+
const required = (value, allValues, props) => value ? undefined : props.translate('myroot.validation.required');
340346
```
341347

342348
**Tip**: The props of your Input components are passed to a redux-form `<Field>` component. So in addition to `validate`, you can also use `warn`.
@@ -348,13 +354,13 @@ const required = (value, _, props) => value ? undefined : props.translate('myroo
348354
Admin-on-rest already bundles a few validator functions, that you can just require and use as field validators:
349355

350356
* `required` if the field is mandatory,
351-
* `minValue` to specify a minimum value for integers,
352-
* `maxValue` to specify a maximum value for integers,
353-
* `minLength` to specify a minimum length for strings,
354-
* `maxLength` to specify a maximum length for strings,
357+
* `minValue(min, message)` to specify a minimum value for integers,
358+
* `maxValue(max, message)` to specify a maximum value for integers,
359+
* `minLength(min, message)` to specify a minimum length for strings,
360+
* `maxLength(max, message)` to specify a maximum length for strings,
355361
* `email` to check that the input is a valid email address,
356-
* `regex` to validate that the input matches a regex,
357-
* `choices` to validate that the input is within a given list,
362+
* `regex(pattern, message)` to validate that the input matches a regex,
363+
* `choices(list, message)` to validate that the input is within a given list,
358364

359365
Example usage:
360366

@@ -376,3 +382,72 @@ export const UserCreate = (props) => (
376382
</Create>
377383
);
378384
```
385+
386+
## Submit On Enter
387+
388+
By default, pressing `ENTER` in any of the form fields submits the form - this is the expected behavior in most cases. However, some of your custom input components (e.g. Google Maps widget) may have special handlers for the `ENTER` key. In that case, to disable the automated form submission on enter, set the `submitOnEnter` prop of the form component to `false`:
389+
390+
```jsx
391+
export const PostEdit = (props) => (
392+
<Edit {...props}>
393+
<SimpleForm submitOnEnter={false}>
394+
...
395+
</SimpleForm>
396+
</Edit>
397+
);
398+
```
399+
400+
## Redirection After Submission
401+
402+
By default:
403+
404+
- Submitting the form in the `<Create>` view redirects to the `<Edit>` view
405+
- Submitting the form in the `<Edit>` view redirects to the `<List>` view
406+
407+
You can customize the redirection by setting the `redirect` prop of the form component. Possible values are "edit", "show", "list", and `false` to disable redirection. For instance, to redirect to the `<Show>` view after edition:
408+
409+
```jsx
410+
export const PostEdit = (props) => (
411+
<Edit {...props}>
412+
<SimpleForm redirect="show">
413+
...
414+
</SimpleForm>
415+
</Edit>
416+
);
417+
```
418+
419+
This affects both the submit button, and the form submission when the user presses `ENTER` in one of the form fields.
420+
421+
## Toolbar
422+
423+
At the bottom of the form, the toolbar displays the submit button. You can override this component by setting the `toolbar` prop, to display the buttons of your choice.
424+
425+
The most common use case is to display two submit buttons in the `<Create>` view:
426+
427+
- one that creates and redirects to the `<Show>` view of the new resource, and
428+
- one that redirects to a blank `<Create>` view after creation (allowing bulk creation)
429+
430+
![Form toolbar](./img/form-toolbar.png)
431+
432+
For that use case, use the `<SaveButton>` component with a custom `redirect` prop:
433+
434+
```jsx
435+
impot { SaveButton, Toolbar } from 'admin-on-rest';
436+
437+
const PostCreateToolbar = props => <Toolbar {...props} >
438+
<SaveButton label="post.action.save_and_show" redirect="show" submitOnEnter={true} />
439+
<SaveButton label="post.action.save_and_add" redirect={false} submitOnEnter={false} raised={false} />
440+
</Toolbar>;
441+
442+
export const PostEdit = (props) => (
443+
<Edit {...props}>
444+
<SimpleForm toolbar={<PostCreateToolbar />} redirect="show">
445+
...
446+
</SimpleForm>
447+
</Edit>
448+
);
449+
```
450+
451+
**Tip**: Use admin-on-rest's `<Toolbar>` component instead of material-ui's `<Toolbar>` component. The former builds up on the latter, and adds support for an alternative mobile layout (and is therefore responsive).
452+
453+
**Tip**: Don't forget to also set the `redirect` prop of the Form component to handle submission by the `ENTER` key.

docs/Fields.md

+55
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,61 @@ The optional `title` prop points to the picture title property, used for both `a
184184

185185
If passed value is an existing path within your JSON object, then it uses the object attribute. Otherwise, it considers its value as an hard-written title.
186186

187+
188+
If the record actually contains an array of images in its property defined by the `source` prop, the `src` prop will be needed to determine the `src` value of the images, for example:
189+
190+
```js
191+
// This is the record
192+
{
193+
pictures: [
194+
{ url: 'image1.jpg', desc: 'First image' },
195+
{ url: 'image2.jpg', desc: 'Second image' },
196+
],
197+
}
198+
199+
<ImageField source="pictures" src="url" title="desc" />
200+
```
201+
202+
## `<FileField>`
203+
204+
If you need to display a file provided by your API, you can use the `<FileField />` component:
205+
206+
```jsx
207+
import { FileField } from 'admin-on-rest';
208+
209+
<FileField source="url" title="title" />
210+
```
211+
212+
This field is also generally used within an [<FileInput />](http://marmelab.com/admin-on-rest/Inputs.html#fileinput) component to display preview.
213+
214+
The optional `title` prop points to the file title property, used for `title` attributes. It can either be an hard-written string, or a path within your JSON object:
215+
216+
```jsx
217+
// { file: { url: 'doc.pdf', title: 'Presentation' } }
218+
219+
// Title would be "file.title", hence "Presentation"
220+
<FileField source="file.url" title="file.title" />
221+
222+
// Title would be "File", as "File" is not a path in previous given object
223+
<FileField source="file.url" title="File" />
224+
```
225+
226+
If passed value is an existing path within your JSON object, then it uses the object attribute. Otherwise, it considers its value as an hard-written title.
227+
228+
If the record actually contains an array of files in its property defined by the `source` prop, the `src` prop will be needed to determine the `href` value of the links, for example:
229+
230+
```js
231+
// This is the record
232+
{
233+
files: [
234+
{ url: 'image1.jpg', desc: 'First image' },
235+
{ url: 'image2.jpg', desc: 'Second image' },
236+
],
237+
}
238+
239+
<FileField source="files" src="url" title="desc" />
240+
```
241+
187242
## `<NumberField>`
188243

189244
Displays a number formatted according to the browser locale, right aligned.

docs/Inputs.md

+48-2
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,18 @@ import { BooleanInput } from 'admin-on-rest';
166166

167167
This input does not handle `null` values. You would need the `<NullableBooleanInput />` component if you have to handle non-set booleans.
168168

169+
You can use the `options` prop to pass any option supported by the Material UI `Toggle` components.
170+
171+
{% raw %}
172+
```jsx
173+
<BooleanInput source="finished" options={{
174+
labelPosition: 'right'
175+
}} />
176+
```
177+
{% endraw %}
178+
179+
Refer to [Material UI Toggle documentation](http://www.material-ui.com/#/components/toggle) for more details.
180+
169181
`<NullableBooleanInput />` renders as a dropdown list, allowing to choose between true, false, and null values.
170182

171183
```jsx
@@ -345,9 +357,13 @@ Previews are enabled using `<ImageInput>` children, as following:
345357
</ImageInput>
346358
```
347359

348-
This component accepts all [react-dropzone properties](https://github.com/okonet/react-dropzone#features), in addition to those of admin-on-rest. For instance, if you need to upload several images at once, just add the `multiple` DropZone attribute to your `<ImageInput />` field.
360+
Writing a custom field component for displaying the current value(s) is easy: it's a standard [field](./Fields.html#writing_your_own_field_component).
361+
362+
When receiving **new** files, `ImageInput` will add a `rawFile` property to the object passed as the `record` prop of children. This `rawFile` is the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) instance of the newly added file. This can be useful to display informations about size or mimetype inside a custom field.
363+
364+
The `ImageInput` component accepts all [react-dropzone properties](https://github.com/okonet/react-dropzone#features), in addition to those of admin-on-rest. For instance, if you need to upload several images at once, just add the `multiple` DropZone attribute to your `<ImageInput />` field.
349365

350-
If the default Dropzone label don't fit with your need, you can pass a `placeholder` attribute to overwrite it. The attribute can be anything React can render (`PropTypes.node`):
366+
If the default Dropzone label doesn't fit with your need, you can pass a `placeholder` attribute to overwrite it. The attribute can be anything React can render (`PropTypes.node`):
351367

352368
```jsx
353369
<ImageInput source="pictures" label="Related pictures" accept="image/*" placeholder={<p>Drop your file here</p>}>
@@ -357,6 +373,36 @@ If the default Dropzone label don't fit with your need, you can pass a `placehol
357373

358374
Note that the image upload returns a [File](https://developer.mozilla.org/en/docs/Web/API/File) object. It is your responsibility to handle it depending on your API behavior. You can for instance encode it in base64, or send it as a multi-part form data. Check [this example](./RestClients.html#decorating-your-rest-client-example-of-file-upload) for base64 encoding data by extending the REST Client.
359375

376+
## `<FileInput>`
377+
378+
`<FileInput>` allows to upload some files using [react-dropzone](https://github.com/okonet/react-dropzone).
379+
380+
![FileInput](./img/file-input.png)
381+
382+
Previews (actually a simple list of files names) are enabled using `<FileInput>` children, as following:
383+
384+
```jsx
385+
<FileInput source="files" label="Related files" accept="application/pdf">
386+
<FileField source="src" title="title" />
387+
</FileInput>
388+
```
389+
390+
Writing a custom field component for displaying the current value(s) is easy: it's a standard [field](./Fields.html#writing_your_own_field_component).
391+
392+
When receiving **new** files, `FileInput` will add a `rawFile` property to the object passed as the `record` prop of children. This `rawFile` is the [File](https://developer.mozilla.org/en-US/docs/Web/API/File) instance of the newly added file. This can be useful to display informations about size or mimetype inside a custom field.
393+
394+
The `FileInput` component accepts all [react-dropzone properties](https://github.com/okonet/react-dropzone#features), in addition to those of admin-on-rest. For instance, if you need to upload several files at once, just add the `multiple` DropZone attribute to your `<FileInput />` field.
395+
396+
If the default Dropzone label doesn't fit with your need, you can pass a `placeholder` attribute to overwrite it. The attribute can be anything React can render (`PropTypes.node`):
397+
398+
```jsx
399+
<FileInput source="files" label="Related files" accept="application/pdf" placeholder={<p>Drop your file here</p>}>
400+
<ImageField source="src" title="title" />
401+
</FileInput>
402+
```
403+
404+
Note that the file upload returns a [File](https://developer.mozilla.org/en/docs/Web/API/File) object. It is your responsibility to handle it depending on your API behavior. You can for instance encode it in base64, or send it as a multi-part form data. Check [this example](./RestClients.html#decorating-your-rest-client-example-of-file-upload) for base64 encoding data by extending the REST Client.
405+
360406
## `<LongTextInput>`
361407

362408
`<LongTextInput>` is the best choice for multiline text values. It renders as an auto expandable textarea.

docs/Reference.md

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ title: "Reference"
3535
* `<EditActions>`
3636
* `<EditButton>`
3737
* [`<EmailField>`](./Fields.html#emailfield)
38+
* [`<FileField>`](./Fields.html#filefield)
39+
* [`<FileInput>`](./Inputs.html#fileinput)
3840
* [`<Filter>`](./List.html#filters)
3941
* `<FilterButton>`
4042
* `<FilterForm>`
@@ -82,7 +84,9 @@ title: "Reference"
8284
* [`<SimpleList>`](./List.html#the-simplelist-component)
8385
* [`<SimpleShowLayout>`](./Show.html#the-simpleshowlayout-component)
8486
* [`<SingleFieldList>`](./List.html#the-singlefieldlist-component)
87+
* `<Tab>`
8588
* [`<TabbedForm>`](./CreateEdit.html#the-tabbedform-component)
89+
* `<TabbedShowLayout>`
8690
* [`<TextField>`](./Fields.html#textfield)
8791
* [`<TextInput>`](./Inputs.html#textinput)
8892
* `<Title>`

docs/Show.md

+23
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,26 @@ export const PostShow = (props) => (
135135
</Show>
136136
);
137137
```
138+
139+
It is possible to override its style by specifying the `style` prop, for example:
140+
141+
```jsx
142+
const styles = {
143+
container: {
144+
display: 'flex',
145+
},
146+
item: {
147+
marginRight: '1rem',
148+
},
149+
};
150+
151+
export const PostShow = (props) => (
152+
<Show {...props}>
153+
<SimpleShowLayout style={styles.container}>
154+
<TextField source="title" style={styles.item} />
155+
<RichTextField source="body" style={styles.item} />
156+
<NumberField source="nb_views" style={styles.item} />
157+
</SimpleShowLayout>
158+
</Show>
159+
);
160+
```

0 commit comments

Comments
 (0)