96 lines
2.6 KiB
JavaScript
96 lines
2.6 KiB
JavaScript
|
const Vue = require('vue');
|
||
|
const VueI18n = require('vue-i18n');
|
||
|
const renderer = require('vue-server-renderer').createRenderer();
|
||
|
const fs = require('fs-extra');
|
||
|
const pdf = require('phantom-html2pdf');
|
||
|
const juice = require('juice');
|
||
|
|
||
|
Vue.use(VueI18n);
|
||
|
|
||
|
if (!process.env.OPENSSL_CONF)
|
||
|
process.env.OPENSSL_CONF = '/etc/ssl/';
|
||
|
|
||
|
module.exports = {
|
||
|
|
||
|
path: `${appPath}/reports`,
|
||
|
|
||
|
/**
|
||
|
* Renders a report component
|
||
|
*
|
||
|
* @param {String} name - Report name
|
||
|
* @param {Object} ctx - Request context
|
||
|
*/
|
||
|
async render(name, ctx) {
|
||
|
const component = require(`${this.path}/${name}`);
|
||
|
|
||
|
await this.preFetch(component, ctx);
|
||
|
|
||
|
const i18n = new VueI18n({
|
||
|
locale: 'es',
|
||
|
});
|
||
|
const app = new Vue({
|
||
|
i18n,
|
||
|
render: h => h(component),
|
||
|
});
|
||
|
|
||
|
return renderer.renderToString(app);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Prefetch all component data from asyncData method
|
||
|
*
|
||
|
* @param {Object} component - Component object
|
||
|
* @param {Object} ctx - Request context
|
||
|
*/
|
||
|
async preFetch(component, ctx) {
|
||
|
let data = {};
|
||
|
|
||
|
await this.attachAssets(component);
|
||
|
|
||
|
if (component.hasOwnProperty('data'))
|
||
|
data = component.data();
|
||
|
|
||
|
if (component.hasOwnProperty('asyncData')) {
|
||
|
const fetch = await component.asyncData(ctx, ctx.body);
|
||
|
const mergedData = {...data, ...fetch};
|
||
|
|
||
|
component.data = function data() {
|
||
|
return mergedData;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (component.components) {
|
||
|
const components = component.components;
|
||
|
const promises = [];
|
||
|
|
||
|
Object.keys(components).forEach(component => {
|
||
|
promises.push(this.preFetch(components[component], ctx));
|
||
|
});
|
||
|
|
||
|
return Promise.all(promises);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
async attachAssets(component) {
|
||
|
const localePath = `${this.path}/${component.name}/locale.js`;
|
||
|
const templatePath = `${this.path}/${component.name}/index.html`;
|
||
|
const stylePath = `${this.path}/${component.name}/assets/css/style.css`;
|
||
|
|
||
|
const template = await fs.readFile(templatePath, 'utf8');
|
||
|
const css = await fs.readFile(stylePath, 'utf8');
|
||
|
|
||
|
component.i18n = require(localePath);
|
||
|
component.template = juice.inlineContent(template, css);
|
||
|
},
|
||
|
|
||
|
async toPdf(name, ctx) {
|
||
|
const options = {
|
||
|
html: await this.render(name, ctx),
|
||
|
};
|
||
|
const result = await pdf.convert(options);
|
||
|
const stream = await result.toStream();
|
||
|
|
||
|
return stream;
|
||
|
},
|
||
|
};
|