@openmrs/esm-fast-data-entry-app 1.0.1-pre.171 → 1.0.1-pre.180
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/__mocks__/react-i18next.js +9 -14
- package/dist/101.js +1 -1
- package/dist/101.js.map +1 -1
- package/dist/188.js.map +1 -1
- package/dist/219.js.map +1 -1
- package/dist/29.js +1 -1
- package/dist/29.js.map +1 -1
- package/dist/326.js.map +1 -1
- package/dist/564.js +1 -1
- package/dist/564.js.map +1 -1
- package/dist/893.js +1 -0
- package/dist/893.js.map +1 -0
- package/dist/91.js +1 -1
- package/dist/91.js.map +1 -1
- package/dist/941.js +2 -0
- package/dist/941.js.map +1 -0
- package/dist/99.js.map +1 -1
- package/dist/991.js +1 -0
- package/dist/991.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
- package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +105 -105
- package/dist/openmrs-esm-fast-data-entry-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +2 -4
- package/prettier.config.js +8 -0
- package/src/CancelModal.tsx +9 -15
- package/src/CompleteModal.tsx +7 -18
- package/src/FormBootstrap.tsx +9 -9
- package/src/Root.tsx +7 -12
- package/src/add-group-modal/AddGroupModal.tsx +46 -109
- package/src/config-schema.ts +35 -36
- package/src/constant.ts +1 -1
- package/src/context/FormWorkflowContext.tsx +26 -39
- package/src/context/FormWorkflowReducer.ts +50 -74
- package/src/context/GroupFormWorkflowContext.tsx +36 -61
- package/src/context/GroupFormWorkflowReducer.ts +69 -105
- package/src/declarations.d.ts +3 -3
- package/src/empty-state/EmptyDataIllustration.tsx +4 -16
- package/src/empty-state/EmptyState.tsx +8 -13
- package/src/form-entry-workflow/FormEntryWorkflow.tsx +26 -44
- package/src/form-entry-workflow/form-review-card/FormReviewCard.tsx +7 -7
- package/src/form-entry-workflow/form-review-card/index.ts +1 -1
- package/src/form-entry-workflow/index.ts +1 -1
- package/src/form-entry-workflow/patient-banner/PatientBanner.test.tsx +5 -5
- package/src/form-entry-workflow/patient-banner/PatientBanner.tsx +14 -27
- package/src/form-entry-workflow/patient-banner/index.ts +1 -1
- package/src/form-entry-workflow/patient-search-header/PatientSearchHeader.tsx +17 -26
- package/src/form-entry-workflow/patient-search-header/index.ts +1 -1
- package/src/form-entry-workflow/workflow-review/WorkflowReview.tsx +12 -12
- package/src/form-entry-workflow/workflow-review/index.ts +1 -1
- package/src/forms-app-menu-link.tsx +4 -6
- package/src/forms-page/FormsPage.tsx +22 -50
- package/src/forms-page/forms-table/FormsTable.tsx +22 -42
- package/src/forms-page/forms-table/index.ts +1 -1
- package/src/forms-page/index.ts +1 -1
- package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +8 -8
- package/src/group-form-entry-workflow/GroupSessionWorkspace.tsx +27 -58
- package/src/group-form-entry-workflow/SessionDetailsForm.tsx +43 -66
- package/src/group-form-entry-workflow/SessionMetaWorkspace.tsx +20 -28
- package/src/group-form-entry-workflow/attendance-table/AttendanceTable.tsx +13 -27
- package/src/group-form-entry-workflow/attendance-table/index.ts +1 -1
- package/src/group-form-entry-workflow/configurable-questions/ConfigurableQuestionsSection.tsx +6 -12
- package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.test.tsx +5 -5
- package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +13 -21
- package/src/group-form-entry-workflow/group-display-header/index.ts +1 -1
- package/src/group-form-entry-workflow/group-search/CompactGroupResults.tsx +24 -35
- package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +13 -15
- package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +22 -38
- package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +18 -25
- package/src/group-form-entry-workflow/group-search-header/index.ts +1 -1
- package/src/group-form-entry-workflow/index.ts +1 -1
- package/src/hooks/index.ts +7 -13
- package/src/hooks/useForm.ts +13 -30
- package/src/hooks/useFormState.ts +3 -3
- package/src/hooks/useGetAllForms.ts +5 -14
- package/src/hooks/useGetEncounter.ts +2 -2
- package/src/hooks/useGetPatient.ts +2 -2
- package/src/hooks/useGetPatients.ts +4 -6
- package/src/hooks/useGetSystemSetting.ts +3 -5
- package/src/hooks/useKeyPress.ts +5 -5
- package/src/hooks/usePostEndpoint.ts +8 -8
- package/src/hooks/useSearchEndpoint.ts +15 -38
- package/src/hooks/useStartVisit.ts +16 -27
- package/src/index.ts +8 -20
- package/src/patient-card/PatientCard.tsx +8 -20
- package/src/patient-card/index.ts +1 -1
- package/src/setup-tests.ts +1 -1
- package/tools/i18next-parser.config.js +19 -19
- package/webpack.config.js +1 -1
- package/dist/143.js +0 -1
- package/dist/143.js.map +0 -1
- package/dist/31.js +0 -2
- package/dist/31.js.map +0 -1
- package/dist/491.js +0 -1
- package/dist/491.js.map +0 -1
- /package/dist/{31.js.LICENSE.txt → 941.js.LICENSE.txt} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { render } from
|
|
3
|
-
import PatientBanner from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import PatientBanner from './PatientBanner';
|
|
4
4
|
|
|
5
|
-
describe(
|
|
6
|
-
it(
|
|
5
|
+
describe('PatientBanner', () => {
|
|
6
|
+
it('renders placeholder information when no data is present', () => {
|
|
7
7
|
render(<PatientBanner />);
|
|
8
8
|
});
|
|
9
9
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { age, ExtensionSlot } from
|
|
2
|
-
import { SkeletonPlaceholder, SkeletonText } from
|
|
3
|
-
import React, { useContext } from
|
|
4
|
-
import styles from
|
|
5
|
-
import { useTranslation } from
|
|
6
|
-
import useGetPatient from
|
|
7
|
-
import FormWorkflowContext from
|
|
1
|
+
import { age, ExtensionSlot } from '@openmrs/esm-framework';
|
|
2
|
+
import { SkeletonPlaceholder, SkeletonText } from '@carbon/react';
|
|
3
|
+
import React, { useContext } from 'react';
|
|
4
|
+
import styles from './styles.scss';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import useGetPatient from '../../hooks/useGetPatient';
|
|
7
|
+
import FormWorkflowContext from '../../context/FormWorkflowContext';
|
|
8
8
|
|
|
9
9
|
const SkeletonPatientInfo = () => {
|
|
10
10
|
return (
|
|
@@ -36,16 +36,14 @@ const PatientBanner = () => {
|
|
|
36
36
|
const { activePatientUuid, workflowState } = useContext(FormWorkflowContext);
|
|
37
37
|
const patient = useGetPatient(activePatientUuid);
|
|
38
38
|
const { t } = useTranslation();
|
|
39
|
-
const patientName = `${patient?.name?.[0].given?.join(
|
|
40
|
-
patient?.name?.[0]?.family
|
|
41
|
-
}`;
|
|
39
|
+
const patientName = `${patient?.name?.[0].given?.join(' ')} ${patient?.name?.[0]?.family}`;
|
|
42
40
|
|
|
43
41
|
const patientPhotoSlotState = React.useMemo(
|
|
44
|
-
() => ({ patientUuid: patient?.id, patientName, size:
|
|
45
|
-
[patient?.id, patientName]
|
|
42
|
+
() => ({ patientUuid: patient?.id, patientName, size: 'small' }),
|
|
43
|
+
[patient?.id, patientName],
|
|
46
44
|
);
|
|
47
45
|
|
|
48
|
-
if (workflowState ===
|
|
46
|
+
if (workflowState === 'NEW_PATIENT') return null;
|
|
49
47
|
|
|
50
48
|
if (!patient) {
|
|
51
49
|
return <SkeletonPatientInfo />;
|
|
@@ -53,29 +51,18 @@ const PatientBanner = () => {
|
|
|
53
51
|
|
|
54
52
|
return (
|
|
55
53
|
<div className={styles.container}>
|
|
56
|
-
<ExtensionSlot
|
|
57
|
-
extensionSlotName="patient-photo-slot"
|
|
58
|
-
state={patientPhotoSlotState}
|
|
59
|
-
/>
|
|
54
|
+
<ExtensionSlot extensionSlotName="patient-photo-slot" state={patientPhotoSlotState} />
|
|
60
55
|
<div className={styles.patientInfoContent}>
|
|
61
56
|
<div className={styles.patientInfoRow}>
|
|
62
57
|
<span className={styles.patientName}>{patientName}</span>
|
|
63
58
|
</div>
|
|
64
59
|
<div className={styles.patientInfoRow}>
|
|
65
|
-
<span>
|
|
66
|
-
{(patient.gender ?? t("unknown", "Unknown")).replace(/^\w/, (c) =>
|
|
67
|
-
c.toUpperCase()
|
|
68
|
-
)}
|
|
69
|
-
</span>
|
|
60
|
+
<span>{(patient.gender ?? t('unknown', 'Unknown')).replace(/^\w/, (c) => c.toUpperCase())}</span>
|
|
70
61
|
<span>·</span>
|
|
71
62
|
<span>{age(patient.birthDate)}</span>
|
|
72
63
|
<span>·</span>
|
|
73
64
|
<span>
|
|
74
|
-
{patient.identifier.length
|
|
75
|
-
? patient.identifier
|
|
76
|
-
.map((identifier) => identifier.value)
|
|
77
|
-
.join(", ")
|
|
78
|
-
: "--"}
|
|
65
|
+
{patient.identifier.length ? patient.identifier.map((identifier) => identifier.value).join(', ') : '--'}
|
|
79
66
|
</span>
|
|
80
67
|
</div>
|
|
81
68
|
</div>
|
|
@@ -1,58 +1,49 @@
|
|
|
1
|
-
import { Add, Close } from
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import { Link } from "react-router-dom";
|
|
10
|
-
import FormWorkflowContext from "../../context/FormWorkflowContext";
|
|
11
|
-
import styles from "./styles.scss";
|
|
12
|
-
import { useTranslation } from "react-i18next";
|
|
1
|
+
import { Add, Close } from '@carbon/react/icons';
|
|
2
|
+
import { ExtensionSlot, interpolateUrl, navigate } from '@openmrs/esm-framework';
|
|
3
|
+
import { Button } from '@carbon/react';
|
|
4
|
+
import React, { useContext } from 'react';
|
|
5
|
+
import { Link } from 'react-router-dom';
|
|
6
|
+
import FormWorkflowContext from '../../context/FormWorkflowContext';
|
|
7
|
+
import styles from './styles.scss';
|
|
8
|
+
import { useTranslation } from 'react-i18next';
|
|
13
9
|
|
|
14
10
|
const PatientSearchHeader = () => {
|
|
15
|
-
const { addPatient, workflowState, activeFormUuid } =
|
|
16
|
-
useContext(FormWorkflowContext);
|
|
11
|
+
const { addPatient, workflowState, activeFormUuid } = useContext(FormWorkflowContext);
|
|
17
12
|
const handleSelectPatient = (patient) => {
|
|
18
13
|
addPatient(patient);
|
|
19
14
|
};
|
|
20
15
|
const { t } = useTranslation();
|
|
21
16
|
|
|
22
|
-
if (workflowState !==
|
|
17
|
+
if (workflowState !== 'NEW_PATIENT') return null;
|
|
23
18
|
|
|
24
|
-
const afterUrl = encodeURIComponent(
|
|
25
|
-
|
|
26
|
-
);
|
|
27
|
-
const patientRegistrationUrl = interpolateUrl(
|
|
28
|
-
`\${openmrsSpaBase}/patient-registration?afterUrl=${afterUrl}`
|
|
29
|
-
);
|
|
19
|
+
const afterUrl = encodeURIComponent(`\${openmrsSpaBase}/forms/form/${activeFormUuid}?patientUuid=\${patientUuid}`);
|
|
20
|
+
const patientRegistrationUrl = interpolateUrl(`\${openmrsSpaBase}/patient-registration?afterUrl=${afterUrl}`);
|
|
30
21
|
|
|
31
22
|
return (
|
|
32
23
|
<div className={styles.searchHeaderContainer}>
|
|
33
|
-
<span className={styles.padded}>{t(
|
|
24
|
+
<span className={styles.padded}>{t('nextPatient', 'Next patient')}:</span>
|
|
34
25
|
<span className={styles.searchBarWrapper}>
|
|
35
26
|
<ExtensionSlot
|
|
36
27
|
name="patient-search-bar-slot"
|
|
37
28
|
state={{
|
|
38
29
|
selectPatientAction: handleSelectPatient,
|
|
39
30
|
buttonProps: {
|
|
40
|
-
kind:
|
|
31
|
+
kind: 'primary',
|
|
41
32
|
},
|
|
42
33
|
}}
|
|
43
34
|
/>
|
|
44
35
|
</span>
|
|
45
|
-
<span className={styles.padded}>{t(
|
|
36
|
+
<span className={styles.padded}>{t('or', 'or')}</span>
|
|
46
37
|
<span>
|
|
47
38
|
<Button onClick={() => navigate({ to: patientRegistrationUrl })}>
|
|
48
|
-
{t(
|
|
39
|
+
{t('createNewPatient', 'Create new patient')} <Add size={20} />
|
|
49
40
|
</Button>
|
|
50
41
|
</span>
|
|
51
42
|
<span style={{ flexGrow: 1 }} />
|
|
52
43
|
<span>
|
|
53
44
|
<Link to="../">
|
|
54
45
|
<Button kind="ghost">
|
|
55
|
-
{t(
|
|
46
|
+
{t('cancel', 'Cancel')} <Close size={20} />
|
|
56
47
|
</Button>
|
|
57
48
|
</Link>
|
|
58
49
|
</span>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Button } from
|
|
2
|
-
import React, { useContext } from
|
|
3
|
-
import { useNavigate } from
|
|
4
|
-
import FormWorkflowContext from
|
|
5
|
-
import FormReviewCard from
|
|
6
|
-
import styles from
|
|
7
|
-
import { useTranslation } from
|
|
1
|
+
import { Button } from '@carbon/react';
|
|
2
|
+
import React, { useContext } from 'react';
|
|
3
|
+
import { useNavigate } from 'react-router-dom';
|
|
4
|
+
import FormWorkflowContext from '../../context/FormWorkflowContext';
|
|
5
|
+
import FormReviewCard from '../form-review-card';
|
|
6
|
+
import styles from './styles.scss';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
8
|
|
|
9
9
|
const WorkflowReview = () => {
|
|
10
10
|
const { patientUuids } = useContext(FormWorkflowContext);
|
|
@@ -14,13 +14,13 @@ const WorkflowReview = () => {
|
|
|
14
14
|
<div className={styles.workspaceWrapper}>
|
|
15
15
|
<div className={styles.workspace}>
|
|
16
16
|
<div className={styles.leftPanel}>
|
|
17
|
-
<h4>{t(
|
|
17
|
+
<h4>{t('review', 'Review')}</h4>
|
|
18
18
|
<div className={styles.navButtons}>
|
|
19
|
-
<Button kind="primary" onClick={() => navigate(
|
|
20
|
-
{t(
|
|
19
|
+
<Button kind="primary" onClick={() => navigate('/')}>
|
|
20
|
+
{t('save&close', 'Save & Close')}
|
|
21
21
|
</Button>
|
|
22
|
-
<Button kind="tertiary" onClick={() => navigate(
|
|
23
|
-
{t(
|
|
22
|
+
<Button kind="tertiary" onClick={() => navigate('/')}>
|
|
23
|
+
{t('cancel', 'Cancel')}
|
|
24
24
|
</Button>
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import { useTranslation } from
|
|
3
|
-
import { ConfigurableLink } from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { ConfigurableLink } from '@openmrs/esm-framework';
|
|
4
4
|
|
|
5
5
|
export default function FormsAppMenuLink() {
|
|
6
6
|
const { t } = useTranslation();
|
|
7
7
|
return (
|
|
8
8
|
// eslint-disable-next-line
|
|
9
|
-
<ConfigurableLink to="${openmrsSpaBase}/forms">
|
|
10
|
-
{t("formsAppMenuLink", "Fast Data Entry")}
|
|
11
|
-
</ConfigurableLink>
|
|
9
|
+
<ConfigurableLink to="${openmrsSpaBase}/forms">{t('formsAppMenuLink', 'Fast Data Entry')}</ConfigurableLink>
|
|
12
10
|
);
|
|
13
11
|
}
|
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
import { useConfig, useSession } from
|
|
2
|
-
import { Tab, Tabs, TabList, TabPanels, TabPanel } from
|
|
3
|
-
import React from
|
|
4
|
-
import { type Config } from
|
|
5
|
-
import { useGetAllForms } from
|
|
6
|
-
import FormsTable from
|
|
7
|
-
import styles from
|
|
8
|
-
import { useTranslation } from
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
fdeWorkflowStorageVersion,
|
|
12
|
-
} from "../context/FormWorkflowReducer";
|
|
13
|
-
import {
|
|
14
|
-
fdeGroupWorkflowStorageName,
|
|
15
|
-
fdeGroupWorkflowStorageVersion,
|
|
16
|
-
} from "../context/GroupFormWorkflowReducer";
|
|
1
|
+
import { useConfig, useSession } from '@openmrs/esm-framework';
|
|
2
|
+
import { Tab, Tabs, TabList, TabPanels, TabPanel } from '@carbon/react';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { type Config } from '../config-schema';
|
|
5
|
+
import { useGetAllForms } from '../hooks';
|
|
6
|
+
import FormsTable from './forms-table';
|
|
7
|
+
import styles from './styles.scss';
|
|
8
|
+
import { useTranslation } from 'react-i18next';
|
|
9
|
+
import { fdeWorkflowStorageName, fdeWorkflowStorageVersion } from '../context/FormWorkflowReducer';
|
|
10
|
+
import { fdeGroupWorkflowStorageName, fdeGroupWorkflowStorageVersion } from '../context/GroupFormWorkflowReducer';
|
|
17
11
|
|
|
18
12
|
// helper function useful for debugging
|
|
19
13
|
// given a list of forms, it will organize into permissions
|
|
@@ -25,7 +19,7 @@ export const getFormPermissions = (forms) => {
|
|
|
25
19
|
(output[form.encounterType.editPrivilege.display] = [
|
|
26
20
|
...(output[form.encounterType.editPrivilege.display] || []),
|
|
27
21
|
form.display,
|
|
28
|
-
])
|
|
22
|
+
]),
|
|
29
23
|
);
|
|
30
24
|
return output;
|
|
31
25
|
};
|
|
@@ -50,35 +44,23 @@ const FormsPage = () => {
|
|
|
50
44
|
const { forms, isLoading, error } = useGetAllForms();
|
|
51
45
|
const cleanRows = prepareRowsForTable(forms);
|
|
52
46
|
const { user } = useSession();
|
|
53
|
-
const savedFormsData = localStorage.getItem(
|
|
54
|
-
|
|
55
|
-
);
|
|
56
|
-
const savedGroupFormsData = localStorage.getItem(
|
|
57
|
-
fdeGroupWorkflowStorageName + ":" + user?.uuid
|
|
58
|
-
);
|
|
47
|
+
const savedFormsData = localStorage.getItem(fdeWorkflowStorageName + ':' + user?.uuid);
|
|
48
|
+
const savedGroupFormsData = localStorage.getItem(fdeGroupWorkflowStorageName + ':' + user?.uuid);
|
|
59
49
|
const activeForms = [];
|
|
60
50
|
const activeGroupForms = [];
|
|
61
51
|
|
|
62
|
-
if (
|
|
63
|
-
savedFormsData &&
|
|
64
|
-
JSON.parse(savedFormsData)?.["_storageVersion"] ===
|
|
65
|
-
fdeWorkflowStorageVersion
|
|
66
|
-
) {
|
|
52
|
+
if (savedFormsData && JSON.parse(savedFormsData)?.['_storageVersion'] === fdeWorkflowStorageVersion) {
|
|
67
53
|
Object.entries(JSON.parse(savedFormsData).forms).forEach(
|
|
68
54
|
([formUuid, form]: [string, { [key: string]: unknown }]) => {
|
|
69
55
|
if (form.workflowState) activeForms.push(formUuid);
|
|
70
|
-
}
|
|
56
|
+
},
|
|
71
57
|
);
|
|
72
58
|
}
|
|
73
|
-
if (
|
|
74
|
-
savedGroupFormsData &&
|
|
75
|
-
JSON.parse(savedGroupFormsData)?.["_storageVersion"] ===
|
|
76
|
-
fdeGroupWorkflowStorageVersion
|
|
77
|
-
) {
|
|
59
|
+
if (savedGroupFormsData && JSON.parse(savedGroupFormsData)?.['_storageVersion'] === fdeGroupWorkflowStorageVersion) {
|
|
78
60
|
Object.entries(JSON.parse(savedGroupFormsData).forms).forEach(
|
|
79
61
|
([formUuid, form]: [string, { [key: string]: unknown }]) => {
|
|
80
62
|
if (form.workflowState) activeGroupForms.push(formUuid);
|
|
81
|
-
}
|
|
63
|
+
},
|
|
82
64
|
);
|
|
83
65
|
}
|
|
84
66
|
|
|
@@ -94,15 +76,11 @@ const FormsPage = () => {
|
|
|
94
76
|
|
|
95
77
|
return (
|
|
96
78
|
<div className={styles.mainContent}>
|
|
97
|
-
<h3 className={styles.pageTitle}>
|
|
98
|
-
{t("fastDataEntry", "Fast Data Entry")}
|
|
99
|
-
</h3>
|
|
79
|
+
<h3 className={styles.pageTitle}>{t('fastDataEntry', 'Fast Data Entry')}</h3>
|
|
100
80
|
<Tabs>
|
|
101
81
|
<TabList>
|
|
102
|
-
<Tab label={t(
|
|
103
|
-
{`${t(
|
|
104
|
-
cleanRows ? cleanRows?.length : "??"
|
|
105
|
-
})`}
|
|
82
|
+
<Tab label={t('allForms', 'All Forms')}>
|
|
83
|
+
{`${t('allForms', 'All Forms')} (${cleanRows ? cleanRows?.length : '??'})`}
|
|
106
84
|
</Tab>
|
|
107
85
|
{categoryRows?.map((category, index) => (
|
|
108
86
|
<Tab label={category.name} key={index}>
|
|
@@ -112,17 +90,11 @@ const FormsPage = () => {
|
|
|
112
90
|
</TabList>
|
|
113
91
|
<TabPanels>
|
|
114
92
|
<TabPanel>
|
|
115
|
-
<FormsTable
|
|
116
|
-
rows={cleanRows}
|
|
117
|
-
{...{ error, isLoading, activeForms, activeGroupForms }}
|
|
118
|
-
/>
|
|
93
|
+
<FormsTable rows={cleanRows} {...{ error, isLoading, activeForms, activeGroupForms }} />
|
|
119
94
|
</TabPanel>
|
|
120
95
|
{categoryRows?.map((category, index) => (
|
|
121
96
|
<TabPanel key={index}>
|
|
122
|
-
<FormsTable
|
|
123
|
-
rows={category.rows}
|
|
124
|
-
{...{ error, isLoading, activeForms, activeGroupForms }}
|
|
125
|
-
/>
|
|
97
|
+
<FormsTable rows={category.rows} {...{ error, isLoading, activeForms, activeGroupForms }} />
|
|
126
98
|
</TabPanel>
|
|
127
99
|
))}
|
|
128
100
|
</TabPanels>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ErrorState } from
|
|
1
|
+
import { ErrorState } from '@openmrs/esm-framework';
|
|
2
2
|
import {
|
|
3
3
|
DataTable,
|
|
4
4
|
DataTableSkeleton,
|
|
@@ -12,35 +12,29 @@ import {
|
|
|
12
12
|
TableToolbar,
|
|
13
13
|
TableToolbarContent,
|
|
14
14
|
TableToolbarSearch,
|
|
15
|
-
} from
|
|
16
|
-
import React from
|
|
17
|
-
import { useTranslation } from
|
|
18
|
-
import { Link } from
|
|
19
|
-
import EmptyState from
|
|
20
|
-
import styles from
|
|
15
|
+
} from '@carbon/react';
|
|
16
|
+
import React from 'react';
|
|
17
|
+
import { useTranslation } from 'react-i18next';
|
|
18
|
+
import { Link } from 'react-router-dom';
|
|
19
|
+
import EmptyState from '../../empty-state/EmptyState';
|
|
20
|
+
import styles from './styles.scss';
|
|
21
21
|
|
|
22
|
-
const FormsTable = ({
|
|
23
|
-
rows,
|
|
24
|
-
error,
|
|
25
|
-
isLoading,
|
|
26
|
-
activeForms,
|
|
27
|
-
activeGroupForms,
|
|
28
|
-
}) => {
|
|
22
|
+
const FormsTable = ({ rows, error, isLoading, activeForms, activeGroupForms }) => {
|
|
29
23
|
const { t } = useTranslation();
|
|
30
24
|
|
|
31
25
|
const tableHeaders = [
|
|
32
26
|
{
|
|
33
|
-
key:
|
|
34
|
-
header: t(
|
|
27
|
+
key: 'display',
|
|
28
|
+
header: t('formName', 'Form Name'),
|
|
35
29
|
isSortable: true,
|
|
36
30
|
},
|
|
37
31
|
{
|
|
38
|
-
key:
|
|
39
|
-
header: t(
|
|
32
|
+
key: 'actions',
|
|
33
|
+
header: t('actions', 'Actions'),
|
|
40
34
|
},
|
|
41
35
|
{
|
|
42
|
-
key:
|
|
43
|
-
header:
|
|
36
|
+
key: 'actions2',
|
|
37
|
+
header: '',
|
|
44
38
|
},
|
|
45
39
|
];
|
|
46
40
|
|
|
@@ -48,50 +42,36 @@ const FormsTable = ({
|
|
|
48
42
|
...row,
|
|
49
43
|
actions: (
|
|
50
44
|
<Link to={`form/${row.uuid}`}>
|
|
51
|
-
{activeForms.includes(row.uuid)
|
|
52
|
-
? t("resumeSession", "Resume Session")
|
|
53
|
-
: t("fillForm", "Fill Form")}
|
|
45
|
+
{activeForms.includes(row.uuid) ? t('resumeSession', 'Resume Session') : t('fillForm', 'Fill Form')}
|
|
54
46
|
</Link>
|
|
55
47
|
),
|
|
56
48
|
actions2: (
|
|
57
49
|
<Link to={`groupform/${row.uuid}`}>
|
|
58
50
|
{activeGroupForms.includes(row.uuid)
|
|
59
|
-
? t(
|
|
60
|
-
: t(
|
|
51
|
+
? t('resumeGroupSession', 'Resume Group Session')
|
|
52
|
+
: t('startGroupSession', 'Start Group Session')}
|
|
61
53
|
</Link>
|
|
62
54
|
),
|
|
63
55
|
}));
|
|
64
56
|
|
|
65
57
|
if (isLoading) return <DataTableSkeleton />;
|
|
66
58
|
if (error) {
|
|
67
|
-
return (
|
|
68
|
-
<ErrorState
|
|
69
|
-
headerTitle={t("errorLoadingData", "Error Loading Data")}
|
|
70
|
-
error={error}
|
|
71
|
-
/>
|
|
72
|
-
);
|
|
59
|
+
return <ErrorState headerTitle={t('errorLoadingData', 'Error Loading Data')} error={error} />;
|
|
73
60
|
}
|
|
74
61
|
if (augmentedRows.length === 0) {
|
|
75
62
|
return (
|
|
76
63
|
<EmptyState
|
|
77
|
-
headerTitle={t(
|
|
64
|
+
headerTitle={t('noFormsFound', 'No Forms To Show')}
|
|
78
65
|
displayText={t(
|
|
79
|
-
|
|
80
|
-
|
|
66
|
+
'noFormsFoundMessage',
|
|
67
|
+
'No forms could be found for this category. Please double check the form concept uuids and access permissions.',
|
|
81
68
|
)}
|
|
82
69
|
/>
|
|
83
70
|
);
|
|
84
71
|
}
|
|
85
72
|
return (
|
|
86
73
|
<DataTable rows={augmentedRows} headers={tableHeaders}>
|
|
87
|
-
{({
|
|
88
|
-
rows,
|
|
89
|
-
headers,
|
|
90
|
-
getTableProps,
|
|
91
|
-
getHeaderProps,
|
|
92
|
-
getRowProps,
|
|
93
|
-
onInputChange,
|
|
94
|
-
}) => {
|
|
74
|
+
{({ rows, headers, getTableProps, getHeaderProps, getRowProps, onInputChange }) => {
|
|
95
75
|
return (
|
|
96
76
|
<TableContainer>
|
|
97
77
|
<div className={styles.toolbarWrapper}>
|
package/src/forms-page/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ExtensionSlot } from
|
|
2
|
-
import React from
|
|
3
|
-
import GroupDisplayHeader from
|
|
4
|
-
import styles from
|
|
5
|
-
import { GroupFormWorkflowProvider } from
|
|
6
|
-
import GroupSearchHeader from
|
|
7
|
-
import SessionMetaWorkspace from
|
|
8
|
-
import GroupSessionWorkspace from
|
|
1
|
+
import { ExtensionSlot } from '@openmrs/esm-framework';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import GroupDisplayHeader from './group-display-header';
|
|
4
|
+
import styles from './styles.scss';
|
|
5
|
+
import { GroupFormWorkflowProvider } from '../context/GroupFormWorkflowContext';
|
|
6
|
+
import GroupSearchHeader from './group-search-header';
|
|
7
|
+
import SessionMetaWorkspace from './SessionMetaWorkspace';
|
|
8
|
+
import GroupSessionWorkspace from './GroupSessionWorkspace';
|
|
9
9
|
|
|
10
10
|
const GroupFormEntryWorkflow = () => {
|
|
11
11
|
return (
|
|
@@ -1,48 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import { v4 as uuid } from "uuid";
|
|
13
|
-
import GroupFormWorkflowContext from "../context/GroupFormWorkflowContext";
|
|
14
|
-
import FormBootstrap from "../FormBootstrap";
|
|
15
|
-
import CompleteModal from "../CompleteModal";
|
|
16
|
-
import CancelModal from "../CancelModal";
|
|
1
|
+
import { getGlobalStore, useConfig, useSession, useStore } from '@openmrs/esm-framework';
|
|
2
|
+
import { Button } from '@carbon/react';
|
|
3
|
+
import React, { useCallback, useContext, useEffect, useState } from 'react';
|
|
4
|
+
import PatientCard from '../patient-card/PatientCard';
|
|
5
|
+
import styles from './styles.scss';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { v4 as uuid } from 'uuid';
|
|
8
|
+
import GroupFormWorkflowContext from '../context/GroupFormWorkflowContext';
|
|
9
|
+
import FormBootstrap from '../FormBootstrap';
|
|
10
|
+
import CompleteModal from '../CompleteModal';
|
|
11
|
+
import CancelModal from '../CancelModal';
|
|
17
12
|
|
|
18
|
-
const formStore = getGlobalStore(
|
|
13
|
+
const formStore = getGlobalStore('ampath-form-state');
|
|
19
14
|
|
|
20
15
|
const WorkflowNavigationButtons = () => {
|
|
21
16
|
const context = useContext(GroupFormWorkflowContext);
|
|
22
|
-
const {
|
|
23
|
-
activeFormUuid,
|
|
24
|
-
submitForNext,
|
|
25
|
-
patientUuids,
|
|
26
|
-
activePatientUuid,
|
|
27
|
-
workflowState,
|
|
28
|
-
} = context;
|
|
17
|
+
const { activeFormUuid, submitForNext, patientUuids, activePatientUuid, workflowState } = context;
|
|
29
18
|
const store = useStore(formStore);
|
|
30
19
|
const formState = store[activeFormUuid];
|
|
31
20
|
const navigationDisabled =
|
|
32
|
-
(formState !==
|
|
33
|
-
formState !== "readyWithValidationErrors";
|
|
21
|
+
(formState !== 'ready' || workflowState !== 'EDIT_FORM') && formState !== 'readyWithValidationErrors';
|
|
34
22
|
const [cancelModalOpen, setCancelModalOpen] = useState(false);
|
|
35
23
|
const [completeModalOpen, setCompleteModalOpen] = useState(false);
|
|
36
24
|
const { t } = useTranslation();
|
|
37
25
|
|
|
38
|
-
const isLastPatient =
|
|
39
|
-
activePatientUuid === patientUuids[patientUuids.length - 1];
|
|
26
|
+
const isLastPatient = activePatientUuid === patientUuids[patientUuids.length - 1];
|
|
40
27
|
|
|
41
28
|
const handleClickNext = () => {
|
|
42
|
-
if (
|
|
43
|
-
workflowState === "EDIT_FORM" ||
|
|
44
|
-
formState === "readyWithValidationErrors"
|
|
45
|
-
) {
|
|
29
|
+
if (workflowState === 'EDIT_FORM' || formState === 'readyWithValidationErrors') {
|
|
46
30
|
submitForNext();
|
|
47
31
|
}
|
|
48
32
|
};
|
|
@@ -50,33 +34,18 @@ const WorkflowNavigationButtons = () => {
|
|
|
50
34
|
return (
|
|
51
35
|
<>
|
|
52
36
|
<div className={styles.rightPanelActionButtons}>
|
|
53
|
-
<Button
|
|
54
|
-
|
|
55
|
-
onClick={handleClickNext}
|
|
56
|
-
disabled={navigationDisabled}
|
|
57
|
-
>
|
|
58
|
-
{isLastPatient
|
|
59
|
-
? t("saveForm", "Save Form")
|
|
60
|
-
: t("nextPatient", "Next patient")}
|
|
37
|
+
<Button kind="primary" onClick={handleClickNext} disabled={navigationDisabled}>
|
|
38
|
+
{isLastPatient ? t('saveForm', 'Save Form') : t('nextPatient', 'Next patient')}
|
|
61
39
|
</Button>
|
|
62
40
|
<Button kind="secondary" onClick={() => setCompleteModalOpen(true)}>
|
|
63
|
-
{t(
|
|
41
|
+
{t('saveAndComplete', 'Save & Complete')}
|
|
64
42
|
</Button>
|
|
65
43
|
<Button kind="tertiary" onClick={() => setCancelModalOpen(true)}>
|
|
66
|
-
{t(
|
|
44
|
+
{t('cancel', 'Cancel')}
|
|
67
45
|
</Button>
|
|
68
46
|
</div>
|
|
69
|
-
<CancelModal
|
|
70
|
-
|
|
71
|
-
setOpen={setCancelModalOpen}
|
|
72
|
-
context={context}
|
|
73
|
-
/>
|
|
74
|
-
<CompleteModal
|
|
75
|
-
open={completeModalOpen}
|
|
76
|
-
setOpen={setCompleteModalOpen}
|
|
77
|
-
context={context}
|
|
78
|
-
validateFirst={false}
|
|
79
|
-
/>
|
|
47
|
+
<CancelModal open={cancelModalOpen} setOpen={setCancelModalOpen} context={context} />
|
|
48
|
+
<CompleteModal open={completeModalOpen} setOpen={setCompleteModalOpen} context={context} validateFirst={false} />
|
|
80
49
|
</>
|
|
81
50
|
);
|
|
82
51
|
};
|
|
@@ -177,7 +146,7 @@ const GroupSessionWorkspace = () => {
|
|
|
177
146
|
activePatientUuid,
|
|
178
147
|
groupVisitTypeUuid,
|
|
179
148
|
updateVisitUuid,
|
|
180
|
-
]
|
|
149
|
+
],
|
|
181
150
|
);
|
|
182
151
|
|
|
183
152
|
// Once form has been posted, save the new encounter uuid so we can edit it later
|
|
@@ -187,17 +156,17 @@ const GroupSessionWorkspace = () => {
|
|
|
187
156
|
saveEncounter(encounter.uuid);
|
|
188
157
|
}
|
|
189
158
|
},
|
|
190
|
-
[saveEncounter]
|
|
159
|
+
[saveEncounter],
|
|
191
160
|
);
|
|
192
161
|
|
|
193
162
|
const switchPatient = useCallback(
|
|
194
163
|
(patientUuid) => {
|
|
195
164
|
submitForNext(patientUuid);
|
|
196
165
|
},
|
|
197
|
-
[submitForNext]
|
|
166
|
+
[submitForNext],
|
|
198
167
|
);
|
|
199
168
|
|
|
200
|
-
if (workflowState ===
|
|
169
|
+
if (workflowState === 'NEW_GROUP_SESSION') return null;
|
|
201
170
|
|
|
202
171
|
return (
|
|
203
172
|
<div className={styles.workspace}>
|
|
@@ -214,7 +183,7 @@ const GroupSessionWorkspace = () => {
|
|
|
214
183
|
/>
|
|
215
184
|
</div>
|
|
216
185
|
<div className={styles.rightPanel}>
|
|
217
|
-
<h4>{t(
|
|
186
|
+
<h4>{t('formsFilled', 'Forms filled')}</h4>
|
|
218
187
|
<div className={styles.patientCardsSection}>
|
|
219
188
|
{patientUuids?.map((patientUuid) => (
|
|
220
189
|
<PatientCard
|