@openmrs/esm-form-engine-lib 2.1.0-pre.1510 → 2.1.0-pre.1511
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/22ec231da647cd2c/22ec231da647cd2c.gz +0 -0
- package/3a3e1d216bd6470d/3a3e1d216bd6470d.gz +0 -0
- package/485e0040f135cee8/485e0040f135cee8.gz +0 -0
- package/__mocks__/forms/rfe-forms/bmi-test-form.json +66 -66
- package/__mocks__/forms/rfe-forms/bsa-test-form.json +66 -66
- package/__mocks__/forms/rfe-forms/edd-test-form.json +87 -87
- package/__mocks__/forms/rfe-forms/external_data_source_form.json +35 -36
- package/__mocks__/forms/rfe-forms/historical-expressions-form.json +1 -1
- package/__mocks__/forms/rfe-forms/labour_and_delivery_test_form.json +1 -1
- package/__mocks__/forms/rfe-forms/months-on-art-form.json +89 -89
- package/__mocks__/forms/rfe-forms/next-visit-test-form.json +77 -77
- package/b3059e748360776a/b3059e748360776a.gz +0 -0
- package/dist/openmrs-esm-form-engine-lib.js +1 -1
- package/package.json +1 -1
- package/src/components/inputs/number/number.component.tsx +2 -1
- package/src/components/inputs/ui-select-extended/ui-select-extended.component.tsx +1 -1
- package/src/components/inputs/ui-select-extended/ui-select-extended.test.tsx +5 -0
- package/src/processors/encounter/encounter-form-processor.ts +2 -7
- package/src/utils/common-expression-helpers.test.ts +74 -5
- package/src/utils/common-expression-helpers.ts +21 -26
- package/src/utils/expression-runner.test.ts +156 -69
- package/src/utils/expression-runner.ts +85 -135
- package/src/utils/expression-parser.test.ts +0 -308
- package/src/utils/expression-parser.ts +0 -158
@@ -1,90 +1,90 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
}
|
2
|
+
"name": "",
|
3
|
+
"pages": [
|
4
|
+
{
|
5
|
+
"label": "POC Test months on ART",
|
6
|
+
"sections": [
|
7
|
+
{
|
8
|
+
"label": "Test months on ART",
|
9
|
+
"isExpanded": "true",
|
10
|
+
"questions": [
|
11
|
+
{
|
12
|
+
"label": "Antiretroviral treatment start date",
|
13
|
+
"type": "obs",
|
14
|
+
"questionOptions": {
|
15
|
+
"rendering": "date",
|
16
|
+
"weeksList": "",
|
17
|
+
"concept": "159599AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
18
|
+
"conceptMappings": [
|
19
|
+
{
|
20
|
+
"type": "PIH",
|
21
|
+
"value": "2516"
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"type": "PIH-Malawi",
|
25
|
+
"value": "2516"
|
26
|
+
},
|
27
|
+
{
|
28
|
+
"type": "SNOMED-MVP",
|
29
|
+
"value": "1595991000105005"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"type": "CIEL",
|
33
|
+
"value": "159599"
|
34
|
+
}
|
35
|
+
]
|
36
|
+
},
|
37
|
+
"id": "artStartDate"
|
38
|
+
},
|
39
|
+
{
|
40
|
+
"label": "Months on ART",
|
41
|
+
"type": "obs",
|
42
|
+
"questionOptions": {
|
43
|
+
"rendering": "number",
|
44
|
+
"calculate": {
|
45
|
+
"calculateExpression": "calcMonthsOnART(artStartDate)"
|
46
|
+
},
|
47
|
+
"concept": "159368AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
48
|
+
"conceptMappings": [
|
49
|
+
{
|
50
|
+
"type": "CIEL",
|
51
|
+
"value": "159368"
|
52
|
+
},
|
53
|
+
{
|
54
|
+
"type": "AMPATH",
|
55
|
+
"value": "1897"
|
56
|
+
},
|
57
|
+
{
|
58
|
+
"type": "SNOMED-CT",
|
59
|
+
"value": "261774000"
|
60
|
+
},
|
61
|
+
{
|
62
|
+
"type": "SNOMED-CT",
|
63
|
+
"value": "261774000"
|
64
|
+
},
|
65
|
+
{
|
66
|
+
"type": "AMPATH",
|
67
|
+
"value": "1897"
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"type": "CIEL",
|
71
|
+
"value": "159368"
|
72
|
+
}
|
73
|
+
],
|
74
|
+
"max": "",
|
75
|
+
"min": "",
|
76
|
+
"showDate": ""
|
77
|
+
},
|
78
|
+
"id": "monthsOnART"
|
79
|
+
}
|
80
|
+
]
|
81
|
+
}
|
82
|
+
]
|
83
|
+
}
|
84
|
+
],
|
85
|
+
"availableIntents": [],
|
86
|
+
"processor": "EncounterFormProcessor",
|
87
|
+
"uuid": "da24c540-cc83-43bc-978f-c1ef180a497f",
|
88
|
+
"referencedForms": [],
|
89
|
+
"encounterType": "79c1f50f-f77d-42e2-ad2a-d29304dde2fe"
|
90
|
+
}
|
@@ -1,78 +1,78 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
}
|
2
|
+
"name": "",
|
3
|
+
"pages": [
|
4
|
+
{
|
5
|
+
"label": "Test Next Visit Calculation",
|
6
|
+
"sections": [
|
7
|
+
{
|
8
|
+
"label": "Test Next Visit",
|
9
|
+
"isExpanded": "true",
|
10
|
+
"questions": [
|
11
|
+
{
|
12
|
+
"label": "Followup Date",
|
13
|
+
"type": "obs",
|
14
|
+
"questionOptions": {
|
15
|
+
"rendering": "date",
|
16
|
+
"concept": "163137AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
17
|
+
"weeksList": ""
|
18
|
+
},
|
19
|
+
"id": "followupDate"
|
20
|
+
},
|
21
|
+
{
|
22
|
+
"label": "ARV dispensed in days",
|
23
|
+
"type": "obs",
|
24
|
+
"questionOptions": {
|
25
|
+
"rendering": "number",
|
26
|
+
"concept": "3a0709e9-d7a8-44b9-9512-111db5ce3989",
|
27
|
+
"max": "",
|
28
|
+
"min": "",
|
29
|
+
"showDate": ""
|
30
|
+
},
|
31
|
+
"id": "arvDispensedInDays"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
"label": "Next visit date",
|
35
|
+
"type": "obs",
|
36
|
+
"questionOptions": {
|
37
|
+
"rendering": "date",
|
38
|
+
"calculate": {
|
39
|
+
"calculateExpression": "calcNextVisitDate(followupDate, arvDispensedInDays)"
|
40
|
+
},
|
41
|
+
"concept": "5096AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
|
42
|
+
"weeksList": "",
|
43
|
+
"conceptMappings": [
|
44
|
+
{
|
45
|
+
"type": "SNOMED-MVP",
|
46
|
+
"value": "50961000105000"
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"type": "AMPATH",
|
50
|
+
"value": "5096"
|
51
|
+
},
|
52
|
+
{
|
53
|
+
"type": "org.openmrs.module.mdrtb",
|
54
|
+
"value": "RETURN VISIT DATE"
|
55
|
+
},
|
56
|
+
{
|
57
|
+
"type": "PIH-Malawi",
|
58
|
+
"value": "5096"
|
59
|
+
},
|
60
|
+
{
|
61
|
+
"type": "CIEL",
|
62
|
+
"value": "5096"
|
63
|
+
}
|
64
|
+
]
|
65
|
+
},
|
66
|
+
"id": "nextVisitDate"
|
67
|
+
}
|
68
|
+
]
|
69
|
+
}
|
70
|
+
]
|
71
|
+
}
|
72
|
+
],
|
73
|
+
"availableIntents": [],
|
74
|
+
"processor": "EncounterFormProcessor",
|
75
|
+
"uuid": "da24c540-cc83-43bc-978f-c1ef180a497f",
|
76
|
+
"referencedForms": [],
|
77
|
+
"encounterType": "79c1f50f-f77d-42e2-ad2a-d29304dde2fe"
|
78
|
+
}
|
Binary file
|
@@ -1 +1 @@
|
|
1
|
-
var _openmrs_esm_form_engine_lib;(()=>{"use strict";var e,r,t,n,o,i,a,l,s,u,f,p,d,c,h,m,v,g,b={8008:(e,r,t)=>{var n={"./start":()=>Promise.all([t.e(901),t.e(420),t.e(72),t.e(385),t.e(
|
1
|
+
var _openmrs_esm_form_engine_lib;(()=>{"use strict";var e,r,t,n,o,i,a,l,s,u,f,p,d,c,h,m,v,g,b={8008:(e,r,t)=>{var n={"./start":()=>Promise.all([t.e(901),t.e(420),t.e(72),t.e(385),t.e(751)]).then((()=>()=>t(6751)))},o=(e,r)=>(t.R=r,r=t.o(n,e)?n[e]():Promise.resolve().then((()=>{throw new Error('Module "'+e+'" does not exist in container.')})),t.R=void 0,r),i=(e,r)=>{if(t.S){var n="default",o=t.S[n];if(o&&o!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[n]=e,t.I(n,r)}};t.d(r,{get:()=>o,init:()=>i})}},y={};function w(e){var r=y[e];if(void 0!==r)return r.exports;var t=y[e]={id:e,loaded:!1,exports:{}};return b[e].call(t.exports,t,t.exports,w),t.loaded=!0,t.exports}w.m=b,w.c=y,w.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return w.d(r,{a:r}),r},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,w.t=function(t,n){if(1&n&&(t=this(t)),8&n)return t;if("object"==typeof t&&t){if(4&n&&t.__esModule)return t;if(16&n&&"function"==typeof t.then)return t}var o=Object.create(null);w.r(o);var i={};e=e||[null,r({}),r([]),r(r)];for(var a=2&n&&t;"object"==typeof a&&!~e.indexOf(a);a=r(a))Object.getOwnPropertyNames(a).forEach((e=>i[e]=()=>t[e]));return i.default=()=>t,w.d(o,i),o},w.d=(e,r)=>{for(var t in r)w.o(r,t)&&!w.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},w.f={},w.e=e=>Promise.all(Object.keys(w.f).reduce(((r,t)=>(w.f[t](e,r),r)),[])),w.u=e=>e+".js",w.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),w.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),t={},n="@openmrs/esm-form-engine-lib:",w.l=(e,r,o,i)=>{if(t[e])t[e].push(r);else{var a,l;if(void 0!==o)for(var s=document.getElementsByTagName("script"),u=0;u<s.length;u++){var f=s[u];if(f.getAttribute("src")==e||f.getAttribute("data-webpack")==n+o){a=f;break}}a||(l=!0,(a=document.createElement("script")).charset="utf-8",a.timeout=120,w.nc&&a.setAttribute("nonce",w.nc),a.setAttribute("data-webpack",n+o),a.src=e),t[e]=[r];var p=(r,n)=>{a.onerror=a.onload=null,clearTimeout(d);var o=t[e];if(delete t[e],a.parentNode&&a.parentNode.removeChild(a),o&&o.forEach((e=>e(n))),r)return r(n)},d=setTimeout(p.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=p.bind(null,a.onerror),a.onload=p.bind(null,a.onload),l&&document.head.appendChild(a)}},w.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},w.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{w.S={};var e={},r={};w.I=(t,n)=>{n||(n=[]);var o=r[t];if(o||(o=r[t]={}),!(n.indexOf(o)>=0)){if(n.push(o),e[t])return e[t];w.o(w.S,t)||(w.S[t]={});var i=w.S[t],a="@openmrs/esm-form-engine-lib",l=(e,r,t,n)=>{var o=i[e]=i[e]||{},l=o[r];(!l||!l.loaded&&(!n!=!l.eager?n:a>l.from))&&(o[r]={get:t,from:a,eager:!!n})},s=[];return"default"===t&&(l("@openmrs/esm-framework","5.8.2-pre.2394",(()=>Promise.all([w.e(151),w.e(72),w.e(766)]).then((()=>()=>w(5151))))),l("@openmrs/esm-patient-common-lib","8.1.1-pre.5183",(()=>Promise.all([w.e(617),w.e(901),w.e(72),w.e(465),w.e(385),w.e(70)]).then((()=>()=>w(8617))))),l("dayjs","1.11.11",(()=>w.e(353).then((()=>()=>w(4353))))),l("i18next","23.11.4",(()=>w.e(635).then((()=>()=>w(2635))))),l("react-i18next","11.18.6",(()=>Promise.all([w.e(422),w.e(72)]).then((()=>()=>w(4422))))),l("react","18.3.1",(()=>w.e(540).then((()=>()=>w(6540))))),l("swr/_internal","2.2.5",(()=>Promise.all([w.e(993),w.e(72)]).then((()=>()=>w(4993))))),l("swr/immutable","2.2.5",(()=>Promise.all([w.e(225),w.e(72),w.e(465)]).then((()=>()=>w(4225))))),l("swr/infinite","2.2.5",(()=>Promise.all([w.e(41),w.e(72),w.e(465)]).then((()=>()=>w(3041)))))),e[t]=s.length?Promise.all(s).then((()=>e[t]=1)):1}}})(),(()=>{var e;w.g.importScripts&&(e=w.g.location+"");var r=w.g.document;if(!e&&r&&(r.currentScript&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");if(t.length)for(var n=t.length-1;n>-1&&(!e||!/^http(s?):/.test(e));)e=t[n--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),w.p=e})(),o=e=>{var r=e=>e.split(".").map((e=>+e==e?+e:e)),t=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(e),n=t[1]?r(t[1]):[];return t[2]&&(n.length++,n.push.apply(n,r(t[2]))),t[3]&&(n.push([]),n.push.apply(n,r(t[3]))),n},i=(e,r)=>{e=o(e),r=o(r);for(var t=0;;){if(t>=e.length)return t<r.length&&"u"!=(typeof r[t])[0];var n=e[t],i=(typeof n)[0];if(t>=r.length)return"u"==i;var a=r[t],l=(typeof a)[0];if(i!=l)return"o"==i&&"n"==l||"s"==l||"u"==i;if("o"!=i&&"u"!=i&&n!=a)return n<a;t++}},a=e=>{var r=e[0],t="";if(1===e.length)return"*";if(r+.5){t+=0==r?">=":-1==r?"<":1==r?"^":2==r?"~":r>0?"=":"!=";for(var n=1,o=1;o<e.length;o++)n--,t+="u"==(typeof(l=e[o]))[0]?"-":(n>0?".":"")+(n=2,l);return t}var i=[];for(o=1;o<e.length;o++){var l=e[o];i.push(0===l?"not("+s()+")":1===l?"("+s()+" || "+s()+")":2===l?i.pop()+" "+i.pop():a(l))}return s();function s(){return i.pop().replace(/^\((.+)\)$/,"$1")}},l=(e,r)=>{if(0 in e){r=o(r);var t=e[0],n=t<0;n&&(t=-t-1);for(var i=0,a=1,s=!0;;a++,i++){var u,f,p=a<e.length?(typeof e[a])[0]:"";if(i>=r.length||"o"==(f=(typeof(u=r[i]))[0]))return!s||("u"==p?a>t&&!n:""==p!=n);if("u"==f){if(!s||"u"!=p)return!1}else if(s)if(p==f)if(a<=t){if(u!=e[a])return!1}else{if(n?u>e[a]:u<e[a])return!1;u!=e[a]&&(s=!1)}else if("s"!=p&&"n"!=p){if(n||a<=t)return!1;s=!1,a--}else{if(a<=t||f<p!=n)return!1;s=!1}else"s"!=p&&"n"!=p&&(s=!1,a--)}}var d=[],c=d.pop.bind(d);for(i=1;i<e.length;i++){var h=e[i];d.push(1==h?c()|c():2==h?c()&c():h?l(h,r):!c())}return!!c()},s=(e,r)=>{var t=e[r];return Object.keys(t).reduce(((e,r)=>!e||!t[e].loaded&&i(e,r)?r:e),0)},u=(e,r,t,n)=>"Unsatisfied version "+t+" from "+(t&&e[r][t].from)+" of shared singleton module "+r+" (required "+a(n)+")",f=(e,r,t,n)=>{var o=s(e,t);return l(n,o)||p(u(e,t,o,n)),d(e[t][o])},p=e=>{"undefined"!=typeof console&&console.warn&&console.warn(e)},d=e=>(e.loaded=1,e.get()),c=(e=>function(r,t,n,o){var i=w.I(r);return i&&i.then?i.then(e.bind(e,r,w.S[r],t,n,o)):e(0,w.S[r],t,n,o)})(((e,r,t,n,o)=>r&&w.o(r,t)?f(r,0,t,n):o())),h={},m={6072:()=>c("default","react",[1,18],(()=>w.e(540).then((()=>()=>w(6540))))),6766:()=>c("default","i18next",[1,23],(()=>w.e(635).then((()=>()=>w(2635))))),8465:()=>c("default","swr/_internal",[1,2],(()=>w.e(993).then((()=>()=>w(4993))))),3941:()=>c("default","react-i18next",[1,11],(()=>w.e(422).then((()=>()=>w(4422))))),5972:()=>c("default","@openmrs/esm-framework",[1,5],(()=>Promise.all([w.e(151),w.e(766)]).then((()=>()=>w(5151))))),6656:()=>c("default","@openmrs/esm-patient-common-lib",[1,8],(()=>Promise.all([w.e(617),w.e(465)]).then((()=>()=>w(8617))))),4209:()=>c("default","swr/immutable",[1,2],(()=>Promise.all([w.e(225),w.e(465)]).then((()=>()=>w(4225))))),231:()=>c("default","dayjs",[1,1],(()=>w.e(353).then((()=>()=>w(4353))))),6339:()=>c("default","swr/infinite",[1,2],(()=>Promise.all([w.e(41),w.e(465)]).then((()=>()=>w(3041)))))},v={70:[4209],72:[6072],385:[3941,5972,6656],465:[8465],751:[231,4209,6339],766:[6766]},g={},w.f.consumes=(e,r)=>{w.o(v,e)&&v[e].forEach((e=>{if(w.o(h,e))return r.push(h[e]);if(!g[e]){var t=r=>{h[e]=0,w.m[e]=t=>{delete w.c[e],t.exports=r()}};g[e]=!0;var n=r=>{delete h[e],w.m[e]=t=>{throw delete w.c[e],r}};try{var o=m[e]();o.then?r.push(h[e]=o.then(t).catch(n)):t(o)}catch(e){n(e)}}}))},(()=>{var e={719:0};w.f.j=(r,t)=>{var n=w.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else if(/^(385|465|72|766)$/.test(r))e[r]=0;else{var o=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=o);var i=w.p+w.u(r),a=new Error;w.l(i,(t=>{if(w.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var o=t&&("load"===t.type?"missing":t.type),i=t&&t.target&&t.target.src;a.message="Loading chunk "+r+" failed.\n("+o+": "+i+")",a.name="ChunkLoadError",a.type=o,a.request=i,n[1](a)}}),"chunk-"+r,r)}};var r=(r,t)=>{var n,o,[i,a,l]=t,s=0;if(i.some((r=>0!==e[r]))){for(n in a)w.o(a,n)&&(w.m[n]=a[n]);l&&l(w)}for(r&&r(t);s<i.length;s++)o=i[s],w.o(e,o)&&e[o]&&e[o][0](),e[o]=0},t=globalThis.webpackChunk_openmrs_esm_form_engine_lib=globalThis.webpackChunk_openmrs_esm_form_engine_lib||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),w.nc=void 0;var _=w(8008);_openmrs_esm_form_engine_lib=_})();
|
package/package.json
CHANGED
@@ -9,6 +9,7 @@ import styles from './number.scss';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
10
10
|
import { useFormProviderContext } from '../../../provider/form-provider';
|
11
11
|
import FieldLabel from '../../field-label/field-label.component';
|
12
|
+
import { isEmpty } from '../../../validators/form-validator';
|
12
13
|
|
13
14
|
const NumberField: React.FC<FormFieldInputProps> = ({ field, value, errors, warnings, setFieldValue }) => {
|
14
15
|
const { t } = useTranslation();
|
@@ -31,7 +32,7 @@ const NumberField: React.FC<FormFieldInputProps> = ({ field, value, errors, warn
|
|
31
32
|
|
32
33
|
const handleChange = useCallback(
|
33
34
|
(event) => {
|
34
|
-
const parsedValue = Number(event.target.value);
|
35
|
+
const parsedValue = isEmpty(event.target.value) ? undefined : Number(event.target.value);
|
35
36
|
setFieldValue(isNaN(parsedValue) ? undefined : parsedValue);
|
36
37
|
},
|
37
38
|
[setFieldValue],
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
2
|
-
import debounce from 'lodash-es
|
2
|
+
import { debounce } from 'lodash-es';
|
3
3
|
import { ComboBox, DropdownSkeleton, Layer, InlineLoading } from '@carbon/react';
|
4
4
|
import { isTrue } from '../../../utils/boolean-utils';
|
5
5
|
import { useTranslation } from 'react-i18next';
|
@@ -17,6 +17,11 @@ global.ResizeObserver = require('resize-observer-polyfill');
|
|
17
17
|
jest.mock('../../../hooks/useRestMaxResultsCount', () => jest.fn().mockReturnValue({ systemSetting: { value: '50' } }));
|
18
18
|
jest.mock('lodash-es/debounce', () => jest.fn((fn) => fn));
|
19
19
|
|
20
|
+
jest.mock('lodash-es', () => ({
|
21
|
+
...jest.requireActual('lodash-es'),
|
22
|
+
debounce: jest.fn((fn) => fn),
|
23
|
+
}));
|
24
|
+
|
20
25
|
jest.mock('../../../api', () => {
|
21
26
|
const originalModule = jest.requireActual('../../../api');
|
22
27
|
return {
|
@@ -28,7 +28,7 @@ import { moduleName } from '../../globals';
|
|
28
28
|
import { extractErrorMessagesFromResponse } from '../../utils/error-utils';
|
29
29
|
import { getPreviousEncounter, saveEncounter } from '../../api';
|
30
30
|
import { useEncounterRole } from '../../hooks/useEncounterRole';
|
31
|
-
import { evaluateAsyncExpression,
|
31
|
+
import { evaluateAsyncExpression, type FormNode } from '../../utils/expression-runner';
|
32
32
|
import { hasRendering } from '../../utils/common-utils';
|
33
33
|
import { extractObsValueAndDisplay } from '../../utils/form-helper';
|
34
34
|
|
@@ -337,12 +337,7 @@ async function evaluateCalculateExpression(
|
|
337
337
|
mode: sessionMode,
|
338
338
|
patient: patient,
|
339
339
|
};
|
340
|
-
|
341
|
-
if (field.questionOptions.calculate.calculateExpression.includes('resolve(')) {
|
342
|
-
value = await evaluateAsyncExpression(expression, node, formFields, values, context);
|
343
|
-
} else {
|
344
|
-
value = evaluateExpression(expression, node, formFields, values, context);
|
345
|
-
}
|
340
|
+
const value = await evaluateAsyncExpression(expression, node, formFields, values, context);
|
346
341
|
if (!isEmpty(value)) {
|
347
342
|
values[field.id] = value;
|
348
343
|
}
|
@@ -1,15 +1,36 @@
|
|
1
1
|
import dayjs from 'dayjs';
|
2
|
-
import { CommonExpressionHelpers } from './common-expression-helpers';
|
2
|
+
import { CommonExpressionHelpers, simpleHash } from './common-expression-helpers';
|
3
|
+
import { type FormField } from '../types';
|
3
4
|
|
4
5
|
describe('CommonExpressionHelpers', () => {
|
5
6
|
let helpers: CommonExpressionHelpers;
|
6
7
|
const mockPatient = { birthDate: '1990-01-01', sex: 'male' };
|
7
|
-
const mockFields = [
|
8
|
+
const mockFields: Array<FormField> = [
|
9
|
+
{
|
10
|
+
label: 'Question 1',
|
11
|
+
type: 'obs',
|
12
|
+
questionOptions: {
|
13
|
+
rendering: 'radio',
|
14
|
+
concept: 'question1_concept',
|
15
|
+
answers: [],
|
16
|
+
},
|
17
|
+
id: 'question1',
|
18
|
+
},
|
19
|
+
{
|
20
|
+
label: 'Question 2',
|
21
|
+
type: 'obs',
|
22
|
+
questionOptions: {
|
23
|
+
rendering: 'radio',
|
24
|
+
concept: 'question2_concept',
|
25
|
+
answers: [],
|
26
|
+
},
|
27
|
+
id: 'question2',
|
28
|
+
},
|
29
|
+
];
|
8
30
|
const mockFieldValues = {};
|
9
|
-
const mockFieldKeys = [];
|
10
31
|
|
11
32
|
beforeEach(() => {
|
12
|
-
helpers = new CommonExpressionHelpers(null, mockPatient, mockFields, mockFieldValues
|
33
|
+
helpers = new CommonExpressionHelpers(null, mockPatient, mockFields, mockFieldValues);
|
13
34
|
});
|
14
35
|
|
15
36
|
describe('isEmpty', () => {
|
@@ -86,13 +107,25 @@ describe('CommonExpressionHelpers', () => {
|
|
86
107
|
describe('useFieldValue', () => {
|
87
108
|
it('should return the field value if the key exists', () => {
|
88
109
|
helpers.allFieldValues = { question1: 'value1' };
|
89
|
-
helpers.allFieldsKeys = ['question1'];
|
90
110
|
expect(helpers.useFieldValue('question1')).toBe('value1');
|
91
111
|
});
|
92
112
|
|
93
113
|
it('should return null if the key does not exist', () => {
|
94
114
|
expect(helpers.useFieldValue('question2')).toBe(null);
|
95
115
|
});
|
116
|
+
|
117
|
+
it("should register dependency of the current node to it's determinant", () => {
|
118
|
+
// question1 as the current node
|
119
|
+
helpers.node = {
|
120
|
+
value: mockFields[0],
|
121
|
+
type: 'field',
|
122
|
+
};
|
123
|
+
helpers.allFieldValues = { question1: 'value1', question2: 'value2' };
|
124
|
+
|
125
|
+
helpers.useFieldValue('question2');
|
126
|
+
// assert that question2 lists question1 as dependent
|
127
|
+
expect(Array.from(mockFields[1].fieldDependents)).toStrictEqual(['question1']);
|
128
|
+
});
|
96
129
|
});
|
97
130
|
|
98
131
|
describe('doesNotMatchExpression', () => {
|
@@ -329,3 +362,39 @@ describe('CommonExpressionHelpers', () => {
|
|
329
362
|
});
|
330
363
|
});
|
331
364
|
});
|
365
|
+
|
366
|
+
describe('simpleHash', () => {
|
367
|
+
test('should return the same hash for the same input string', () => {
|
368
|
+
const expression = "linkedToCare == '488b58ff-64f5-4f8a-8979-fa79940b1594'";
|
369
|
+
const hash1 = simpleHash(expression);
|
370
|
+
const hash2 = simpleHash(expression);
|
371
|
+
expect(hash1).toBe(hash2);
|
372
|
+
});
|
373
|
+
|
374
|
+
test('should return different hashes for different input strings', () => {
|
375
|
+
const expression1 = "linkedToCare == '488b58ff-64f5-4f8a-8979-fa79940b1594'";
|
376
|
+
const expression2 = "linkedToCare !== '488b58ff-64f5-4f8a-8979-fa79940b1594'";
|
377
|
+
const hash1 = simpleHash(expression1);
|
378
|
+
const hash2 = simpleHash(expression2);
|
379
|
+
expect(hash1).not.toBe(hash2);
|
380
|
+
});
|
381
|
+
|
382
|
+
test('should handle empty string and return 0', () => {
|
383
|
+
const expression = '';
|
384
|
+
const hash = simpleHash(expression);
|
385
|
+
expect(hash).toBe(0);
|
386
|
+
});
|
387
|
+
|
388
|
+
test('should handle long strings without errors', () => {
|
389
|
+
const longExpression = 'left != right &'.repeat(1000);
|
390
|
+
const hash = simpleHash(longExpression);
|
391
|
+
expect(hash).toBeDefined();
|
392
|
+
});
|
393
|
+
|
394
|
+
test('should return consistent hash for strings with Unicode characters', () => {
|
395
|
+
const str = '😊💻';
|
396
|
+
const hash1 = simpleHash(str);
|
397
|
+
const hash2 = simpleHash(str);
|
398
|
+
expect(hash1).toBe(hash2);
|
399
|
+
});
|
400
|
+
});
|
@@ -11,7 +11,6 @@ import { type FormNode } from './expression-runner';
|
|
11
11
|
import { isEmpty as isValueEmpty } from '../validators/form-validator';
|
12
12
|
import * as apiFunctions from '../api';
|
13
13
|
import { getZRefByGenderAndAge } from './zscore-service';
|
14
|
-
import { ConceptFalse, ConceptTrue } from '../constants';
|
15
14
|
import { formatDate, parseDate } from '@openmrs/esm-framework';
|
16
15
|
|
17
16
|
export class CommonExpressionHelpers {
|
@@ -19,20 +18,12 @@ export class CommonExpressionHelpers {
|
|
19
18
|
patient: any = null;
|
20
19
|
allFields: FormField[] = [];
|
21
20
|
allFieldValues: Record<string, any> = {};
|
22
|
-
allFieldsKeys: string[] = [];
|
23
21
|
api = apiFunctions;
|
24
22
|
isEmpty = isValueEmpty;
|
25
23
|
|
26
|
-
constructor(
|
27
|
-
node: FormNode,
|
28
|
-
patient: any,
|
29
|
-
allFields: FormField[],
|
30
|
-
allFieldValues: Record<string, any>,
|
31
|
-
allFieldsKeys: string[],
|
32
|
-
) {
|
24
|
+
constructor(node: FormNode, patient: any, allFields: FormField[], allFieldValues: Record<string, any>) {
|
33
25
|
this.allFields = allFields;
|
34
26
|
this.allFieldValues = allFieldValues;
|
35
|
-
this.allFieldsKeys = allFieldsKeys;
|
36
27
|
this.node = node;
|
37
28
|
this.patient = patient;
|
38
29
|
}
|
@@ -88,10 +79,12 @@ export class CommonExpressionHelpers {
|
|
88
79
|
};
|
89
80
|
|
90
81
|
useFieldValue = (questionId: string) => {
|
91
|
-
|
92
|
-
|
82
|
+
const targetField = this.allFields.find((field) => field.id === questionId);
|
83
|
+
if (targetField) {
|
84
|
+
// track field dependency
|
85
|
+
registerDependency(this.node, targetField);
|
93
86
|
}
|
94
|
-
return null;
|
87
|
+
return this.allFieldValues[questionId] ?? null;
|
95
88
|
};
|
96
89
|
|
97
90
|
doesNotMatchExpression = (regexString: string, val: string | null | undefined): boolean => {
|
@@ -473,6 +466,21 @@ export class CommonExpressionHelpers {
|
|
473
466
|
};
|
474
467
|
}
|
475
468
|
|
469
|
+
/**
|
470
|
+
* Simple hash function to generate a unique identifier for a string.
|
471
|
+
* @param str - The string to hash.
|
472
|
+
* @returns A unique identifier for the string.
|
473
|
+
*/
|
474
|
+
export function simpleHash(str: string) {
|
475
|
+
let hash = 0;
|
476
|
+
for (let i = 0; i < str.length; i++) {
|
477
|
+
const char = str.charCodeAt(i);
|
478
|
+
hash = (hash << 5) - hash + char;
|
479
|
+
hash |= 0;
|
480
|
+
}
|
481
|
+
return hash;
|
482
|
+
}
|
483
|
+
|
476
484
|
export function registerDependency(node: FormNode, determinant: FormField) {
|
477
485
|
if (!node || !determinant) {
|
478
486
|
return;
|
@@ -497,16 +505,3 @@ export function registerDependency(node: FormNode, determinant: FormField) {
|
|
497
505
|
determinant.fieldDependents.add(node.value['id']);
|
498
506
|
}
|
499
507
|
}
|
500
|
-
|
501
|
-
export const booleanConceptToBoolean = (booleanConceptRepresentation): boolean => {
|
502
|
-
const { value } = booleanConceptRepresentation;
|
503
|
-
if (!booleanConceptRepresentation) {
|
504
|
-
throw new Error('booleanConceptRepresentation cannot be a null value');
|
505
|
-
}
|
506
|
-
if (value == ConceptTrue) {
|
507
|
-
return true;
|
508
|
-
}
|
509
|
-
if (value == ConceptFalse) {
|
510
|
-
return false;
|
511
|
-
}
|
512
|
-
};
|