Skip to content

Latest commit

 

History

History
192 lines (139 loc) · 7.97 KB

getting-started.md

File metadata and controls

192 lines (139 loc) · 7.97 KB

Getting Started

Installation

Install the skeleton and the library:

Start by installing the Yarn package manager (NPM is also supported) and the Create React App tool.

Then, create a new React application for your admin:

$ create-react-app my-admin

React and React DOM will be directly provided as dependencies of Admin On REST. As having different versions of React causes issues, remove react and react-dom from the dependencies section of the generated package.json file:

-    "react": "^15.6.1",
-    "react-dom": "^15.6.1"

Finally, install the @api-platform/admin library:

$ yarn add @api-platform/admin

Creating the Admin

Edit the src/App.js file like the following:

import React from 'react';
import { HydraAdmin } from '@api-platform/admin';

export default () => <HydraAdmin entrypoint="https://demo.api-platform.com"/>; // Replace with your own API entrypoint

Your new administration interface is ready! Type yarn start to try it!

Note: if you don't want to hardcode the API URL, you can use an environment variable.

Customizing the Admin

The API Platform's admin parses the Hydra documentation exposed by the API and transforms it to an object data structure. This data structure can be customized to add, remove or customize resources and properties. To do so, we can leverage the AdminBuilder component provided by the library. It's a lower level component than the HydraAdmin one we used in the previous example. It allows to access to the object storing the structure of admin's screens.

Using Custom Components

In the following example, we change components used for the description property of the books resource to ones accepting HTML (respectively RichTextField that renders HTML markup and RichTextInput, a WYSWYG editor). (To use the RichTextInput, the aor-rich-text-input package is must be installed: yarn add aor-rich-text-input).

import React from 'react';
import { RichTextField } from 'admin-on-rest';
import RichTextInput from 'aor-rich-text-input';
import HydraAdmin from 'api-platform-admin/lib/hydra/HydraAdmin';
import parseHydraDocumentation from 'api-doc-parser/lib/hydra/parseHydraDocumentation';

const entrypoint = 'https://demo.api-platform.com';

const apiDocumentationParser = entrypoint => parseHydraDocumentation(entrypoint)
  .then(api => {
    api.resources.map(resource => {
      const books = api.resources.find(r => 'books' === r.name);
      books.fields.find(f => 'description' === f.name).fieldComponent = <RichTextField source="description" key="description"/>;
      books.fields.find(f => 'description' === f.name).inputComponent = <RichTextInput source="description" key="description"/>;

      return resource;
    });

    return api;
  })
;

export default (props) => (
  <HydraAdmin apiDocumentationParser={apiDocumentationParser} entrypoint={entrypoint}/>
);

The fieldComponent property of the Field class allows to set the component used to render a property in list and show screens. The inputComponent property allows to set the component to use to render the input used in create and edit screens.

Any field or input provided by the Admin On Rest library can be used.

To go further, take a look to the "Including admin-on-rest on another React app" documentation page of Admin On Rest to learn how to use directly redux, react-router, and redux-saga along with components provided by this library.

Managing Files and Images

In the following example, we will:

  • find every ImageObject resources. For each contentUrl fields, we will use ImageField as field and ImageInput as input.
  • ImageInput will return a File instance. In this example, we will send a multi-part form data to a special action (https://demo.api-platform.com/images/upload). The action will return the ID of the uploaded image. We will "replace" the File instance by the ID in normalizeData.
  • As contentUrl fields will return a string, we have to convert Hydra data to AOR data. This action will be done by denormalizeData.
import { FunctionField, ImageField, ImageInput } from 'admin-on-rest/lib/mui';
import React from 'react';
import HydraAdmin from 'api-platform-admin/lib/hydra/HydraAdmin';
import parseHydraDocumentation from 'api-doc-parser/lib/hydra/parseHydraDocumentation';

const entrypoint = 'https://demo.api-platform.com';

const apiDocumentationParser = entrypoint => parseHydraDocumentation(entrypoint)
  .then(api => {
    api.resources.map(resource => {
      if ('http://schema.org/ImageObject' === resource.id) {
        resource.fields.map(field => {
          if ('http://schema.org/contentUrl' === field.id) {
            field.denormalizeData = value => ({
              src: value
            });

            field.fieldComponent = (
              <FunctionField
                key={field.name}
                render={
                  record => (
                    <ImageField key={field.name} record={record} source={`${field.name}.src`}/>
                  )
                }
                source={field.name}
              />
            );

            field.inputComponent = (
              <ImageInput accept="image/*" key={field.name} multiple={false} source={field.name}>
                <ImageField source="src"/>
              </ImageInput>
            );

            field.normalizeData = value => {
              if (value[0] && value[0].rawFile instanceof File) {
                const body = new FormData();
                body.append('file', value[0].rawFile);

                return fetch(`${entrypoint}/images/upload`, { body, method: 'POST' })
                  .then(response => response.json());
              }

              return value.src;
            };
          }

          return field;
        });
      }

      return resource;
    });

    return api;
  })
;

export default (props) => (
  <HydraAdmin apiDocumentationParser={apiDocumentationParser} entrypoint={entrypoint}/>
);

Note: In this example, we choose to send the file via a multi-part form data, but you are totally free to use another solution (like base64). But keep in mind that multi-part form data is the most efficient solution.

Using a Custom Validation Function or Inject Custom Props

You can use fieldProps and inputProps to respectively inject custom properties to fields and inputs generated by API Platform Admin. This is particularly useful to add custom validation rules:

import React, { Component } from 'react';
import { AdminBuilder, hydraClient } from 'api-platform-admin';
import parseHydraDocumentation from 'api-doc-parser/lib/hydra/parseHydraDocumentation';

const entrypoint = 'https://demo.api-platform.com';

export default class extends Component {
  state = {api: null};

  componentDidMount() {
    parseHydraDocumentation(entrypoint).then(api => {
      const books = api.resources.find(r => 'books' === r.name);

      books.writableFields.find(f => 'description' === f.name).inputProps = {
        validate: value => value.length >= 30 ? undefined : 'Minimum length: 30';
      };

      this.setState({api: api});
    })
  }

  render() {
    if (null === this.state.api) return <div>Loading...</div>;

    return <AdminBuilder api={this.state.api} restClient={hydraClient(entrypoint)}/>
  }
}