@@ -228,3 +228,170 @@ export default class extends Component {
228
228
}
229
229
}
230
230
```
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