@openmrs/esm-patient-programs-app 8.0.2-pre.4918 → 8.0.2-pre.4929
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/.turbo/turbo-build.log +12 -11
- package/dist/234.js +1 -1
- package/dist/234.js.map +1 -1
- package/dist/574.js +1 -1
- package/dist/610.js +1 -0
- package/dist/610.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-programs-app.js +1 -1
- package/dist/openmrs-esm-patient-programs-app.js.buildmanifest.json +32 -32
- package/dist/routes.json +1 -1
- package/package.json +3 -3
- package/src/dashboard.meta.ts +2 -0
- package/src/programs/programs-detailed-summary.component.tsx +25 -19
- package/src/programs/programs-detailed-summary.test.tsx +18 -3
- package/src/programs/programs-form.scss +4 -0
- package/src/programs/programs-form.test.tsx +59 -67
- package/src/programs/programs-form.workspace.tsx +60 -77
- package/src/programs/programs.resource.tsx +3 -10
- package/translations/en.json +2 -0
- package/dist/461.js +0 -1
- package/dist/461.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
var _openmrs_esm_patient_programs_app;(()=>{"use strict";var e,r,t,n,o,a,i,l,s,u,p,f,d,h,m,c={1342:(e,r,t)=>{var n={"./start":()=>Promise.all([t.e(255),t.e(731),t.e(268),t.e(325),t.e(868),t.e(
|
|
1
|
+
var _openmrs_esm_patient_programs_app;(()=>{"use strict";var e,r,t,n,o,a,i,l,s,u,p,f,d,h,m,c={1342:(e,r,t)=>{var n={"./start":()=>Promise.all([t.e(255),t.e(731),t.e(268),t.e(325),t.e(868),t.e(610)]).then((()=>()=>t(3610)))},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),a=(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:()=>a})}},v={};function g(e){var r=v[e];if(void 0!==r)return r.exports;var t=v[e]={id:e,loaded:!1,exports:{}};return c[e].call(t.exports,t,t.exports,g),t.loaded=!0,t.exports}g.m=c,g.c=v,g.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return g.d(r,{a:r}),r},g.d=(e,r)=>{for(var t in r)g.o(r,t)&&!g.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},g.f={},g.e=e=>Promise.all(Object.keys(g.f).reduce(((r,t)=>(g.f[t](e,r),r)),[])),g.u=e=>e+".js",g.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),g.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},r="@openmrs/esm-patient-programs-app:",g.l=(t,n,o,a)=>{if(e[t])e[t].push(n);else{var i,l;if(void 0!==o)for(var s=document.getElementsByTagName("script"),u=0;u<s.length;u++){var p=s[u];if(p.getAttribute("src")==t||p.getAttribute("data-webpack")==r+o){i=p;break}}i||(l=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,g.nc&&i.setAttribute("nonce",g.nc),i.setAttribute("data-webpack",r+o),i.src=t),e[t]=[n];var f=(r,n)=>{i.onerror=i.onload=null,clearTimeout(d);var o=e[t];if(delete e[t],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach((e=>e(n))),r)return r(n)},d=setTimeout(f.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=f.bind(null,i.onerror),i.onload=f.bind(null,i.onload),l&&document.head.appendChild(i)}},g.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},g.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{g.S={};var e={},r={};g.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];g.o(g.S,t)||(g.S[t]={});var a=g.S[t],i="@openmrs/esm-patient-programs-app",l=(e,r,t,n)=>{var o=a[e]=a[e]||{},l=o[r];(!l||!l.loaded&&(!n!=!l.eager?n:i>l.from))&&(o[r]={get:t,from:i,eager:!!n})},s=[];return"default"===t&&(l("@openmrs/esm-framework","5.6.1-pre.2043",(()=>Promise.all([g.e(130),g.e(268)]).then((()=>()=>g(130))))),l("@openmrs/esm-patient-common-lib","8.0.2-pre.4929",(()=>Promise.all([g.e(255),g.e(731),g.e(268),g.e(325),g.e(793),g.e(868)]).then((()=>()=>g(4793))))),l("dayjs","1.11.11",(()=>g.e(879).then((()=>()=>g(8879))))),l("react-i18next","11.18.6",(()=>Promise.all([g.e(443),g.e(268)]).then((()=>()=>g(443))))),l("react-router-dom","6.16.0",(()=>Promise.all([g.e(591),g.e(268)]).then((()=>()=>g(6591))))),l("react","18.3.1",(()=>g.e(784).then((()=>()=>g(2784))))),l("swr/_internal","2.2.4",(()=>Promise.all([g.e(729),g.e(268)]).then((()=>()=>g(4729))))),l("swr/immutable","2.2.4",(()=>Promise.all([g.e(255),g.e(268),g.e(325),g.e(303)]).then((()=>()=>g(2303)))))),e[t]=s.length?Promise.all(s).then((()=>e[t]=1)):1}}})(),(()=>{var e;g.g.importScripts&&(e=g.g.location+"");var r=g.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;)e=t[n--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),g.p=e})(),t=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},n=(e,r)=>{e=t(e),r=t(r);for(var n=0;;){if(n>=e.length)return n<r.length&&"u"!=(typeof r[n])[0];var o=e[n],a=(typeof o)[0];if(n>=r.length)return"u"==a;var i=r[n],l=(typeof i)[0];if(a!=l)return"o"==a&&"n"==l||"s"==l||"u"==a;if("o"!=a&&"u"!=a&&o!=i)return o<i;n++}},o=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,a=1;a<e.length;a++)n--,t+="u"==(typeof(l=e[a]))[0]?"-":(n>0?".":"")+(n=2,l);return t}var i=[];for(a=1;a<e.length;a++){var l=e[a];i.push(0===l?"not("+s()+")":1===l?"("+s()+" || "+s()+")":2===l?i.pop()+" "+i.pop():o(l))}return s();function s(){return i.pop().replace(/^\((.+)\)$/,"$1")}},a=(e,r)=>{if(0 in e){r=t(r);var n=e[0],o=n<0;o&&(n=-n-1);for(var i=0,l=1,s=!0;;l++,i++){var u,p,f=l<e.length?(typeof e[l])[0]:"";if(i>=r.length||"o"==(p=(typeof(u=r[i]))[0]))return!s||("u"==f?l>n&&!o:""==f!=o);if("u"==p){if(!s||"u"!=f)return!1}else if(s)if(f==p)if(l<=n){if(u!=e[l])return!1}else{if(o?u>e[l]:u<e[l])return!1;u!=e[l]&&(s=!1)}else if("s"!=f&&"n"!=f){if(o||l<=n)return!1;s=!1,l--}else{if(l<=n||p<f!=o)return!1;s=!1}else"s"!=f&&"n"!=f&&(s=!1,l--)}}var d=[],h=d.pop.bind(d);for(i=1;i<e.length;i++){var m=e[i];d.push(1==m?h()|h():2==m?h()&h():m?a(m,r):!h())}return!!h()},i=(e,r)=>{var t=e[r];return Object.keys(t).reduce(((e,r)=>!e||!t[e].loaded&&n(e,r)?r:e),0)},l=(e,r,t,n)=>"Unsatisfied version "+t+" from "+(t&&e[r][t].from)+" of shared singleton module "+r+" (required "+o(n)+")",s=(e,r,t,n)=>{var o=i(e,t);return a(n,o)||u(l(e,t,o,n)),p(e[t][o])},u=e=>{"undefined"!=typeof console&&console.warn&&console.warn(e)},p=e=>(e.loaded=1,e.get()),f=(e=>function(r,t,n,o){var a=g.I(r);return a&&a.then?a.then(e.bind(e,r,g.S[r],t,n,o)):e(0,g.S[r],t,n,o)})(((e,r,t,n,o)=>r&&g.o(r,t)?s(r,0,t,n):o())),d={},h={268:()=>f("default","react",[1,18],(()=>g.e(784).then((()=>()=>g(2784))))),3325:()=>f("default","swr/_internal",[1,2],(()=>g.e(729).then((()=>()=>g(4729))))),8744:()=>f("default","react-router-dom",[1,6],(()=>g.e(591).then((()=>()=>g(6591))))),9198:()=>f("default","swr/immutable",[1,2],(()=>g.e(152).then((()=>()=>g(2303))))),884:()=>f("default","@openmrs/esm-patient-common-lib",[1,8],(()=>g.e(793).then((()=>()=>g(4793))))),2870:()=>f("default","@openmrs/esm-framework",[1,5],(()=>g.e(130).then((()=>()=>g(130))))),4924:()=>f("default","react-i18next",[1,11],(()=>g.e(443).then((()=>()=>g(443))))),3565:()=>f("default","dayjs",[1,1],(()=>g.e(879).then((()=>()=>g(8879)))))},m={234:[3565],268:[268],325:[3325],793:[8744,9198],868:[884,2870,4924]},g.f.consumes=(e,r)=>{g.o(m,e)&&m[e].forEach((e=>{if(g.o(d,e))return r.push(d[e]);var t=r=>{d[e]=0,g.m[e]=t=>{delete g.c[e],t.exports=r()}},n=r=>{delete d[e],g.m[e]=t=>{throw delete g.c[e],r}};try{var o=h[e]();o.then?r.push(d[e]=o.then(t).catch(n)):t(o)}catch(e){n(e)}}))},(()=>{var e={55:0};g.f.j=(r,t)=>{var n=g.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else if(/^([28]68|325)$/.test(r))e[r]=0;else{var o=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=o);var a=g.p+g.u(r),i=new Error;g.l(a,(t=>{if(g.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var o=t&&("load"===t.type?"missing":t.type),a=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+o+": "+a+")",i.name="ChunkLoadError",i.type=o,i.request=a,n[1](i)}}),"chunk-"+r,r)}};var r=(r,t)=>{var n,o,[a,i,l]=t,s=0;if(a.some((r=>0!==e[r]))){for(n in i)g.o(i,n)&&(g.m[n]=i[n]);l&&l(g)}for(r&&r(t);s<a.length;s++)o=a[s],g.o(e,o)&&e[o]&&e[o][0](),e[o]=0},t=globalThis.webpackChunk_openmrs_esm_patient_programs_app=globalThis.webpackChunk_openmrs_esm_patient_programs_app||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),g.nc=void 0;var b=g(1342);_openmrs_esm_patient_programs_app=b})();
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"auxiliaryFiles": [
|
|
25
25
|
"openmrs-esm-patient-programs-app.js.map"
|
|
26
26
|
],
|
|
27
|
-
"hash": "
|
|
27
|
+
"hash": "6398877435681d9e",
|
|
28
28
|
"childrenByOrder": {}
|
|
29
29
|
},
|
|
30
30
|
{
|
|
@@ -83,10 +83,10 @@
|
|
|
83
83
|
"initial": true,
|
|
84
84
|
"entry": true,
|
|
85
85
|
"recorded": false,
|
|
86
|
-
"size":
|
|
86
|
+
"size": 2208492,
|
|
87
87
|
"sizes": {
|
|
88
88
|
"consume-shared": 210,
|
|
89
|
-
"javascript":
|
|
89
|
+
"javascript": 2186649,
|
|
90
90
|
"share-init": 336,
|
|
91
91
|
"runtime": 21297
|
|
92
92
|
},
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"auxiliaryFiles": [
|
|
104
104
|
"main.js.map"
|
|
105
105
|
],
|
|
106
|
-
"hash": "
|
|
106
|
+
"hash": "37100798388a0f40",
|
|
107
107
|
"childrenByOrder": {}
|
|
108
108
|
},
|
|
109
109
|
{
|
|
@@ -111,9 +111,9 @@
|
|
|
111
111
|
"initial": false,
|
|
112
112
|
"entry": false,
|
|
113
113
|
"recorded": false,
|
|
114
|
-
"size":
|
|
114
|
+
"size": 27527,
|
|
115
115
|
"sizes": {
|
|
116
|
-
"javascript":
|
|
116
|
+
"javascript": 27485,
|
|
117
117
|
"consume-shared": 42
|
|
118
118
|
},
|
|
119
119
|
"names": [],
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"auxiliaryFiles": [
|
|
129
129
|
"234.js.map"
|
|
130
130
|
],
|
|
131
|
-
"hash": "
|
|
131
|
+
"hash": "4494853da8f7ebf4",
|
|
132
132
|
"childrenByOrder": {}
|
|
133
133
|
},
|
|
134
134
|
{
|
|
@@ -322,22 +322,21 @@
|
|
|
322
322
|
"initial": false,
|
|
323
323
|
"entry": false,
|
|
324
324
|
"recorded": false,
|
|
325
|
-
"size":
|
|
325
|
+
"size": 1245,
|
|
326
326
|
"sizes": {
|
|
327
|
-
"javascript":
|
|
327
|
+
"javascript": 1245
|
|
328
328
|
},
|
|
329
329
|
"names": [],
|
|
330
330
|
"idHints": [],
|
|
331
331
|
"runtime": [
|
|
332
|
-
"@openmrs/esm-patient-programs-app"
|
|
332
|
+
"@openmrs/esm-patient-programs-app",
|
|
333
|
+
"main"
|
|
333
334
|
],
|
|
334
335
|
"files": [
|
|
335
|
-
"
|
|
336
|
-
],
|
|
337
|
-
"auxiliaryFiles": [
|
|
338
|
-
"461.js.map"
|
|
336
|
+
"574.js"
|
|
339
337
|
],
|
|
340
|
-
"
|
|
338
|
+
"auxiliaryFiles": [],
|
|
339
|
+
"hash": "1d6815387798556d",
|
|
341
340
|
"childrenByOrder": {}
|
|
342
341
|
},
|
|
343
342
|
{
|
|
@@ -345,21 +344,26 @@
|
|
|
345
344
|
"initial": false,
|
|
346
345
|
"entry": false,
|
|
347
346
|
"recorded": false,
|
|
348
|
-
"
|
|
347
|
+
"reason": "reused as split chunk (cache group: defaultVendors)",
|
|
348
|
+
"size": 251616,
|
|
349
349
|
"sizes": {
|
|
350
|
-
"javascript":
|
|
350
|
+
"javascript": 251616
|
|
351
351
|
},
|
|
352
352
|
"names": [],
|
|
353
|
-
"idHints": [
|
|
353
|
+
"idHints": [
|
|
354
|
+
"vendors"
|
|
355
|
+
],
|
|
354
356
|
"runtime": [
|
|
355
357
|
"@openmrs/esm-patient-programs-app",
|
|
356
358
|
"main"
|
|
357
359
|
],
|
|
358
360
|
"files": [
|
|
359
|
-
"
|
|
361
|
+
"591.js"
|
|
360
362
|
],
|
|
361
|
-
"auxiliaryFiles": [
|
|
362
|
-
|
|
363
|
+
"auxiliaryFiles": [
|
|
364
|
+
"591.js.map"
|
|
365
|
+
],
|
|
366
|
+
"hash": "b72af9509e77ddec",
|
|
363
367
|
"childrenByOrder": {}
|
|
364
368
|
},
|
|
365
369
|
{
|
|
@@ -367,26 +371,22 @@
|
|
|
367
371
|
"initial": false,
|
|
368
372
|
"entry": false,
|
|
369
373
|
"recorded": false,
|
|
370
|
-
"
|
|
371
|
-
"size": 251616,
|
|
374
|
+
"size": 46487,
|
|
372
375
|
"sizes": {
|
|
373
|
-
"javascript":
|
|
376
|
+
"javascript": 46487
|
|
374
377
|
},
|
|
375
378
|
"names": [],
|
|
376
|
-
"idHints": [
|
|
377
|
-
"vendors"
|
|
378
|
-
],
|
|
379
|
+
"idHints": [],
|
|
379
380
|
"runtime": [
|
|
380
|
-
"@openmrs/esm-patient-programs-app"
|
|
381
|
-
"main"
|
|
381
|
+
"@openmrs/esm-patient-programs-app"
|
|
382
382
|
],
|
|
383
383
|
"files": [
|
|
384
|
-
"
|
|
384
|
+
"610.js"
|
|
385
385
|
],
|
|
386
386
|
"auxiliaryFiles": [
|
|
387
|
-
"
|
|
387
|
+
"610.js.map"
|
|
388
388
|
],
|
|
389
|
-
"hash": "
|
|
389
|
+
"hash": "6c06b6ff1f828b59",
|
|
390
390
|
"childrenByOrder": {}
|
|
391
391
|
},
|
|
392
392
|
{
|
package/dist/routes.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.2.0"},"extensions":[{"name":"programs-overview-widget","component":"programsOverview","meta":{"columnSpan":4},"order":6},{"name":"programs-details-widget","slot":"patient-chart-programs-dashboard-slot","component":"programsDetailedSummary","meta":{"columnSpan":1},"order":6},{"name":"programs-summary-dashboard","slot":"patient-chart-dashboard-slot","component":"programsDashboardLink","meta":{"slot":"patient-chart-programs-dashboard-slot","columns":1,"path":"Programs"},"order":10}],"pages":[],"workspaces":[{"name":"programs-form-workspace","title":"programEnrollmentWorkspaceTitle","component":"programsFormWorkspace"}],"version":"8.0.2-pre.
|
|
1
|
+
{"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.2.0"},"extensions":[{"name":"programs-overview-widget","component":"programsOverview","meta":{"columnSpan":4},"order":6},{"name":"programs-details-widget","slot":"patient-chart-programs-dashboard-slot","component":"programsDetailedSummary","meta":{"columnSpan":1},"order":6},{"name":"programs-summary-dashboard","slot":"patient-chart-dashboard-slot","component":"programsDashboardLink","meta":{"slot":"patient-chart-programs-dashboard-slot","columns":1,"path":"Programs"},"order":10}],"pages":[],"workspaces":[{"name":"programs-form-workspace","title":"programEnrollmentWorkspaceTitle","component":"programsFormWorkspace"}],"version":"8.0.2-pre.4929"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-patient-programs-app",
|
|
3
|
-
"version": "8.0.2-pre.
|
|
3
|
+
"version": "8.0.2-pre.4929",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "Patient programs microfrontend for the OpenMRS SPA",
|
|
6
6
|
"browser": "dist/openmrs-esm-patient-programs-app.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@carbon/react": "^1.12.0",
|
|
41
|
-
"@openmrs/esm-patient-common-lib": "^8.0.2-pre.
|
|
41
|
+
"@openmrs/esm-patient-common-lib": "^8.0.2-pre.4929",
|
|
42
42
|
"lodash-es": "^4.17.21"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"swr": "2.x"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@openmrs/esm-patient-common-lib": "8.0.2-pre.
|
|
55
|
+
"@openmrs/esm-patient-common-lib": "8.0.2-pre.4929",
|
|
56
56
|
"webpack": "^5.88.2"
|
|
57
57
|
},
|
|
58
58
|
"stableVersion": "8.0.1"
|
package/src/dashboard.meta.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, useMemo } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { type TFunction, useTranslation } from 'react-i18next';
|
|
4
4
|
import {
|
|
5
5
|
Button,
|
|
6
6
|
DataTable,
|
|
@@ -35,19 +35,19 @@ interface ProgramsDetailedSummaryProps {
|
|
|
35
35
|
|
|
36
36
|
interface ProgramEditButtonProps {
|
|
37
37
|
programEnrollmentId: string;
|
|
38
|
+
t: TFunction;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patientUuid }) => {
|
|
41
42
|
const { t } = useTranslation();
|
|
43
|
+
const { hideAddProgramButton } = useConfig<ConfigObject>();
|
|
42
44
|
const layout = useLayoutType();
|
|
43
45
|
const isTablet = layout === 'tablet';
|
|
44
46
|
const isDesktop = desktopLayout(layout);
|
|
45
|
-
const { hideAddProgramButton } = useConfig<ConfigObject>();
|
|
46
47
|
const displayText = t('programEnrollments', 'Program enrollments');
|
|
47
48
|
const headerTitle = t('carePrograms', 'Care Programs');
|
|
48
49
|
|
|
49
|
-
const { enrollments, isLoading, isError, isValidating, availablePrograms
|
|
50
|
-
usePrograms(patientUuid);
|
|
50
|
+
const { enrollments, isLoading, isError, isValidating, availablePrograms } = usePrograms(patientUuid);
|
|
51
51
|
|
|
52
52
|
const tableHeaders: Array<typeof DataTableHeader> = useMemo(
|
|
53
53
|
() => [
|
|
@@ -71,9 +71,9 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
71
71
|
[t],
|
|
72
72
|
);
|
|
73
73
|
|
|
74
|
-
const tableRows = useMemo(
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
const tableRows = useMemo(
|
|
75
|
+
() =>
|
|
76
|
+
enrollments?.map((program) => ({
|
|
77
77
|
id: program.uuid,
|
|
78
78
|
display: program.display,
|
|
79
79
|
location: program.location?.display ?? '--',
|
|
@@ -81,12 +81,21 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
81
81
|
status: program.dateCompleted
|
|
82
82
|
? `${t('completedOn', 'Completed On')} ${formatDate(new Date(program.dateCompleted))}`
|
|
83
83
|
: t('active', 'Active'),
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
})),
|
|
85
|
+
[enrollments, t],
|
|
86
|
+
);
|
|
87
87
|
|
|
88
88
|
const launchProgramsForm = useCallback(() => launchPatientWorkspace('programs-form-workspace'), []);
|
|
89
89
|
|
|
90
|
+
const isEnrolledInAllPrograms = useMemo(() => {
|
|
91
|
+
if (!availablePrograms?.length || !enrollments?.length) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const activeEnrollments = enrollments.filter((enrollment) => !enrollment.dateCompleted);
|
|
96
|
+
return activeEnrollments.length === availablePrograms.length;
|
|
97
|
+
}, [availablePrograms, enrollments]);
|
|
98
|
+
|
|
90
99
|
if (isLoading) return <DataTableSkeleton role="progressbar" compact={isDesktop} zebra />;
|
|
91
100
|
if (isError) return <ErrorState error={isError} headerTitle={headerTitle} />;
|
|
92
101
|
if (enrollments?.length) {
|
|
@@ -98,23 +107,21 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
98
107
|
<Button
|
|
99
108
|
kind="ghost"
|
|
100
109
|
renderIcon={(props) => <Add size={16} {...props} />}
|
|
101
|
-
iconDescription=
|
|
110
|
+
iconDescription={t('addPrograms', 'Add programs')}
|
|
102
111
|
onClick={launchProgramsForm}
|
|
103
|
-
disabled={availablePrograms?.length && eligiblePrograms?.length === 0}
|
|
104
112
|
>
|
|
105
113
|
{t('add', 'Add')}
|
|
106
114
|
</Button>
|
|
107
115
|
)}
|
|
108
116
|
</CardHeader>
|
|
109
|
-
{
|
|
117
|
+
{isEnrolledInAllPrograms && (
|
|
110
118
|
<InlineNotification
|
|
111
119
|
style={{ minWidth: '100%', margin: '0rem', padding: '0rem' }}
|
|
112
|
-
kind={'info'}
|
|
113
120
|
lowContrast
|
|
114
121
|
subtitle={t('noEligibleEnrollments', 'There are no more programs left to enroll this patient in')}
|
|
115
122
|
title={t('fullyEnrolled', 'Enrolled in all programs')}
|
|
116
123
|
/>
|
|
117
|
-
)
|
|
124
|
+
)}
|
|
118
125
|
<DataTable rows={tableRows} headers={tableHeaders} isSortable size={isTablet ? 'lg' : 'sm'} useZebraStyles>
|
|
119
126
|
{({ rows, headers, getHeaderProps, getTableProps }) => (
|
|
120
127
|
<TableContainer>
|
|
@@ -142,7 +149,7 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
142
149
|
<TableCell key={cell.id}>{cell.value?.content ?? cell.value}</TableCell>
|
|
143
150
|
))}
|
|
144
151
|
<TableCell className="cds--table-column-menu">
|
|
145
|
-
<ProgramEditButton programEnrollmentId={enrollments[i]?.uuid} />
|
|
152
|
+
<ProgramEditButton programEnrollmentId={enrollments[i]?.uuid} t={t} />
|
|
146
153
|
</TableCell>
|
|
147
154
|
</TableRow>
|
|
148
155
|
))}
|
|
@@ -157,10 +164,9 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
157
164
|
return <EmptyState displayText={displayText} headerTitle={headerTitle} launchForm={launchProgramsForm} />;
|
|
158
165
|
};
|
|
159
166
|
|
|
160
|
-
function ProgramEditButton({ programEnrollmentId }: ProgramEditButtonProps) {
|
|
167
|
+
function ProgramEditButton({ programEnrollmentId, t }: ProgramEditButtonProps) {
|
|
161
168
|
const isTablet = useLayoutType() === 'tablet';
|
|
162
|
-
const
|
|
163
|
-
const launchEditProgramsForm = React.useCallback(
|
|
169
|
+
const launchEditProgramsForm = useCallback(
|
|
164
170
|
() => launchPatientWorkspace('programs-form-workspace', { programEnrollmentId }),
|
|
165
171
|
[programEnrollmentId],
|
|
166
172
|
);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { screen, within } from '@testing-library/react';
|
|
3
2
|
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { screen, within } from '@testing-library/react';
|
|
4
4
|
import { openmrsFetch } from '@openmrs/esm-framework';
|
|
5
5
|
import { launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
6
|
-
import { mockEnrolledProgramsResponse } from '__mocks__';
|
|
6
|
+
import { mockCareProgramsResponse, mockEnrolledInAllProgramsResponse, mockEnrolledProgramsResponse } from '__mocks__';
|
|
7
7
|
import { mockPatient, renderWithSwr, waitForLoadingToFinish } from 'tools';
|
|
8
8
|
import ProgramsDetailedSummary from './programs-detailed-summary.component';
|
|
9
9
|
|
|
@@ -27,7 +27,7 @@ jest.mock('@openmrs/esm-patient-common-lib', () => {
|
|
|
27
27
|
};
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
describe('ProgramsDetailedSummary
|
|
30
|
+
describe('ProgramsDetailedSummary', () => {
|
|
31
31
|
it('renders an empty state view when the patient is not enrolled into any programs', async () => {
|
|
32
32
|
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: [] } });
|
|
33
33
|
|
|
@@ -99,6 +99,21 @@ describe('ProgramsDetailedSummary ', () => {
|
|
|
99
99
|
programEnrollmentId: mockEnrolledProgramsResponse[0].uuid,
|
|
100
100
|
});
|
|
101
101
|
});
|
|
102
|
+
|
|
103
|
+
it('renders a notification when the patient is enrolled in all available programs', async () => {
|
|
104
|
+
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledInAllProgramsResponse } });
|
|
105
|
+
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockCareProgramsResponse } });
|
|
106
|
+
|
|
107
|
+
renderProgramsOverview();
|
|
108
|
+
|
|
109
|
+
await waitForLoadingToFinish();
|
|
110
|
+
|
|
111
|
+
expect(screen.getByRole('row', { name: /hiv care and treatment/i })).toBeInTheDocument();
|
|
112
|
+
expect(screen.getByRole('row', { name: /hiv differentiated care/i })).toBeInTheDocument();
|
|
113
|
+
expect(screen.getByRole('row', { name: /oncology screening and diagnosis/i })).toBeInTheDocument();
|
|
114
|
+
expect(screen.getByText(/enrolled in all programs/i)).toBeInTheDocument();
|
|
115
|
+
expect(screen.getByText(/there are no more programs left to enroll this patient in/i)).toBeInTheDocument();
|
|
116
|
+
});
|
|
102
117
|
});
|
|
103
118
|
|
|
104
119
|
function renderProgramsOverview() {
|
|
@@ -1,51 +1,42 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { throwError } from 'rxjs';
|
|
3
|
-
import { of } from 'rxjs/internal/observable/of';
|
|
4
|
-
import { render, screen, within } from '@testing-library/react';
|
|
5
2
|
import userEvent from '@testing-library/user-event';
|
|
6
|
-
import {
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { openmrsFetch, showSnackbar } from '@openmrs/esm-framework';
|
|
5
|
+
import { mockPatient } from 'tools';
|
|
7
6
|
import { mockCareProgramsResponse, mockEnrolledProgramsResponse, mockLocationsResponse } from '__mocks__';
|
|
8
7
|
import { createProgramEnrollment, updateProgramEnrollment } from './programs.resource';
|
|
9
|
-
import { mockPatient } from 'tools';
|
|
10
8
|
import ProgramsForm from './programs-form.workspace';
|
|
11
9
|
|
|
12
|
-
const testProps = {
|
|
13
|
-
closeWorkspace: jest.fn(),
|
|
14
|
-
closeWorkspaceWithSavedChanges: jest.fn(),
|
|
15
|
-
patientUuid: mockPatient.id,
|
|
16
|
-
promptBeforeClosing: jest.fn(),
|
|
17
|
-
setTitle: jest.fn(),
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const mockCreateErrorHandler = createErrorHandler as jest.Mock;
|
|
21
10
|
const mockCreateProgramEnrollment = createProgramEnrollment as jest.Mock;
|
|
22
11
|
const mockUpdateProgramEnrollment = updateProgramEnrollment as jest.Mock;
|
|
23
12
|
const mockOpenmrsFetch = openmrsFetch as jest.Mock;
|
|
24
13
|
const mockShowSnackbar = showSnackbar as jest.Mock;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
jest.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
45
|
-
});
|
|
14
|
+
const mockCloseWorkspaceWithSavedChanges = jest.fn();
|
|
15
|
+
|
|
16
|
+
jest.mock('@openmrs/esm-framework', () => ({
|
|
17
|
+
...jest.requireActual('@openmrs/esm-framework'),
|
|
18
|
+
showSnackbar: jest.fn(),
|
|
19
|
+
useLocations: jest.fn().mockImplementation(() => mockLocationsResponse),
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
jest.mock('./programs.resource', () => ({
|
|
23
|
+
...jest.requireActual('./programs.resource'),
|
|
24
|
+
createProgramEnrollment: jest.fn(),
|
|
25
|
+
updateProgramEnrollment: jest.fn(),
|
|
26
|
+
useEnrollments: jest.fn().mockReturnValue({
|
|
27
|
+
data: mockEnrolledProgramsResponse,
|
|
28
|
+
isLoading: false,
|
|
29
|
+
isError: false,
|
|
30
|
+
mutateEnrollments: jest.fn().mockResolvedValue(undefined),
|
|
31
|
+
}),
|
|
32
|
+
}));
|
|
46
33
|
|
|
47
34
|
describe('ProgramsForm', () => {
|
|
48
|
-
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
jest.clearAllMocks();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('renders a success toast notification upon successfully recording a program enrollment', async () => {
|
|
49
40
|
const user = userEvent.setup();
|
|
50
41
|
|
|
51
42
|
const inpatientWardUuid = 'b1a8b05e-3542-4037-bbd3-998ee9c40574';
|
|
@@ -53,18 +44,21 @@ describe('ProgramsForm', () => {
|
|
|
53
44
|
|
|
54
45
|
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockCareProgramsResponse } });
|
|
55
46
|
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledProgramsResponse } });
|
|
56
|
-
mockCreateProgramEnrollment.
|
|
47
|
+
mockCreateProgramEnrollment.mockResolvedValueOnce({ status: 201, statusText: 'Created' });
|
|
57
48
|
|
|
58
49
|
renderProgramsForm();
|
|
59
50
|
|
|
51
|
+
const programNameInput = screen.getByRole('combobox', { name: /program name/i });
|
|
52
|
+
const enrollmentDateInput = screen.getByRole('textbox', { name: /date enrolled/i });
|
|
53
|
+
const enrollmentLocationInput = screen.getByRole('combobox', { name: /enrollment location/i });
|
|
60
54
|
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
|
|
56
|
+
await user.click(enrollButton);
|
|
57
|
+
expect(screen.getByText(/programrequired/i)).toBeInTheDocument();
|
|
64
58
|
|
|
65
59
|
await user.type(enrollmentDateInput, '2020-05-05');
|
|
66
|
-
await user.selectOptions(
|
|
67
|
-
await user.selectOptions(
|
|
60
|
+
await user.selectOptions(programNameInput, [oncologyScreeningProgramUuid]);
|
|
61
|
+
await user.selectOptions(enrollmentLocationInput, [inpatientWardUuid]);
|
|
68
62
|
|
|
69
63
|
expect(screen.getByRole('option', { name: /Inpatient Ward/i })).toBeInTheDocument();
|
|
70
64
|
|
|
@@ -81,34 +75,27 @@ describe('ProgramsForm', () => {
|
|
|
81
75
|
new AbortController(),
|
|
82
76
|
);
|
|
83
77
|
|
|
78
|
+
expect(mockCloseWorkspaceWithSavedChanges).toHaveBeenCalledTimes(1);
|
|
84
79
|
expect(mockShowSnackbar).toHaveBeenCalledTimes(1);
|
|
85
80
|
expect(mockShowSnackbar).toHaveBeenCalledWith({
|
|
86
|
-
isLowContrast: true,
|
|
87
81
|
subtitle: 'It is now visible in the Programs table',
|
|
88
82
|
kind: 'success',
|
|
89
83
|
title: 'Program enrollment saved',
|
|
90
84
|
});
|
|
91
85
|
});
|
|
92
86
|
|
|
93
|
-
|
|
87
|
+
it('updates a program enrollment', async () => {
|
|
94
88
|
const user = userEvent.setup();
|
|
95
89
|
|
|
96
90
|
renderProgramsForm(mockEnrolledProgramsResponse[0].uuid);
|
|
97
91
|
|
|
98
92
|
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
99
|
-
const
|
|
100
|
-
const dateCompletedInput = within(dateCompletedGroup).getByRole('textbox');
|
|
93
|
+
const completionDateInput = screen.getByRole('textbox', { name: /date completed/i });
|
|
101
94
|
|
|
102
|
-
mockUpdateProgramEnrollment.
|
|
103
|
-
|
|
104
|
-
await user.type(dateCompletedInput, '05/05/2020');
|
|
105
|
-
|
|
106
|
-
expect(dateCompletedInput).toHaveValue('05/05/2020');
|
|
95
|
+
mockUpdateProgramEnrollment.mockResolvedValueOnce({ status: 200, statusText: 'OK' });
|
|
107
96
|
|
|
97
|
+
await user.type(completionDateInput, '05/05/2020');
|
|
108
98
|
await user.tab();
|
|
109
|
-
|
|
110
|
-
expect(enrollButton).toBeEnabled();
|
|
111
|
-
|
|
112
99
|
await user.click(enrollButton);
|
|
113
100
|
|
|
114
101
|
expect(mockUpdateProgramEnrollment).toHaveBeenCalledTimes(1);
|
|
@@ -126,7 +113,6 @@ describe('ProgramsForm', () => {
|
|
|
126
113
|
|
|
127
114
|
expect(mockShowSnackbar).toHaveBeenCalledWith(
|
|
128
115
|
expect.objectContaining({
|
|
129
|
-
isLowContrast: true,
|
|
130
116
|
subtitle: 'Changes to the program are now visible in the Programs table',
|
|
131
117
|
kind: 'success',
|
|
132
118
|
title: 'Program enrollment updated',
|
|
@@ -134,7 +120,7 @@ describe('ProgramsForm', () => {
|
|
|
134
120
|
);
|
|
135
121
|
});
|
|
136
122
|
|
|
137
|
-
|
|
123
|
+
it('renders an error notification if there was a problem recording a program enrollment', async () => {
|
|
138
124
|
const user = userEvent.setup();
|
|
139
125
|
|
|
140
126
|
const inpatientWardUuid = 'b1a8b05e-3542-4037-bbd3-998ee9c40574';
|
|
@@ -148,29 +134,27 @@ describe('ProgramsForm', () => {
|
|
|
148
134
|
},
|
|
149
135
|
};
|
|
150
136
|
|
|
151
|
-
mockOpenmrsFetch.
|
|
152
|
-
mockOpenmrsFetch.
|
|
153
|
-
mockCreateProgramEnrollment.
|
|
137
|
+
mockOpenmrsFetch.mockReturnValue({ data: { results: mockCareProgramsResponse } });
|
|
138
|
+
mockOpenmrsFetch.mockReturnValue({ data: { results: mockEnrolledProgramsResponse } });
|
|
139
|
+
mockCreateProgramEnrollment.mockRejectedValueOnce(error);
|
|
154
140
|
|
|
155
141
|
renderProgramsForm();
|
|
156
142
|
|
|
143
|
+
const programNameInput = screen.getByRole('combobox', { name: /program name/i });
|
|
144
|
+
const enrollmentDateInput = screen.getByRole('textbox', { name: /date enrolled/i });
|
|
145
|
+
const enrollmentLocationInput = screen.getByRole('combobox', { name: /enrollment location/i });
|
|
157
146
|
const enrollButton = screen.getByRole('button', { name: /save and close/i });
|
|
158
|
-
const enrollmentDateInput = screen.getAllByRole('textbox', { name: '' })[0];
|
|
159
|
-
const selectLocationInput = screen.getAllByRole('combobox', { name: '' })[1];
|
|
160
|
-
const selectProgramInput = screen.getAllByRole('combobox', { name: '' })[0];
|
|
161
147
|
|
|
162
148
|
await user.type(enrollmentDateInput, '2020-05-05');
|
|
163
|
-
await user.selectOptions(
|
|
164
|
-
await user.selectOptions(
|
|
149
|
+
await user.selectOptions(programNameInput, [oncologyScreeningProgramUuid]);
|
|
150
|
+
await user.selectOptions(enrollmentLocationInput, [inpatientWardUuid]);
|
|
165
151
|
|
|
166
152
|
expect(enrollButton).toBeEnabled();
|
|
167
153
|
|
|
168
154
|
await user.click(enrollButton);
|
|
169
155
|
|
|
170
|
-
expect(mockCreateErrorHandler).toHaveBeenCalledTimes(1);
|
|
171
156
|
expect(mockShowSnackbar).toHaveBeenCalledWith({
|
|
172
|
-
|
|
173
|
-
subtitle: 'Internal Server Error',
|
|
157
|
+
subtitle: 'An unknown error occurred',
|
|
174
158
|
kind: 'error',
|
|
175
159
|
title: 'Error saving program enrollment',
|
|
176
160
|
});
|
|
@@ -178,5 +162,13 @@ describe('ProgramsForm', () => {
|
|
|
178
162
|
});
|
|
179
163
|
|
|
180
164
|
function renderProgramsForm(programEnrollmentUuidToEdit?: string) {
|
|
165
|
+
const testProps = {
|
|
166
|
+
closeWorkspace: jest.fn(),
|
|
167
|
+
closeWorkspaceWithSavedChanges: mockCloseWorkspaceWithSavedChanges,
|
|
168
|
+
patientUuid: mockPatient.id,
|
|
169
|
+
promptBeforeClosing: jest.fn(),
|
|
170
|
+
setTitle: jest.fn(),
|
|
171
|
+
};
|
|
172
|
+
|
|
181
173
|
render(<ProgramsForm {...testProps} programEnrollmentId={programEnrollmentUuidToEdit} />);
|
|
182
174
|
}
|