@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
package/.vscode/settings.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{
|
|
2
|
-
"search.useIgnoreFiles": true,
|
|
3
|
-
"search.useGlobalIgnoreFiles": true
|
|
1
|
+
{
|
|
2
|
+
"search.useIgnoreFiles": true,
|
|
3
|
+
"search.useGlobalIgnoreFiles": true
|
|
4
4
|
}
|
package/HANDOVER.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Handover: Medicus PDF Generator
|
|
2
|
+
|
|
3
|
+
**Audience:** software engineers taking over this project who are not frontend specialists. You don't need deep CSS/HTML expertise to maintain this — you need to understand it as a **data-in, PDF-out rendering pipeline** with some unusual, homegrown templating. This document is the fast path to being productive. Full details, with file:line-level citations, are in [`docs/`](docs/README.md) — this file tells you what matters most and when to go read which doc.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. What this thing actually is
|
|
8
|
+
|
|
9
|
+
`@medicus.ai/medicus-report-pdf-generator` is an **npm library**, not a service. There is no HTTP server, no listener, no routes anywhere in this repo. A host application (per the README, originally a Meteor app) `require()`s it and calls its exported functions directly — or, optionally, through `run.js`, which forks a child process for isolation.
|
|
10
|
+
|
|
11
|
+
It has:
|
|
12
|
+
- **No authentication or authorization.** No JWT, no sessions, no API keys — check `package.json`, there's nothing auth-related in the dependency list. Whatever calls this library is trusted completely; access control is 100% the host application's job.
|
|
13
|
+
- **No database.** Every call is stateless: JSON in, PDF/HTML/base64 out. The only persistent side effects are files written to `output/` or the OS temp directory (see §6).
|
|
14
|
+
- **Four distinct report "products"**, each with its own generator file and its own quirks (see §4). They are not built on a shared rendering engine — each independently reimplements the same "read HTML fragment from disk, do string replacement, build a DOM with jsdom+jQuery, hand to Puppeteer" pattern.
|
|
15
|
+
|
|
16
|
+
If you remember one mental model: **this package is a fancy `data.json + template.html → report.pdf` compiler, called once per report, with no state carried between calls** (aside from a few shared-singleton gotchas noted below).
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 2. The one fact that will save you the most time
|
|
21
|
+
|
|
22
|
+
**`index.js` requires `lib/pdf_generator.min.js` — not `lib/pdf_generator.js`.**
|
|
23
|
+
|
|
24
|
+
These look like a source/minified-build pair. They are not. There's no build script anywhere in this repo that produces one from the other (no webpack config exists, despite `webpack` sitting in `devDependencies`). Git history proves it: `pdf_generator.js` was last edited in **March 2021**; `pdf_generator.min.js` was last edited in **July 2025** — completely independent edit histories, over four years apart.
|
|
25
|
+
|
|
26
|
+
**If you're asked to fix a bug in the core "Medicus" lab report and you edit `lib/pdf_generator.js`, your fix will silently not ship.** Edit `lib/pdf_generator.min.js` instead. This is the single highest-value thing to internalize before touching this codebase. Full detail: [`docs/01-architecture-overview.md §1.4`](docs/01-architecture-overview.md#14-critical-fact-the-core-report-renderer-that-actually-runs-is-pdf_generatorminjs-not-pdf_generatorjs).
|
|
27
|
+
|
|
28
|
+
(Longer-term: either delete `pdf_generator.js` and rename `.min.js` to something honest, or wire up a real build step. Either fixes this permanently.)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 3. How data flows in
|
|
33
|
+
|
|
34
|
+
Every report-generating export in `index.js` follows the same shape: the caller passes a JSON *string* (or, for the core report, a raw base64 string) whose real content — patient data, biomarkers, scores, questions, whatever — is **base64-encoded** inside a `data` field, alongside plain-text sibling fields like `client`, `language`, and (if emailing) SMTP config.
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
{
|
|
38
|
+
"data": "<base64 of the actual report JSON>",
|
|
39
|
+
"client": "Mediclinic",
|
|
40
|
+
"language": "en",
|
|
41
|
+
"host": "smtp...", "port": 587, "authUser": "...", "authPass": "...", // only if emailing
|
|
42
|
+
"pdfPassword": "..." // generateFullPdf only — output gets encrypted
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Base64 is encoding, not security.** Anyone who can see a request to this library (including anyone reading a debug log) can trivially recover everything inside it, including SMTP credentials riding alongside the report data. See §7.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 4. The four report pipelines — know which one you're in before debugging
|
|
51
|
+
|
|
52
|
+
- **Core "Medicus"** — module `lib/pdf_generator.min.js`. Clinical lab report: biomarkers, panels, reference ranges, doctor notes, insights. No questionnaires. Entry point: `generateMedicusPDF`.
|
|
53
|
+
- **Wellbeing** — module `lib/wellbeing_report_generator.js` (+ `lib/template.js`, `lib/big_integral_questionnaire.js`). Patient wellbeing/lifestyle report — questionnaire scores and Q&A, optionally merged with a full lab report ("SmartReport"). Entry points: `generateNascoPDF` (plain), `generateFullPdf` (branded + SmartReport + PDF encryption).
|
|
54
|
+
- **Corporate** — module `lib/corporate_report_generator.js`. Population-level analytics report for an employer/corporate client. Entry point: `generateCorporateReportPDF`.
|
|
55
|
+
- **SanusX** — module `lib/sanusx_report_generator.js`. Consumer "Health Hero" wellbeing report with an avatar/scoring gimmick. Entry point: `generateSanuxPDF`.
|
|
56
|
+
|
|
57
|
+
They genuinely don't share code — a fix in one does not apply to the others. Before debugging "the report looks wrong," identify which of these four you're actually looking at. Full detail per pipeline, including known bugs specific to each: [`docs/04-report-pipelines.md`](docs/04-report-pipelines.md).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 5. Whitelabelling in one paragraph (and its landmines)
|
|
62
|
+
|
|
63
|
+
Branding is chosen by a plain string (`client`/`clientName`) in the request payload, which each generator maps — independently, and **inconsistently** — to a `config/{Brand}.json` file (colors, logos) and sometimes a `templates/{Brand}/` folder (full HTML layout). There is no environment variable and no central "client registry." Five different pieces of code (the wellbeing generator, the corporate generator, the email module, the sanusx generator, and the fact that the core report doesn't do this at all) each have their own rule for turning a client string into a filename, and they disagree on casing and on which strings get special-cased (only `"pha"` → `"Pha"` is handled specially, and only in some of them). One of these (`corporate_report_generator.js`) lower-cases the client string before building a path to a capitalized filename — this only works today because of case-insensitive filesystems; it will break on Linux. `sanusx_report_generator.js` ignores the client string for branding entirely. **Before onboarding a new brand, read [`docs/02-configuration-and-whitelabelling.md`](docs/02-configuration-and-whitelabelling.md) in full** — guessing "just add a config file" will not be enough.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 6. Where do the questions come from? (the thing you specifically asked about)
|
|
68
|
+
|
|
69
|
+
**This library does not own or store questionnaire content.** There is no question bank, no question-ID lookup, no survey schema in this repository. Every question's text and its answer arrive **together, pre-rendered**, as flat `{title, value}` pairs inside the JSON payload — the host application (whatever system runs the actual questionnaire/survey with the patient) is responsible for assembling that array before calling this library.
|
|
70
|
+
|
|
71
|
+
Concretely, in the wellbeing pipeline:
|
|
72
|
+
```js
|
|
73
|
+
"Profile": [
|
|
74
|
+
{ "title": "What is your gender?", "value": "Male" },
|
|
75
|
+
{ "title": "Over the last 2 weeks, how often have you been bothered by feeling down, depressed, or hopeless?",
|
|
76
|
+
"value": "More than half the days" }
|
|
77
|
+
// ...
|
|
78
|
+
]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
This gets laid out as a two-column "Quiz Answers" table by `renderDoctorDetails()` in `lib/wellbeing_report_generator.js` — plain layout code, no interpretation of what the question means. Numeric scores (PHQ‑9 totals, etc.) are a *separate* field (`data.wellbeing.calculation`) that's also pre-computed upstream — this library doesn't score anything either. The core lab-report pipeline has no question concept at all (its domain is biomarkers, not questionnaires).
|
|
82
|
+
|
|
83
|
+
**One trap:** `lib/big_integral_questionnaire.js` looks like a real questionnaire-rendering feature but currently renders **100% hardcoded dummy data** — it is a design/preview scaffold, not wired to real patient answers. If someone asks why it doesn't reflect real data, that's expected, not a bug to "fix" quickly — it needs real wiring designed first.
|
|
84
|
+
|
|
85
|
+
Also worth flagging to whoever owns data quality upstream: the answer *values* rendered into this table are **not HTML-escaped**. If free-text ever flows into `Profile[].value` from a less-trusted source, that's an injection risk into the rendered page.
|
|
86
|
+
|
|
87
|
+
Full detail, including exactly which field goes where in which pipeline: [`docs/05-questions-and-data-model.md`](docs/05-questions-and-data-model.md).
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 7. Security posture — what to tell people who ask
|
|
92
|
+
|
|
93
|
+
- **No auth in this library** (see §1). Access control lives entirely in the host application.
|
|
94
|
+
- **SMTP credentials travel as plaintext JSON fields**, inside a payload that's only base64-encoded, not encrypted. This is the most concrete, fixable security gap: see [`docs/07-email-notifications.md §7.4`](docs/07-email-notifications.md#74-security-considerations). If asked to harden this, moving SMTP credentials to host-app-side environment configuration (rather than per-call payload fields) is the right direction.
|
|
95
|
+
- The `secure` flag callers pass for SMTP is silently ignored (dead code) — the transport actually always forces STARTTLS via `requireTLS: true`, so it's not literally insecure, just misleading.
|
|
96
|
+
- Unescaped answer text in the wellbeing Q&A table (§6) is a latent XSS-into-rendered-PDF risk if upstream data isn't sanitized.
|
|
97
|
+
- No secrets are hardcoded in the codebase itself (verified during this review).
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 8. Internationalization and RTL — the short version
|
|
102
|
+
|
|
103
|
+
Two separate, independently configured instances of the `i18n` npm package exist: one for the core report (`locales/`), one for **everything else** — wellbeing, corporate, *and* SanusX — (`locales/wellbeing/`, despite the folder name). If you're hunting for a translation string and the generator you're editing isn't the core lab report, look in `locales/wellbeing/`, not `locales/`.
|
|
104
|
+
|
|
105
|
+
RTL (Arabic) support works via three overlapping mechanisms (whole alternate template files, alternate block partials, inline CSS direction switches) and — important gotcha — three of the four generators forcibly rewrite any Arabic-ish language code to `ar-SA`, meaning `ar-AE` is effectively unreachable. SanusX's RTL is outright broken (never triggers). Locale state also lives on a shared, process-global singleton, so concurrent report-generation calls in the same process can theoretically leak one request's language into another's — the codebase already fixed an analogous bug for temp file paths but not for this. Full detail: [`docs/06-internationalization.md`](docs/06-internationalization.md).
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 9. Running/testing this locally
|
|
110
|
+
|
|
111
|
+
There's no formal test framework (no Jest/Mocha in `devDependencies`, `package.json`'s only script is `"start": "node index.js"`, which just requires the library — it does nothing on its own). What exists instead:
|
|
112
|
+
|
|
113
|
+
- **`test.js`** (root) — an ad hoc script that calls `generateHTMLWellbeingReportWithSmartReport`/`generatePDFReport` directly against fixture data from `testing-reports/` and writes to `output/nasco-sample.pdf` (and an encrypted copy via `node-qpdf2`). Swap which fixture variable is assigned to `data`/`client` at the top of the file to test a different brand/scenario.
|
|
114
|
+
- **`testing-reports/{mediclinic,pha}/*.js`** — example payloads (`doctor-data.js` has `IsDoctor: true` with a full PHQ‑9/GAD‑7-style `Profile` array — the best reference for the Q&A shape described in §6).
|
|
115
|
+
- **`preview-big-integral.js`** — standalone harness for the `big_integral_questionnaire.js` dummy-data table.
|
|
116
|
+
- **`tests/test.js`, `tests/test-qr-code.js`** — more ad hoc scripts; `test-qr-code.js` is the reference for how `generatePatientQR` expects a caller-pre-rendered HTML/SVG string.
|
|
117
|
+
- Puppeteer needs a compatible Chromium available; `downloadfile.js` is a one-off helper that fetches a pinned Chromium build for Windows if you need it locally.
|
|
118
|
+
|
|
119
|
+
There is no CI test suite validating rendered PDF output — verification today is manual (run a script, open the resulting PDF in `output/`).
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 10. If you're prioritizing what to fix first
|
|
124
|
+
|
|
125
|
+
In order of leverage for time invested:
|
|
126
|
+
|
|
127
|
+
1. Resolve the `pdf_generator.js` vs `.min.js` divergence (§2) — either delete the stale file or add a real build step. Highest risk of silent, confusing bugs.
|
|
128
|
+
2. Unify client-name → config/template resolution into one shared helper, used by all five places that currently reimplement it differently (§5).
|
|
129
|
+
3. Fix the SMTP-credentials-in-plaintext-payload pattern (§7) — at minimum, stop it from ever landing in debug logs; ideally move it out of the payload entirely.
|
|
130
|
+
4. Scope locale state per-request instead of a shared singleton (§8) — currently a latent concurrency bug.
|
|
131
|
+
5. Everything else is cataloged, ranked, and cross-referenced in [`docs/08-known-issues-and-technical-debt.md`](docs/08-known-issues-and-technical-debt.md) — treat that file as your punch list.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 11. Full documentation index
|
|
136
|
+
|
|
137
|
+
For anything beyond this summary, go to [`docs/README.md`](docs/README.md), which indexes:
|
|
138
|
+
|
|
139
|
+
1. [Architecture Overview](docs/01-architecture-overview.md)
|
|
140
|
+
2. [Configuration & Whitelabelling](docs/02-configuration-and-whitelabelling.md)
|
|
141
|
+
3. [Templating & Rendering Pipeline](docs/03-templating-and-rendering.md)
|
|
142
|
+
4. [Report Pipelines](docs/04-report-pipelines.md)
|
|
143
|
+
5. [Questions, Answers & the Data Model](docs/05-questions-and-data-model.md)
|
|
144
|
+
6. [Internationalization (i18n) & RTL](docs/06-internationalization.md)
|
|
145
|
+
7. [Email Notifications](docs/07-email-notifications.md)
|
|
146
|
+
8. [Known Issues & Technical Debt](docs/08-known-issues-and-technical-debt.md)
|
package/README.md
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
# Medicus Pdf Generator
|
|
2
|
-
|
|
3
|
-
This package is a stand-alone lightweight nodejs library for generating medical reports in a PDF format.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
using this command.
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @medicus.ai/medicus-report-pdf-generator
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Usage
|
|
14
|
-
|
|
15
|
-
```python
|
|
16
|
-
const {generateMedicusPDF} = require('@medicus.ai/medicus-report-pdf-generator');
|
|
17
|
-
|
|
18
|
-
async function generatePDF(json) {
|
|
19
|
-
try {
|
|
20
|
-
const data = await generateMedicusPDF(json);
|
|
21
|
-
return data;
|
|
22
|
-
}
|
|
23
|
-
catch (e) {
|
|
24
|
-
throw new Meteor.Error(500, 'error', e);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
1
|
+
# Medicus Pdf Generator
|
|
2
|
+
|
|
3
|
+
This package is a stand-alone lightweight nodejs library for generating medical reports in a PDF format.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
using this command.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @medicus.ai/medicus-report-pdf-generator
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
const {generateMedicusPDF} = require('@medicus.ai/medicus-report-pdf-generator');
|
|
17
|
+
|
|
18
|
+
async function generatePDF(json) {
|
|
19
|
+
try {
|
|
20
|
+
const data = await generateMedicusPDF(json);
|
|
21
|
+
return data;
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
throw new Meteor.Error(500, 'error', e);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
27
|
```
|
package/app/i18n.config.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
const i18n = require('i18n');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
i18n.configure({
|
|
5
|
-
locales: ['en', 'de', 'fr', 'ar-AE', 'ar-SA', 'pt', 'zh-CN'],
|
|
6
|
-
defaultLocale: 'en',
|
|
7
|
-
// sets a custom cookie name to parse locale settings from - defaults to NULL
|
|
8
|
-
cookie: 'currentLang',
|
|
9
|
-
queryParameter: 'lang',
|
|
10
|
-
directory: path.resolve(__dirname + '/../locales'),
|
|
11
|
-
api: {
|
|
12
|
-
'__': 'translate',
|
|
13
|
-
'__n': 'translateN'
|
|
14
|
-
},
|
|
15
|
-
// Downcase locale when passed on queryParam; e.g. lang=en-US becomes
|
|
16
|
-
// en-us. When set to false, the queryParam value will be used as passed;
|
|
17
|
-
// e.g. lang=en-US remains en-US.
|
|
18
|
-
preserveLegacyCase: true
|
|
19
|
-
});
|
|
20
|
-
|
|
1
|
+
const i18n = require('i18n');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
i18n.configure({
|
|
5
|
+
locales: ['en', 'de', 'fr', 'ar-AE', 'ar-SA', 'pt', 'zh-CN'],
|
|
6
|
+
defaultLocale: 'en',
|
|
7
|
+
// sets a custom cookie name to parse locale settings from - defaults to NULL
|
|
8
|
+
cookie: 'currentLang',
|
|
9
|
+
queryParameter: 'lang',
|
|
10
|
+
directory: path.resolve(__dirname + '/../locales'),
|
|
11
|
+
api: {
|
|
12
|
+
'__': 'translate',
|
|
13
|
+
'__n': 'translateN'
|
|
14
|
+
},
|
|
15
|
+
// Downcase locale when passed on queryParam; e.g. lang=en-US becomes
|
|
16
|
+
// en-us. When set to false, the queryParam value will be used as passed;
|
|
17
|
+
// e.g. lang=en-US remains en-US.
|
|
18
|
+
preserveLegacyCase: true
|
|
19
|
+
});
|
|
20
|
+
|
|
21
21
|
module.exports = i18n;
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
const i18n = require('i18n');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
i18n.configure({
|
|
5
|
-
locales: ['en', 'de', 'fr', 'ar-AE', 'ar-SA', 'pt', 'zh-CN', 'tr', 'es'],
|
|
6
|
-
defaultLocale: 'en',
|
|
7
|
-
// sets a custom cookie name to parse locale settings from - defaults to NULL
|
|
8
|
-
cookie: 'currentLang',
|
|
9
|
-
queryParameter: 'lang',
|
|
10
|
-
directory: path.resolve(__dirname + '/../locales/wellbeing'),
|
|
11
|
-
api: {
|
|
12
|
-
'__': 'translate',
|
|
13
|
-
'__n': 'translateN'
|
|
14
|
-
},
|
|
15
|
-
// Downcase locale when passed on queryParam; e.g. lang=en-US becomes
|
|
16
|
-
// en-us. When set to false, the queryParam value will be used as passed;
|
|
17
|
-
// e.g. lang=en-US remains en-US.
|
|
18
|
-
preserveLegacyCase: true
|
|
19
|
-
});
|
|
20
|
-
|
|
1
|
+
const i18n = require('i18n');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
i18n.configure({
|
|
5
|
+
locales: ['en', 'de', 'fr', 'ar-AE', 'ar-SA', 'pt', 'zh-CN', 'tr', 'es'],
|
|
6
|
+
defaultLocale: 'en',
|
|
7
|
+
// sets a custom cookie name to parse locale settings from - defaults to NULL
|
|
8
|
+
cookie: 'currentLang',
|
|
9
|
+
queryParameter: 'lang',
|
|
10
|
+
directory: path.resolve(__dirname + '/../locales/wellbeing'),
|
|
11
|
+
api: {
|
|
12
|
+
'__': 'translate',
|
|
13
|
+
'__n': 'translateN'
|
|
14
|
+
},
|
|
15
|
+
// Downcase locale when passed on queryParam; e.g. lang=en-US becomes
|
|
16
|
+
// en-us. When set to false, the queryParam value will be used as passed;
|
|
17
|
+
// e.g. lang=en-US remains en-US.
|
|
18
|
+
preserveLegacyCase: true
|
|
19
|
+
});
|
|
20
|
+
|
|
21
21
|
module.exports = i18n;
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LocaleService
|
|
3
|
-
*/
|
|
4
|
-
function LocaleService(i18nProvider) {
|
|
5
|
-
this.i18nProvider = i18nProvider;
|
|
6
|
-
this.getCurrentLocale = function () {
|
|
7
|
-
return this.i18nProvider.getLocale();
|
|
8
|
-
}
|
|
9
|
-
this.translatePlurals = function (phrase, count) {
|
|
10
|
-
return this.i18nProvider.translateN(phrase, count)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.setLocale = function (locale) {
|
|
15
|
-
if (this.getLocales().indexOf(locale) !== -1) {
|
|
16
|
-
this.i18nProvider.setLocale(locale)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
this.t = function (string, args = undefined) {
|
|
21
|
-
return this.i18nProvider.__(string, args).message
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
this.getLocales = function () {
|
|
25
|
-
return this.i18nProvider.getLocales();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
1
|
+
/**
|
|
2
|
+
* LocaleService
|
|
3
|
+
*/
|
|
4
|
+
function LocaleService(i18nProvider) {
|
|
5
|
+
this.i18nProvider = i18nProvider;
|
|
6
|
+
this.getCurrentLocale = function () {
|
|
7
|
+
return this.i18nProvider.getLocale();
|
|
8
|
+
}
|
|
9
|
+
this.translatePlurals = function (phrase, count) {
|
|
10
|
+
return this.i18nProvider.translateN(phrase, count)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
this.setLocale = function (locale) {
|
|
15
|
+
if (this.getLocales().indexOf(locale) !== -1) {
|
|
16
|
+
this.i18nProvider.setLocale(locale)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
this.t = function (string, args = undefined) {
|
|
21
|
+
return this.i18nProvider.__(string, args).message
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
this.getLocales = function () {
|
|
25
|
+
return this.i18nProvider.getLocales();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
29
|
module.exports = LocaleService;
|