@medicus.ai/medicus-report-pdf-generator 1.3.13 → 1.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +3 -3
- package/HANDOVER.md +146 -0
- package/README.md +26 -26
- package/app/i18n.config.js +20 -20
- package/app/i18n_wellbeing.config.js +20 -20
- package/app/services/localeService.js +28 -28
- package/assets/Mediclinic/css/nasco_report.css +6297 -6297
- package/assets/Mediclinic/css/nasco_report_rtl.css +851 -851
- package/assets/Mediclinic/css/style.css +33 -33
- package/assets/Mediclinic/js/js.js +112 -112
- package/assets/Mediclinic/js/raphael.js +8437 -8437
- package/assets/arabic.css +275 -275
- package/assets/charts.min.js +7 -7
- package/assets/corporate_report/css/report.css +582 -582
- package/assets/corporate_report/css/report_rtl.css +144 -144
- package/assets/corporate_report/js/js.js +14 -14
- package/assets/data/data.json +124 -124
- package/assets/data/data2.json +675 -675
- package/assets/data/pdf_data_with_history.json +1255 -1255
- package/assets/doctor-note-insight-icon.svg +11 -11
- package/assets/imc/css/style.css +61 -61
- package/assets/jquery-1.4.min.js +151 -151
- package/assets/jquery-2.1.0.min.js +3 -3
- package/assets/js.js +201 -201
- package/assets/medicus_pdf/arabic.css +444 -444
- package/assets/medicus_pdf/styles.css +2427 -2427
- package/assets/print.css +4 -4
- package/assets/qr-code-style.css +68 -68
- package/assets/qrcode.min.js +3 -3
- package/assets/raphael-min.js +10 -10
- package/assets/sanusx/css/sanusx_report.css +707 -707
- package/assets/sizing.js +2 -2
- package/assets/styles.css +1545 -1545
- package/assets/styles.min.css +1358 -1358
- package/assets/translation.js +30 -30
- package/assets/wellbeing/css/nasco_report.css +3472 -3472
- package/assets/wellbeing/css/nasco_report_rtl.css +679 -679
- package/assets/wellbeing/js/js.js +111 -111
- package/assets/wellbeing/js/raphael.js +8437 -8437
- package/base64/cairo-font.js +2 -2
- package/config/Mediclinic.json +37 -37
- package/config/Najeeb.ai.json +35 -35
- package/config/Pha.json +64 -64
- package/config/bionext.json +37 -37
- package/config/default.json +35 -35
- package/config/diagnostikare.json +34 -34
- package/config/maisonsante.json +39 -39
- package/config/nasco.json +35 -35
- package/config/sanitas.json +35 -35
- package/config/sanusx.json +34 -34
- package/config/test.txt +4 -4
- package/data converter.js +53 -53
- package/docs/01-architecture-overview.md +149 -0
- package/docs/02-configuration-and-whitelabelling.md +111 -0
- package/docs/03-templating-and-rendering.md +71 -0
- package/docs/04-report-pipelines.md +128 -0
- package/docs/05-questions-and-data-model.md +67 -0
- package/docs/06-internationalization.md +59 -0
- package/docs/07-email-notifications.md +59 -0
- package/docs/08-known-issues-and-technical-debt.md +41 -0
- package/docs/README.md +22 -0
- package/downloadfile.js +6 -6
- package/example.txt +1188 -1188
- package/index.js +481 -480
- package/lib/big_integral_questionnaire.js +370 -298
- package/lib/corporate_report_generator.js +399 -399
- package/lib/pdf_generator.min.js +525 -525
- package/lib/sanusx_report_generator.js +533 -533
- package/lib/sendEmail.js +343 -343
- package/lib/template.js +2227 -2227
- package/lib/wellbeing_report_generator.js +2164 -2134
- package/locales/ar-AE.json +169 -169
- package/locales/ar-SA.json +169 -169
- package/locales/ar.json +397 -397
- package/locales/de.json +169 -169
- package/locales/en.json +229 -229
- package/locales/fr.json +168 -168
- package/locales/pt.json +165 -165
- package/locales/wellbeing/ar-AE.json +149 -149
- package/locales/wellbeing/ar-SA.json +257 -257
- package/locales/wellbeing/de.json +301 -301
- package/locales/wellbeing/en.json +423 -423
- package/locales/wellbeing/es.json +133 -133
- package/locales/wellbeing/fr.json +121 -121
- package/locales/wellbeing/it-IT.json +121 -121
- package/locales/wellbeing/pt.json +121 -121
- package/locales/wellbeing/tr.json +121 -121
- package/locales/wellbeing/zh-CN.json +121 -121
- package/locales/zh-CN.json +165 -165
- package/package.json +47 -47
- package/preview-big-integral.js +75 -75
- package/run.js +15 -15
- package/templates/Mediclinic/blocks/first-section.html +205 -205
- package/templates/Mediclinic/blocks/footer.html +7 -7
- package/templates/Mediclinic/blocks/header-template.html +5 -5
- package/templates/Mediclinic/blocks/header.html +20 -20
- package/templates/Mediclinic/blocks/patient-table.html +38 -38
- package/templates/Mediclinic/blocks/pdf-header.html +9 -9
- package/templates/Mediclinic/blocks/tips.html +8 -8
- package/templates/Mediclinic/ltr_no_pages.html +37 -37
- package/templates/Mediclinic/rtl_no_pages.html +42 -42
- package/templates/Mediclinic/wellbeing_template.html +41 -41
- package/templates/Pha/blocks/first-section.html +207 -207
- package/templates/Pha/blocks/footer.html +7 -7
- package/templates/Pha/blocks/header-template.html +5 -5
- package/templates/Pha/blocks/header.html +20 -20
- package/templates/Pha/blocks/patient-table.html +38 -38
- package/templates/Pha/blocks/pdf-header.html +8 -8
- package/templates/Pha/blocks/tips.html +8 -8
- package/templates/Pha/ltr_no_pages.html +37 -37
- package/templates/Pha/rtl_no_pages.html +42 -42
- package/templates/Pha/wellbeing_template.html +41 -41
- package/templates/base.html +23 -23
- package/templates/blocks/ar-first-page-header.html +68 -68
- package/templates/blocks/ar-footer.html +54 -54
- package/templates/blocks/ar-header.html +67 -67
- package/templates/blocks/biomarker-compact-ar.html +27 -27
- package/templates/blocks/biomarker-compact.html +27 -27
- package/templates/blocks/biomarker-details.html +41 -41
- package/templates/blocks/biomarker-insight.html +22 -22
- package/templates/blocks/biomarker-min.html +9 -9
- package/templates/blocks/doctor-note.html +11 -11
- package/templates/blocks/footer.html +35 -35
- package/templates/blocks/header-first-page.html +46 -46
- package/templates/blocks/header.html +49 -49
- package/templates/blocks/panel-compact.html +38 -38
- package/templates/blocks/panel-details.html +16 -16
- package/templates/blocks/report-summary.html +16 -16
- package/templates/blocks/section-title.html +4 -4
- package/templates/blocks/signature.html +16 -16
- package/templates/blocks/summary-insight.html +15 -15
- package/templates/blocks/summary.html +9 -9
- package/templates/corporate_report/cover_page.html +23 -23
- package/templates/corporate_report/footer.html +9 -9
- package/templates/corporate_report/ltr_no_pages.html +20 -20
- package/templates/corporate_report/page.html +24 -24
- package/templates/corporate_report/participant_analytics.html +5 -5
- package/templates/corporate_report/rtl_no_pages.html +20 -20
- package/templates/empty.html +10 -10
- package/templates/first_page_head.html +157 -157
- package/templates/imc/first-header-template.html +53 -53
- package/templates/ltr.html +1368 -1368
- package/templates/ltr_no_pages.html +89 -89
- package/templates/maisonsante/blocks/first-section.html +151 -207
- package/templates/maisonsante/blocks/footer.html +7 -7
- package/templates/maisonsante/blocks/header-template.html +5 -5
- package/templates/maisonsante/blocks/header.html +20 -20
- package/templates/maisonsante/blocks/patient-table.html +38 -38
- package/templates/maisonsante/blocks/pdf-header.html +8 -8
- package/templates/maisonsante/blocks/tips.html +8 -8
- package/templates/maisonsante/ltr_no_pages.html +38 -38
- package/templates/maisonsante/rtl_no_pages.html +43 -43
- package/templates/maisonsante/wellbeing_template.html +41 -41
- package/templates/no_pages.html +1224 -1224
- package/templates/popup/popup-template.html +129 -129
- package/templates/rtl_no_pages.html +92 -92
- package/templates/sanusx/blocks/footer.html +6 -6
- package/templates/sanusx/blocks/header.html +20 -20
- package/templates/sanusx/blocks/personal-details.html +123 -123
- package/templates/sanusx/blocks/predictions-section.html +57 -57
- package/templates/sanusx/blocks/recommendations-section.html +6 -6
- package/templates/sanusx/blocks/super-power-section.html +29 -29
- package/templates/sanusx/blocks/tips.html +8 -8
- package/templates/sanusx/ltr_no_pages.html +26 -26
- package/templates/sanusx/rtl_no_pages.html +36 -36
- package/templates/template.html +1377 -1377
- package/templates/wellbeing/blocks/first-section.html +106 -106
- package/templates/wellbeing/blocks/footer.html +7 -7
- package/templates/wellbeing/blocks/header.html +37 -37
- package/templates/wellbeing/blocks/tips.html +8 -8
- package/templates/wellbeing/ltr_no_pages.html +35 -35
- package/templates/wellbeing/rtl_no_pages.html +36 -36
- package/templates/wellbeing/wellbeing_template.html +43 -43
- package/test.js +74 -74
- package/testing-reports/mediclinic/arabic-data.js +0 -439
- package/testing-reports/mediclinic/doctor-data.js +0 -523
- package/testing-reports/mediclinic/with-wellbeing.js +0 -415
- package/testing-reports/pha/notes-example.js +0 -397
|
@@ -1,400 +1,400 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const fs = require("fs");
|
|
3
|
-
const {promisify} = require('util');
|
|
4
|
-
const {JSDOM} = require("jsdom");
|
|
5
|
-
const fetch = require("node-fetch");
|
|
6
|
-
const path = require("path");
|
|
7
|
-
const LocaleService = require('../app/services/localeService.js');
|
|
8
|
-
const i18n = require('../app/i18n_wellbeing.config.js');
|
|
9
|
-
const puppeteer = require("puppeteer");
|
|
10
|
-
const hummus = require('hummus');
|
|
11
|
-
const memoryStreams = require('memory-streams');
|
|
12
|
-
|
|
13
|
-
var localeService = new LocaleService(i18n);
|
|
14
|
-
let isRTL = false;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let OUT_FILE = 'output/corporate-report-pdf.html';
|
|
18
|
-
let Pdf_file = '';
|
|
19
|
-
const appDir = path.dirname(require.main.filename);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
let debug = true;
|
|
23
|
-
|
|
24
|
-
let debugLog = (val1, val2 = "") => {
|
|
25
|
-
if (debug) {
|
|
26
|
-
console.log(val1, val2);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
/***
|
|
32
|
-
* HTML file generator to fill the html template
|
|
33
|
-
* based on the json data from the POST request
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
let logo = ""
|
|
37
|
-
let main_color = ""
|
|
38
|
-
let body_font_color = ""
|
|
39
|
-
let report_date_color = ""
|
|
40
|
-
let section_title_color = ""
|
|
41
|
-
let section_title_border_color = ""
|
|
42
|
-
let chart_title = ""
|
|
43
|
-
let summary_background = ""
|
|
44
|
-
let relation_content_border_color = ""
|
|
45
|
-
let relation_content_bg = ""
|
|
46
|
-
let table_tr_even_bg = ""
|
|
47
|
-
let recommends_bg = ""
|
|
48
|
-
let show_second_footer_logo = ""
|
|
49
|
-
let recommends_title = ""
|
|
50
|
-
let show_medicus_logo = ""
|
|
51
|
-
let generateHTMLCorporateReport = async (data, isDebugging) => {
|
|
52
|
-
|
|
53
|
-
debug = isDebugging;
|
|
54
|
-
let dateNow = Date.now()
|
|
55
|
-
OUT_FILE = path.resolve(__dirname + '/../output/corporate-report-pdf' + dateNow + '.html');
|
|
56
|
-
Pdf_file = '/output/corporate-report-pdf' + dateNow + '.html'
|
|
57
|
-
let isRtl = false;
|
|
58
|
-
// data.language = 'es'
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
let client = data.clientName ? data.clientName.toLowerCase() : 'default'
|
|
62
|
-
let pathFile = path.resolve(__dirname + '/../config/' + client + '.json');
|
|
63
|
-
let defaultConfig = require('../config/default.json');
|
|
64
|
-
if (fs.existsSync(pathFile)) {
|
|
65
|
-
defaultConfig = require('../config/' + client + '.json');
|
|
66
|
-
}
|
|
67
|
-
logo = defaultConfig['corporate_report']['logo'];
|
|
68
|
-
main_color = defaultConfig['corporate_report']['main_color'];
|
|
69
|
-
report_date_color = defaultConfig['corporate_report']['report_date_color'];
|
|
70
|
-
section_title_color = defaultConfig['corporate_report']['section_title_color'];
|
|
71
|
-
section_title_border_color = defaultConfig['corporate_report']['section_title_border_color'];
|
|
72
|
-
chart_title = defaultConfig['corporate_report']['chart_title'];
|
|
73
|
-
summary_background = defaultConfig['corporate_report']['summary_background'];
|
|
74
|
-
relation_content_border_color = defaultConfig['corporate_report']['relation_content_border_color'];
|
|
75
|
-
relation_content_bg = defaultConfig['corporate_report']['relation_content_bg'];
|
|
76
|
-
table_tr_even_bg = defaultConfig['corporate_report']['table_tr_even_bg'];
|
|
77
|
-
recommends_bg = defaultConfig['corporate_report']['recommends_bg'];
|
|
78
|
-
show_second_footer_logo = defaultConfig['corporate_report']['show_second_footer_logo'];
|
|
79
|
-
body_font_color = defaultConfig['corporate_report']['body_font_color']
|
|
80
|
-
recommends_title = defaultConfig['corporate_report']['recommends_title']
|
|
81
|
-
show_medicus_logo = defaultConfig['corporate_report']['show_medicus_logo']
|
|
82
|
-
|
|
83
|
-
/*
|
|
84
|
-
if (data.language.indexOf('ar') !== -1) {
|
|
85
|
-
data.language = 'ar-SA';
|
|
86
|
-
isRtl = true;
|
|
87
|
-
}*/
|
|
88
|
-
|
|
89
|
-
/*check if the language is an RTL language*/
|
|
90
|
-
if (!data.language) {
|
|
91
|
-
localeService.setLocale("en")
|
|
92
|
-
} else {
|
|
93
|
-
if (data.language.indexOf('ar') !== -1) {
|
|
94
|
-
data.language = 'ar-SA';
|
|
95
|
-
isRTL = true;
|
|
96
|
-
}
|
|
97
|
-
localeService.setLocale(data.language);
|
|
98
|
-
debugLog("pdf language:", data.language);
|
|
99
|
-
}
|
|
100
|
-
/*choose the right template*/
|
|
101
|
-
let html = !isRTL ? fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/ltr_no_pages.html'), 'utf8') :
|
|
102
|
-
fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/rtl_no_pages.html'), 'utf8')
|
|
103
|
-
|
|
104
|
-
let coverPageTemplate = fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/cover_page.html'), 'utf8');
|
|
105
|
-
let participantAnalyticsTemplate = fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/participant_analytics.html'), 'utf8');
|
|
106
|
-
let pageAnalyticsTemplate = fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/page.html'), 'utf8');
|
|
107
|
-
let footerTemplate = fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/footer.html'), 'utf8');
|
|
108
|
-
footerTemplate = footerTemplate
|
|
109
|
-
.replace("{{logo}}", logo)
|
|
110
|
-
.replace("{{footer_Color}}", report_date_color)
|
|
111
|
-
.replace("{{Page}}", localeService.t('Page'))
|
|
112
|
-
/*create the dom element*/
|
|
113
|
-
const dom = new JSDOM(html);
|
|
114
|
-
let historyData = [];
|
|
115
|
-
debugLog("templates loaded");
|
|
116
|
-
let display_second_log = show_second_footer_logo ? "" : "display:none";
|
|
117
|
-
let show_medicus = show_medicus_logo ? path.resolve(__dirname + "/../assets/corporate_report/images/medicus-logo-footer.png") : ""
|
|
118
|
-
coverPageTemplate = coverPageTemplate
|
|
119
|
-
.replace("{{logo}}", logo)
|
|
120
|
-
.replace("{{reportHeader}}", data.reportHeader)
|
|
121
|
-
.replace("{{reportTitle}}", data.reportTitle)
|
|
122
|
-
.replace("{{reportDate}}", data.reportDate)
|
|
123
|
-
.replace("{{Copyright}}", localeService.t('Copyright'))
|
|
124
|
-
.replace("{{secondFooterLogoStyle}}", display_second_log)
|
|
125
|
-
.replace("{{medicusLogo}}", show_medicus)
|
|
126
|
-
.replace("{{companyLogo}}", data.reportLogo)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
/*get the window from the dom to be used as a jquery function*/
|
|
130
|
-
const $ = (require('jquery'))(dom.window);
|
|
131
|
-
$('#content').append(coverPageTemplate);
|
|
132
|
-
|
|
133
|
-
let participantAnalyticsTemplateHTML = participantAnalyticsTemplate.replace("{{ParticipantAnalytics}}", localeService.t('Participant Analytics'));
|
|
134
|
-
$('#content').append(participantAnalyticsTemplateHTML);
|
|
135
|
-
$(".cover-overlay-container").addClass(client);
|
|
136
|
-
$('#content').append('<style>' +
|
|
137
|
-
'.report-header{color: ' + body_font_color + ' !important;}' +
|
|
138
|
-
'.report-title,.single-relation,.relation-title,.recommends-title,.recommends-section ul,.sources-section a{color: ' + main_color + ' !important;}' +
|
|
139
|
-
'.section-title{color: ' + section_title_color + ' !important;border-bottom: 3px solid ' + section_title_border_color + ';}' +
|
|
140
|
-
'.chart_title{color: ' + chart_title + ' !important;}' +
|
|
141
|
-
'.element-summary-text,.summary-bg{background: ' + summary_background + ' !important;}' +
|
|
142
|
-
'.relation-content,table.data-by-gender th{border-color: ' + relation_content_border_color + ' !important;}' +
|
|
143
|
-
'.relation-content{background: ' + relation_content_bg + ' !important;}' +
|
|
144
|
-
'table.data-by-gender tbody tr:nth-child(even){background-color: ' + table_tr_even_bg + ' !important;}' +
|
|
145
|
-
'.report-date,table.data-by-gender th,table.data-by-gender tbody tr:first-child td,.sources-title{color: ' + report_date_color + ' !important;}' +
|
|
146
|
-
'.recommends-section{background: ' + recommends_bg + ' !important;}' +
|
|
147
|
-
|
|
148
|
-
'</style>');
|
|
149
|
-
|
|
150
|
-
let participantAnalytics = data.participantAnalytics
|
|
151
|
-
|
|
152
|
-
participantAnalytics.map((participantAnalytic) => {
|
|
153
|
-
let barChart = renderBarChart(participantAnalytic)
|
|
154
|
-
$('.participant-analytics-section .container').append(barChart);
|
|
155
|
-
})
|
|
156
|
-
let elementsHTML = ""
|
|
157
|
-
if (!empty(data.elements)) {
|
|
158
|
-
data.elements.map((element, index) => {
|
|
159
|
-
let pageId = "page-" + index;
|
|
160
|
-
elementsHTML = pageAnalyticsTemplate.replace("{{pageId}}", pageId)
|
|
161
|
-
.replace("{{pageTitle}}", element.elementTitle);
|
|
162
|
-
$('#content').append(elementsHTML);
|
|
163
|
-
/*check summary*/
|
|
164
|
-
if (!empty(element.summary)) {
|
|
165
|
-
$("#" + pageId + " .element-summary-text").html(element.summary);
|
|
166
|
-
} else {
|
|
167
|
-
$("#" + pageId + " .element-summary-text").remove()
|
|
168
|
-
}
|
|
169
|
-
if (!empty(element.chartValues)) {
|
|
170
|
-
$(renderBarChart(element.chartValues)).insertAfter("#" + pageId + " .element-summary-container");
|
|
171
|
-
}
|
|
172
|
-
if (!empty(element.secondChartValues)) {
|
|
173
|
-
$(renderBarChart(element.secondChartValues)).insertAfter("#" + pageId + " .side-chart-container");
|
|
174
|
-
}
|
|
175
|
-
/*check relations*/
|
|
176
|
-
if (!empty(element.relations)) {
|
|
177
|
-
console.log("element.relations", element.relations.length)
|
|
178
|
-
element.relations.map((relation) => {
|
|
179
|
-
$("#" + pageId + " .relations-section-container .relations-section-titles").append("<div class='single-relation'>" +
|
|
180
|
-
"<div class='relation-title'>" + relation.title + "</div>" +
|
|
181
|
-
"<div class='relation-content'>" + relation.text + "</div>" +
|
|
182
|
-
"<div class='relation-content-bottom-bg'></div>" +
|
|
183
|
-
"</div>" +
|
|
184
|
-
"</div>");
|
|
185
|
-
$("#" + pageId + ".relation-content").html(relation.text)
|
|
186
|
-
})
|
|
187
|
-
} else {
|
|
188
|
-
$("#" + pageId + " .relations-section-container").remove();
|
|
189
|
-
}
|
|
190
|
-
/*check data by gender*/
|
|
191
|
-
if (!empty(element.dataByGender)) {
|
|
192
|
-
|
|
193
|
-
let tabelHeader = element.dataByGender[0]
|
|
194
|
-
let tabelHeaderHTML = '<thead>'
|
|
195
|
-
tabelHeader.map((header) => {
|
|
196
|
-
tabelHeaderHTML += "<th colspan='" + header.count + "'>" + header.value + "</th>"
|
|
197
|
-
})
|
|
198
|
-
tabelHeaderHTML += '</thead>'
|
|
199
|
-
let tabelBody = element.dataByGender.slice(1)
|
|
200
|
-
let dataByGenderHTML = '<tbody>'
|
|
201
|
-
tabelBody.map((genderData) => {
|
|
202
|
-
dataByGenderHTML += "<tr>"
|
|
203
|
-
genderData.map((td) => {
|
|
204
|
-
dataByGenderHTML += "<td>" + td.value + "</td>"
|
|
205
|
-
})
|
|
206
|
-
dataByGenderHTML += "</tr>"
|
|
207
|
-
})
|
|
208
|
-
dataByGenderHTML += "</tbody>"
|
|
209
|
-
$("#" + pageId + " .data-by-gender").append(tabelHeaderHTML);
|
|
210
|
-
$("#" + pageId + " .data-by-gender").append(dataByGenderHTML);
|
|
211
|
-
} else {
|
|
212
|
-
$("#" + pageId + " .data-by-gender").remove();
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (!empty(element.recommends)) {
|
|
216
|
-
let recommendsHTML = '<div class=\'recommends-title\'>' + `${recommends_title} ${localeService.t('recommends...')}` + '</div><ul>';
|
|
217
|
-
element.recommends.map((recommend) => {
|
|
218
|
-
recommendsHTML += "<li>" +
|
|
219
|
-
"<img src='" + __dirname + '/../assets/corporate_report/images/bulb.png' + "' />" +
|
|
220
|
-
"<span>" + recommend.tip + "</span>" +
|
|
221
|
-
"</li>"
|
|
222
|
-
})
|
|
223
|
-
recommendsHTML += '</ul>'
|
|
224
|
-
$("#" + pageId + " .recommends-section-content").html(recommendsHTML);
|
|
225
|
-
} else {
|
|
226
|
-
$("#" + pageId + " .recommends-section").remove();
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (!empty(element.sources)) {
|
|
231
|
-
let sourcesHTML = `<div class=\'sources-title\'>${localeService.t('Sources')}</div>`
|
|
232
|
-
element.sources.map((source) => {
|
|
233
|
-
sourcesHTML += "<span>"
|
|
234
|
-
if (!empty(source.link)) {
|
|
235
|
-
sourcesHTML += "<a class='hyperlink' href='" + source.link + "' target='_blank'>";
|
|
236
|
-
}
|
|
237
|
-
sourcesHTML += source.title
|
|
238
|
-
if (!empty(source.link)) {
|
|
239
|
-
sourcesHTML += "</a>";
|
|
240
|
-
}
|
|
241
|
-
sourcesHTML += "</span>"
|
|
242
|
-
})
|
|
243
|
-
$("#" + pageId + " .sources-section").html(sourcesHTML);
|
|
244
|
-
$(".links").html(sourcesHTML);
|
|
245
|
-
} else {
|
|
246
|
-
$("#" + pageId + " .sources-section").remove();
|
|
247
|
-
}
|
|
248
|
-
})
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
let OUTPUT_DIRECTORY = path.resolve(`${__dirname}/../output`);
|
|
253
|
-
if (!fs.existsSync(OUTPUT_DIRECTORY)) {
|
|
254
|
-
fs.mkdirSync(OUTPUT_DIRECTORY)
|
|
255
|
-
}
|
|
256
|
-
await promisify(fs.writeFile)(OUT_FILE, dom.serialize());
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
let REQUEST_OUTPUT_DIRECTORY = path.resolve(`${__dirname}/../output/request`);
|
|
260
|
-
if (!fs.existsSync(REQUEST_OUTPUT_DIRECTORY)) {
|
|
261
|
-
fs.mkdirSync(REQUEST_OUTPUT_DIRECTORY)
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return {
|
|
265
|
-
"html": dom.serialize(),
|
|
266
|
-
"outputFile": OUT_FILE,
|
|
267
|
-
"page1": coverPageTemplate,
|
|
268
|
-
"header": '',
|
|
269
|
-
"footer": footerTemplate,
|
|
270
|
-
"historyData": historyData,
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
let generatePDFCorporateReport = async (data) => {
|
|
276
|
-
try {
|
|
277
|
-
let contentHtml = data.html;
|
|
278
|
-
OUT_FILE = data.outputFile;
|
|
279
|
-
let footer = data.footer;
|
|
280
|
-
let browser = await puppeteer.launch({
|
|
281
|
-
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
282
|
-
headless: true,
|
|
283
|
-
ignoreHTTPSErrors: true,
|
|
284
|
-
'defaultViewport': {'width': 1024, 'height': 1600}
|
|
285
|
-
});
|
|
286
|
-
let page = await browser.newPage();
|
|
287
|
-
debugLog("page launched!");
|
|
288
|
-
|
|
289
|
-
await page.setContent(contentHtml, {waitUntil: 'networkidle2'});
|
|
290
|
-
|
|
291
|
-
await page.evaluateHandle('document.fonts.ready');
|
|
292
|
-
// await page.setViewport({width: 1440, height: 900, deviceScaleFactor: 2});
|
|
293
|
-
await page.addScriptTag({url: 'https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js'});
|
|
294
|
-
debugLog("fonts loaded!");
|
|
295
|
-
|
|
296
|
-
await page.goto("file:///" + path.resolve(__dirname + `/../${Pdf_file}`), {
|
|
297
|
-
timeout: 30000000,
|
|
298
|
-
waitUntil: 'networkidle2'
|
|
299
|
-
}).catch(e => {
|
|
300
|
-
console.log("ERROR IS File path: " + e.message);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
debugLog("page opened!");
|
|
304
|
-
let buffer1 = await page.pdf({
|
|
305
|
-
format: 'A4',
|
|
306
|
-
landscape: false,
|
|
307
|
-
fitWindow: true,
|
|
308
|
-
printBackground: true,
|
|
309
|
-
displayHeaderFooter: true,
|
|
310
|
-
margin: {
|
|
311
|
-
top: 0,
|
|
312
|
-
bottom: 60,
|
|
313
|
-
right: 0,
|
|
314
|
-
left: 0
|
|
315
|
-
},
|
|
316
|
-
headerTemplate: '',
|
|
317
|
-
"footerTemplate": footer
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
debugLog("Buffer1 loaded!");
|
|
321
|
-
await browser.close();
|
|
322
|
-
return buffer1;
|
|
323
|
-
|
|
324
|
-
} catch (e) {
|
|
325
|
-
debugLog("ERROR!: ", e);
|
|
326
|
-
return "";
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
const combinePDFBuffers = (firstBuffer, secondBuffer) => {
|
|
331
|
-
var outStream = new memoryStreams.WritableStream();
|
|
332
|
-
|
|
333
|
-
try {
|
|
334
|
-
var firstPDFStream = new hummus.PDFRStreamForBuffer(firstBuffer);
|
|
335
|
-
var secondPDFStream = new hummus.PDFRStreamForBuffer(secondBuffer);
|
|
336
|
-
|
|
337
|
-
var pdfWriter = hummus.createWriterToModify(firstPDFStream, new hummus.PDFStreamForResponse(outStream));
|
|
338
|
-
pdfWriter.appendPDFPagesFromPDF(secondPDFStream);
|
|
339
|
-
pdfWriter.end();
|
|
340
|
-
var newBuffer = outStream.toBuffer();
|
|
341
|
-
outStream.end();
|
|
342
|
-
|
|
343
|
-
return newBuffer;
|
|
344
|
-
} catch (e) {
|
|
345
|
-
outStream.end();
|
|
346
|
-
throw new Error('Error during PDF combination: ' + e.message);
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
const isEmpty = (obj) => {
|
|
350
|
-
for (let key in obj) {
|
|
351
|
-
if (obj.hasOwnProperty(key))
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
return true;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const empty = (value) => {
|
|
358
|
-
return (typeof value === "undefined" || typeof value === 'undefined' || typeof value === undefined || value === null || value === '' || value === "" || value.length === 0 || value === 'undefined');
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
let renderBarChart = (data) => {
|
|
363
|
-
let total = 100;
|
|
364
|
-
let barChart = ""
|
|
365
|
-
if (!empty(data) && !empty(data.data)) {
|
|
366
|
-
barChart = "<div class='side-chart-container'>"
|
|
367
|
-
if (!empty(data.title)) {
|
|
368
|
-
barChart += "<div class='chart_title'>" + data.title + "</div>"
|
|
369
|
-
if (data.title === "Activity") {
|
|
370
|
-
total = data.data[1].value
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
if (!empty(data.data)) {
|
|
374
|
-
barChart += "<div class='side-chart side-chart-with-border'><table>"
|
|
375
|
-
let dataLength = data.data.length
|
|
376
|
-
let barChartClass = ''
|
|
377
|
-
if (dataLength > 5) {
|
|
378
|
-
barChartClass = 'divide-bar'
|
|
379
|
-
}
|
|
380
|
-
data.data.map((chartData) => {
|
|
381
|
-
barChart += "<tr>"
|
|
382
|
-
barChart += "<td>" +
|
|
383
|
-
"<div class='bar-chart " + barChartClass + "' style='background: " + chartData.color + "' data-value='" + chartData.value + "' data-total='" + total + "'>" + chartData.value + "</div>\n" +
|
|
384
|
-
"</td>"
|
|
385
|
-
barChart += "<td class='bar-title'><span>" + chartData.title + "</span></td>"
|
|
386
|
-
barChart += "</tr>"
|
|
387
|
-
})
|
|
388
|
-
|
|
389
|
-
barChart += "</table></div>";
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
barChart += "</div>";
|
|
393
|
-
}
|
|
394
|
-
return barChart;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
module.exports = {
|
|
398
|
-
generatePDFCorporateReport,
|
|
399
|
-
generateHTMLCorporateReport,
|
|
1
|
+
"use strict";
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const {promisify} = require('util');
|
|
4
|
+
const {JSDOM} = require("jsdom");
|
|
5
|
+
const fetch = require("node-fetch");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const LocaleService = require('../app/services/localeService.js');
|
|
8
|
+
const i18n = require('../app/i18n_wellbeing.config.js');
|
|
9
|
+
const puppeteer = require("puppeteer");
|
|
10
|
+
const hummus = require('hummus');
|
|
11
|
+
const memoryStreams = require('memory-streams');
|
|
12
|
+
|
|
13
|
+
var localeService = new LocaleService(i18n);
|
|
14
|
+
let isRTL = false;
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
let OUT_FILE = 'output/corporate-report-pdf.html';
|
|
18
|
+
let Pdf_file = '';
|
|
19
|
+
const appDir = path.dirname(require.main.filename);
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
let debug = true;
|
|
23
|
+
|
|
24
|
+
let debugLog = (val1, val2 = "") => {
|
|
25
|
+
if (debug) {
|
|
26
|
+
console.log(val1, val2);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
/***
|
|
32
|
+
* HTML file generator to fill the html template
|
|
33
|
+
* based on the json data from the POST request
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
let logo = ""
|
|
37
|
+
let main_color = ""
|
|
38
|
+
let body_font_color = ""
|
|
39
|
+
let report_date_color = ""
|
|
40
|
+
let section_title_color = ""
|
|
41
|
+
let section_title_border_color = ""
|
|
42
|
+
let chart_title = ""
|
|
43
|
+
let summary_background = ""
|
|
44
|
+
let relation_content_border_color = ""
|
|
45
|
+
let relation_content_bg = ""
|
|
46
|
+
let table_tr_even_bg = ""
|
|
47
|
+
let recommends_bg = ""
|
|
48
|
+
let show_second_footer_logo = ""
|
|
49
|
+
let recommends_title = ""
|
|
50
|
+
let show_medicus_logo = ""
|
|
51
|
+
let generateHTMLCorporateReport = async (data, isDebugging) => {
|
|
52
|
+
|
|
53
|
+
debug = isDebugging;
|
|
54
|
+
let dateNow = Date.now()
|
|
55
|
+
OUT_FILE = path.resolve(__dirname + '/../output/corporate-report-pdf' + dateNow + '.html');
|
|
56
|
+
Pdf_file = '/output/corporate-report-pdf' + dateNow + '.html'
|
|
57
|
+
let isRtl = false;
|
|
58
|
+
// data.language = 'es'
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
let client = data.clientName ? data.clientName.toLowerCase() : 'default'
|
|
62
|
+
let pathFile = path.resolve(__dirname + '/../config/' + client + '.json');
|
|
63
|
+
let defaultConfig = require('../config/default.json');
|
|
64
|
+
if (fs.existsSync(pathFile)) {
|
|
65
|
+
defaultConfig = require('../config/' + client + '.json');
|
|
66
|
+
}
|
|
67
|
+
logo = defaultConfig['corporate_report']['logo'];
|
|
68
|
+
main_color = defaultConfig['corporate_report']['main_color'];
|
|
69
|
+
report_date_color = defaultConfig['corporate_report']['report_date_color'];
|
|
70
|
+
section_title_color = defaultConfig['corporate_report']['section_title_color'];
|
|
71
|
+
section_title_border_color = defaultConfig['corporate_report']['section_title_border_color'];
|
|
72
|
+
chart_title = defaultConfig['corporate_report']['chart_title'];
|
|
73
|
+
summary_background = defaultConfig['corporate_report']['summary_background'];
|
|
74
|
+
relation_content_border_color = defaultConfig['corporate_report']['relation_content_border_color'];
|
|
75
|
+
relation_content_bg = defaultConfig['corporate_report']['relation_content_bg'];
|
|
76
|
+
table_tr_even_bg = defaultConfig['corporate_report']['table_tr_even_bg'];
|
|
77
|
+
recommends_bg = defaultConfig['corporate_report']['recommends_bg'];
|
|
78
|
+
show_second_footer_logo = defaultConfig['corporate_report']['show_second_footer_logo'];
|
|
79
|
+
body_font_color = defaultConfig['corporate_report']['body_font_color']
|
|
80
|
+
recommends_title = defaultConfig['corporate_report']['recommends_title']
|
|
81
|
+
show_medicus_logo = defaultConfig['corporate_report']['show_medicus_logo']
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
if (data.language.indexOf('ar') !== -1) {
|
|
85
|
+
data.language = 'ar-SA';
|
|
86
|
+
isRtl = true;
|
|
87
|
+
}*/
|
|
88
|
+
|
|
89
|
+
/*check if the language is an RTL language*/
|
|
90
|
+
if (!data.language) {
|
|
91
|
+
localeService.setLocale("en")
|
|
92
|
+
} else {
|
|
93
|
+
if (data.language.indexOf('ar') !== -1) {
|
|
94
|
+
data.language = 'ar-SA';
|
|
95
|
+
isRTL = true;
|
|
96
|
+
}
|
|
97
|
+
localeService.setLocale(data.language);
|
|
98
|
+
debugLog("pdf language:", data.language);
|
|
99
|
+
}
|
|
100
|
+
/*choose the right template*/
|
|
101
|
+
let html = !isRTL ? fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/ltr_no_pages.html'), 'utf8') :
|
|
102
|
+
fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/rtl_no_pages.html'), 'utf8')
|
|
103
|
+
|
|
104
|
+
let coverPageTemplate = fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/cover_page.html'), 'utf8');
|
|
105
|
+
let participantAnalyticsTemplate = fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/participant_analytics.html'), 'utf8');
|
|
106
|
+
let pageAnalyticsTemplate = fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/page.html'), 'utf8');
|
|
107
|
+
let footerTemplate = fs.readFileSync(path.resolve(__dirname + '/../templates/corporate_report/footer.html'), 'utf8');
|
|
108
|
+
footerTemplate = footerTemplate
|
|
109
|
+
.replace("{{logo}}", logo)
|
|
110
|
+
.replace("{{footer_Color}}", report_date_color)
|
|
111
|
+
.replace("{{Page}}", localeService.t('Page'))
|
|
112
|
+
/*create the dom element*/
|
|
113
|
+
const dom = new JSDOM(html);
|
|
114
|
+
let historyData = [];
|
|
115
|
+
debugLog("templates loaded");
|
|
116
|
+
let display_second_log = show_second_footer_logo ? "" : "display:none";
|
|
117
|
+
let show_medicus = show_medicus_logo ? path.resolve(__dirname + "/../assets/corporate_report/images/medicus-logo-footer.png") : ""
|
|
118
|
+
coverPageTemplate = coverPageTemplate
|
|
119
|
+
.replace("{{logo}}", logo)
|
|
120
|
+
.replace("{{reportHeader}}", data.reportHeader)
|
|
121
|
+
.replace("{{reportTitle}}", data.reportTitle)
|
|
122
|
+
.replace("{{reportDate}}", data.reportDate)
|
|
123
|
+
.replace("{{Copyright}}", localeService.t('Copyright'))
|
|
124
|
+
.replace("{{secondFooterLogoStyle}}", display_second_log)
|
|
125
|
+
.replace("{{medicusLogo}}", show_medicus)
|
|
126
|
+
.replace("{{companyLogo}}", data.reportLogo)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
/*get the window from the dom to be used as a jquery function*/
|
|
130
|
+
const $ = (require('jquery'))(dom.window);
|
|
131
|
+
$('#content').append(coverPageTemplate);
|
|
132
|
+
|
|
133
|
+
let participantAnalyticsTemplateHTML = participantAnalyticsTemplate.replace("{{ParticipantAnalytics}}", localeService.t('Participant Analytics'));
|
|
134
|
+
$('#content').append(participantAnalyticsTemplateHTML);
|
|
135
|
+
$(".cover-overlay-container").addClass(client);
|
|
136
|
+
$('#content').append('<style>' +
|
|
137
|
+
'.report-header{color: ' + body_font_color + ' !important;}' +
|
|
138
|
+
'.report-title,.single-relation,.relation-title,.recommends-title,.recommends-section ul,.sources-section a{color: ' + main_color + ' !important;}' +
|
|
139
|
+
'.section-title{color: ' + section_title_color + ' !important;border-bottom: 3px solid ' + section_title_border_color + ';}' +
|
|
140
|
+
'.chart_title{color: ' + chart_title + ' !important;}' +
|
|
141
|
+
'.element-summary-text,.summary-bg{background: ' + summary_background + ' !important;}' +
|
|
142
|
+
'.relation-content,table.data-by-gender th{border-color: ' + relation_content_border_color + ' !important;}' +
|
|
143
|
+
'.relation-content{background: ' + relation_content_bg + ' !important;}' +
|
|
144
|
+
'table.data-by-gender tbody tr:nth-child(even){background-color: ' + table_tr_even_bg + ' !important;}' +
|
|
145
|
+
'.report-date,table.data-by-gender th,table.data-by-gender tbody tr:first-child td,.sources-title{color: ' + report_date_color + ' !important;}' +
|
|
146
|
+
'.recommends-section{background: ' + recommends_bg + ' !important;}' +
|
|
147
|
+
|
|
148
|
+
'</style>');
|
|
149
|
+
|
|
150
|
+
let participantAnalytics = data.participantAnalytics
|
|
151
|
+
|
|
152
|
+
participantAnalytics.map((participantAnalytic) => {
|
|
153
|
+
let barChart = renderBarChart(participantAnalytic)
|
|
154
|
+
$('.participant-analytics-section .container').append(barChart);
|
|
155
|
+
})
|
|
156
|
+
let elementsHTML = ""
|
|
157
|
+
if (!empty(data.elements)) {
|
|
158
|
+
data.elements.map((element, index) => {
|
|
159
|
+
let pageId = "page-" + index;
|
|
160
|
+
elementsHTML = pageAnalyticsTemplate.replace("{{pageId}}", pageId)
|
|
161
|
+
.replace("{{pageTitle}}", element.elementTitle);
|
|
162
|
+
$('#content').append(elementsHTML);
|
|
163
|
+
/*check summary*/
|
|
164
|
+
if (!empty(element.summary)) {
|
|
165
|
+
$("#" + pageId + " .element-summary-text").html(element.summary);
|
|
166
|
+
} else {
|
|
167
|
+
$("#" + pageId + " .element-summary-text").remove()
|
|
168
|
+
}
|
|
169
|
+
if (!empty(element.chartValues)) {
|
|
170
|
+
$(renderBarChart(element.chartValues)).insertAfter("#" + pageId + " .element-summary-container");
|
|
171
|
+
}
|
|
172
|
+
if (!empty(element.secondChartValues)) {
|
|
173
|
+
$(renderBarChart(element.secondChartValues)).insertAfter("#" + pageId + " .side-chart-container");
|
|
174
|
+
}
|
|
175
|
+
/*check relations*/
|
|
176
|
+
if (!empty(element.relations)) {
|
|
177
|
+
console.log("element.relations", element.relations.length)
|
|
178
|
+
element.relations.map((relation) => {
|
|
179
|
+
$("#" + pageId + " .relations-section-container .relations-section-titles").append("<div class='single-relation'>" +
|
|
180
|
+
"<div class='relation-title'>" + relation.title + "</div>" +
|
|
181
|
+
"<div class='relation-content'>" + relation.text + "</div>" +
|
|
182
|
+
"<div class='relation-content-bottom-bg'></div>" +
|
|
183
|
+
"</div>" +
|
|
184
|
+
"</div>");
|
|
185
|
+
$("#" + pageId + ".relation-content").html(relation.text)
|
|
186
|
+
})
|
|
187
|
+
} else {
|
|
188
|
+
$("#" + pageId + " .relations-section-container").remove();
|
|
189
|
+
}
|
|
190
|
+
/*check data by gender*/
|
|
191
|
+
if (!empty(element.dataByGender)) {
|
|
192
|
+
|
|
193
|
+
let tabelHeader = element.dataByGender[0]
|
|
194
|
+
let tabelHeaderHTML = '<thead>'
|
|
195
|
+
tabelHeader.map((header) => {
|
|
196
|
+
tabelHeaderHTML += "<th colspan='" + header.count + "'>" + header.value + "</th>"
|
|
197
|
+
})
|
|
198
|
+
tabelHeaderHTML += '</thead>'
|
|
199
|
+
let tabelBody = element.dataByGender.slice(1)
|
|
200
|
+
let dataByGenderHTML = '<tbody>'
|
|
201
|
+
tabelBody.map((genderData) => {
|
|
202
|
+
dataByGenderHTML += "<tr>"
|
|
203
|
+
genderData.map((td) => {
|
|
204
|
+
dataByGenderHTML += "<td>" + td.value + "</td>"
|
|
205
|
+
})
|
|
206
|
+
dataByGenderHTML += "</tr>"
|
|
207
|
+
})
|
|
208
|
+
dataByGenderHTML += "</tbody>"
|
|
209
|
+
$("#" + pageId + " .data-by-gender").append(tabelHeaderHTML);
|
|
210
|
+
$("#" + pageId + " .data-by-gender").append(dataByGenderHTML);
|
|
211
|
+
} else {
|
|
212
|
+
$("#" + pageId + " .data-by-gender").remove();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (!empty(element.recommends)) {
|
|
216
|
+
let recommendsHTML = '<div class=\'recommends-title\'>' + `${recommends_title} ${localeService.t('recommends...')}` + '</div><ul>';
|
|
217
|
+
element.recommends.map((recommend) => {
|
|
218
|
+
recommendsHTML += "<li>" +
|
|
219
|
+
"<img src='" + __dirname + '/../assets/corporate_report/images/bulb.png' + "' />" +
|
|
220
|
+
"<span>" + recommend.tip + "</span>" +
|
|
221
|
+
"</li>"
|
|
222
|
+
})
|
|
223
|
+
recommendsHTML += '</ul>'
|
|
224
|
+
$("#" + pageId + " .recommends-section-content").html(recommendsHTML);
|
|
225
|
+
} else {
|
|
226
|
+
$("#" + pageId + " .recommends-section").remove();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
if (!empty(element.sources)) {
|
|
231
|
+
let sourcesHTML = `<div class=\'sources-title\'>${localeService.t('Sources')}</div>`
|
|
232
|
+
element.sources.map((source) => {
|
|
233
|
+
sourcesHTML += "<span>"
|
|
234
|
+
if (!empty(source.link)) {
|
|
235
|
+
sourcesHTML += "<a class='hyperlink' href='" + source.link + "' target='_blank'>";
|
|
236
|
+
}
|
|
237
|
+
sourcesHTML += source.title
|
|
238
|
+
if (!empty(source.link)) {
|
|
239
|
+
sourcesHTML += "</a>";
|
|
240
|
+
}
|
|
241
|
+
sourcesHTML += "</span>"
|
|
242
|
+
})
|
|
243
|
+
$("#" + pageId + " .sources-section").html(sourcesHTML);
|
|
244
|
+
$(".links").html(sourcesHTML);
|
|
245
|
+
} else {
|
|
246
|
+
$("#" + pageId + " .sources-section").remove();
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
let OUTPUT_DIRECTORY = path.resolve(`${__dirname}/../output`);
|
|
253
|
+
if (!fs.existsSync(OUTPUT_DIRECTORY)) {
|
|
254
|
+
fs.mkdirSync(OUTPUT_DIRECTORY)
|
|
255
|
+
}
|
|
256
|
+
await promisify(fs.writeFile)(OUT_FILE, dom.serialize());
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
let REQUEST_OUTPUT_DIRECTORY = path.resolve(`${__dirname}/../output/request`);
|
|
260
|
+
if (!fs.existsSync(REQUEST_OUTPUT_DIRECTORY)) {
|
|
261
|
+
fs.mkdirSync(REQUEST_OUTPUT_DIRECTORY)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
"html": dom.serialize(),
|
|
266
|
+
"outputFile": OUT_FILE,
|
|
267
|
+
"page1": coverPageTemplate,
|
|
268
|
+
"header": '',
|
|
269
|
+
"footer": footerTemplate,
|
|
270
|
+
"historyData": historyData,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
let generatePDFCorporateReport = async (data) => {
|
|
276
|
+
try {
|
|
277
|
+
let contentHtml = data.html;
|
|
278
|
+
OUT_FILE = data.outputFile;
|
|
279
|
+
let footer = data.footer;
|
|
280
|
+
let browser = await puppeteer.launch({
|
|
281
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
282
|
+
headless: true,
|
|
283
|
+
ignoreHTTPSErrors: true,
|
|
284
|
+
'defaultViewport': {'width': 1024, 'height': 1600}
|
|
285
|
+
});
|
|
286
|
+
let page = await browser.newPage();
|
|
287
|
+
debugLog("page launched!");
|
|
288
|
+
|
|
289
|
+
await page.setContent(contentHtml, {waitUntil: 'networkidle2'});
|
|
290
|
+
|
|
291
|
+
await page.evaluateHandle('document.fonts.ready');
|
|
292
|
+
// await page.setViewport({width: 1440, height: 900, deviceScaleFactor: 2});
|
|
293
|
+
await page.addScriptTag({url: 'https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js'});
|
|
294
|
+
debugLog("fonts loaded!");
|
|
295
|
+
|
|
296
|
+
await page.goto("file:///" + path.resolve(__dirname + `/../${Pdf_file}`), {
|
|
297
|
+
timeout: 30000000,
|
|
298
|
+
waitUntil: 'networkidle2'
|
|
299
|
+
}).catch(e => {
|
|
300
|
+
console.log("ERROR IS File path: " + e.message);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
debugLog("page opened!");
|
|
304
|
+
let buffer1 = await page.pdf({
|
|
305
|
+
format: 'A4',
|
|
306
|
+
landscape: false,
|
|
307
|
+
fitWindow: true,
|
|
308
|
+
printBackground: true,
|
|
309
|
+
displayHeaderFooter: true,
|
|
310
|
+
margin: {
|
|
311
|
+
top: 0,
|
|
312
|
+
bottom: 60,
|
|
313
|
+
right: 0,
|
|
314
|
+
left: 0
|
|
315
|
+
},
|
|
316
|
+
headerTemplate: '',
|
|
317
|
+
"footerTemplate": footer
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
debugLog("Buffer1 loaded!");
|
|
321
|
+
await browser.close();
|
|
322
|
+
return buffer1;
|
|
323
|
+
|
|
324
|
+
} catch (e) {
|
|
325
|
+
debugLog("ERROR!: ", e);
|
|
326
|
+
return "";
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const combinePDFBuffers = (firstBuffer, secondBuffer) => {
|
|
331
|
+
var outStream = new memoryStreams.WritableStream();
|
|
332
|
+
|
|
333
|
+
try {
|
|
334
|
+
var firstPDFStream = new hummus.PDFRStreamForBuffer(firstBuffer);
|
|
335
|
+
var secondPDFStream = new hummus.PDFRStreamForBuffer(secondBuffer);
|
|
336
|
+
|
|
337
|
+
var pdfWriter = hummus.createWriterToModify(firstPDFStream, new hummus.PDFStreamForResponse(outStream));
|
|
338
|
+
pdfWriter.appendPDFPagesFromPDF(secondPDFStream);
|
|
339
|
+
pdfWriter.end();
|
|
340
|
+
var newBuffer = outStream.toBuffer();
|
|
341
|
+
outStream.end();
|
|
342
|
+
|
|
343
|
+
return newBuffer;
|
|
344
|
+
} catch (e) {
|
|
345
|
+
outStream.end();
|
|
346
|
+
throw new Error('Error during PDF combination: ' + e.message);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
const isEmpty = (obj) => {
|
|
350
|
+
for (let key in obj) {
|
|
351
|
+
if (obj.hasOwnProperty(key))
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const empty = (value) => {
|
|
358
|
+
return (typeof value === "undefined" || typeof value === 'undefined' || typeof value === undefined || value === null || value === '' || value === "" || value.length === 0 || value === 'undefined');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
let renderBarChart = (data) => {
|
|
363
|
+
let total = 100;
|
|
364
|
+
let barChart = ""
|
|
365
|
+
if (!empty(data) && !empty(data.data)) {
|
|
366
|
+
barChart = "<div class='side-chart-container'>"
|
|
367
|
+
if (!empty(data.title)) {
|
|
368
|
+
barChart += "<div class='chart_title'>" + data.title + "</div>"
|
|
369
|
+
if (data.title === "Activity") {
|
|
370
|
+
total = data.data[1].value
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
if (!empty(data.data)) {
|
|
374
|
+
barChart += "<div class='side-chart side-chart-with-border'><table>"
|
|
375
|
+
let dataLength = data.data.length
|
|
376
|
+
let barChartClass = ''
|
|
377
|
+
if (dataLength > 5) {
|
|
378
|
+
barChartClass = 'divide-bar'
|
|
379
|
+
}
|
|
380
|
+
data.data.map((chartData) => {
|
|
381
|
+
barChart += "<tr>"
|
|
382
|
+
barChart += "<td>" +
|
|
383
|
+
"<div class='bar-chart " + barChartClass + "' style='background: " + chartData.color + "' data-value='" + chartData.value + "' data-total='" + total + "'>" + chartData.value + "</div>\n" +
|
|
384
|
+
"</td>"
|
|
385
|
+
barChart += "<td class='bar-title'><span>" + chartData.title + "</span></td>"
|
|
386
|
+
barChart += "</tr>"
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
barChart += "</table></div>";
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
barChart += "</div>";
|
|
393
|
+
}
|
|
394
|
+
return barChart;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
module.exports = {
|
|
398
|
+
generatePDFCorporateReport,
|
|
399
|
+
generateHTMLCorporateReport,
|
|
400
400
|
};
|