@openmrs/esm-fast-data-entry-app 1.0.0-pre.9 → 1.0.1-pre.15
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/.eslintrc.js +10 -0
- package/.husky/pre-push +1 -6
- package/.tx/config +9 -0
- package/.yarn/plugins/@yarnpkg/plugin-version.cjs +550 -0
- package/.yarn/versions/c1451405.yml +0 -0
- package/README.md +39 -12
- package/dist/openmrs-esm-fast-data-entry-app.js +1 -1
- package/docs/config-icrc-forms.png +0 -0
- package/docs/config-other-forms.png +0 -0
- package/docs/configuring-form-categories.md +77 -0
- package/docs/fde-workflow.mov +0 -0
- package/docs/form-workflow-state-diagram.png +0 -0
- package/jest.config.json +20 -18
- package/package.json +99 -106
- package/src/FormBootstrap.tsx +151 -0
- package/src/Root.tsx +14 -3
- package/src/add-group-modal/AddGroupModal.tsx +262 -0
- package/src/add-group-modal/styles.scss +45 -0
- package/src/config-schema.ts +63 -31
- package/src/context/FormWorkflowContext.tsx +114 -0
- package/src/context/FormWorkflowReducer.ts +277 -0
- package/src/context/GroupFormWorkflowContext.tsx +143 -0
- package/src/context/GroupFormWorkflowReducer.ts +296 -0
- package/src/empty-state/EmptyDataIllustration.tsx +51 -0
- package/src/empty-state/EmptyState.tsx +33 -0
- package/src/empty-state/styles.scss +55 -0
- package/src/form-entry-workflow/FormEntryWorkflow.tsx +230 -0
- package/src/form-entry-workflow/form-review-card/FormReviewCard.tsx +50 -0
- package/src/form-entry-workflow/form-review-card/index.ts +3 -0
- package/src/form-entry-workflow/form-review-card/styles.scss +39 -0
- package/src/form-entry-workflow/index.ts +3 -0
- package/src/form-entry-workflow/patient-banner/PatientBanner.test.tsx +9 -0
- package/src/form-entry-workflow/patient-banner/PatientBanner.tsx +86 -0
- package/src/form-entry-workflow/patient-banner/index.ts +3 -0
- package/src/form-entry-workflow/patient-banner/styles.scss +45 -0
- package/src/form-entry-workflow/patient-search-header/PatientSearchHeader.tsx +63 -0
- package/src/form-entry-workflow/patient-search-header/index.ts +3 -0
- package/src/form-entry-workflow/patient-search-header/styles.scss +22 -0
- package/src/form-entry-workflow/styles.scss +64 -0
- package/src/form-entry-workflow/workflow-review/WorkflowReview.tsx +35 -0
- package/src/form-entry-workflow/workflow-review/index.ts +3 -0
- package/src/form-entry-workflow/workflow-review/styles.scss +34 -0
- package/src/forms-app-menu-link.tsx +3 -2
- package/src/forms-page/FormsPage.tsx +129 -0
- package/src/forms-page/forms-table/FormsTable.tsx +131 -0
- package/src/forms-page/forms-table/index.ts +3 -0
- package/src/forms-page/forms-table/styles.scss +20 -0
- package/src/forms-page/index.ts +3 -0
- package/src/forms-page/styles.scss +11 -0
- package/src/group-form-entry-workflow/GroupFormEntryWorkflow.tsx +413 -0
- package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.test.tsx +9 -0
- package/src/group-form-entry-workflow/group-display-header/GroupDisplayHeader.tsx +71 -0
- package/src/group-form-entry-workflow/group-display-header/index.ts +3 -0
- package/src/group-form-entry-workflow/group-display-header/styles.scss +60 -0
- package/src/group-form-entry-workflow/group-search/CompactGroupResults.tsx +139 -0
- package/src/group-form-entry-workflow/group-search/CompactGroupSearch.tsx +68 -0
- package/src/group-form-entry-workflow/group-search/GroupSearch.tsx +150 -0
- package/src/group-form-entry-workflow/group-search/compact-group-result.scss +64 -0
- package/src/group-form-entry-workflow/group-search/compact-group-search.scss +35 -0
- package/src/group-form-entry-workflow/group-search/group-search.scss +96 -0
- package/src/group-form-entry-workflow/group-search-header/GroupSearchHeader.tsx +49 -0
- package/src/group-form-entry-workflow/group-search-header/index.ts +3 -0
- package/src/group-form-entry-workflow/group-search-header/styles.scss +20 -0
- package/src/group-form-entry-workflow/index.ts +3 -0
- package/src/group-form-entry-workflow/styles.scss +96 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useFormState.ts +23 -0
- package/src/hooks/useGetAllForms.ts +45 -0
- package/src/hooks/useGetEncounter.ts +21 -0
- package/src/hooks/useGetPatient.ts +23 -0
- package/src/hooks/useKeyPress.ts +31 -0
- package/src/hooks/usePostEndpoint.ts +70 -0
- package/src/hooks/useSearchEndpoint.ts +120 -0
- package/src/index.ts +20 -4
- package/src/patient-card/PatientCard.tsx +67 -0
- package/src/patient-card/index.ts +3 -0
- package/src/patient-card/styles.scss +45 -0
- package/translations/en.json +54 -4
- package/tsconfig.json +26 -23
- package/.eslintrc +0 -4
- package/.github/workflows/node.js.yml +0 -79
- package/.husky/pre-commit +0 -6
- package/dist/24.js +0 -3
- package/dist/24.js.LICENSE.txt +0 -16
- package/dist/24.js.map +0 -1
- package/dist/294.js +0 -3
- package/dist/294.js.LICENSE.txt +0 -14
- package/dist/294.js.map +0 -1
- package/dist/296.js +0 -2
- package/dist/296.js.map +0 -1
- package/dist/299.js +0 -2
- package/dist/299.js.map +0 -1
- package/dist/382.js +0 -3
- package/dist/382.js.LICENSE.txt +0 -8
- package/dist/382.js.map +0 -1
- package/dist/415.js +0 -2
- package/dist/415.js.map +0 -1
- package/dist/574.js +0 -1
- package/dist/595.js +0 -3
- package/dist/595.js.LICENSE.txt +0 -1
- package/dist/595.js.map +0 -1
- package/dist/69.js +0 -2
- package/dist/69.js.map +0 -1
- package/dist/735.js +0 -3
- package/dist/735.js.LICENSE.txt +0 -29
- package/dist/735.js.map +0 -1
- package/dist/777.js +0 -2
- package/dist/777.js.map +0 -1
- package/dist/860.js +0 -2
- package/dist/860.js.map +0 -1
- package/dist/906.js +0 -2
- package/dist/906.js.map +0 -1
- package/dist/openmrs-esm-fast-data-entry-app.js.buildmanifest.json +0 -369
- package/dist/openmrs-esm-fast-data-entry-app.js.map +0 -1
- package/dist/openmrs-esm-fast-data-entry-app.old +0 -2
- package/src/boxes/extensions/blue-box.tsx +0 -15
- package/src/boxes/extensions/box.scss +0 -23
- package/src/boxes/extensions/brand-box.tsx +0 -15
- package/src/boxes/extensions/red-box.tsx +0 -15
- package/src/boxes/slot/boxes.css +0 -23
- package/src/boxes/slot/boxes.tsx +0 -19
- package/src/forms/FormsRoot.tsx +0 -32
- package/src/forms/FormsTable.tsx +0 -64
- package/src/forms/mockData.ts +0 -43
- package/src/greeter/greeter.css +0 -4
- package/src/greeter/greeter.test.tsx +0 -29
- package/src/greeter/greeter.tsx +0 -25
- package/src/hello.css +0 -3
- package/src/hello.test.tsx +0 -45
- package/src/hello.tsx +0 -30
- package/src/patient-getter/patient-getter.resource.ts +0 -31
- package/src/patient-getter/patient-getter.test.tsx +0 -28
- package/src/patient-getter/patient-getter.tsx +0 -28
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { fetchCurrentPatient } from "@openmrs/esm-framework";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
|
|
4
|
+
const useGetPatient = (patientUuid) => {
|
|
5
|
+
const [patient, setPatient] = useState(null);
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (!patientUuid) {
|
|
9
|
+
setPatient(null);
|
|
10
|
+
} else {
|
|
11
|
+
getPatient(patientUuid);
|
|
12
|
+
}
|
|
13
|
+
}, [patientUuid]);
|
|
14
|
+
|
|
15
|
+
const getPatient = async (uuid) => {
|
|
16
|
+
const result = await fetchCurrentPatient(uuid);
|
|
17
|
+
setPatient(result?.data);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return patient;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default useGetPatient;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
|
|
3
|
+
const useKeyPress = (targetKey) => {
|
|
4
|
+
const [keyPressed, setKeyPressed] = useState(false);
|
|
5
|
+
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const downHandler = ({ key }) => {
|
|
8
|
+
if (key === targetKey) {
|
|
9
|
+
setKeyPressed(true);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const upHandler = ({ key }) => {
|
|
14
|
+
if (key === targetKey) {
|
|
15
|
+
setKeyPressed(false);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
window.addEventListener("keydown", downHandler);
|
|
20
|
+
window.addEventListener("keyup", upHandler);
|
|
21
|
+
|
|
22
|
+
return () => {
|
|
23
|
+
window.removeEventListener("keydown", downHandler);
|
|
24
|
+
window.removeEventListener("keyup", upHandler);
|
|
25
|
+
};
|
|
26
|
+
}, [targetKey]);
|
|
27
|
+
|
|
28
|
+
return keyPressed;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default useKeyPress;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { openmrsFetch } from "@openmrs/esm-framework";
|
|
2
|
+
import { useCallback, useState } from "react";
|
|
3
|
+
|
|
4
|
+
const usePostEndpoint = ({ endpointUrl }) => {
|
|
5
|
+
const [submissionInProgress, setSubmissionInProgress] = useState(null);
|
|
6
|
+
const [result, setResult] = useState(null);
|
|
7
|
+
const [error, setError] = useState(null);
|
|
8
|
+
|
|
9
|
+
const onFormPosted = useCallback(
|
|
10
|
+
(result) => {
|
|
11
|
+
setSubmissionInProgress(false);
|
|
12
|
+
if (error) {
|
|
13
|
+
setError(null);
|
|
14
|
+
}
|
|
15
|
+
setResult(result.data);
|
|
16
|
+
},
|
|
17
|
+
[error]
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const onError = useCallback(
|
|
21
|
+
(error) => {
|
|
22
|
+
setSubmissionInProgress(false);
|
|
23
|
+
if (result) {
|
|
24
|
+
setResult(null);
|
|
25
|
+
}
|
|
26
|
+
setError(error?.responseBody?.error ?? error?.responseBody ?? error);
|
|
27
|
+
},
|
|
28
|
+
[result]
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const post = useCallback(
|
|
32
|
+
async (data) => {
|
|
33
|
+
setSubmissionInProgress(true);
|
|
34
|
+
return openmrsFetch(endpointUrl, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: {
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
},
|
|
39
|
+
body: data,
|
|
40
|
+
})
|
|
41
|
+
.then(onFormPosted)
|
|
42
|
+
.catch(onError);
|
|
43
|
+
},
|
|
44
|
+
[endpointUrl, onError, onFormPosted]
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const reset = () => {
|
|
48
|
+
setSubmissionInProgress(null);
|
|
49
|
+
setResult(null);
|
|
50
|
+
setError(null);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
post,
|
|
55
|
+
isPosting: submissionInProgress,
|
|
56
|
+
result,
|
|
57
|
+
error,
|
|
58
|
+
reset,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const usePostVisit = () => {
|
|
63
|
+
return usePostEndpoint({ endpointUrl: "/ws/rest/v1/visit" });
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const usePostCohort = () => {
|
|
67
|
+
return usePostEndpoint({ endpointUrl: "/ws/rest/v1/cohortm/cohort" });
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { usePostEndpoint, usePostVisit, usePostCohort };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { openmrsFetch, FetchResponse } from "@openmrs/esm-framework";
|
|
2
|
+
import { useCallback, useMemo } from "react";
|
|
3
|
+
import useSWRInfinite from "swr/infinite";
|
|
4
|
+
|
|
5
|
+
export interface SearchResponse {
|
|
6
|
+
data: Array<Record<string, unknown>> | null;
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
error: Error;
|
|
9
|
+
loadingNewData: boolean;
|
|
10
|
+
hasMore: boolean;
|
|
11
|
+
currentPage: number;
|
|
12
|
+
totalResults: number;
|
|
13
|
+
setPage: (size: number | ((_size: number) => number)) => Promise<
|
|
14
|
+
FetchResponse<{
|
|
15
|
+
results: Array<Record<string, unknown>>;
|
|
16
|
+
links: Array<{
|
|
17
|
+
rel: "prev" | "next";
|
|
18
|
+
}>;
|
|
19
|
+
}>[]
|
|
20
|
+
>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface SearchInfiniteProps {
|
|
24
|
+
baseUrl?: string;
|
|
25
|
+
searchTerm: string;
|
|
26
|
+
parameters?: Record<string, unknown> | undefined;
|
|
27
|
+
searching: boolean;
|
|
28
|
+
resultsToFetch?: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const useSearchEndpointInfinite = (
|
|
32
|
+
arg0: SearchInfiniteProps
|
|
33
|
+
): SearchResponse => {
|
|
34
|
+
const {
|
|
35
|
+
baseUrl,
|
|
36
|
+
searchTerm,
|
|
37
|
+
parameters,
|
|
38
|
+
searching = true,
|
|
39
|
+
resultsToFetch = 10,
|
|
40
|
+
} = arg0;
|
|
41
|
+
|
|
42
|
+
const getUrl = useCallback(
|
|
43
|
+
(
|
|
44
|
+
page: number,
|
|
45
|
+
prevPageData: FetchResponse<{
|
|
46
|
+
results: Array<Record<string, unknown>>;
|
|
47
|
+
links: Array<{ rel: "prev" | "next" }>;
|
|
48
|
+
}>
|
|
49
|
+
) => {
|
|
50
|
+
if (
|
|
51
|
+
prevPageData &&
|
|
52
|
+
!prevPageData?.data?.links.some((link) => link.rel === "next")
|
|
53
|
+
) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
let url = `${baseUrl}?q=${searchTerm}`;
|
|
57
|
+
const params = {
|
|
58
|
+
// merge passed parameters and default parameters
|
|
59
|
+
// this way the defaults can be overriden if needed
|
|
60
|
+
totalCount: true,
|
|
61
|
+
limit: resultsToFetch,
|
|
62
|
+
...parameters,
|
|
63
|
+
};
|
|
64
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
65
|
+
// don't send null parmeters
|
|
66
|
+
if (value !== null && value !== undefined) {
|
|
67
|
+
url += `&${key}=${value}`;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
if (page) {
|
|
71
|
+
url += `&startIndex=${page * resultsToFetch}`;
|
|
72
|
+
}
|
|
73
|
+
return url;
|
|
74
|
+
},
|
|
75
|
+
[baseUrl, searchTerm, parameters, resultsToFetch]
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const { data, isValidating, setSize, error, size } = useSWRInfinite<
|
|
79
|
+
FetchResponse<{
|
|
80
|
+
results: Array<Record<string, unknown>>;
|
|
81
|
+
links: Array<{ rel: "prev" | "next" }>;
|
|
82
|
+
totalCount: number;
|
|
83
|
+
}>,
|
|
84
|
+
Error
|
|
85
|
+
>(searching ? getUrl : null, openmrsFetch);
|
|
86
|
+
|
|
87
|
+
const results = useMemo(
|
|
88
|
+
() => ({
|
|
89
|
+
data: data
|
|
90
|
+
? [].concat(...(data?.map((resp) => resp?.data?.results) ?? []))
|
|
91
|
+
: null,
|
|
92
|
+
isLoading: !data && !error,
|
|
93
|
+
error,
|
|
94
|
+
hasMore: data?.length
|
|
95
|
+
? !!data[data.length - 1].data?.links?.some(
|
|
96
|
+
(link) => link.rel === "next"
|
|
97
|
+
)
|
|
98
|
+
: false,
|
|
99
|
+
loadingNewData: isValidating,
|
|
100
|
+
setPage: setSize,
|
|
101
|
+
currentPage: size,
|
|
102
|
+
totalResults: data?.[0]?.data?.totalCount,
|
|
103
|
+
}),
|
|
104
|
+
[data, isValidating, error, setSize, size]
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return results;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const useSearchCohortInfinite = ({
|
|
111
|
+
...props
|
|
112
|
+
}: SearchInfiniteProps): SearchResponse => {
|
|
113
|
+
return useSearchEndpointInfinite({
|
|
114
|
+
baseUrl: "/ws/rest/v1/cohortm/cohort",
|
|
115
|
+
resultsToFetch: 10,
|
|
116
|
+
...props,
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export { useSearchEndpointInfinite, useSearchCohortInfinite };
|
package/src/index.ts
CHANGED
|
@@ -5,9 +5,17 @@
|
|
|
5
5
|
* microfrontend.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getAsyncLifecycle,
|
|
10
|
+
defineConfigSchema,
|
|
11
|
+
registerBreadcrumbs,
|
|
12
|
+
} from "@openmrs/esm-framework";
|
|
9
13
|
import { configSchema } from "./config-schema";
|
|
10
14
|
|
|
15
|
+
declare let __VERSION__: string;
|
|
16
|
+
// __VERSION__ is replaced by Webpack with the version from package.json
|
|
17
|
+
const version = __VERSION__;
|
|
18
|
+
|
|
11
19
|
/**
|
|
12
20
|
* This tells the app shell how to obtain translation files: that they
|
|
13
21
|
* are JSON files in the directory `../translations` (which you should
|
|
@@ -44,15 +52,23 @@ const backendDependencies = {
|
|
|
44
52
|
* `/openmrs/spa/hello`.
|
|
45
53
|
*/
|
|
46
54
|
function setupOpenMRS() {
|
|
47
|
-
const moduleName = "@openmrs/esm-fast-data-entry";
|
|
55
|
+
const moduleName = "@openmrs/esm-fast-data-entry-app";
|
|
48
56
|
|
|
49
57
|
const options = {
|
|
50
|
-
featureName: "fast-data-entry",
|
|
58
|
+
featureName: "fast-data-entry-app",
|
|
51
59
|
moduleName,
|
|
52
60
|
};
|
|
53
61
|
|
|
54
62
|
defineConfigSchema(moduleName, configSchema);
|
|
55
63
|
|
|
64
|
+
registerBreadcrumbs([
|
|
65
|
+
{
|
|
66
|
+
path: `${window.spaBase}/forms`,
|
|
67
|
+
title: "Forms",
|
|
68
|
+
parent: `${window.spaBase}/home`,
|
|
69
|
+
},
|
|
70
|
+
]);
|
|
71
|
+
|
|
56
72
|
return {
|
|
57
73
|
pages: [
|
|
58
74
|
{
|
|
@@ -72,4 +88,4 @@ function setupOpenMRS() {
|
|
|
72
88
|
};
|
|
73
89
|
}
|
|
74
90
|
|
|
75
|
-
export { backendDependencies, importTranslation, setupOpenMRS };
|
|
91
|
+
export { backendDependencies, importTranslation, setupOpenMRS, version };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CheckmarkOutline, WarningAlt } from "@carbon/react/icons";
|
|
2
|
+
import { SkeletonText } from "@carbon/react";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import useGetPatient from "../hooks/useGetPatient";
|
|
5
|
+
import styles from "./styles.scss";
|
|
6
|
+
|
|
7
|
+
const CardContainer = ({ onClick = () => undefined, active, children }) => {
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
onClick={onClick}
|
|
11
|
+
className={`${styles.cardContainer} ${!active && styles.inactiveCard}`}
|
|
12
|
+
role="button"
|
|
13
|
+
tabIndex={0}
|
|
14
|
+
>
|
|
15
|
+
{children}
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const PatientCard = ({
|
|
21
|
+
patientUuid,
|
|
22
|
+
activePatientUuid,
|
|
23
|
+
editEncounter,
|
|
24
|
+
encounters,
|
|
25
|
+
}) => {
|
|
26
|
+
const patient = useGetPatient(patientUuid);
|
|
27
|
+
const givenName = patient?.name?.[0]?.given?.[0];
|
|
28
|
+
const familyName = patient?.name?.[0]?.family;
|
|
29
|
+
const identifier = patient?.identifier?.[0]?.value;
|
|
30
|
+
|
|
31
|
+
if (!patient) {
|
|
32
|
+
return (
|
|
33
|
+
<CardContainer active={true}>
|
|
34
|
+
<SkeletonText className={styles.skeletonText} />
|
|
35
|
+
</CardContainer>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const active = activePatientUuid === patientUuid;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<CardContainer
|
|
43
|
+
onClick={active ? () => undefined : () => editEncounter(patientUuid)}
|
|
44
|
+
active={active}
|
|
45
|
+
>
|
|
46
|
+
<div className={styles.patientInfo}>
|
|
47
|
+
<div className={styles.identifier}>{identifier}</div>
|
|
48
|
+
<div
|
|
49
|
+
className={`${styles.displayName} ${
|
|
50
|
+
active && styles.activeDisplayName
|
|
51
|
+
}`}
|
|
52
|
+
>
|
|
53
|
+
{givenName} {familyName}
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
<div>
|
|
57
|
+
{patientUuid in encounters ? (
|
|
58
|
+
<CheckmarkOutline size={16} className={styles.statusSuccess} />
|
|
59
|
+
) : (
|
|
60
|
+
<WarningAlt size={16} className={styles.statusWarning} />
|
|
61
|
+
)}
|
|
62
|
+
</div>
|
|
63
|
+
</CardContainer>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default PatientCard;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@use '@carbon/styles/scss/spacing';
|
|
2
|
+
@use '@carbon/colors';
|
|
3
|
+
// @use '@carbon/styles/scss/type';
|
|
4
|
+
// @import '~@openmrs/esm-styleguide/src/vars';
|
|
5
|
+
|
|
6
|
+
.cardContainer {
|
|
7
|
+
padding: spacing.$spacing-05;
|
|
8
|
+
display: flex;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.skeletonText {
|
|
12
|
+
max-width: 8rem;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.identifier {
|
|
16
|
+
font-weight: 300;
|
|
17
|
+
font-size: 0.8rem;
|
|
18
|
+
line-height: 0.9rem;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.displayName {
|
|
22
|
+
font-weight: bold;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.activeDisplayName {
|
|
26
|
+
color: colors.$blue-50;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.inactiveCard {
|
|
30
|
+
&:hover {
|
|
31
|
+
background-color: colors.$gray-30;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.patientInfo {
|
|
36
|
+
flex-grow: 1;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.statusSuccess {
|
|
40
|
+
fill: colors.$green-60;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.statusWarning {
|
|
44
|
+
fill: colors.$yellow-40;
|
|
45
|
+
}
|
package/translations/en.json
CHANGED
|
@@ -1,4 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"
|
|
3
|
-
"
|
|
4
|
-
|
|
1
|
+
{
|
|
2
|
+
"actions": "Actions",
|
|
3
|
+
"allFieldsRequired": "All fields are required unless marked optional",
|
|
4
|
+
"areYouSure": "Are you sure?",
|
|
5
|
+
"cancel": "Cancel",
|
|
6
|
+
"cancelExplanation": "You will lose any unsaved changes on the current form. Do you want to discard the current session?",
|
|
7
|
+
"changeGroup": "Choose a different group",
|
|
8
|
+
"chooseGroupError": "Please choose a group.",
|
|
9
|
+
"createNewPatient": "Create new patient",
|
|
10
|
+
"createGroup": "Create Group",
|
|
11
|
+
"createNewGroup": "Create New Group",
|
|
12
|
+
"createNewSession": "Create New Session",
|
|
13
|
+
"complete": "Complete",
|
|
14
|
+
"dataErrorMessage": "Something went wrong loading data from the server.",
|
|
15
|
+
"description": "Description",
|
|
16
|
+
"discard": "Discard",
|
|
17
|
+
"error": "Error",
|
|
18
|
+
"errorCoppy": "Sorry, there was an error. You can try to reload this page, or contact the site administrator and quote the error code above.",
|
|
19
|
+
"errorLoadingData": "Error Loading Data",
|
|
20
|
+
"fastDataEntry": "Fast Data Entry",
|
|
21
|
+
"fillForm": "Fill Form",
|
|
22
|
+
"formName": "Form Name",
|
|
23
|
+
"goToForm": "Go To Form",
|
|
24
|
+
"group": "Group",
|
|
25
|
+
"groupNameError": "Please enter a group name.",
|
|
26
|
+
"members": "members",
|
|
27
|
+
"newGroupName": "New Group Name",
|
|
28
|
+
"nextPatient": "Next Patient",
|
|
29
|
+
"noFormsFound": "No Forms To Show",
|
|
30
|
+
"noFormsFoundMessage": "No forms could be found for this category. Please double check the form concept uuids and access permissions.",
|
|
31
|
+
"noMoreResults": "End of search results",
|
|
32
|
+
"noGroupsFoundMessage": "Sorry, no groups have been found",
|
|
33
|
+
"noPatientError": "Please enter at least one patient.",
|
|
34
|
+
"or": "or",
|
|
35
|
+
"orLabelName": "OR label name",
|
|
36
|
+
"patientsInGroup": "Patients in group",
|
|
37
|
+
"postError": "POST Error",
|
|
38
|
+
"practitionerName": "Practitioner Name",
|
|
39
|
+
"remove": "Remove",
|
|
40
|
+
"resumeSession": "Resume Session",
|
|
41
|
+
"resumeGroupSession": "Resume Group Session",
|
|
42
|
+
"saveAndComplete": "Save & Complete",
|
|
43
|
+
"saveExplanation": "Do you want to save the current form and exit the workflow?",
|
|
44
|
+
"saveSession": "Save Session",
|
|
45
|
+
"searchResultsText": "search result(s)",
|
|
46
|
+
"selectPatientFirst": "Please select a patient first",
|
|
47
|
+
"sessionDate": "Session Date",
|
|
48
|
+
"sessionDetails": "Session details",
|
|
49
|
+
"sessionName": "Session Name",
|
|
50
|
+
"sessionNotes": "Session Notes",
|
|
51
|
+
"startGroupSession": "Start Group Session",
|
|
52
|
+
"trySearchWithPatientUniqueID": "Try searching with the cohort's description",
|
|
53
|
+
"unknownPostError": "An unknown error occured while saving data"
|
|
54
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"esModuleInterop": true,
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"allowSyntheticDefaultImports": true,
|
|
6
|
-
"jsx": "react",
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
"moduleResolution": "node",
|
|
9
|
-
"lib": [
|
|
10
|
-
"dom",
|
|
11
|
-
"es5",
|
|
12
|
-
"scripthost",
|
|
13
|
-
"es2015",
|
|
14
|
-
"es2015.promise",
|
|
15
|
-
"es2016.array.include",
|
|
16
|
-
"es2018",
|
|
17
|
-
"es2020"
|
|
18
|
-
],
|
|
19
|
-
"resolveJsonModule": true,
|
|
20
|
-
"noEmit": true,
|
|
21
|
-
"target": "esnext"
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"esModuleInterop": true,
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"allowSyntheticDefaultImports": true,
|
|
6
|
+
"jsx": "react",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"lib": [
|
|
10
|
+
"dom",
|
|
11
|
+
"es5",
|
|
12
|
+
"scripthost",
|
|
13
|
+
"es2015",
|
|
14
|
+
"es2015.promise",
|
|
15
|
+
"es2016.array.include",
|
|
16
|
+
"es2018",
|
|
17
|
+
"es2020"
|
|
18
|
+
],
|
|
19
|
+
"resolveJsonModule": true,
|
|
20
|
+
"noEmit": true,
|
|
21
|
+
"target": "esnext",
|
|
22
|
+
// "paths": {
|
|
23
|
+
// "@openmrs/*": ["./node_modules/@openmrs/*"]
|
|
24
|
+
// }
|
|
25
|
+
}
|
|
26
|
+
}
|
package/.eslintrc
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
name: Node.js CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [main]
|
|
8
|
-
release:
|
|
9
|
-
types:
|
|
10
|
-
- created
|
|
11
|
-
|
|
12
|
-
env:
|
|
13
|
-
ESM_NAME: "@openmrs/esm-fast-data-entry-app"
|
|
14
|
-
JS_NAME: "openmrs-esm-fast-data-entry-app.js"
|
|
15
|
-
|
|
16
|
-
jobs:
|
|
17
|
-
build:
|
|
18
|
-
runs-on: ubuntu-latest
|
|
19
|
-
|
|
20
|
-
steps:
|
|
21
|
-
- uses: actions/checkout@v2
|
|
22
|
-
- name: Use Node.js
|
|
23
|
-
uses: actions/setup-node@v1
|
|
24
|
-
with:
|
|
25
|
-
node-version: "16.x"
|
|
26
|
-
- run: yarn
|
|
27
|
-
- run: yarn lint
|
|
28
|
-
- run: yarn coverage
|
|
29
|
-
- run: yarn typescript
|
|
30
|
-
- run: yarn build
|
|
31
|
-
- name: Upload Artifacts
|
|
32
|
-
uses: actions/upload-artifact@v2
|
|
33
|
-
with:
|
|
34
|
-
name: dist
|
|
35
|
-
path: |
|
|
36
|
-
dist
|
|
37
|
-
|
|
38
|
-
pre_release:
|
|
39
|
-
runs-on: ubuntu-latest
|
|
40
|
-
|
|
41
|
-
needs: build
|
|
42
|
-
|
|
43
|
-
if: ${{ github.event_name == 'push' }}
|
|
44
|
-
|
|
45
|
-
steps:
|
|
46
|
-
- uses: actions/checkout@v2
|
|
47
|
-
- name: Download Artifacts
|
|
48
|
-
uses: actions/download-artifact@v2
|
|
49
|
-
- name: Use Node.js
|
|
50
|
-
uses: actions/setup-node@v1
|
|
51
|
-
with:
|
|
52
|
-
node-version: "16.x"
|
|
53
|
-
registry-url: "https://registry.npmjs.org"
|
|
54
|
-
- run: npm install
|
|
55
|
-
- run: sed -i -e "s/\(\"version\":\\s\+\"\([0-9]\+\.\?\)\+\)/\1-pre.${{ github.run_number }}/" 'package.json'
|
|
56
|
-
- run: npm publish --tag next
|
|
57
|
-
env:
|
|
58
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
|
|
59
|
-
|
|
60
|
-
release:
|
|
61
|
-
runs-on: ubuntu-latest
|
|
62
|
-
|
|
63
|
-
needs: build
|
|
64
|
-
|
|
65
|
-
if: ${{ github.event_name == 'release' }}
|
|
66
|
-
|
|
67
|
-
steps:
|
|
68
|
-
- uses: actions/checkout@v2
|
|
69
|
-
- name: Download Artifacts
|
|
70
|
-
uses: actions/download-artifact@v2
|
|
71
|
-
- name: Use Node.js
|
|
72
|
-
uses: actions/setup-node@v1
|
|
73
|
-
with:
|
|
74
|
-
node-version: "16.x"
|
|
75
|
-
registry-url: 'https://registry.npmjs.org'
|
|
76
|
-
- run: yarn
|
|
77
|
-
- run: yarn publish
|
|
78
|
-
env:
|
|
79
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
|