Create a Smart Action

Let's go back to the development environment to going further in the back office's customization. It's now time to code a little bit to get the most out of our Smart features.

The goal of the Smart features is to offer the flexibility of coding any specific business logic to get the most out of our back office. This is how Forest Admin pretends to be as flexible as a homemade back office.

A Smart Action is a button that triggers server-side logic through an API call. Moderating comments, logging into a customer’s account (a.k.a impersonate) or banning a user are exactly the kind of important tasks to unlock in order to manage your day-to-day operations.

In this example, we will create the Mark as live Smart Action to update a company's status from pending or rejected to live.

Declare a Smart Action

Lumber
Rails
Express/Sequelize
Express/Mongoose

Create the /forest/ folder and then a file companies.js that corresponds to the collection where we want to create our Smart Action.

/forest/companies
const Liana = require('forest-express-sequelize');
Liana.collection('companies', {
actions: [{
name: 'Mark as Live'
}],
});

Create the file company.rb in your /collections folder that corresponds to the collection where we want to create our Smart Action.

/lib/forest_liana/collections/company.rb
class Forest::Company
include ForestLiana::Collection
collection :Company
action 'Mark as Live'
end

Create the /forest/ folder and then a file companies.js that corresponds to the collection where we want to create our Smart Action.

/forest/companies
const Liana = require('forest-express-sequelize');
Liana.collection('companies', {
actions: [{
name: 'Mark as Live'
}],
});

Create the /forest/ folder and then a file companies.js that corresponds to the collection where we want to create our Smart Action.

/forest/companies
const Liana = require('forest-express-mongoose');
Liana.collection('companies', {
actions: [{
name: 'Mark as Live'
}],
});

Then, restart the back office server and we will be able to see our Smart Action from the UI.

But of course, if we click on the Smart Action nothing will happen because we didn't code anything yet.

Implement a Smart Action

The business logic in this Smart Action is extremely simple. It updates the attribute status of a company to the value live.

When you click on a Smart Action, an API call POST /forest/actions/<dasherized-action-name> is triggered.

Lumber
Rails
Express/Sequelize
Express/Mongoose

To handle this call, we have created the file /routes/companies.js that contains the Smart Action's code implementation.

/routes/companies.js
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const models = require('../models');
router.post('/actions/mark-as-live', Liana.ensureAuthenticated, (req, res) => {
let companyId = req.body.data.attributes.ids[0];
return models.companies
.update({ status: 'live' }, { where: { id: companyId }})
.then(() => res.send({ success: 'Company is now live!' }));
});
module.exports = router;

To handle this call, we need to implement the route that contains the Smart Action's code implementation.

/config/routes.rb
Rails.application.routes.draw do
# MUST be declared before the mount ForestLiana::Engine.
namespace :forest do
post '/actions/mark-as-live' => 'companies#mark_as_live'
end
mount ForestLiana::Engine => '/forest'
end
/controllers/forest/companies_controller.rb
class Forest::CompaniesController < ForestLiana::ApplicationController
def mark_as_live
company_id = params.dig('data', 'attributes', 'ids').first
Company.update(company_id, status: 'live')
head :no_content
end
end

To handle this call, we have created the file /routes/companies.js that contains the Smart Action's code implementation.

/routes/companies.js
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const models = require('../models');
router.post('/actions/mark-as-live', Liana.ensureAuthenticated, (req, res) => {
let companyId = req.body.data.attributes.ids[0];
return models.companies
.update({ status: 'live' }, { where: { id: companyId }})
.then(() => res.send({ success: 'Company is now live!' }));
});
module.exports = router;

To handle this call, we have created the file /routes/companies.js that contains the Smart Action's code implementation.

/routes/companies.js
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-mongoose');
const Company = require('../models/companies');
router.post('/actions/mark-as-live', Liana.ensureAuthenticated, (req, res) => {
let companyId = req.body.data.attributes.ids[0];
return Company
.findOneAndUpdate({ _id: companyId }, { $set: { status: 'live' }})
.then(() => res.send({ success: 'Company is now live!' }));
});
module.exports = router;

Once triggered, the route implementation is executed and simply change the status to live in this example. Of course, you're free to code your own business logic which can be as complex as you want.

Done! 🎉