Admin-on-rest: a framework for building admin interfaces with React.

Tengku Hafidz
Rate Engineering
Published in
7 min readOct 20, 2017

As much as we know building an admin interface for our company is inevitable, we tend to drag it. Perhaps its cos we’re unwilling to take away too much of the most precious assets of any growing company for it, which is time.

Lucky for us, we found admin-on-rest.

How do we allow admins access to our database without asking them to download our database?

What is Admin-on-rest?

“A frontend Framework for building admin applications running in the browser on top of REST services, using ES6, React and Material Design.”

Essentially, It is an easy-to-use open-source react-based framework that reduces a lot of the hassle that comes with building an admin dashboard interface.

Out of the box, admin-on-rest comes with a bunch of presets to make things simply work. The beauty of it, however, lies in its simplicity to customise any parts of it on our own. To quote the marmelab (its producers), “Batteries Included But Removable”.

In this article, I am going to show how easy it is to

  1. build a basic admin interface , and
  2. customise it according to your company’s specific needs.

Building The Basic Admin Interface in Under 10 Minutes

In this section, I am going to share a quick guide to illustrate how simple it is to get the started with admin-on-rest.

In this walkthrough, we’ll be using a fake REST API called JSONPlaceholder. It was designed for testing and prototyping, as the datasource for the admin.

So let’s get right to it.

  1. Create a new create-react-app project, install admin-on-rest package, and run it.
npm install -g create-react-app
create-react-app test-admin
cd test-admin/
npm add admin-on-rest --save
npm start

2. Replace the codes in src/App.js with the following:

import React from 'react';
import { jsonServerRestClient, Admin, Resource, Delete } from 'admin-on-rest';

import { PostList, PostEdit, PostCreate } from './posts';

const App = () => (
<Admin restClient={jsonServerRestClient('http://jsonplaceholder.typicode.com')}>
<Resource name="posts" list={PostList} edit={PostEdit} create={PostCreate} remove={Delete}/>
</Admin>
);

export default App;

Points to note:

  • The <Admin> component expects a REST client parameter that can translate REST commands into HTTP requests.
  • jsonServerRestClient() is provided by admin-on-rest to handle responses in the same format as the endpoints from JSONPlaceholder. If your REST API responds in a different format, you will have to make a custom REST client to handle it (or you can hack it out like I have — covered in the next section).
  • There can be multiple <Resource> components within <Admin> component, with the name attribute specifying the endpoint its requesting from.
    e.g: <Resource name="posts" />makes contact with http://jsonplaceholder.typicode.com/posts

3. Create a posts.js in src folder and fill it in with the following code:

import React from 'react';
import {
List, Edit, Create, Datagrid,
ReferenceField, TextField, EditButton,
DisabledInput, LongTextInput, ReferenceInput,
SelectInput, SimpleForm, TextInput
} from 'admin-on-rest';

export const PostList = (props) => (
<List {...props}>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
<TextField source="body" />
<EditButton />
</Datagrid>
</List>
);

export const PostEdit = (props) => (
<Edit {...props}>
<SimpleForm>
<DisabledInput source="id" />
<TextInput source="title" />
<LongTextInput source="body" />
</SimpleForm>
</Edit>
);

export const PostCreate = (props) => (
<Create {...props}>
<SimpleForm>
<TextInput source="title" />
<LongTextInput source="body" />
</SimpleForm>
</Create>
);

Points To Note:

  • The source attribute holds the name of the REST API response key whose value we are interested in retrieving.
  • JSONPlaceholder API is a read-only. It is not able to actually create or edit posts.

More explanation can be found in their comprehensive official documentation.

The Outcome
Tadaa. Magical. Just like that, we have built a basic admin interface.

This means that once you sort of get what’s going on in the codes above, you can practically build a useable admin interface in under 10 minutes with admin-on-rest.

Here is how the interface will look like if you followed the 3 steps shared above.

PostList
PostCreate
PostEdit
PostDelete

Customising The Interface

Most of the times, some customisation and enhancements are needed. The following are 3 of the things that I did when building my company’s admin interface.

  1. Customising the REST Client

