lforms 29.3.0 → 33.2.0
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/CHANGELOG.md +261 -0
- package/README.md +97 -14
- package/changed-features.md +99 -0
- package/dist/lforms/LICENSE.md +70 -0
- package/dist/lforms/README.md +100 -0
- package/dist/lforms/fhir/R4/lformsFHIR.min.js +2 -0
- package/dist/lforms/fhir/R4/lformsFHIR.min.js.map +1 -0
- package/dist/lforms/fhir/STU3/lformsFHIR.min.js +2 -0
- package/dist/lforms/fhir/STU3/lformsFHIR.min.js.map +1 -0
- package/dist/lforms/fhir/lformsFHIRAll.min.js +2 -0
- package/dist/lforms/fhir/lformsFHIRAll.min.js.map +1 -0
- package/dist/lforms/webcomponent/assets/lib/zone.min.js +134 -0
- package/dist/lforms/webcomponent/down_arrow_gray_10_10.png +0 -0
- package/dist/lforms/webcomponent/favicon.ico +0 -0
- package/dist/lforms/webcomponent/index.html +9 -0
- package/dist/lforms/webcomponent/lhc-forms.js +2471 -0
- package/dist/lforms/webcomponent/magnifying_glass.png +0 -0
- package/dist/lforms/webcomponent/main.js +2464 -0
- package/dist/lforms/webcomponent/main.js.map +1 -0
- package/dist/lforms/webcomponent/polyfills.js +2 -0
- package/dist/lforms/webcomponent/polyfills.js.map +1 -0
- package/dist/lforms/webcomponent/runtime.js +2 -0
- package/dist/lforms/webcomponent/runtime.js.map +1 -0
- package/dist/lforms/webcomponent/scripts.js +3 -0
- package/dist/lforms/webcomponent/scripts.js.map +1 -0
- package/dist/lforms/webcomponent/styles.css +3 -0
- package/dist/lforms/webcomponent/styles.css.map +1 -0
- package/form_definition.md +382 -0
- package/lforms-33.2.0.tgz +0 -0
- package/package.json +94 -88
- package/r4-support.md +147 -0
- package/sdc-support.md +127 -0
- package/app/.npmignore +0 -3
- package/app/images/blank.gif +0 -0
- package/app/images/signal-stop.png +0 -0
- package/app/index.html +0 -10
- package/app/lforms.js +0 -56
- package/app/lforms.tpl.js +0 -964
- package/app/scripts/angular-packages.js +0 -11
- package/app/scripts/bootstrap-decorators.js +0 -31
- package/app/scripts/bower-index.js +0 -14
- package/app/scripts/fhir/R4/export.js +0 -33
- package/app/scripts/fhir/R4/fhirRequire.js +0 -36
- package/app/scripts/fhir/R4/lformsFHIR.js +0 -27260
- package/app/scripts/fhir/R4/sdc-export.js +0 -455
- package/app/scripts/fhir/R4/sdc-import.js +0 -483
- package/app/scripts/fhir/STU3/export.js +0 -27
- package/app/scripts/fhir/STU3/fhirRequire.js +0 -36
- package/app/scripts/fhir/STU3/lformsFHIR.js +0 -27291
- package/app/scripts/fhir/STU3/sdc-export.js +0 -493
- package/app/scripts/fhir/STU3/sdc-import.js +0 -494
- package/app/scripts/fhir/diagnostic-report.js +0 -707
- package/app/scripts/fhir/export-common.js +0 -209
- package/app/scripts/fhir/expression-processor.js +0 -670
- package/app/scripts/fhir/extensions/rendering-style.js +0 -23
- package/app/scripts/fhir/fhir-common.js +0 -3
- package/app/scripts/fhir/obs-prepop.mjs +0 -97
- package/app/scripts/fhir/runtime-common.js +0 -33
- package/app/scripts/fhir/sdc-common.js +0 -334
- package/app/scripts/fhir/sdc-export-common.js +0 -1046
- package/app/scripts/fhir/sdc-import-common.js +0 -1343
- package/app/scripts/fhir/versions.js +0 -8
- package/app/scripts/index.js +0 -20
- package/app/scripts/lforms-config.js +0 -12
- package/app/scripts/lforms-constants.js +0 -10
- package/app/scripts/lforms-controllers.js +0 -1196
- package/app/scripts/lforms-directives.js +0 -424
- package/app/scripts/lforms-index.js +0 -20
- package/app/scripts/lib/cross_browser.js +0 -21
- package/app/scripts/lib/lforms-data.js +0 -3591
- package/app/scripts/lib/lforms-hl7.js +0 -525
- package/app/scripts/lib/lforms-util.js +0 -1122
- package/app/scripts/lib/lforms-validate.js +0 -277
- package/app/scripts/lib/polyfill.js +0 -81
- package/app/scripts/themeList.js +0 -17
- package/app/styles/lforms.css +0 -1219
- package/app/styles/redmond-theme/README.txt +0 -2
- package/app/styles/redmond-theme/images/ui-bg_glass_75_d0e5f5_1x400.png +0 -0
- package/app/styles/redmond-theme/images/ui-bg_glass_85_dfeffc_1x400.png +0 -0
- package/app/styles/redmond-theme/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- package/app/styles/redmond-theme/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png +0 -0
- package/app/styles/redmond-theme/images/ui-bg_inset-hard_100_f5f8f9_1x100.png +0 -0
- package/app/styles/redmond-theme/images/ui-bg_inset-hard_100_fcfdfd_1x100.png +0 -0
- package/app/styles/redmond-theme/images/ui-icons_217bc0_256x240.png +0 -0
- package/app/styles/redmond-theme/images/ui-icons_2e83ff_256x240.png +0 -0
- package/app/styles/redmond-theme/images/ui-icons_469bdd_256x240.png +0 -0
- package/app/styles/redmond-theme/images/ui-icons_6da8d5_256x240.png +0 -0
- package/app/styles/redmond-theme/images/ui-icons_cd0a0a_256x240.png +0 -0
- package/app/styles/redmond-theme/images/ui-icons_d8e7f3_256x240.png +0 -0
- package/app/styles/redmond-theme/images/ui-icons_f9bd01_256x240.png +0 -0
- package/app/styles/redmond-theme/jquery-ui.css +0 -1311
- package/app/styles/redmond-theme/jquery-ui.min.css +0 -7
- package/app/styles/redmond-theme/theme.css +0 -443
- package/app/styles/themes.css +0 -1541
- package/app/styles/themes.css.map +0 -9
- package/app/styles/themes.scss +0 -411
- package/app/version.json +0 -1
- package/app/views/partials/attachment.html +0 -38
- package/app/views/partials/field-answers.html +0 -67
- package/app/views/partials/field-units.html +0 -24
- package/app/views/partials/form-controls.html +0 -19
- package/app/views/partials/form-header.html +0 -35
- package/app/views/partials/form-options.html +0 -50
- package/app/views/partials/form-title.html +0 -20
- package/app/views/partials/form-view.html +0 -13
- package/app/views/partials/item-options.html +0 -48
- package/app/views/partials/item.html +0 -126
- package/app/views/partials/itemPrefixAndText.html +0 -4
- package/app/views/partials/layout-horizontal.html +0 -156
- package/app/views/partials/layout-matrix.html +0 -145
- package/app/views/partials/popover-content.html +0 -1
- package/app/views/partials/repeating-button.html +0 -16
- package/app/views/partials/table-item.html +0 -30
- package/app/views/partials/template-table.html +0 -69
- package/app/views/partials/uib-popover-templates/uib-popover-template.html +0 -13
- package/app/views/partials/uib-popover-templates/uib-popover.html +0 -11
|
@@ -1,707 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A package to handle FHIR DiagnosticReport for LForms
|
|
3
|
-
* https://www.hl7.org/fhir/diagnosticreport.html
|
|
4
|
-
*
|
|
5
|
-
* Note that this was written for DSTU2 and has not been updated.
|
|
6
|
-
*
|
|
7
|
-
* It provides the following functions:
|
|
8
|
-
* createDiagnosticReport()
|
|
9
|
-
* -- Convert existing LOINC panels/forms data in LForms format into FHIR DiagnosticReport data
|
|
10
|
-
* mergeDiagnosticReportToLForms()
|
|
11
|
-
* -- Merge FHIR SDC DiagnosticReport data into corresponding LForms data
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
var LForms = require('../lforms-index');
|
|
15
|
-
|
|
16
|
-
var dr = {
|
|
17
|
-
|
|
18
|
-
// a prefix for references to Observation resources
|
|
19
|
-
_OBX_REF_PREFIX: "Observation/",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Functions for creating a DiagnosticReport instance from an LFormsData object
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/** Get date in a standard string format
|
|
27
|
-
* @param dateObj, a date object
|
|
28
|
-
* @returns {string} a formatted date string
|
|
29
|
-
* @private
|
|
30
|
-
*/
|
|
31
|
-
_getFormattedDate : function (dateObj) {
|
|
32
|
-
//"2013-01-27T11:45:33+11:00",
|
|
33
|
-
return dateObj ? LForms.Util.dateToDTMString(dateObj) : "";
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Get the additional data in a form's formHeaderItems
|
|
39
|
-
* Note: For DiagnosticReport only the effectiveDateTime is needed
|
|
40
|
-
* @param formData an LFormsData object
|
|
41
|
-
* @returns {{}} the extra data captured in the "OBR" fields of an LForms form
|
|
42
|
-
* @private
|
|
43
|
-
*/
|
|
44
|
-
_getExtensionData : function(formData) {
|
|
45
|
-
var extension = {};
|
|
46
|
-
if (formData.templateOptions.formHeaderItems &&
|
|
47
|
-
formData.templateOptions.formHeaderItems.length>0) {
|
|
48
|
-
for(var i=0, iLen= formData.templateOptions.formHeaderItems.length; i<iLen; i++) {
|
|
49
|
-
var obrItem = formData.templateOptions.formHeaderItems[i];
|
|
50
|
-
if (obrItem.questionCode === 'date_done' && obrItem.value) {
|
|
51
|
-
extension["lforms_dateDone"] = obrItem.value;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (obrItem.questionCode === 'where_done' && obrItem.value) {
|
|
55
|
-
extension["lforms_whereDone"] = {
|
|
56
|
-
display: obrItem.value.text
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (obrItem.questionCode === 'time_done' && obrItem.value) {
|
|
60
|
-
extension["lforms_timeDone"] = obrItem.value;
|
|
61
|
-
}
|
|
62
|
-
if (obrItem.questionCode === 'comment' && obrItem.value) {
|
|
63
|
-
extension["lforms_comments"] = obrItem.value;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return extension;
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* A recursive function that generates the DiagnosticReport content by
|
|
74
|
-
* going through the LForms form data structure
|
|
75
|
-
* @param item an LForms item
|
|
76
|
-
* @param contained the "contained" field in a DiagnosticReport where all the Observation instances are kept.
|
|
77
|
-
* @returns {{result: Array, resultObj: Array}} the content part of a Diagnostic Report instance
|
|
78
|
-
* @private
|
|
79
|
-
*/
|
|
80
|
-
_createDiagnosticReportContent : function (item, contained) {
|
|
81
|
-
// return the content of "result" and "contained"
|
|
82
|
-
var content = {
|
|
83
|
-
result: [],
|
|
84
|
-
resultObj: []
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
for(var i=0, iLen=item.items.length; i<iLen; i++) {
|
|
88
|
-
var subItem = item.items[i];
|
|
89
|
-
if (subItem) {
|
|
90
|
-
var obx = this._commonExport._createObservation(subItem, true);
|
|
91
|
-
if (subItem.items && subItem.items.length>0) {
|
|
92
|
-
// single obx returned if it is a header item
|
|
93
|
-
obx[0].related = [];
|
|
94
|
-
var ret = this._createDiagnosticReportContent(subItem, contained);
|
|
95
|
-
for(var j=0, jLen=ret.result.length; j<jLen; j++) {
|
|
96
|
-
var subObxRef = ret.result[j];
|
|
97
|
-
obx[0].related.push({
|
|
98
|
-
type: "has-member",
|
|
99
|
-
target: {
|
|
100
|
-
reference: subObxRef.reference
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
for (var l=0, lLen=obx.length; l<lLen; l++) {
|
|
106
|
-
contained.push(obx[l]);
|
|
107
|
-
content.result.push({
|
|
108
|
-
reference: "#" + obx[l].id
|
|
109
|
-
});
|
|
110
|
-
content.resultObj.push(obx[l]);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return content;
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Convert a DiagnosticReport resource with contained Observation resources to
|
|
120
|
-
* a FHIR Bundle resource that includes a DiagnosticReport resource and associated Observation resources
|
|
121
|
-
* @param dr a DiagnosticReport resource with contained Observation resources
|
|
122
|
-
* @param bundleType the FHIR Bundle type. Only "transaction" and "collection" types are allowed.
|
|
123
|
-
* @returns {{}} a Bundle resource that includes a DiagnosticReport resource and associated Observation resources
|
|
124
|
-
*/
|
|
125
|
-
_convertFromContainedToBundle: function (dr, bundleType) {
|
|
126
|
-
var bundleDr = {};
|
|
127
|
-
|
|
128
|
-
// default bundleType
|
|
129
|
-
if (!bundleType) {
|
|
130
|
-
bundleType = "transaction";
|
|
131
|
-
}
|
|
132
|
-
if (dr) {
|
|
133
|
-
switch(bundleType) {
|
|
134
|
-
case "transaction":
|
|
135
|
-
bundleDr = this._convertContainedToTransactionBundle(dr);
|
|
136
|
-
break;
|
|
137
|
-
case "collection":
|
|
138
|
-
bundleDr = this._convertContainedToCollectionBundle(dr);
|
|
139
|
-
break;
|
|
140
|
-
default:
|
|
141
|
-
console.log("Bundle type not supported: " + bundleType);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return bundleDr;
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Convert a DiagnosticReport resource with contained Observation resources to
|
|
150
|
-
* a FHIR "transaction" typed Bundle resource that includes a DiagnosticReport resource
|
|
151
|
-
* and associated Observation resources
|
|
152
|
-
* @param dr a DiagnosticReport resource with contained Observation resources
|
|
153
|
-
* @returns {{}} a Bundle resource that includes a DiagnosticReport resource and associated Observation resources
|
|
154
|
-
* @private
|
|
155
|
-
*/
|
|
156
|
-
_convertContainedToTransactionBundle: function(dr) {
|
|
157
|
-
|
|
158
|
-
var bundleDr = {
|
|
159
|
-
resourceType:"Bundle",
|
|
160
|
-
type: "transaction",
|
|
161
|
-
entry: []
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
var contained = dr.contained;
|
|
165
|
-
delete dr.contained;
|
|
166
|
-
|
|
167
|
-
// update reference to Observation resources
|
|
168
|
-
for (var i=0, iLen=dr.result.length; i<iLen; i++) {
|
|
169
|
-
var ref = dr.result[i];
|
|
170
|
-
ref.reference = this._OBX_REF_PREFIX + ref.reference.slice(1);
|
|
171
|
-
}
|
|
172
|
-
// add DiagnosticReport resource into Bundle entry
|
|
173
|
-
bundleDr.entry.push({
|
|
174
|
-
resource: dr,
|
|
175
|
-
request: {
|
|
176
|
-
method: "POST",
|
|
177
|
-
url: "DiagnosticReport"
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// add Observation resources into Bundle entry
|
|
182
|
-
for (var j=0, jLen=contained.length; j<jLen; j++) {
|
|
183
|
-
var res = contained[j];
|
|
184
|
-
|
|
185
|
-
// if it has related Observation resources (as it is a section in LForms)
|
|
186
|
-
// update values of the references to the related Observation resources
|
|
187
|
-
if (res.related) {
|
|
188
|
-
for (var k=0, kLen=res.related.length; k<kLen; k++) {
|
|
189
|
-
var targetObservation = res.related[k];
|
|
190
|
-
targetObservation.target.reference = this._OBX_REF_PREFIX + targetObservation.target.reference.slice(1);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// add to the Bundle entry
|
|
195
|
-
bundleDr.entry.push({
|
|
196
|
-
resource: res,
|
|
197
|
-
request: {
|
|
198
|
-
method: "POST",
|
|
199
|
-
url: "Observation"
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return bundleDr;
|
|
205
|
-
},
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Convert a DiagnosticReport resource with contained Observation resources to
|
|
210
|
-
* a FHIR "collection" typed Bundle resource that includes a DiagnosticReport resource
|
|
211
|
-
* and associated Observation resources
|
|
212
|
-
* @param dr a DiagnosticReport resource with contained Observation resources
|
|
213
|
-
* @returns {{}} a Bundle resource that includes a DiagnosticReport resource and associated Observation resources
|
|
214
|
-
* @private
|
|
215
|
-
*/
|
|
216
|
-
_convertContainedToCollectionBundle: function(dr) {
|
|
217
|
-
var bundleDr = {
|
|
218
|
-
resourceType:"Bundle",
|
|
219
|
-
type: "collection",
|
|
220
|
-
entry: []
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
var contained = dr.contained;
|
|
224
|
-
delete dr.contained;
|
|
225
|
-
|
|
226
|
-
// add DiagnosticReport resource into Bundle entry
|
|
227
|
-
bundleDr.entry.push({
|
|
228
|
-
resource: dr
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
// add Observation resources into Bundle entry
|
|
232
|
-
for (var j=0, jLen=contained.length; j<jLen; j++) {
|
|
233
|
-
var res = contained[j];
|
|
234
|
-
// add to the Bundle entry
|
|
235
|
-
bundleDr.entry.push({
|
|
236
|
-
resource: res
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return bundleDr;
|
|
241
|
-
},
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* Generate FHIR DiagnosticReport data from an LForms form data
|
|
246
|
-
* @param formData an LFormsData object
|
|
247
|
-
* @param subject optional, A local FHIR resource that is the subject for this
|
|
248
|
-
* DiagnoticReport.
|
|
249
|
-
* @param inBundle optional, a flag that a DiagnosticReport resources and associated Observation resources
|
|
250
|
-
* should be placed into a FHIR Bundle. The default is false.
|
|
251
|
-
* @param bundleType, optional, the FHIR Bundle type if inBundle is true.
|
|
252
|
-
* Only "transaction" and "collection" types are allowed.
|
|
253
|
-
* @returns {{}} a Diagnostic Report instance
|
|
254
|
-
*/
|
|
255
|
-
createDiagnosticReport : function(formData, subject, inBundle, bundleType) {
|
|
256
|
-
var dr = null, contained =[];
|
|
257
|
-
if (formData) {
|
|
258
|
-
|
|
259
|
-
var formAndUserData = formData.getFormData(true,true,true);
|
|
260
|
-
|
|
261
|
-
var drContent = this._createDiagnosticReportContent(formAndUserData, contained);
|
|
262
|
-
|
|
263
|
-
dr = {
|
|
264
|
-
resourceType: "DiagnosticReport",
|
|
265
|
-
id: this._commonExport._getUniqueId(formAndUserData.code),
|
|
266
|
-
status: "final",
|
|
267
|
-
code: {
|
|
268
|
-
"coding": [
|
|
269
|
-
{
|
|
270
|
-
"system": "http://loinc.org",
|
|
271
|
-
"code": formAndUserData.code,
|
|
272
|
-
"display": formAndUserData.name
|
|
273
|
-
}
|
|
274
|
-
],
|
|
275
|
-
"text": formAndUserData.name
|
|
276
|
-
},
|
|
277
|
-
result: drContent.result,
|
|
278
|
-
contained: contained
|
|
279
|
-
};
|
|
280
|
-
this._commonExport._addVersionTag(dr);
|
|
281
|
-
|
|
282
|
-
if (subject)
|
|
283
|
-
dr.subject = LForms.Util.createLocalFHIRReference(subject);
|
|
284
|
-
|
|
285
|
-
// obr data
|
|
286
|
-
var extension = this._getExtensionData(formAndUserData);
|
|
287
|
-
if (extension["lforms_dateDone"]) {
|
|
288
|
-
dr["effectiveDateTime"] = extension["lforms_dateDone"];
|
|
289
|
-
}
|
|
290
|
-
// issued
|
|
291
|
-
dr["issued"] = this._getFormattedDate(new Date());
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
var ret = inBundle ? this._convertFromContainedToBundle(dr, bundleType) : dr;
|
|
295
|
-
LForms.Util.pruneNulls(ret);
|
|
296
|
-
return ret;
|
|
297
|
-
},
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Functions for merging a DiagnosticReport instance into an LFormsData object
|
|
302
|
-
*/
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Find an observation from the "contained" list by an observation id
|
|
306
|
-
* @param refId an observation instance's id
|
|
307
|
-
* @param contained the "contained" field in a DiagnosticReport instance
|
|
308
|
-
* @returns {{}} an observation instance
|
|
309
|
-
* @private
|
|
310
|
-
*/
|
|
311
|
-
_findObxById : function(refId, contained) {
|
|
312
|
-
var obx = null;
|
|
313
|
-
if (refId) {
|
|
314
|
-
var id = refId[0] === "#" ? refId.slice(1) : refId;
|
|
315
|
-
for(var i=0, iLen=contained.length; i<iLen; i++) {
|
|
316
|
-
if (contained[i].id === id) {
|
|
317
|
-
obx = contained[i];
|
|
318
|
-
break;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
return obx;
|
|
323
|
-
},
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Merge an Observation instance into an item object
|
|
328
|
-
* @param obx an observation instance
|
|
329
|
-
* @param item an item in an LForms object
|
|
330
|
-
* @private
|
|
331
|
-
*/
|
|
332
|
-
_setupItemValueAndUnit : function(obx, item) {
|
|
333
|
-
if (item && obx.code.coding[0].code === item.questionCode) {
|
|
334
|
-
var dataType = item.dataType;
|
|
335
|
-
// any one has a unit must be a numerical type, let use REAL for now.
|
|
336
|
-
// dataType conversion should be handled when panel data are added to lforms-service.
|
|
337
|
-
if ((!dataType || dataType==="ST") && item.units && item.units.length>0 ) {
|
|
338
|
-
dataType = "REAL";
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
switch (dataType) {
|
|
342
|
-
case "INT":
|
|
343
|
-
if (obx.valueInteger) {
|
|
344
|
-
item.value = obx.valueInteger;
|
|
345
|
-
break;
|
|
346
|
-
}
|
|
347
|
-
// else handle as Quantity
|
|
348
|
-
case "REAL": // handle as Quantity
|
|
349
|
-
case "QTY":
|
|
350
|
-
let qty = obx.valueQuantity;
|
|
351
|
-
item.value = qty.value;
|
|
352
|
-
let unitName = qty.unit || qty.code;
|
|
353
|
-
if (unitName || qty.code || qty.system) {
|
|
354
|
-
item.unit = {};
|
|
355
|
-
if (unitName)
|
|
356
|
-
item.unit.name = unitName;
|
|
357
|
-
if (qty.code)
|
|
358
|
-
item.unit.code = qty.code;
|
|
359
|
-
if (qty.system)
|
|
360
|
-
item.unit.system = qty.system;
|
|
361
|
-
}
|
|
362
|
-
break;
|
|
363
|
-
case "DT":
|
|
364
|
-
item.value = LForms.Util.stringToDTDateISO(obx.valueDate);
|
|
365
|
-
break;
|
|
366
|
-
case "DTM":
|
|
367
|
-
item.value = LForms.Util.stringToDate(obx.valueDateTime);
|
|
368
|
-
break;
|
|
369
|
-
case "CNE":
|
|
370
|
-
case "CWE":
|
|
371
|
-
// get the value from Observation resource.
|
|
372
|
-
// for multiple-selected answers/values in LForms, each selected answer is exported as
|
|
373
|
-
// a separated Observation resource
|
|
374
|
-
var itemValue;
|
|
375
|
-
if (obx.valueCodeableConcept) {
|
|
376
|
-
itemValue = {
|
|
377
|
-
"code": obx.valueCodeableConcept.coding[0].code,
|
|
378
|
-
"text": obx.valueCodeableConcept.coding[0].display,
|
|
379
|
-
"codeSystem": obx.valueCodeableConcept.coding[0].system
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
else if (obx.valueString) {
|
|
383
|
-
itemValue = obx.valueString;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
if (item.answerCardinality &&
|
|
387
|
-
(item.answerCardinality.max === "*" || parseInt(item.answerCardinality.max) > 1)) {
|
|
388
|
-
if (!item.value) {
|
|
389
|
-
item.value = [];
|
|
390
|
-
}
|
|
391
|
-
item.value.push(itemValue)
|
|
392
|
-
}
|
|
393
|
-
else {
|
|
394
|
-
item.value = itemValue;
|
|
395
|
-
}
|
|
396
|
-
break;
|
|
397
|
-
case "SECTION":
|
|
398
|
-
case "TITLE":
|
|
399
|
-
case "":
|
|
400
|
-
// do nothing
|
|
401
|
-
break;
|
|
402
|
-
default:
|
|
403
|
-
item.value = obx.valueString;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
},
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
/**
|
|
410
|
-
* Find the number of the repeating items that have the same code
|
|
411
|
-
* in the "contained" field of a DiagnosticReport instance
|
|
412
|
-
* @param refIdList a list Observation instance IDs to be checked
|
|
413
|
-
* @param code an item code
|
|
414
|
-
* @param contained a list of Observation instances (in the "contained")
|
|
415
|
-
* @returns a structural info object for a repeating item
|
|
416
|
-
* of the repeating items
|
|
417
|
-
* @private
|
|
418
|
-
*/
|
|
419
|
-
_findTotalRepeatingNum : function(refIdList, code, contained) {
|
|
420
|
-
|
|
421
|
-
var total = 0;
|
|
422
|
-
var refIds = [];
|
|
423
|
-
for (var i=0, iLen=refIdList.length; i<iLen; i++) {
|
|
424
|
-
var obx = this._findObxById(refIdList[i], contained);
|
|
425
|
-
if (obx.code.coding[0].code === code) {
|
|
426
|
-
refIds.push(refIdList[i]);
|
|
427
|
-
total += 1;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
return {
|
|
432
|
-
total: total,
|
|
433
|
-
refIds: refIds
|
|
434
|
-
}
|
|
435
|
-
},
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
/**
|
|
439
|
-
* Get structural info of a DiagnosticReport by going though each level of observations
|
|
440
|
-
* @param parentObxInfo the structural info of a parent Observation
|
|
441
|
-
* @param parentRefId the instance ID of a parent Observation
|
|
442
|
-
* @param diagnosticReport a DiagnosticReport instance
|
|
443
|
-
* @private
|
|
444
|
-
*/
|
|
445
|
-
_checkRepeatingItems : function(parentObxInfo, parentRefId, diagnosticReport) {
|
|
446
|
-
|
|
447
|
-
var obxInfoList = [];
|
|
448
|
-
var repeatingItemInfo = {};
|
|
449
|
-
var obxIdList = [];
|
|
450
|
-
|
|
451
|
-
// the report level
|
|
452
|
-
if (!parentRefId && diagnosticReport.result) {
|
|
453
|
-
for (var i=0, iLen=diagnosticReport.result.length; i<iLen; i++) {
|
|
454
|
-
obxIdList.push(diagnosticReport.result[i].reference);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
// obx level
|
|
458
|
-
else {
|
|
459
|
-
var parentObx = this._findObxById(parentRefId, diagnosticReport.contained);
|
|
460
|
-
if (parentObx && parentObx.related) {
|
|
461
|
-
for (var i=0, iLen=parentObx.related.length; i<iLen; i++) {
|
|
462
|
-
obxIdList.push(parentObx.related[i].target.reference);
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// go through each observation instance
|
|
468
|
-
for (var i=0, iLen=obxIdList.length; i<iLen; i++) {
|
|
469
|
-
var refId = obxIdList[i];
|
|
470
|
-
var obx = this._findObxById(refId, diagnosticReport.contained);
|
|
471
|
-
var itemCode = obx.code.coding[0].code;
|
|
472
|
-
// first obx that has the same item code, either repeating or non-repeating
|
|
473
|
-
if (!repeatingItemInfo[itemCode]) {
|
|
474
|
-
var repeatingInfo = this._findTotalRepeatingNum(obxIdList, itemCode, diagnosticReport.contained);
|
|
475
|
-
repeatingItemInfo[itemCode] = {
|
|
476
|
-
total: repeatingInfo.total,
|
|
477
|
-
refIds: repeatingInfo.refIds
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
// create structure info for the obx
|
|
481
|
-
var repeatingRefIds = repeatingItemInfo[itemCode].refIds;
|
|
482
|
-
for (var j=0, jLen=repeatingRefIds.length; j<jLen; j++) {
|
|
483
|
-
if (refId === repeatingRefIds[j]) {
|
|
484
|
-
var obxInfo = {
|
|
485
|
-
code: itemCode,
|
|
486
|
-
refId: refId,
|
|
487
|
-
index: j,
|
|
488
|
-
total: repeatingItemInfo[itemCode].total
|
|
489
|
-
};
|
|
490
|
-
// check observation instances in the sub level
|
|
491
|
-
this._checkRepeatingItems(obxInfo, refId, diagnosticReport);
|
|
492
|
-
obxInfoList.push(obxInfo);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
parentObxInfo.obxInfoList = obxInfoList;
|
|
497
|
-
},
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* Get structure information of a DiagnosticReport instance
|
|
502
|
-
* @param diagnosticReport a DiagnosticReport instance
|
|
503
|
-
* @returns {{}} a Diagnostic Report data structure object
|
|
504
|
-
* @private
|
|
505
|
-
*/
|
|
506
|
-
_getReportStructure : function(diagnosticReport) {
|
|
507
|
-
var reportStructure = {
|
|
508
|
-
obxInfoList: []
|
|
509
|
-
};
|
|
510
|
-
|
|
511
|
-
if (diagnosticReport) {
|
|
512
|
-
this._checkRepeatingItems(reportStructure, null, diagnosticReport);
|
|
513
|
-
}
|
|
514
|
-
return reportStructure;
|
|
515
|
-
},
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* Find a matching repeating item
|
|
520
|
-
* @param parentItem a parent item
|
|
521
|
-
* @param itemCode code of a repeating (or non-repeating) item
|
|
522
|
-
* @param index index of the item in the sub item array of the parent item
|
|
523
|
-
* @returns {{}} a matching item
|
|
524
|
-
* @private
|
|
525
|
-
*/
|
|
526
|
-
_findTheMatchingItemByCodeAndIndex : function(parentItem, itemCode, index) {
|
|
527
|
-
var item = null;
|
|
528
|
-
var idx = 0;
|
|
529
|
-
if (parentItem.items) {
|
|
530
|
-
for(var i=0, iLen=parentItem.items.length; i<iLen; i++) {
|
|
531
|
-
var subItem = parentItem.items[i];
|
|
532
|
-
if (itemCode === subItem.questionCode) {
|
|
533
|
-
if ((subItem.dataType === "CNE" || subItem.dataType === "CWE") &&
|
|
534
|
-
subItem.answerCardinality && (subItem.answerCardinality.max ==="*" || parseInt(subItem.answerCardinality.max)>1) ) {
|
|
535
|
-
item = subItem;
|
|
536
|
-
break;
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
else if (idx === index) {
|
|
540
|
-
item = subItem;
|
|
541
|
-
break;
|
|
542
|
-
}
|
|
543
|
-
else {
|
|
544
|
-
idx += 1;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
return item;
|
|
550
|
-
},
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* Add repeating items
|
|
555
|
-
* @param parentItem a parent item
|
|
556
|
-
* @param itemCode code of a repeating item
|
|
557
|
-
* @param total total number of the repeating item with the same code
|
|
558
|
-
* @private
|
|
559
|
-
*/
|
|
560
|
-
_addRepeatingItems : function(parentItem, itemCode, total) {
|
|
561
|
-
// find the first (and the only one) item
|
|
562
|
-
var item = null;
|
|
563
|
-
if (parentItem.items) {
|
|
564
|
-
for(var i=0, iLen=parentItem.items.length; i<iLen; i++) {
|
|
565
|
-
if (itemCode === parentItem.items[i].questionCode) {
|
|
566
|
-
item = parentItem.items[i];
|
|
567
|
-
break;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
// insert new items unless it is a CNE/CWE and has multiple answers.
|
|
571
|
-
if (item && !((item.dataType === "CNE" || item.dataType ==="CWE") &&
|
|
572
|
-
item.answerCardinality &&
|
|
573
|
-
(item.answerCardinality.max === "*" || parseInt(item.answerCardinality.max) > 1))) {
|
|
574
|
-
while(total > 1) {
|
|
575
|
-
var newItem = LForms.Util.deepCopy(item);
|
|
576
|
-
parentItem.items.splice(i, 0, newItem);
|
|
577
|
-
total -= 1;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
},
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* Merge Observation instances into items on the same level
|
|
586
|
-
* @param parentObxInfo structural information of a parent item
|
|
587
|
-
* @param parentItem a parent item
|
|
588
|
-
* @param diagnosticReport a DiagnosticReport instance
|
|
589
|
-
* @private
|
|
590
|
-
*/
|
|
591
|
-
_processObxAndItem : function(parentObxInfo, parentItem, diagnosticReport) {
|
|
592
|
-
for(var i=0, iLen=parentObxInfo.obxInfoList.length; i<iLen; i++) {
|
|
593
|
-
|
|
594
|
-
var obxInfo = parentObxInfo.obxInfoList[i];
|
|
595
|
-
var obx = this._findObxById(obxInfo.refId, diagnosticReport.contained);
|
|
596
|
-
if (obx) {
|
|
597
|
-
// first repeating obx
|
|
598
|
-
if (obxInfo.total > 1 && obxInfo.index === 0) {
|
|
599
|
-
// add repeating items in form data
|
|
600
|
-
this._addRepeatingItems(parentItem, obxInfo.code, obxInfo.total);
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
var item = this._findTheMatchingItemByCodeAndIndex(parentItem, obxInfo.code, obxInfo.index);
|
|
604
|
-
this._setupItemValueAndUnit(obx, item);
|
|
605
|
-
|
|
606
|
-
// process items on sub level
|
|
607
|
-
if (obxInfo.obxInfoList && obxInfo.obxInfoList.length>0) {
|
|
608
|
-
this._processObxAndItem(obxInfo, item, diagnosticReport);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
},
|
|
613
|
-
|
|
614
|
-
/**
|
|
615
|
-
* Convert a FHIR Bundle resource that includes a DiagnosticReport resource and associated Observation resources
|
|
616
|
-
* to a DiagnosticReport resource with contained Observation resources
|
|
617
|
-
* @param bundleDr a Bundle that includes a DiagnosticReport resource and associated Observation resources.
|
|
618
|
-
* Only "searchset" type is allowed.
|
|
619
|
-
* @returns {{}} a DiagnosticReport resource with contained Observation resources
|
|
620
|
-
*/
|
|
621
|
-
_convertFromBundleToContained: function (bundleDr) {
|
|
622
|
-
|
|
623
|
-
var containedDr;
|
|
624
|
-
// "searchset" is the only supported type at this point.
|
|
625
|
-
if (bundleDr && bundleDr.type === "searchset") {
|
|
626
|
-
var entry = bundleDr.entry;
|
|
627
|
-
// find the DiagnosticReport in the bundle
|
|
628
|
-
for (var i=0, iLen=entry.length; i<iLen; i++) {
|
|
629
|
-
if (entry[i].resource.resourceType === "DiagnosticReport") {
|
|
630
|
-
containedDr = entry[i].resource;
|
|
631
|
-
// change reference ids in result
|
|
632
|
-
for (var j=0, jLen=containedDr.result.length; j<jLen; j++) {
|
|
633
|
-
var ref = containedDr.result[j];
|
|
634
|
-
if (ref.reference && ref.reference.match(new RegExp(this._OBX_REF_PREFIX))) {
|
|
635
|
-
ref.reference = ref.reference.slice(this._OBX_REF_PREFIX.length);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
containedDr.contained =[];
|
|
639
|
-
break;
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
// if DiagnosticReport is found
|
|
643
|
-
if (containedDr) {
|
|
644
|
-
// Move all Observation resource into "contained" field of the DiagnosticReport resource
|
|
645
|
-
for (var i=0, iLen=entry.length; i<iLen; i++) {
|
|
646
|
-
if (entry[i].resource.resourceType === "Observation") {
|
|
647
|
-
var obx = entry[i].resource;
|
|
648
|
-
// change reference ids in related
|
|
649
|
-
if (obx.related) {
|
|
650
|
-
for (var j=0, jLen=obx.related.length; j<jLen; j++) {
|
|
651
|
-
var related = obx.related[j];
|
|
652
|
-
if (related.target && related.target.reference &&
|
|
653
|
-
related.target.reference.match(new RegExp(this._OBX_REF_PREFIX))) {
|
|
654
|
-
related.target.reference = related.target.reference.slice(this._OBX_REF_PREFIX.length);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
containedDr.contained.push(obx)
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
return containedDr;
|
|
665
|
-
},
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
/**
|
|
669
|
-
* Merge a DiagnosticReport instance into an LForms form definition or LFormsData object
|
|
670
|
-
* @param formData an LForms form definition or LFormsData object.
|
|
671
|
-
* @param diagnosticReport a DiagnosticReport resource with contained Observation resources,
|
|
672
|
-
* or a Bundle that includes a DiagnosticReport resource and associated Observation resources
|
|
673
|
-
* @param bundleType, optional, the FHIR Bundle type if inBundle is true.
|
|
674
|
-
* @returns {{}} an updated LForms form definition, with answer data
|
|
675
|
-
*/
|
|
676
|
-
mergeDiagnosticReportToLForms : function(formData, diagnosticReport) {
|
|
677
|
-
|
|
678
|
-
if (!(formData instanceof LForms.LFormsData)) {
|
|
679
|
-
// get the default settings in case they are missing in the form data
|
|
680
|
-
// not to set item values by default values for saved forms with user data
|
|
681
|
-
formData.hasSavedData = true;
|
|
682
|
-
formData = (new LForms.LFormsData(formData)).getFormData();
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
var inBundle = diagnosticReport && diagnosticReport.resourceType === "Bundle";
|
|
686
|
-
|
|
687
|
-
// move Observation resources in Bundle to be in "contained" in DiagnosticReport resource
|
|
688
|
-
// as a base data structure for converting
|
|
689
|
-
var dr = inBundle ? this._convertFromBundleToContained(diagnosticReport) : diagnosticReport;
|
|
690
|
-
|
|
691
|
-
var reportStructure = this._getReportStructure(dr);
|
|
692
|
-
|
|
693
|
-
this._processObxAndItem(reportStructure, formData, dr);
|
|
694
|
-
|
|
695
|
-
// date
|
|
696
|
-
if (dr.effectiveDateTime && formData.templateOptions.formHeaderItems) {
|
|
697
|
-
var whenDone = new LForms.Util.dateToString(dr.effectiveDateTime);
|
|
698
|
-
if (whenDone) {
|
|
699
|
-
formData.templateOptions.formHeaderItems[0].value = whenDone;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
return formData;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
};
|
|
706
|
-
|
|
707
|
-
export default dr;
|