@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.
Files changed (178) hide show
  1. package/.vscode/settings.json +3 -3
  2. package/HANDOVER.md +146 -0
  3. package/README.md +26 -26
  4. package/app/i18n.config.js +20 -20
  5. package/app/i18n_wellbeing.config.js +20 -20
  6. package/app/services/localeService.js +28 -28
  7. package/assets/Mediclinic/css/nasco_report.css +6297 -6297
  8. package/assets/Mediclinic/css/nasco_report_rtl.css +851 -851
  9. package/assets/Mediclinic/css/style.css +33 -33
  10. package/assets/Mediclinic/js/js.js +112 -112
  11. package/assets/Mediclinic/js/raphael.js +8437 -8437
  12. package/assets/arabic.css +275 -275
  13. package/assets/charts.min.js +7 -7
  14. package/assets/corporate_report/css/report.css +582 -582
  15. package/assets/corporate_report/css/report_rtl.css +144 -144
  16. package/assets/corporate_report/js/js.js +14 -14
  17. package/assets/data/data.json +124 -124
  18. package/assets/data/data2.json +675 -675
  19. package/assets/data/pdf_data_with_history.json +1255 -1255
  20. package/assets/doctor-note-insight-icon.svg +11 -11
  21. package/assets/imc/css/style.css +61 -61
  22. package/assets/jquery-1.4.min.js +151 -151
  23. package/assets/jquery-2.1.0.min.js +3 -3
  24. package/assets/js.js +201 -201
  25. package/assets/medicus_pdf/arabic.css +444 -444
  26. package/assets/medicus_pdf/styles.css +2427 -2427
  27. package/assets/print.css +4 -4
  28. package/assets/qr-code-style.css +68 -68
  29. package/assets/qrcode.min.js +3 -3
  30. package/assets/raphael-min.js +10 -10
  31. package/assets/sanusx/css/sanusx_report.css +707 -707
  32. package/assets/sizing.js +2 -2
  33. package/assets/styles.css +1545 -1545
  34. package/assets/styles.min.css +1358 -1358
  35. package/assets/translation.js +30 -30
  36. package/assets/wellbeing/css/nasco_report.css +3472 -3472
  37. package/assets/wellbeing/css/nasco_report_rtl.css +679 -679
  38. package/assets/wellbeing/js/js.js +111 -111
  39. package/assets/wellbeing/js/raphael.js +8437 -8437
  40. package/base64/cairo-font.js +2 -2
  41. package/config/Mediclinic.json +37 -37
  42. package/config/Najeeb.ai.json +35 -35
  43. package/config/Pha.json +64 -64
  44. package/config/bionext.json +37 -37
  45. package/config/default.json +35 -35
  46. package/config/diagnostikare.json +34 -34
  47. package/config/maisonsante.json +39 -39
  48. package/config/nasco.json +35 -35
  49. package/config/sanitas.json +35 -35
  50. package/config/sanusx.json +34 -34
  51. package/config/test.txt +4 -4
  52. package/data converter.js +53 -53
  53. package/docs/01-architecture-overview.md +149 -0
  54. package/docs/02-configuration-and-whitelabelling.md +111 -0
  55. package/docs/03-templating-and-rendering.md +71 -0
  56. package/docs/04-report-pipelines.md +128 -0
  57. package/docs/05-questions-and-data-model.md +67 -0
  58. package/docs/06-internationalization.md +59 -0
  59. package/docs/07-email-notifications.md +59 -0
  60. package/docs/08-known-issues-and-technical-debt.md +41 -0
  61. package/docs/README.md +22 -0
  62. package/downloadfile.js +6 -6
  63. package/example.txt +1188 -1188
  64. package/index.js +481 -480
  65. package/lib/big_integral_questionnaire.js +370 -298
  66. package/lib/corporate_report_generator.js +399 -399
  67. package/lib/pdf_generator.min.js +525 -525
  68. package/lib/sanusx_report_generator.js +533 -533
  69. package/lib/sendEmail.js +343 -343
  70. package/lib/template.js +2227 -2227
  71. package/lib/wellbeing_report_generator.js +2164 -2134
  72. package/locales/ar-AE.json +169 -169
  73. package/locales/ar-SA.json +169 -169
  74. package/locales/ar.json +397 -397
  75. package/locales/de.json +169 -169
  76. package/locales/en.json +229 -229
  77. package/locales/fr.json +168 -168
  78. package/locales/pt.json +165 -165
  79. package/locales/wellbeing/ar-AE.json +149 -149
  80. package/locales/wellbeing/ar-SA.json +257 -257
  81. package/locales/wellbeing/de.json +301 -301
  82. package/locales/wellbeing/en.json +423 -423
  83. package/locales/wellbeing/es.json +133 -133
  84. package/locales/wellbeing/fr.json +121 -121
  85. package/locales/wellbeing/it-IT.json +121 -121
  86. package/locales/wellbeing/pt.json +121 -121
  87. package/locales/wellbeing/tr.json +121 -121
  88. package/locales/wellbeing/zh-CN.json +121 -121
  89. package/locales/zh-CN.json +165 -165
  90. package/package.json +47 -47
  91. package/preview-big-integral.js +75 -75
  92. package/run.js +15 -15
  93. package/templates/Mediclinic/blocks/first-section.html +205 -205
  94. package/templates/Mediclinic/blocks/footer.html +7 -7
  95. package/templates/Mediclinic/blocks/header-template.html +5 -5
  96. package/templates/Mediclinic/blocks/header.html +20 -20
  97. package/templates/Mediclinic/blocks/patient-table.html +38 -38
  98. package/templates/Mediclinic/blocks/pdf-header.html +9 -9
  99. package/templates/Mediclinic/blocks/tips.html +8 -8
  100. package/templates/Mediclinic/ltr_no_pages.html +37 -37
  101. package/templates/Mediclinic/rtl_no_pages.html +42 -42
  102. package/templates/Mediclinic/wellbeing_template.html +41 -41
  103. package/templates/Pha/blocks/first-section.html +207 -207
  104. package/templates/Pha/blocks/footer.html +7 -7
  105. package/templates/Pha/blocks/header-template.html +5 -5
  106. package/templates/Pha/blocks/header.html +20 -20
  107. package/templates/Pha/blocks/patient-table.html +38 -38
  108. package/templates/Pha/blocks/pdf-header.html +8 -8
  109. package/templates/Pha/blocks/tips.html +8 -8
  110. package/templates/Pha/ltr_no_pages.html +37 -37
  111. package/templates/Pha/rtl_no_pages.html +42 -42
  112. package/templates/Pha/wellbeing_template.html +41 -41
  113. package/templates/base.html +23 -23
  114. package/templates/blocks/ar-first-page-header.html +68 -68
  115. package/templates/blocks/ar-footer.html +54 -54
  116. package/templates/blocks/ar-header.html +67 -67
  117. package/templates/blocks/biomarker-compact-ar.html +27 -27
  118. package/templates/blocks/biomarker-compact.html +27 -27
  119. package/templates/blocks/biomarker-details.html +41 -41
  120. package/templates/blocks/biomarker-insight.html +22 -22
  121. package/templates/blocks/biomarker-min.html +9 -9
  122. package/templates/blocks/doctor-note.html +11 -11
  123. package/templates/blocks/footer.html +35 -35
  124. package/templates/blocks/header-first-page.html +46 -46
  125. package/templates/blocks/header.html +49 -49
  126. package/templates/blocks/panel-compact.html +38 -38
  127. package/templates/blocks/panel-details.html +16 -16
  128. package/templates/blocks/report-summary.html +16 -16
  129. package/templates/blocks/section-title.html +4 -4
  130. package/templates/blocks/signature.html +16 -16
  131. package/templates/blocks/summary-insight.html +15 -15
  132. package/templates/blocks/summary.html +9 -9
  133. package/templates/corporate_report/cover_page.html +23 -23
  134. package/templates/corporate_report/footer.html +9 -9
  135. package/templates/corporate_report/ltr_no_pages.html +20 -20
  136. package/templates/corporate_report/page.html +24 -24
  137. package/templates/corporate_report/participant_analytics.html +5 -5
  138. package/templates/corporate_report/rtl_no_pages.html +20 -20
  139. package/templates/empty.html +10 -10
  140. package/templates/first_page_head.html +157 -157
  141. package/templates/imc/first-header-template.html +53 -53
  142. package/templates/ltr.html +1368 -1368
  143. package/templates/ltr_no_pages.html +89 -89
  144. package/templates/maisonsante/blocks/first-section.html +151 -207
  145. package/templates/maisonsante/blocks/footer.html +7 -7
  146. package/templates/maisonsante/blocks/header-template.html +5 -5
  147. package/templates/maisonsante/blocks/header.html +20 -20
  148. package/templates/maisonsante/blocks/patient-table.html +38 -38
  149. package/templates/maisonsante/blocks/pdf-header.html +8 -8
  150. package/templates/maisonsante/blocks/tips.html +8 -8
  151. package/templates/maisonsante/ltr_no_pages.html +38 -38
  152. package/templates/maisonsante/rtl_no_pages.html +43 -43
  153. package/templates/maisonsante/wellbeing_template.html +41 -41
  154. package/templates/no_pages.html +1224 -1224
  155. package/templates/popup/popup-template.html +129 -129
  156. package/templates/rtl_no_pages.html +92 -92
  157. package/templates/sanusx/blocks/footer.html +6 -6
  158. package/templates/sanusx/blocks/header.html +20 -20
  159. package/templates/sanusx/blocks/personal-details.html +123 -123
  160. package/templates/sanusx/blocks/predictions-section.html +57 -57
  161. package/templates/sanusx/blocks/recommendations-section.html +6 -6
  162. package/templates/sanusx/blocks/super-power-section.html +29 -29
  163. package/templates/sanusx/blocks/tips.html +8 -8
  164. package/templates/sanusx/ltr_no_pages.html +26 -26
  165. package/templates/sanusx/rtl_no_pages.html +36 -36
  166. package/templates/template.html +1377 -1377
  167. package/templates/wellbeing/blocks/first-section.html +106 -106
  168. package/templates/wellbeing/blocks/footer.html +7 -7
  169. package/templates/wellbeing/blocks/header.html +37 -37
  170. package/templates/wellbeing/blocks/tips.html +8 -8
  171. package/templates/wellbeing/ltr_no_pages.html +35 -35
  172. package/templates/wellbeing/rtl_no_pages.html +36 -36
  173. package/templates/wellbeing/wellbeing_template.html +43 -43
  174. package/test.js +74 -74
  175. package/testing-reports/mediclinic/arabic-data.js +0 -439
  176. package/testing-reports/mediclinic/doctor-data.js +0 -523
  177. package/testing-reports/mediclinic/with-wellbeing.js +0 -415
  178. 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
  };