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,97 +0,0 @@
|
|
|
1
|
-
// A module for Observation-based pre-population.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Starts the (likely asynchronous) requests to retrieve linked Observation
|
|
6
|
-
* resources for pre-population. When the resources have been retrieved,
|
|
7
|
-
* prepoluation will be performed.
|
|
8
|
-
* @param lfData the LFormsData object for the form being prepopulated.
|
|
9
|
-
* @return a promise resolving after the resources have been retrieved and
|
|
10
|
-
* any prepopulation has been performed.
|
|
11
|
-
*/
|
|
12
|
-
export function requestLinkedObs(lfData) {
|
|
13
|
-
if (LForms.fhirContext && lfData._fhir) {
|
|
14
|
-
// We will need to know what version of FHIR the server is using. Make
|
|
15
|
-
// sure that is available before continuing.
|
|
16
|
-
if (!LForms._serverFHIRReleaseID) {
|
|
17
|
-
// Go fetch the server's FHIR version first before continuing
|
|
18
|
-
return new Promise(function(resolve, reject) {
|
|
19
|
-
LForms.Util.getServerFHIRReleaseID(function(relID) {
|
|
20
|
-
if (!relID)
|
|
21
|
-
reject("Unable to obtain the server's FHIR version");
|
|
22
|
-
else
|
|
23
|
-
resolve(requestLinkedObs(lfData));
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
var pendingPromises = [];
|
|
29
|
-
LForms.Util.validateFHIRVersion(LForms._serverFHIRReleaseID);
|
|
30
|
-
var serverFHIR = LForms.FHIR[LForms._serverFHIRReleaseID];
|
|
31
|
-
let obsLinkURI = lfData._fhir.SDC.fhirExtObsLinkPeriod;
|
|
32
|
-
for (var i=0, len=lfData.itemList.length; i<len; ++i) {
|
|
33
|
-
let item = lfData.itemList[i];
|
|
34
|
-
const obsExt = item._fhirExt && item._fhirExt[obsLinkURI];
|
|
35
|
-
if (obsExt) { // an array of at least 1 if present
|
|
36
|
-
var duration = obsExt[0].valueDuration; // optional
|
|
37
|
-
var fhirClient = LForms.fhirContext;
|
|
38
|
-
|
|
39
|
-
// Get a comma separated list of codes
|
|
40
|
-
const codeQuery = item.codeList.map((code) => {
|
|
41
|
-
const codeSystem = code.system === 'LOINC' ? serverFHIR.LOINC_URI : code.system;
|
|
42
|
-
return [codeSystem, code.code].join('|');
|
|
43
|
-
}).join(',');
|
|
44
|
-
|
|
45
|
-
const queryParams = {
|
|
46
|
-
code: codeQuery, _sort: '-date',
|
|
47
|
-
status: 'final,amended,corrected',
|
|
48
|
-
_count: 5 // only need one, but we need to filter out focus=true below
|
|
49
|
-
};
|
|
50
|
-
// Temporarily disabling the addition of the focus search
|
|
51
|
-
// parameter, because of support issues. Instead, for now, we
|
|
52
|
-
// will check the focus parameter when the Observation is
|
|
53
|
-
// returned. Later, we might query the server to find out whether
|
|
54
|
-
// :missing is supported.
|
|
55
|
-
//if (LForms._serverFHIRReleaseID != 'STU3') // STU3 does not know about "focus"
|
|
56
|
-
// queryParams.focus = {$missing: true}; // TBD -- sometimes :missing is not supported
|
|
57
|
-
|
|
58
|
-
// Constrain the date range
|
|
59
|
-
if (duration && duration.value && duration.code) {
|
|
60
|
-
// Convert value to milliseconds
|
|
61
|
-
var result = LForms.ucumPkg.UcumLhcUtils.getInstance().convertUnitTo(duration.code, duration.value, 'ms');
|
|
62
|
-
if (result.status === 'succeeded') {
|
|
63
|
-
var date = new Date(new Date() - result.toVal);
|
|
64
|
-
queryParams.date = 'gt'+date.toISOString();
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
pendingPromises.push(
|
|
68
|
-
fhirClient.patient.request(lfData._buildURL(['Observation'],
|
|
69
|
-
queryParams)
|
|
70
|
-
).then(function(successData) {
|
|
71
|
-
var bundle = successData;
|
|
72
|
-
if (bundle.entry) {
|
|
73
|
-
var foundObs;
|
|
74
|
-
for (var j=0, jLen=bundle.entry.length; j<jLen && !foundObs; ++j) {
|
|
75
|
-
var obs = bundle.entry[j].resource;
|
|
76
|
-
if (!obs.focus) { // in case we couldn't use focus:missing above
|
|
77
|
-
serverFHIR.SDC.importObsValue(item, obs);
|
|
78
|
-
if (item.value) { // obs.value[x] could be missing
|
|
79
|
-
foundObs = true;
|
|
80
|
-
if (item.unit)
|
|
81
|
-
lfData._setUnitDisplay(item.unit);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return item.questionCode; // code is not needed, but useful for debugging
|
|
87
|
-
})
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return Promise.all(pendingPromises);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import renderingStyle from './extensions/rendering-style';
|
|
2
|
-
var extProcessors = {};
|
|
3
|
-
extProcessors[renderingStyle.extURL] = renderingStyle.processExtension;
|
|
4
|
-
|
|
5
|
-
export function addCommonRuntimeFns(ns) {
|
|
6
|
-
var self = ns;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Processes the extensions on either lfNode, or lfNode[lfFieldName], if
|
|
10
|
-
* lfFieldName is provided. Only the extensions for which processors
|
|
11
|
-
* are written (in the "extensions" sub-directory) are considered.
|
|
12
|
-
* @param lfNode the node in the LFormsData structure on which the information
|
|
13
|
-
* from the extension will be stored.
|
|
14
|
-
* @param lfFieldName (optional). Sometimes the extension information is on a
|
|
15
|
-
* sub-node, (e.g. 'obj_text') in which case this should be the field for
|
|
16
|
-
* retrieving that sub-node.
|
|
17
|
-
*/
|
|
18
|
-
self.processExtensions = function(lfNode, lfFieldName) {
|
|
19
|
-
var fieldData = lfFieldName ? lfNode[lfFieldName] : lfNode;
|
|
20
|
-
if (fieldData) {
|
|
21
|
-
var extensions = fieldData.extension;
|
|
22
|
-
if (extensions) {
|
|
23
|
-
for (var i=0, len=extensions.length; i<len; ++i) {
|
|
24
|
-
var extData = extensions[i];
|
|
25
|
-
var extURL = extData.url;
|
|
26
|
-
var processor = extProcessors[extURL];
|
|
27
|
-
if (processor)
|
|
28
|
-
processor(lfNode, lfFieldName, extData);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
}
|
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
import {requestLinkedObs} from './obs-prepop.mjs';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Defines SDC functions (used by both import and export, or for other
|
|
5
|
-
* SDC-related purposes) that are the same across the different FHIR versions.
|
|
6
|
-
* The function takes SDC namespace object defined in the sdc export code,
|
|
7
|
-
* and adds additional functions to it.
|
|
8
|
-
*/
|
|
9
|
-
function addCommonSDCFns(ns) {
|
|
10
|
-
"use strict";
|
|
11
|
-
|
|
12
|
-
var self = ns;
|
|
13
|
-
self.requestLinkedObs = requestLinkedObs;
|
|
14
|
-
|
|
15
|
-
// A mapping of data types of items from LHC-Forms to FHIR Questionnaire
|
|
16
|
-
self._lformsTypesToFHIRTypes = {
|
|
17
|
-
"SECTION": 'group',
|
|
18
|
-
"TITLE": 'display',
|
|
19
|
-
"ST": 'string',
|
|
20
|
-
"BL": 'boolean',
|
|
21
|
-
"REAL": 'decimal',
|
|
22
|
-
"INT": 'integer',
|
|
23
|
-
"DT": 'date',
|
|
24
|
-
"DTM": 'dateTime',
|
|
25
|
-
"TM": 'time',
|
|
26
|
-
"TX": 'text',
|
|
27
|
-
"URL": 'url',
|
|
28
|
-
"CNE": 'choice',
|
|
29
|
-
"CWE": 'open-choice',
|
|
30
|
-
"QTY": 'quantity',
|
|
31
|
-
"attachment": 'attachment'
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// A mapping from LHC-Forms data types to the partial field names of the value fields
|
|
35
|
-
// and initial value fields in FHIR Questionnaire
|
|
36
|
-
self._lformsTypesToFHIRFields = {
|
|
37
|
-
"attachment": "Attachment",
|
|
38
|
-
"INT": 'Integer',
|
|
39
|
-
"REAL": 'Decimal',
|
|
40
|
-
"DT": 'Date',
|
|
41
|
-
"DTM": 'DateTime',
|
|
42
|
-
"TM": 'Time',
|
|
43
|
-
"ST": 'String',
|
|
44
|
-
"TX": 'String',
|
|
45
|
-
"BL": 'Boolean',
|
|
46
|
-
"URL": 'Url',
|
|
47
|
-
"CNE": 'Coding',
|
|
48
|
-
"CWE": 'Coding',
|
|
49
|
-
"QTY": 'Quantity'
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
self._operatorMapping = {
|
|
53
|
-
'minExclusive': '>',
|
|
54
|
-
'maxExclusive': '<',
|
|
55
|
-
'minInclusive': '>=',
|
|
56
|
-
'maxInclusive': '<=',
|
|
57
|
-
'value': '=',
|
|
58
|
-
'notEqual': '!=',
|
|
59
|
-
'>': 'minExclusive',
|
|
60
|
-
'<': 'maxExclusive',
|
|
61
|
-
'>=': 'minInclusive',
|
|
62
|
-
'<=': 'maxInclusive',
|
|
63
|
-
'=': 'value',
|
|
64
|
-
'!=': 'notEqual',
|
|
65
|
-
'exists': 'exists'
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Check if a LForms item has repeating questions
|
|
70
|
-
* @param item a LForms item
|
|
71
|
-
* @returns {*|boolean}
|
|
72
|
-
* @private
|
|
73
|
-
*/
|
|
74
|
-
self._questionRepeats = function(item) {
|
|
75
|
-
return item && item.questionCardinality && item.questionCardinality.max &&
|
|
76
|
-
(item.questionCardinality.max === "*" || parseInt(item.questionCardinality.max) > 1);
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Check if a LForms item has repeating answers
|
|
82
|
-
* @param item a LForms item
|
|
83
|
-
* @returns {*|boolean}
|
|
84
|
-
* @private
|
|
85
|
-
*/
|
|
86
|
-
self._answerRepeats = function(item) {
|
|
87
|
-
return item && item.answerCardinality && item.answerCardinality.max &&
|
|
88
|
-
(item.answerCardinality.max === "*" || parseInt(item.answerCardinality.max) > 1);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Do a shallow copy of specified fields from source to target.
|
|
94
|
-
*
|
|
95
|
-
* @param source - Source object
|
|
96
|
-
* @param target - Target object
|
|
97
|
-
* @param fieldList - Array of fields to copy from the source. If the field is
|
|
98
|
-
* not found in the source, it is ignored.
|
|
99
|
-
*/
|
|
100
|
-
self.copyFields = function(source, target, fieldList) {
|
|
101
|
-
if(source && target && fieldList && fieldList.length > 0) {
|
|
102
|
-
fieldList.forEach(function(field) {
|
|
103
|
-
if(source.hasOwnProperty(field)) {
|
|
104
|
-
target[field] = source[field];
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// Store the UCUM code system URI
|
|
112
|
-
self.UCUM_URI = 'http://unitsofmeasure.org';
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Set the given key/value to the object if the value is not undefined, not null, and not an empty string.
|
|
117
|
-
* @param obj the object to set the key/value on. It can be null/undefined, and if so, a new object will
|
|
118
|
-
* be created and returned (only if the value is valid).
|
|
119
|
-
* @param key the key for the given value to be set to the given object, required.
|
|
120
|
-
* @param value the value to be set to the given object using the given key.
|
|
121
|
-
* @return if the input object is not null/undefined, it will be returned;
|
|
122
|
-
* if the input object is null/undefined:
|
|
123
|
-
* - return the given object as is if the value is invalid, or
|
|
124
|
-
* - a newly created object with the given key/value set.
|
|
125
|
-
* @private
|
|
126
|
-
*/
|
|
127
|
-
self._setIfHasValue = function (obj, key, value) {
|
|
128
|
-
if(value !== undefined && value !== null && value !== '') {
|
|
129
|
-
if(! obj) {
|
|
130
|
-
obj = {};
|
|
131
|
-
}
|
|
132
|
-
obj[key] = value;
|
|
133
|
-
}
|
|
134
|
-
return obj;
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Copy between lforms trigger value coding and FHIR enableWhen valueCoding. It only copies 3 fields:
|
|
140
|
-
* code, system, and display/text (called "text" in lforms, "display" in FHIR)
|
|
141
|
-
* @param srcCoding the coding object to copy from
|
|
142
|
-
* @param dstCoding the coding object to copy to, may be null/undefined, and if null/undefined, a new object
|
|
143
|
-
* will be created but only if the srcCoding has at least one of code, system, display/text
|
|
144
|
-
* @param lforms2Fhir The direction of copying, can be true or false. The direction matters because in lforms,
|
|
145
|
-
* the text/display field is called "text", while in FHIR, it's called "display"
|
|
146
|
-
* @return the resulting dstCoding object.
|
|
147
|
-
* @private
|
|
148
|
-
*/
|
|
149
|
-
self._copyTriggerCoding = function(srcCoding, dstCoding, lforms2Fhir) {
|
|
150
|
-
let srcTextField = lforms2Fhir? 'text': 'display';
|
|
151
|
-
let dstTextField = lforms2Fhir? 'display': 'text';
|
|
152
|
-
|
|
153
|
-
dstCoding = self._setIfHasValue(dstCoding, 'code', srcCoding.code);
|
|
154
|
-
dstCoding = self._setIfHasValue(dstCoding, 'system', srcCoding.system);
|
|
155
|
-
dstCoding = self._setIfHasValue(dstCoding, dstTextField, srcCoding[srcTextField]);
|
|
156
|
-
|
|
157
|
-
return dstCoding;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Returns true if the given item (or LFormsData) has an expression
|
|
163
|
-
* which needs to be re-evaluated when the user changes their response.
|
|
164
|
-
* @param itemOrLFData the item or LFormsData to be checked. It is assumed
|
|
165
|
-
* that the relevant extensions will be in an _fhirExt hash where
|
|
166
|
-
* the key is the URI of the extension and the values are arrays of the FHIR
|
|
167
|
-
* extension structure.
|
|
168
|
-
*/
|
|
169
|
-
self.hasResponsiveExpression = function(itemOrLFData) {
|
|
170
|
-
var ext = itemOrLFData._fhirExt;
|
|
171
|
-
return ext ? !!(ext[self.fhirExtCalculatedExp] || ext[self.fhirExtAnswerExp] ||
|
|
172
|
-
ext[self.fhirExtEnableWhenExp]) : false;
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Returns true if the given item has an expression
|
|
178
|
-
* which sets the list.
|
|
179
|
-
* @param item the item to be checked. It is assumed
|
|
180
|
-
* that the relevant extensions will be in an _fhirExt hash where
|
|
181
|
-
* the key is the URI of the extension and the values are arrays of the FHIR
|
|
182
|
-
* extension structure.
|
|
183
|
-
*/
|
|
184
|
-
self.hasListExpression = function(item) {
|
|
185
|
-
var ext = item._fhirExt;
|
|
186
|
-
// This should one day include a check for cqf-expression, when we add
|
|
187
|
-
// support for it
|
|
188
|
-
return ext ? !!(ext[self.fhirExtAnswerExp]) : false;
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Returns true if the given item (or LFormsData) has an expression
|
|
194
|
-
* which needs to be evaluated only once, when form is first rendered.
|
|
195
|
-
* @param itemOrLFData the item or LFormsData to be checked. It is assumed
|
|
196
|
-
* that the relevant extensions will be in an _fhirExt hash where
|
|
197
|
-
* the key is the URI of the extension and the values are arrays of the FHIR
|
|
198
|
-
* extension structure.
|
|
199
|
-
*/
|
|
200
|
-
self.hasInitialExpression = function(itemOrLFData) {
|
|
201
|
-
return !!(itemOrLFData._fhirExt && itemOrLFData._fhirExt[self.fhirExtInitialExp]);
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Builds a map from extension URIs to arrays of the FHIR extension
|
|
207
|
-
* structures, and stores it on the item. Also builds an array of all
|
|
208
|
-
* Expression extensions.
|
|
209
|
-
*
|
|
210
|
-
* @param itemOrLFData a form item or an LFormsData which possibly contain
|
|
211
|
-
* FHIR extensions (in an "extension" property).
|
|
212
|
-
*/
|
|
213
|
-
self.buildExtensionMap = function(itemOrLFData) {
|
|
214
|
-
// Initialize a map for testing whether an extension is an Expression extension.
|
|
215
|
-
// The keys are the URIs, and the values are see to true.
|
|
216
|
-
if (!self.isExpressionExtension) {
|
|
217
|
-
self.isExpressionExtension = [self.fhirExtCalculatedExp,
|
|
218
|
-
self.fhirExtInitialExp, self.fhirExtAnswerExp, self.fhirExtVariable,
|
|
219
|
-
self.fhirExtEnableWhenExp].reduce((x, k)=>{x[k]=true; return x}, {});
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (itemOrLFData.extension) {
|
|
223
|
-
var m = {};
|
|
224
|
-
var exprExtensions = [];
|
|
225
|
-
for (let ext of itemOrLFData.extension) {
|
|
226
|
-
var extArray = m[ext.url];
|
|
227
|
-
if (!extArray)
|
|
228
|
-
extArray = m[ext.url] = [];
|
|
229
|
-
extArray.push(ext);
|
|
230
|
-
if (self.isExpressionExtension[ext.url])
|
|
231
|
-
exprExtensions.push(ext);
|
|
232
|
-
}
|
|
233
|
-
itemOrLFData._fhirExt = m;
|
|
234
|
-
if (exprExtensions.length)
|
|
235
|
-
itemOrLFData._exprExtensions = exprExtensions;
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Requests launchContext resources. Assumes LForms.Util.setFHIRContext() has
|
|
242
|
-
* been called.
|
|
243
|
-
* @param lfData a LFormsData object for the form.
|
|
244
|
-
* @return an array of Promises which resolve when the attempt to load the
|
|
245
|
-
* resources has completed (succesful or not, they resolve without being
|
|
246
|
-
* rejected).
|
|
247
|
-
*/
|
|
248
|
-
self.loadLaunchContext = function(lfData) {
|
|
249
|
-
// launchContext
|
|
250
|
-
var contextItems = LForms.Util.findObjectInArray(lfData.extension, 'url',
|
|
251
|
-
self.fhirExtLaunchContext, 0, true);
|
|
252
|
-
// Per https://jira.hl7.org/browse/FHIR-29664 (approved; not yet applied- // 2020-11-19).
|
|
253
|
-
const validContexts = {patient: {Patient: 1}, encounter: {Encounter: 1},
|
|
254
|
-
user: {Patient: 1, Practitioner: 1, PractitionerRole: 1, RelatedPerson: 1},
|
|
255
|
-
study: {Study: 1}};
|
|
256
|
-
const supportedContextNames = {Patient: 1, User: 1, Encounter: 1};
|
|
257
|
-
const pendingPromises = [];
|
|
258
|
-
for (var i=0, len=contextItems.length; i<len; ++i) {
|
|
259
|
-
let contextItemExt = contextItems[i].extension;
|
|
260
|
-
let name=null, typeList=[];
|
|
261
|
-
|
|
262
|
-
for (var j=0, jLen=contextItemExt.length; j<jLen; ++j) {
|
|
263
|
-
var fieldExt = contextItemExt[j];
|
|
264
|
-
if (!name && fieldExt.url === 'name') {
|
|
265
|
-
let nameCode = fieldExt.valueId
|
|
266
|
-
if (validContexts[nameCode]) {
|
|
267
|
-
name = nameCode;
|
|
268
|
-
// It is no longer necessary to check that the name is a valid
|
|
269
|
-
// FHIR variable, because per
|
|
270
|
-
// https://jira.hl7.org/browse/FHIR-29664, the values are now
|
|
271
|
-
// constrained to a known list. I am leaving the line below
|
|
272
|
-
// comented out for reference in case that changes again.
|
|
273
|
-
// lfData._checkFHIRVarName(name); // might throw
|
|
274
|
-
}
|
|
275
|
-
else {
|
|
276
|
-
console.warn("A launch context of name "+nameCode+
|
|
277
|
-
" was requested by the form, but the supported types are: "+
|
|
278
|
-
Object.keys(validContexts).join(", "));
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
else if (fieldExt.url === 'type') { // there can be more than one
|
|
282
|
-
typeList.push(fieldExt.valueCode);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
if (name && typeList.length) {
|
|
286
|
-
pendingPromises.push(new Promise(function(resolve, reject) {
|
|
287
|
-
let contextResource = LForms.fhirContext[name];
|
|
288
|
-
if (!contextResource.id) {
|
|
289
|
-
console.warn('A launch context resource of name '+name+
|
|
290
|
-
' was requested by the form, but none was available');
|
|
291
|
-
// The loading of this resource should not be critical for the
|
|
292
|
-
// Questionnaire, because it is just for prepopulation. Don't
|
|
293
|
-
// reject the promise.
|
|
294
|
-
resolve();
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
contextResource.read().then(function(resource) {
|
|
298
|
-
if (resource) {
|
|
299
|
-
let resType = resource.resourceType;
|
|
300
|
-
if (typeList.indexOf(resType) == -1) {
|
|
301
|
-
console.warn("Could not retrieve a resource of the requested" +
|
|
302
|
-
" types for launch context name " +name);
|
|
303
|
-
}
|
|
304
|
-
else {
|
|
305
|
-
// Validate the "type"
|
|
306
|
-
let validTypes = validContexts[name];
|
|
307
|
-
if (!validTypes[resType]) {
|
|
308
|
-
console.warn("A launch context resource of type "+resType+
|
|
309
|
-
" was requested by the form, but the supported types for name "+
|
|
310
|
-
name + " are: "+ Object.keys(validTypes).join(", "));
|
|
311
|
-
}
|
|
312
|
-
else {
|
|
313
|
-
lfData._fhirVariables[name] = resource;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
resolve();
|
|
318
|
-
},
|
|
319
|
-
function fail(reason) {
|
|
320
|
-
console.warn('A launch context of name '+name+' was requested, '+
|
|
321
|
-
'but could not be read.');
|
|
322
|
-
console.error(reason);
|
|
323
|
-
resolve(); // per above, we are not rejecting the promise
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
}));
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return pendingPromises;
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
export default addCommonSDCFns;
|