@openmrs/esm-patient-programs-app 3.2.1-pre.97 → 4.0.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/.turbo/turbo-build.log +33 -35
- package/dist/238.js +2 -0
- package/dist/{707.js.LICENSE.txt → 238.js.LICENSE.txt} +0 -0
- package/dist/402.js +1 -1
- package/dist/435.js +1 -0
- package/dist/461.js +1 -0
- package/dist/574.js +1 -1
- package/dist/641.js +1 -0
- package/dist/709.js +1 -0
- package/dist/733.js +1 -0
- package/dist/734.js +2 -0
- package/dist/734.js.LICENSE.txt +53 -0
- package/dist/784.js +1 -1
- package/dist/784.js.LICENSE.txt +2 -7
- package/dist/821.js +1 -0
- package/dist/858.js +1 -1
- package/dist/main.js +1 -0
- package/dist/openmrs-esm-patient-programs-app.js +1 -1
- package/dist/openmrs-esm-patient-programs-app.js.buildmanifest.json +134 -205
- package/dist/openmrs-esm-patient-programs-app.old +1 -1
- package/package.json +12 -14
- package/src/config-schema.ts +12 -0
- package/src/dashboard.meta.tsx +1 -1
- package/src/index.ts +8 -3
- package/src/programs/program-action-button/program-action-button.component.tsx +50 -0
- package/src/programs/programs-detailed-summary.component.tsx +68 -37
- package/src/programs/programs-detailed-summary.scss +1 -4
- package/src/programs/programs-detailed-summary.test.tsx +26 -7
- package/src/programs/programs-form.component.tsx +246 -109
- package/src/programs/programs-form.scss +1 -9
- package/src/programs/programs-form.test.tsx +113 -110
- package/src/programs/programs-overview.component.tsx +60 -46
- package/src/programs/programs-overview.scss +1 -3
- package/src/programs/programs-overview.test.tsx +6 -7
- package/src/programs/programs.resource.tsx +63 -8
- package/src/types/index.ts +16 -2
- package/translations/en.json +10 -2
- package/dist/13.js +0 -1
- package/dist/142.js +0 -1
- package/dist/145.js +0 -1
- package/dist/186.js +0 -2
- package/dist/186.js.LICENSE.txt +0 -23
- package/dist/252.js +0 -2
- package/dist/252.js.LICENSE.txt +0 -23
- package/dist/336.js +0 -2
- package/dist/336.js.LICENSE.txt +0 -20
- package/dist/373.js +0 -1
- package/dist/635.js +0 -2
- package/dist/635.js.LICENSE.txt +0 -16
- package/dist/692.js +0 -1
- package/dist/701.js +0 -1
- package/dist/707.js +0 -2
- package/dist/76.js +0 -1
- package/dist/932.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
var _openmrs_esm_patient_programs_app;(()=>{"use strict";var e,r,t,n,o,a,i,s,l,p,u,f,d,c,h,m,v,g={1342:(e,r,t)=>{var n={"./start":()=>t.e(435).then((()=>()=>t(2435)))},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})}},b={};function y(e){var r=b[e];if(void 0!==r)return r.exports;var t=b[e]={id:e,loaded:!1,exports:{}};return g[e].call(t.exports,t,t.exports,y),t.loaded=!0,t.exports}y.m=g,y.c=b,y.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return y.d(r,{a:r}),r},y.d=(e,r)=>{for(var t in r)y.o(r,t)&&!y.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},y.f={},y.e=e=>Promise.all(Object.keys(y.f).reduce(((r,t)=>(y.f[t](e,r),r)),[])),y.u=e=>e+".js",y.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),y.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},r="@openmrs/esm-patient-programs-app:",y.l=(t,n,o,a)=>{if(e[t])e[t].push(n);else{var i,s;if(void 0!==o)for(var l=document.getElementsByTagName("script"),p=0;p<l.length;p++){var u=l[p];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==r+o){i=u;break}}i||(s=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,y.nc&&i.setAttribute("nonce",y.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),s&&document.head.appendChild(i)}},y.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},y.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{y.S={};var e={},r={};y.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];y.o(y.S,t)||(y.S[t]={});var a=y.S[t],i="@openmrs/esm-patient-programs-app",s=(e,r,t,n)=>{var o=a[e]=a[e]||{},s=o[r];(!s||!s.loaded&&(!n!=!s.eager?n:i>s.from))&&(o[r]={get:t,from:i,eager:!!n})},l=[];return"default"===t&&(s("@openmrs/esm-framework","4.0.1-pre.238",(()=>Promise.all([y.e(858),y.e(268)]).then((()=>()=>y(6858))))),s("@openmrs/esm-patient-common-lib","4.0.0",(()=>Promise.all([y.e(734),y.e(238),y.e(268),y.e(924),y.e(402),y.e(660)]).then((()=>()=>y(9402))))),s("dayjs","1.11.5",(()=>y.e(879).then((()=>()=>y(8879))))),s("react-i18next","11.18.6",(()=>Promise.all([y.e(709),y.e(268)]).then((()=>()=>y(709))))),s("react","18.2.0",(()=>y.e(784).then((()=>()=>y(2784))))),s("rxjs","6.6.7",(()=>y.e(206).then((()=>()=>y(5206)))))),e[t]=l.length?Promise.all(l).then((()=>e[t]=1)):1}}})(),(()=>{var e;y.g.importScripts&&(e=y.g.location+"");var r=y.g.document;if(!e&&r&&(r.currentScript&&(e=r.currentScript.src),!e)){var t=r.getElementsByTagName("script");t.length&&(e=t[t.length-1].src)}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),y.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],s=(typeof i)[0];if(a!=s)return"o"==a&&"n"==s||"s"==s||"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(s=e[a]))[0]?"-":(n>0?".":"")+(n=2,s);return t}var i=[];for(a=1;a<e.length;a++){var s=e[a];i.push(0===s?"not("+l()+")":1===s?"("+l()+" || "+l()+")":2===s?i.pop()+" "+i.pop():o(s))}return l();function l(){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,s=1,l=!0;;s++,i++){var p,u,f=s<e.length?(typeof e[s])[0]:"";if(i>=r.length||"o"==(u=(typeof(p=r[i]))[0]))return!l||("u"==f?s>n&&!o:""==f!=o);if("u"==u){if(!l||"u"!=f)return!1}else if(l)if(f==u)if(s<=n){if(p!=e[s])return!1}else{if(o?p>e[s]:p<e[s])return!1;p!=e[s]&&(l=!1)}else if("s"!=f&&"n"!=f){if(o||s<=n)return!1;l=!1,s--}else{if(s<=n||u<f!=o)return!1;l=!1}else"s"!=f&&"n"!=f&&(l=!1,s--)}}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?a(h,r):!c())}return!!c()},i=(e,r)=>{var t=e[r];return Object.keys(t).reduce(((e,r)=>!e||!t[e].loaded&&n(e,r)?r:e),0)},s=(e,r,t,n)=>"Unsatisfied version "+t+" from "+(t&&e[r][t].from)+" of shared singleton module "+r+" (required "+o(n)+")",l=(e,r,t,n)=>{var o=i(e,t);return u(e[t][o])},p=(e,r,t,n)=>{var o=i(e,t);return a(n,o)||"undefined"!=typeof console&&console.warn&&console.warn(s(e,t,o,n)),u(e[t][o])},u=e=>(e.loaded=1,e.get()),d=(f=e=>function(r,t,n,o){var a=y.I(r);return a&&a.then?a.then(e.bind(e,r,y.S[r],t,n,o)):e(r,y.S[r],t,n,o)})(((e,r,t,n)=>r&&y.o(r,t)?l(r,0,t):n())),c=f(((e,r,t,n,o)=>r&&y.o(r,t)?p(r,0,t,n):o())),h={},m={268:()=>c("default","react",[1,18],(()=>y.e(784).then((()=>()=>y(2784))))),4924:()=>c("default","react-i18next",[1,11],(()=>y.e(709).then((()=>()=>y(709))))),2444:()=>c("default","rxjs",[1,6],(()=>y.e(206).then((()=>()=>y(5206))))),6081:()=>d("default","@openmrs/esm-framework/src/internal",(()=>y.e(858).then((()=>()=>y(6858))))),906:()=>c("default","@openmrs/esm-framework",[1,4],(()=>Promise.all([y.e(858),y.e(268)]).then((()=>()=>y(6858))))),6217:()=>c("default","@openmrs/esm-patient-common-lib",[1,4],(()=>Promise.all([y.e(734),y.e(238),y.e(268),y.e(924),y.e(402)]).then((()=>()=>y(9402))))),3565:()=>c("default","dayjs",[1,1],(()=>y.e(879).then((()=>()=>y(8879)))))},v={268:[268],402:[2444,6081],435:[906,6217],660:[906,6217],733:[3565],924:[4924]},y.f.consumes=(e,r)=>{y.o(v,e)&&v[e].forEach((e=>{if(y.o(h,e))return r.push(h[e]);var t=r=>{h[e]=0,y.m[e]=t=>{delete y.c[e],t.exports=r()}},n=r=>{delete h[e],y.m[e]=t=>{throw delete y.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={55:0};y.f.j=(r,t)=>{var n=y.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else if(/^(268|660|924)$/.test(r))e[r]=0;else{var o=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=o);var a=y.p+y.u(r),i=new Error;y.l(a,(t=>{if(y.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,s]=t,l=0;if(a.some((r=>0!==e[r]))){for(n in i)y.o(i,n)&&(y.m[n]=i[n]);s&&s(y)}for(r&&r(t);l<a.length;l++)o=a[l],y.o(e,o)&&e[o]&&e[o][0](),e[o]=0},t=self.webpackChunk_openmrs_esm_patient_programs_app=self.webpackChunk_openmrs_esm_patient_programs_app||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),y.nc=void 0;var w=y(1342);_openmrs_esm_patient_programs_app=w})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-patient-programs-app",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
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",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"debug": "npm run serve",
|
|
13
13
|
"build": "webpack --mode production",
|
|
14
14
|
"analyze": "webpack --mode=production --env analyze=true",
|
|
15
|
-
"lint": "eslint src --ext tsx,ts",
|
|
15
|
+
"lint": "eslint src --ext tsx,ts --fix --max-warnings=0",
|
|
16
16
|
"typescript": "tsc",
|
|
17
17
|
"extract-translations": "i18next 'src/**/*.component.tsx' --config ../../tools/i18next-parser.config.js"
|
|
18
18
|
},
|
|
@@ -34,23 +34,21 @@
|
|
|
34
34
|
"url": "https://github.com/openmrs/openmrs-esm-patient-chart/issues"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@carbon/
|
|
38
|
-
"@
|
|
39
|
-
"@openmrs/esm-patient-common-lib": "^3.2.1-pre.97",
|
|
40
|
-
"carbon-components-react": "^7.25.0",
|
|
41
|
-
"d3": "^7.0.3",
|
|
37
|
+
"@carbon/react": "^1.12.0",
|
|
38
|
+
"@openmrs/esm-patient-common-lib": "^4.0.0",
|
|
42
39
|
"lodash-es": "^4.17.15"
|
|
43
40
|
},
|
|
44
41
|
"peerDependencies": {
|
|
45
|
-
"@openmrs/esm-framework": "
|
|
46
|
-
"@openmrs/esm-patient-common-lib": "
|
|
47
|
-
"carbon-components": "10.x",
|
|
48
|
-
"carbon-icons": "7.x",
|
|
42
|
+
"@openmrs/esm-framework": "4.x",
|
|
43
|
+
"@openmrs/esm-patient-common-lib": "4.x",
|
|
49
44
|
"dayjs": "1.x",
|
|
50
|
-
"react": "
|
|
45
|
+
"react": "18.x",
|
|
51
46
|
"react-i18next": "11.x",
|
|
52
|
-
"react-router-dom": "
|
|
47
|
+
"react-router-dom": "6.x",
|
|
53
48
|
"rxjs": "6.x"
|
|
54
49
|
},
|
|
55
|
-
"
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"webpack": "^5.74.0"
|
|
52
|
+
},
|
|
53
|
+
"gitHead": "860283e200996f87c42c23ca0d5d4f8abf060aab"
|
|
56
54
|
}
|
package/src/dashboard.meta.tsx
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { defineConfigSchema, getAsyncLifecycle, getSyncLifecycle } from '@openmrs/esm-framework';
|
|
2
2
|
import { createDashboardLink } from '@openmrs/esm-patient-common-lib';
|
|
3
|
+
import { configSchema } from './config-schema';
|
|
3
4
|
import { dashboardMeta } from './dashboard.meta';
|
|
4
5
|
|
|
6
|
+
declare var __VERSION__: string;
|
|
7
|
+
// __VERSION__ is replaced by Webpack with the version from package.json
|
|
8
|
+
const version = __VERSION__;
|
|
9
|
+
|
|
5
10
|
const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
|
|
6
11
|
|
|
7
12
|
const backendDependencies = {
|
|
@@ -16,7 +21,7 @@ function setupOpenMRS() {
|
|
|
16
21
|
moduleName,
|
|
17
22
|
};
|
|
18
23
|
|
|
19
|
-
defineConfigSchema(moduleName,
|
|
24
|
+
defineConfigSchema(moduleName, configSchema);
|
|
20
25
|
|
|
21
26
|
return {
|
|
22
27
|
extensions: [
|
|
@@ -48,11 +53,11 @@ function setupOpenMRS() {
|
|
|
48
53
|
name: 'programs-form-workspace',
|
|
49
54
|
load: getAsyncLifecycle(() => import('./programs/programs-form.component'), options),
|
|
50
55
|
meta: {
|
|
51
|
-
title: 'Record
|
|
56
|
+
title: 'Record program enrollment',
|
|
52
57
|
},
|
|
53
58
|
},
|
|
54
59
|
],
|
|
55
60
|
};
|
|
56
61
|
}
|
|
57
62
|
|
|
58
|
-
export { backendDependencies, importTranslation, setupOpenMRS };
|
|
63
|
+
export { backendDependencies, importTranslation, setupOpenMRS, version };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Button } from '@carbon/react';
|
|
4
|
+
import { TaskAdd } from '@carbon/react/icons';
|
|
5
|
+
import { formEntrySub, launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
6
|
+
import { ConfigurableProgram } from '../../types';
|
|
7
|
+
|
|
8
|
+
interface ProgramActionButton {
|
|
9
|
+
enrollment: ConfigurableProgram;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const ProgramActionButton: React.FC<ProgramActionButton> = ({ enrollment }) => {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const formUuid =
|
|
15
|
+
enrollment.enrollmentStatus === 'eligible' ? enrollment.enrollmentFormUuid : enrollment.discontinuationFormUuid;
|
|
16
|
+
const launchEnrollmentForm = (enrollmentStatus: string) => {
|
|
17
|
+
formEntrySub.next({ formUuid, encounterUuid: '' });
|
|
18
|
+
launchPatientWorkspace('patient-form-entry-workspace', {
|
|
19
|
+
workspaceTitle: `${enrollment?.display} ${enrollmentStatus} Form`,
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if (enrollment.enrollmentStatus === 'eligible') {
|
|
24
|
+
return (
|
|
25
|
+
<Button
|
|
26
|
+
iconDescription="Enroll to program"
|
|
27
|
+
onClick={() => launchEnrollmentForm(t('enrollment', 'Enrollment'))}
|
|
28
|
+
renderIcon={(props) => <TaskAdd size={20} {...props} />}
|
|
29
|
+
kind="tertiary"
|
|
30
|
+
size="sm"
|
|
31
|
+
>
|
|
32
|
+
{t('enroll', 'Enroll')}
|
|
33
|
+
</Button>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Button
|
|
39
|
+
iconDescription="Discontinue enrollment"
|
|
40
|
+
onClick={() => launchEnrollmentForm(t('discontinue', 'Discontinue'))}
|
|
41
|
+
renderIcon={(props) => <TaskAdd size={20} {...props} />}
|
|
42
|
+
kind="danger--ghost"
|
|
43
|
+
size="sm"
|
|
44
|
+
>
|
|
45
|
+
{t('discontinue', 'Discontinue')}
|
|
46
|
+
</Button>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default ProgramActionButton;
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import Add16 from '@carbon/icons-react/es/add/16';
|
|
3
|
-
import filter from 'lodash-es/filter';
|
|
4
|
-
import includes from 'lodash-es/includes';
|
|
5
|
-
import map from 'lodash-es/map';
|
|
6
|
-
import styles from './programs-detailed-summary.scss';
|
|
7
|
-
import { CardHeader, EmptyState, ErrorState, launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
8
2
|
import { useTranslation } from 'react-i18next';
|
|
9
|
-
import
|
|
3
|
+
import capitalize from 'lodash-es/capitalize';
|
|
10
4
|
import {
|
|
11
5
|
Button,
|
|
12
6
|
DataTable,
|
|
7
|
+
DataTableHeader,
|
|
8
|
+
DataTableRow,
|
|
13
9
|
DataTableSkeleton,
|
|
14
10
|
InlineLoading,
|
|
11
|
+
InlineNotification,
|
|
15
12
|
Table,
|
|
13
|
+
TableBody,
|
|
16
14
|
TableCell,
|
|
17
15
|
TableContainer,
|
|
18
|
-
TableBody,
|
|
19
16
|
TableHead,
|
|
20
17
|
TableHeader,
|
|
21
18
|
TableRow,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} from '
|
|
26
|
-
import {
|
|
19
|
+
} from '@carbon/react';
|
|
20
|
+
import { Add, Edit } from '@carbon/react/icons';
|
|
21
|
+
import { formatDate, formatDatetime, useConfig, usePagination, ConfigObject } from '@openmrs/esm-framework';
|
|
22
|
+
import { CardHeader, EmptyState, ErrorState, launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
23
|
+
import { useAvailablePrograms, useEnrollments, usePrograms } from './programs.resource';
|
|
24
|
+
import { ConfigurableProgram } from '../types';
|
|
25
|
+
import ProgramActionButton from './program-action-button/program-action-button.component';
|
|
26
|
+
import styles from './programs-detailed-summary.scss';
|
|
27
27
|
|
|
28
28
|
interface ProgramsDetailedSummaryProps {
|
|
29
29
|
patientUuid: string;
|
|
@@ -33,13 +33,18 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
33
33
|
const { t } = useTranslation();
|
|
34
34
|
const displayText = t('programEnrollments', 'Program enrollments');
|
|
35
35
|
const headerTitle = t('carePrograms', 'Care Programs');
|
|
36
|
+
const config = useConfig() as ConfigObject;
|
|
37
|
+
const programsCount = 5;
|
|
38
|
+
const isConfigurable = config.customUrl ? true : false;
|
|
36
39
|
|
|
37
|
-
const {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const { enrollments, isLoading, isError, isValidating, availablePrograms, eligiblePrograms, configurablePrograms } =
|
|
41
|
+
usePrograms(patientUuid);
|
|
42
|
+
|
|
43
|
+
const {
|
|
44
|
+
results: paginatedEnrollments,
|
|
45
|
+
goTo,
|
|
46
|
+
currentPage,
|
|
47
|
+
} = usePagination(isConfigurable ? configurablePrograms : enrollments ?? [], programsCount);
|
|
43
48
|
|
|
44
49
|
const tableHeaders: Array<DataTableHeader> = React.useMemo(
|
|
45
50
|
() => [
|
|
@@ -59,11 +64,15 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
59
64
|
key: 'status',
|
|
60
65
|
header: t('status', 'Status'),
|
|
61
66
|
},
|
|
67
|
+
{
|
|
68
|
+
key: 'actions',
|
|
69
|
+
header: t('actions', 'Actions'),
|
|
70
|
+
},
|
|
62
71
|
],
|
|
63
72
|
[t],
|
|
64
73
|
);
|
|
65
74
|
|
|
66
|
-
const tableRows
|
|
75
|
+
const tableRows = React.useMemo(() => {
|
|
67
76
|
return enrollments?.map((program) => {
|
|
68
77
|
return {
|
|
69
78
|
id: program.uuid,
|
|
@@ -73,6 +82,7 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
73
82
|
status: program.dateCompleted
|
|
74
83
|
? `${t('completedOn', 'Completed On')} ${formatDate(new Date(program.dateCompleted))}`
|
|
75
84
|
: t('active', 'Active'),
|
|
85
|
+
actions: <ProgramEditButton programEnrollmentId={program.uuid} />,
|
|
76
86
|
};
|
|
77
87
|
});
|
|
78
88
|
}, [enrollments, t]);
|
|
@@ -88,7 +98,7 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
88
98
|
<span>{isValidating ? <InlineLoading /> : null}</span>
|
|
89
99
|
<Button
|
|
90
100
|
kind="ghost"
|
|
91
|
-
renderIcon={
|
|
101
|
+
renderIcon={(props) => <Add size={16} {...props} />}
|
|
92
102
|
iconDescription="Add programs"
|
|
93
103
|
onClick={launchProgramsForm}
|
|
94
104
|
disabled={availablePrograms?.length && eligiblePrograms?.length === 0}
|
|
@@ -96,19 +106,19 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
96
106
|
{t('add', 'Add')}
|
|
97
107
|
</Button>
|
|
98
108
|
</CardHeader>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
<Table {...getTableProps()}
|
|
109
|
+
{availablePrograms?.length && eligiblePrograms?.length === 0 ? (
|
|
110
|
+
<InlineNotification
|
|
111
|
+
style={{ minWidth: '100%', margin: '0rem', padding: '0rem' }}
|
|
112
|
+
kind={'info'}
|
|
113
|
+
lowContrast
|
|
114
|
+
subtitle={t('noEligibleEnrollments', 'There are no more programs left to enroll this patient in')}
|
|
115
|
+
title={t('fullyEnrolled', 'Enrolled in all programs')}
|
|
116
|
+
/>
|
|
117
|
+
) : null}
|
|
118
|
+
<DataTable rows={tableRows} headers={tableHeaders} isSortable size="xs" useZebraStyles>
|
|
119
|
+
{({ rows, headers, getHeaderProps, getTableProps }) => (
|
|
120
|
+
<TableContainer>
|
|
121
|
+
<Table {...getTableProps()}>
|
|
112
122
|
<TableHead>
|
|
113
123
|
<TableRow>
|
|
114
124
|
{headers.map((header) => (
|
|
@@ -134,13 +144,34 @@ const ProgramsDetailedSummary: React.FC<ProgramsDetailedSummaryProps> = ({ patie
|
|
|
134
144
|
))}
|
|
135
145
|
</TableBody>
|
|
136
146
|
</Table>
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
</
|
|
147
|
+
</TableContainer>
|
|
148
|
+
)}
|
|
149
|
+
</DataTable>
|
|
140
150
|
</div>
|
|
141
151
|
);
|
|
142
152
|
}
|
|
143
153
|
return <EmptyState displayText={displayText} headerTitle={headerTitle} launchForm={launchProgramsForm} />;
|
|
144
154
|
};
|
|
145
155
|
|
|
156
|
+
interface ProgramEditButtonProps {
|
|
157
|
+
programEnrollmentId: string;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function ProgramEditButton({ programEnrollmentId }: ProgramEditButtonProps) {
|
|
161
|
+
const launchEditProgramsForm = React.useCallback(
|
|
162
|
+
() => launchPatientWorkspace('programs-form-workspace', { programEnrollmentId }),
|
|
163
|
+
[programEnrollmentId],
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
return (
|
|
167
|
+
<Button
|
|
168
|
+
kind="ghost"
|
|
169
|
+
renderIcon={(props) => <Edit size={16} {...props} />}
|
|
170
|
+
iconDescription="Edit Program"
|
|
171
|
+
onClick={launchEditProgramsForm}
|
|
172
|
+
hasIconOnly
|
|
173
|
+
/>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
146
177
|
export default ProgramsDetailedSummary;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { screen } from '@testing-library/react';
|
|
2
|
+
import { screen, within, waitFor } from '@testing-library/react';
|
|
3
3
|
import userEvent from '@testing-library/user-event';
|
|
4
4
|
import { openmrsFetch, usePagination } from '@openmrs/esm-framework';
|
|
5
|
+
import { launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
6
|
+
import { mockPatient } from '../../../../__mocks__/patient.mock';
|
|
5
7
|
import { mockEnrolledProgramsResponse } from '../../../../__mocks__/programs.mock';
|
|
6
8
|
import { renderWithSwr, waitForLoadingToFinish } from '../../../../tools/test-helpers';
|
|
7
|
-
import { launchPatientWorkspace } from '@openmrs/esm-patient-common-lib';
|
|
8
9
|
import ProgramsDetailedSummary from './programs-detailed-summary.component';
|
|
9
10
|
|
|
11
|
+
jest.setTimeout(20000);
|
|
12
|
+
|
|
10
13
|
const mockOpenmrsFetch = openmrsFetch as jest.Mock;
|
|
11
14
|
const mockUsePagination = usePagination as jest.Mock;
|
|
12
15
|
|
|
@@ -70,6 +73,8 @@ describe('ProgramsDetailedSummary ', () => {
|
|
|
70
73
|
});
|
|
71
74
|
|
|
72
75
|
it("renders a detailed tabular summary of the patient's program enrollments", async () => {
|
|
76
|
+
const user = userEvent.setup();
|
|
77
|
+
|
|
73
78
|
mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockEnrolledProgramsResponse } });
|
|
74
79
|
mockUsePagination.mockImplementation(() => ({
|
|
75
80
|
currentPage: 1,
|
|
@@ -89,16 +94,30 @@ describe('ProgramsDetailedSummary ', () => {
|
|
|
89
94
|
|
|
90
95
|
const addButton = screen.getByRole('button', { name: /Add/ });
|
|
91
96
|
expect(addButton).toBeInTheDocument();
|
|
92
|
-
|
|
93
|
-
expect(
|
|
94
|
-
expect(
|
|
97
|
+
const row = screen.getByRole('row', { name: /hiv care and treatment/i });
|
|
98
|
+
expect(row).toBeInTheDocument();
|
|
99
|
+
expect(within(row).getByRole('cell', { name: /16-Jan-2020/i })).toBeInTheDocument();
|
|
100
|
+
expect(within(row).getByRole('cell', { name: /active$/i })).toBeInTheDocument();
|
|
101
|
+
const editButton = within(row).getByRole('button', { name: /Edit Program$/i });
|
|
102
|
+
expect(editButton).toBeInTheDocument();
|
|
95
103
|
|
|
96
104
|
// Clicking "Add" launches the programs form in a workspace
|
|
97
|
-
|
|
105
|
+
await waitFor(() => user.click(addButton));
|
|
106
|
+
|
|
98
107
|
expect(launchPatientWorkspace).toHaveBeenCalledWith('programs-form-workspace');
|
|
108
|
+
|
|
109
|
+
// Clicking the edit button launches the edit form in a workspace
|
|
110
|
+
await waitFor(() => user.click(editButton));
|
|
111
|
+
|
|
112
|
+
expect(launchPatientWorkspace).toHaveBeenCalledWith('programs-form-workspace', {
|
|
113
|
+
programEnrollmentId: mockEnrolledProgramsResponse[0].uuid,
|
|
114
|
+
});
|
|
99
115
|
});
|
|
100
116
|
});
|
|
101
117
|
|
|
102
118
|
function renderProgramsOverview() {
|
|
103
|
-
|
|
119
|
+
const testProps = {
|
|
120
|
+
patientUuid: mockPatient.id,
|
|
121
|
+
};
|
|
122
|
+
renderWithSwr(<ProgramsDetailedSummary {...testProps} />);
|
|
104
123
|
}
|