'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' + ' \n' + ' \n' + ' {{#if results}}\n' + ' \n' + ' {{#each results}}\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{/each}}\n' + ' \n' + ' {{/if}}\n' + '
\n' + ' {{#translate}}Email{{/translate}}\n' + ' \n' + ' {{#translate}}Tracker Count{{/translate}}\n' + '
\n' + ' {{email}}\n' + ' \n' + ' {{tracker_count}}\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' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{#if results}}\n' + ' \n' + ' {{#each results}}\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{/each}}\n' + ' \n' + ' {{/if}}\n' + '
\n' + ' {{#translate}}Country{{/translate}}\n' + ' \n' + ' {{#translate}}Opened{{/translate}}\n' + ' \n' + ' {{#translate}}All{{/translate}}\n' + ' \n' + ' {{#translate}}Percentage{{/translate}}\n' + '
\n' + ' {{custom_country}}\n' + ' \n' + ' {{count_opened}}\n' + ' \n' + ' {{count_all}}\n' + ' \n' + ' {{percentage}}%\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;