'use strict';
const express = require('express');
const passport = require('../lib/passport');
const router = new express.Router();
const _ = require('../lib/translate')._;
const reportTemplates = require('../lib/models/report-templates');
const tools = require('../lib/tools');
const util = require('util');
const htmlescape = require('escape-html');
const striptags = require('striptags');
const allowedMimeTypes = {
'text/html': 'HTML',
'text/csv': 'CSV'
};
router.all('/*', (req, res, next) => {
if (!req.user) {
req.flash('danger', _('Need to be logged in to access restricted content'));
return res.redirect('/users/login?next=' + encodeURIComponent(req.originalUrl));
}
res.setSelectedMenu('reports');
next();
});
router.get('/', (req, res) => {
res.render('report-templates/report-templates', {
title: _('Report Templates')
});
});
router.post('/ajax', (req, res) => {
reportTemplates.filter(req.body, (err, data, total, filteredTotal) => {
if (err) {
return res.json({
error: err.message || err,
data: []
});
}
res.json({
draw: req.body.draw,
recordsTotal: total,
recordsFiltered: filteredTotal,
data: data.map((row, i) => [
(Number(req.body.start) || 0) + 1 + i,
htmlescape(row.name || ''),
htmlescape(striptags(row.description) || ''),
'' + row.created.toISOString() + '',
' ' + _('Edit') + '']
)
});
});
});
router.get('/create', passport.csrfProtection, (req, res) => {
const data = req.query;
const wizard = req.query['type'] || '';
if (wizard == 'subscribers-all') {
if (!('description' in data)) data.description = 'Generates a campaign report listing all subscribers along with their statistics.';
if (!('mimeType' in data)) data.mimeType = 'text/html';
if (!('userFields' in data)) data.userFields =
'[\n' +
' {\n' +
' "id": "campaign",\n' +
' "name": "Campaign",\n' +
' "type": "campaign",\n' +
' "minOccurences": 1,\n' +
' "maxOccurences": 1\n' +
' }\n' +
']';
if (!('js' in data)) data.js =
'campaigns.results(inputs.campaign, ["*"], "", (err, results) => {\n' +
' if (err) {\n' +
' return callback(err);\n' +
' }\n' +
'\n' +
' const data = {\n' +
' results: results\n' +
' };\n' +
'\n' +
' return callback(null, data);\n' +
'});';
if (!('hbs' in data)) data.hbs =
'
{{title}}
\n' +
'\n' +
'\n' +
'
\n' +
' \n' +
' \n' +
' {{#translate}}Email{{/translate}}\n' +
' | \n' +
' \n' +
' {{#translate}}Tracker Count{{/translate}}\n' +
' | \n' +
' \n' +
' {{#if results}}\n' +
' \n' +
' {{#each results}}\n' +
' \n' +
' \n' +
' {{email}}\n' +
' | \n' +
' \n' +
' {{tracker_count}}\n' +
' | \n' +
'
\n' +
' {{/each}}\n' +
' \n' +
' {{/if}}\n' +
'
\n' +
'
';
} else if (wizard == 'subscribers-grouped') {
if (!('description' in data)) data.description = 'Generates a campaign report with results are aggregated by some "Country" custom field.';
if (!('mimeType' in data)) data.mimeType = 'text/html';
if (!('userFields' in data)) data.userFields =
'[\n' +
' {\n' +
' "id": "campaign",\n' +
' "name": "Campaign",\n' +
' "type": "campaign",\n' +
' "minOccurences": 1,\n' +
' "maxOccurences": 1\n' +
' }\n' +
']';
if (!('js' in data)) data.js =
'campaigns.results(inputs.campaign, ["custom_country", "count(*) AS count_all", "SUM(IF(tracker.count IS NULL, 0, 1)) AS count_opened"], "GROUP BY custom_country", (err, results) => {\n' +
' if (err) {\n' +
' return callback(err);\n' +
' }\n' +
'\n' +
' for (let row of results) {\n' +
' row["percentage"] = Math.round((row.count_opened / row.count_all) * 100);\n' +
' }\n' +
'\n' +
' let data = {\n' +
' results: results\n' +
' };\n' +
'\n' +
' return callback(null, data);\n' +
'});';
if (!('hbs' in data)) data.hbs =
'{{title}}
\n' +
'\n' +
'\n' +
'
\n' +
' \n' +
' \n' +
' {{#translate}}Country{{/translate}}\n' +
' | \n' +
' \n' +
' {{#translate}}Opened{{/translate}}\n' +
' | \n' +
' \n' +
' {{#translate}}All{{/translate}}\n' +
' | \n' +
' \n' +
' {{#translate}}Percentage{{/translate}}\n' +
' | \n' +
' \n' +
' {{#if results}}\n' +
' \n' +
' {{#each results}}\n' +
' \n' +
' \n' +
' {{custom_country}}\n' +
' | \n' +
' \n' +
' {{count_opened}}\n' +
' | \n' +
' \n' +
' {{count_all}}\n' +
' | \n' +
' \n' +
' {{percentage}}%\n' +
' | \n' +
'
\n' +
' {{/each}}\n' +
' \n' +
' {{/if}}\n' +
'
\n' +
'
';
} else if (wizard == 'export-list-csv') {
if (!('description' in data)) data.description = 'Exports a list as a CSV file.';
if (!('mimeType' in data)) data.mimeType = 'text/csv';
if (!('userFields' in data)) data.userFields =
'[\n' +
' {\n' +
' "id": "list",\n' +
' "name": "List",\n' +
' "type": "list",\n' +
' "minOccurences": 1,\n' +
' "maxOccurences": 1\n' +
' }\n' +
']';
if (!('js' in data)) data.js =
'subscriptions.list(inputs.list.id,0,0, (err, results) => {\n' +
' if (err) {\n' +
' return callback(err);\n' +
' }\n' +
'\n' +
' let data = {\n' +
' results: results\n' +
' };\n' +
'\n' +
' return callback(null, data);\n' +
'});';
if (!('hbs' in data)) data.hbs =
'{{#each results}}\n' +
'{{firstName}},{{lastName}},{{email}}\n' +
'{{/each}}';
}
data.csrfToken = req.csrfToken();
data.title = _('Create Report Template');
data.useEditor = true;
data.mimeTypes = Object.keys(allowedMimeTypes).map(key => ({
key: key,
value: allowedMimeTypes[key],
selected: data.mimeType == key
}));
res.render('report-templates/create', data);
});
router.post('/create', passport.parseForm, passport.csrfProtection, (req, res) => {
reportTemplates.createOrUpdate(true, req.body, (err, id) => {
if (err || !id) {
req.flash('danger', err && err.message || err || _('Could not create report template'));
return res.redirect('/report-templates/create?' + tools.queryParams(req.body));
}
req.flash('success', util.format(_('Report template ā%sā created'), req.body.name));
res.redirect('/report-templates');
});
});
router.get('/edit/:id', passport.csrfProtection, (req, res) => {
reportTemplates.get(req.params.id, (err, template) => {
if (err || !template) {
req.flash('danger', err && err.message || err || _('Could not find report template with specified ID'));
return res.redirect('/report-templates');
}
template.csrfToken = req.csrfToken();
template.title = _('Edit Report Template');
template.useEditor = true;
template.mimeTypes = Object.keys(allowedMimeTypes).map(key => ({
key: key,
value: allowedMimeTypes[key],
selected: template.mimeType == key
}));
res.render('report-templates/edit', template);
});
});
router.post('/edit', passport.parseForm, passport.csrfProtection, (req, res) => {
reportTemplates.createOrUpdate(false, req.body, (err, updated) => {
if (err) {
req.flash('danger', err.message || err);
} else if (updated) {
req.flash('success', _('Report template updated'));
} else {
req.flash('info', _('Report template not updated'));
}
if (req.body['submit'] == 'update-and-stay') {
return res.redirect('/report-templates/edit/' + req.body.id);
} else {
return res.redirect('/report-templates');
}
});
});
router.post('/delete', passport.parseForm, passport.csrfProtection, (req, res) => {
reportTemplates.delete(req.body.id, (err, deleted) => {
if (err) {
req.flash('danger', err && err.message || err);
} else if (deleted) {
req.flash('success', _('Report template deleted'));
} else {
req.flash('info', _('Could not delete specified report template'));
}
return res.redirect('/report-templates');
});
});
module.exports = router;