The first stumbling block I surfaced was due to the fact that I could not utilise the ready-made jsonServerRestClient(). This is so as the response format for our REST API is in a different format than what the REST client is meant to handle.

This is the kind of REST API response format jsonServerRestClient() was coded to handle:

[
{
id: 1,
title: "hello world",
body: "quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est",
},
{
id: 2,
title: "bye world",
body: "est rerum tempore vitae sequi sint nihil reprehenderit dolor beatae ea dolores neque fugiat blanditiis voluptate porro vel"
},
]

This is the response format of our REST API:

status: "success",
message: "",
data: [
{
id: 1,
title: "hello world",
body: "quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est",
},
{
id: 2,
title: "bye world",
body: "est rerum tempore vitae sequi sint nihil reprehenderit dolor beatae ea dolores neque fugiat blanditiis voluptate porro vel"
},
]

Since the difference is that small, instead of writing our own custom REST client, I decided to work around that issue by tweaking the jsonServerRestClient by adding a .data behind the necessary responses and params.

For example, in line 111, instead of the json = response.json, we added .data behind that to reflect our response format.

109. var convertHTTPResponseToREST = function 
110. convertHTTPResponseToREST(response, type, resource, params) {
111. var headers = response.headers,
112. json = response.json.data;
.
.
.
128. });

2. Displaying Meaningful Status Fields

Another particular thing that we needed to customise was in presenting the status field in a meaningful way.

The issue was that the REST API that we make contact with returns statuses in its codes instead of its names.

For example, account status field will display numbers like: 0, 1, 2, instead of its meaningful names like: ‘GUEST’, ‘UNVERIFIED’, ‘VERIFIED’.

This makes that the status fields barely useful.

In handling this, I made a new file called statusHandler.js and stored all the different statuses there to make the status codes correspond to meaningful status names. Here is a snippet of statusHandler.js.

import React from 'react';export const accountStatus = [
{ id: 0, name: 'GUEST' },
{ id: 1, name: 'UNVERIFIED' },
{ id: 2, name: 'VERIFIED' }
];
export const couponStatus = [
{ id: 0, name: 'AVAILABLE' },
{ id: 1, name: 'EXPIRED' },
{ id: 2, name: 'ERROR' },
{ id: 3, name: 'SUCCESS' }
];
.
.
.
const statusTypes = {
'users_account_type': accountStatus,
'coupons_status': couponStatus
};
export const statusFunctionField = (statusId, statusType) => {
if(statusId !== null && statusTypes[statusType] && statusTypes[statusType][statusId]) {
return (
<div style={{ color: statusTypes[statusType][statusId].color}}>
{ statusTypes[statusType][statusId].name }
</div>
);
} else {
return <div> N/A </div>;
}
};

Then, in the file that displays the status, I used the <FunctionField /> component (provided by admin-on-rest) and called statusFunctionField() (from statusHandler.js) with the relevant parameters, which would render the status accordingly as.

For example, in calling coupinStatus in coupons.js:

import React from 'react';
import {
List, Datagrid,
TextField, FunctionField
} from 'admin-on-rest';
import {
couponStatus,
statusFunctionField
} from './global/statusHandler';
export const CouponList = (props) => (
<List {...props}>
<Datagrid>
<TextField source="id"/>
<TextField source="code"/>
<TextField source="merchant"/>
<FunctionField
source="status"
render={ record => statusFunctionField(record.status, 'coupons_status') }/>
</Datagrid>
</List>
);

After doing this, the status field should now display meaningful status names instead of unhelpful status codes.

3. Making Custom Components

On top of using the fields provided by admin-on-rest, we are free to make our own custom components and slot it anywhere we want it.

For example, my company needed a refund button at the end of each row in one of our charges lists. The only thing we needed to do was to write the <RefundButton /> component and place it where we want it to show.

Next Step

Using the process I shared above, you should be able to set up your company admin interface with minimal effort and in a very short amount of time.

Of course, you may need further customisations and enhancements as you go on to build your admin interfaces. For most cases, I believe the admin-on-rest documentation should have you covered, so have a look. Otherwise, you can always “take away the batteries” and write your own custom codes to make certain parts work exactly the way you want it to.

Try it out and have fun!

--

--