Skip to content

Commit 5a6f053

Browse files
helios-agdunglas
authored andcommitted
Added example usage of react-admin Admin component (#619)
* Added example usage of react-admin Admin component instead of HydraAdmin and AdminBuilder * Update getting-started.md
1 parent 5afec80 commit 5a6f053

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

admin/getting-started.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,170 @@ export default class extends Component {
228228
}
229229
}
230230
```
231+
232+
### Using the Hydra Data Provider Directly with react-admin
233+
234+
By default, the `HydraAdmin` component shipped with API Platform Admin will generate a convenient admin interface for every resources and every properties exposed by the API. But sometimes, you may prefer having full control over the generated admin.
235+
236+
To do so, an alternative approach is [to configure every react-admin components manually](https://marmelab.com/react-admin/Tutorial.html) instead of letting the library generating it, but to still leverage the built-in Hydra [data provider](https://marmelab.com/react-admin/DataProviders.html):
237+
238+
```javascript
239+
// admin/src/App.js
240+
241+
import React, { Component } from 'react';
242+
import { Admin, Resource } from 'react-admin';
243+
import parseHydraDocumentation from '@api-platform/api-doc-parser/lib/hydra/parseHydraDocumentation';
244+
import { hydraClient, fetchHydra as baseFetchHydra } from '@api-platform/admin';
245+
import authProvider from './authProvider';
246+
import { Redirect } from 'react-router-dom';
247+
import { createMuiTheme } from '@material-ui/core/styles';
248+
import Layout from './Component/Layout';
249+
import { UserShow } from './Components/User/Show';
250+
import { UserEdit } from './Components/User/Edit';
251+
import { UserCreate } from './Components/User/Create';
252+
import { UserList } from './Components/User/List';
253+
254+
const theme = createMuiTheme({
255+
palette: {
256+
type: 'light'
257+
},
258+
});
259+
260+
const entrypoint = process.env.REACT_APP_API_ENTRYPOINT;
261+
const fetchHeaders = {'Authorization': `Bearer ${window.localStorage.getItem('token')}`};
262+
const fetchHydra = (url, options = {}) => baseFetchHydra(url, {
263+
...options,
264+
headers: new Headers(fetchHeaders),
265+
});
266+
const dataProvider = api => hydraClient(api, fetchHydra);
267+
const apiDocumentationParser = entrypoint => parseHydraDocumentation(entrypoint, { headers: new Headers(fetchHeaders) })
268+
.then(
269+
({ api }) => ({api}),
270+
(result) => {
271+
switch (result.status) {
272+
case 401:
273+
return Promise.resolve({
274+
api: result.api,
275+
customRoutes: [{
276+
props: {
277+
path: '/',
278+
render: () => <Redirect to={`/login`}/>,
279+
},
280+
}],
281+
});
282+
283+
default:
284+
return Promise.reject(result);
285+
}
286+
},
287+
);
288+
289+
export default class extends Component {
290+
state = { api: null };
291+
292+
componentDidMount() {
293+
apiDocumentationParser(entrypoint).then(({ api }) => {
294+
this.setState({ api });
295+
}).catch((e) => {
296+
console.log(e);
297+
});
298+
}
299+
300+
render() {
301+
if (null === this.state.api) return <div>Loading...</div>;
302+
return (
303+
<Admin api={ this.state.api }
304+
apiDocumentationParser={ apiDocumentationParser }
305+
dataProvider= { dataProvider(this.state.api) }
306+
theme={ theme }
307+
appLayout={ Layout }
308+
authProvider={ authProvider }
309+
>
310+
<Resource name="users" list={ UserList } create={ UserCreate } show={ UserShow } edit={ UserEdit } title="Users"/>
311+
</Admin>
312+
)
313+
}
314+
}
315+
```
316+
317+
And accordingly create files `Show.js`, `Create.js`, `List.js`, `Edit.js`
318+
in the `admin/src/Component/User` directory:
319+
320+
```javascript
321+
// admin/src/Component/User/Create.js
322+
323+
import React from 'react';
324+
import { Create, SimpleForm, TextInput, email, required } from 'react-admin';
325+
326+
export const UserCreate = (props) => (
327+
<Create { ...props }>
328+
<SimpleForm>
329+
<TextInput source="email" label="Email" validate={ email() } />
330+
<TextInput source="plainPassword" label="Password" validate={ required() } />
331+
<TextInput source="name" label="Name"/>
332+
<TextInput source="phone" label="Phone"/>
333+
</SimpleForm>
334+
</Create>
335+
);
336+
337+
```
338+
339+
```javascript
340+
// admin/src/Component/User/Edit.js
341+
342+
import React from 'react';
343+
import { Edit, SimpleForm, DisabledInput, TextInput, DateInput, email } from 'react-admin';
344+
345+
export const UserEdit = (props) => (
346+
<Edit {...props}>
347+
<SimpleForm>
348+
<DisabledInput source="originId" label="ID"/>
349+
<TextInput source="email" label="Email" validate={ email() } />
350+
<TextInput source="name" label="Name"/>
351+
<TextInput source="phone" label="Phone"/>
352+
<DateInput disabled source="createdAt" label="Date"/>
353+
</SimpleForm>
354+
</Edit>
355+
);
356+
```
357+
358+
```javascript
359+
// admin/src/Component/User/List.js
360+
361+
import React from 'react';
362+
import { List, Datagrid, TextField, EmailField, DateField, ShowButton, EditButton } from 'react-admin';
363+
import { CustomPagination } from '../Pagination/CustomPagination';
364+
365+
export const UserList = (props) => (
366+
<List {...props} title="Users" pagination={ <CustomPagination/> } perPage={ 30 }>
367+
<Datagrid>
368+
<TextField source="originId" label="ID"/>
369+
<EmailField source="email" label="Email" />
370+
<TextField source="name" label="Name"/>
371+
<TextField source="phone" label="Phone"/>
372+
<DateField source="createdAt" label="Date"/>
373+
<ShowButton />
374+
<EditButton />
375+
</Datagrid>
376+
</List>
377+
);
378+
```
379+
380+
```javascript
381+
// admin/src/Component/User/Show.js
382+
import React from 'react';
383+
import { Show, SimpleShowLayout, TextField, DateField, EmailField, EditButton } from 'react-admin';
384+
385+
export const UserShow = (props) => (
386+
<Show { ...props }>
387+
<SimpleShowLayout>
388+
<TextField source="originId" label="ID"/>
389+
<EmailField source="email" label="Email" />
390+
<TextField source="name" label="Name"/>
391+
<TextField source="phone" label="Phone"/>
392+
<DateField source="createdAt" label="Date"/>
393+
<EditButton />
394+
</SimpleShowLayout>
395+
</Show>
396+
);
397+
```

0 commit comments

Comments
 (0)