Create a Smart Chart

Creating a Smart Chart

Sometimes, charts data are complicated and closely tied to your business. Forest Admin allows you to code how the chart is computed. Choose Smart as the data source when configuring your chart. Forest Admin will make the HTTP call to Smart Chart URL when retrieving the chart values for the rendering.

Value Smart Chart

On our Live Demo, we have a MRR value chart which computes our Monthly Recurring Revenue. This chart queries the Stripe API to get all charges made in the current month (in March for this example).

SQL
Mongodb

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

{ value: <number> }
/routes/dashboard.js
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
router.post('/stats/mrr', Liana.ensureAuthenticated, (req, res) => {
let mrr = 0;
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-31').unix();
return stripe.charges
.list({
created: { gte: from, lte: to }
})
.then((response) => {
return P.each(response.data, (charge) => {
mrr += charge.amount;
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: mrr
}).perform();
res.send(json);
});
});
module.exports = router;

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

{ value: <number> }
/routes/dashboard.js
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-mongoose');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
router.post('/stats/mrr', Liana.ensureAuthenticated, (req, res) => {
let mrr = 0;
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-31').unix();
return stripe.charges
.list({
created: { gte: from, lte: to }
})
.then((response) => {
return P.each(response.data, (charge) => {
mrr += charge.amount;
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: mrr
}).perform();
res.send(json);
});
});
module.exports = router;

Repartition Smart Chart

On our Live Demo, we have a Charges repartition chart which shows a repartition chart distributed by credit card country. This chart queries the Stripe API to get all charges made in the current month (in March for this example) and check the credit card country.

SQL
Mongodb

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

{
value: [{
key: <string> ,
value: <number>
}, {
key: <string> ,
value: <number>
}, …]
}
/routes/dashboard.js
const _ = require('lodash');
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
router.post('/stats/credit-card-country-repartition', Liana.ensureAuthenticated, (req, res) => {
let repartition = [];
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-20').unix();
return stripe.charges
.list({
created: { gte: from, lte: to }
})
.then((response) => {
return P.each(response.data, (charge) => {
let country = charge.source.country || 'Others';
let entry = _.find(repartition, { key: country });
if (!entry) {
repartition.push({ key: country, value: 1 });
} else {
entry.value++;
}
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: repartition
}).perform();
res.send(json);
});
});
module.exports = router;

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

{
value: [{
key: <string> ,
value: <number>
}, {
key: <string> ,
value: <number>
}, …]
}
/routes/dashboard.js
const _ = require('lodash');
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-mongoose');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
router.post('/stats/credit-card-country-repartition', Liana.ensureAuthenticated, (req, res) => {
let repartition = [];
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-20').unix();
return stripe.charges
.list({
created: { gte: from, lte: to }
})
.then((response) => {
return P.each(response.data, (charge) => {
console.log(charge.source);
let country = charge.source.country || 'Others';
let entry = _.find(repartition, { key: country });
if (!entry) {
repartition.push({ key: country, value: 1 });
} else {
entry.value++;
}
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: repartition
}).perform();
res.send(json);
});
});
module.exports = router;

Time-based Smart Chart

On our Live Demo, we have a Charges time-based chart which shows the number of charges per day. This chart queries the Stripe API to get all charges made in the current month (in March for this example) and group data by day.

SQL
Mongodb

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

{
value: [{
label: <string> ,
values: { value: <number> }
}, {
label: <string> ,
values: { value: <number> }
}, …]
}
/routes/dashboard.js
const _ = require('lodash');
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-sequelize');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
router.post('/stats/charges-per-day', Liana.ensureAuthenticated, (req, res) => {
let values = [];
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-31').unix();
return stripe.charges
.list({
created: { gte: from, lte: to }
})
.then((response) => {
return P.each(response.data, (charge) => {
let date = moment.unix(charge.created).startOf('day').format('LLL');
let entry = _.find(values, { label: date });
if (!entry) {
values.push({ label: date, values: { value: 1 } });
} else {
entry.values.value++;
}
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: values
}).perform();
res.send(json);
});
});
module.exports = router;

When serializing the data, we use the Liana.StatSerializer() serializer. Check the value syntax below.

{
value: [{
label: <string> ,
values: { value: <number> }
}, {
label: <string> ,
values: { value: <number> }
}, …]
}
/routes/dashboard.js
const _ = require('lodash');
const P = require('bluebird');
const express = require('express');
const router = express.Router();
const Liana = require('forest-express-mongoose');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const moment = require('moment');
router.post('/stats/charges-per-day', Liana.ensureAuthenticated, (req, res) => {
let values = [];
let from = moment.utc('2018-03-01').unix();
let to = moment.utc('2018-03-31').unix();
return stripe.charges
.list({
created: { gte: from, lte: to }
})
.then((response) => {
return P.each(response.data, (charge) => {
let date = moment.unix(charge.created).startOf('day').format('LLL');
let entry = _.find(values, { label: date });
if (!entry) {
values.push({ label: date, values: { value: 1 } });
} else {
entry.values.value++;
}
});
})
.then(() => {
let json = new Liana.StatSerializer({
value: values
}).perform();
res.send(json);
});
});
module.exports = router;