@pih/esm-commons-app 2.1.1-pre.9 → 2.1.1-pre.93

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.
Files changed (82) hide show
  1. package/.turbo/turbo-build.log +29 -27
  2. package/dist/123.js +2 -0
  3. package/dist/123.js.LICENSE.txt +9 -0
  4. package/dist/123.js.map +1 -0
  5. package/dist/157.js +2 -0
  6. package/dist/157.js.LICENSE.txt +40 -0
  7. package/dist/157.js.map +1 -0
  8. package/dist/300.js +1 -1
  9. package/dist/304.js +1 -0
  10. package/dist/304.js.map +1 -0
  11. package/dist/400.js +1 -0
  12. package/dist/400.js.map +1 -0
  13. package/dist/41.js +1 -1
  14. package/dist/41.js.map +1 -1
  15. package/dist/421.js +1 -0
  16. package/dist/421.js.map +1 -0
  17. package/dist/47.js +1 -0
  18. package/dist/47.js.map +1 -0
  19. package/dist/481.js +1 -0
  20. package/dist/481.js.map +1 -0
  21. package/dist/502.js +1 -0
  22. package/dist/502.js.map +1 -0
  23. package/dist/55.js +1 -1
  24. package/dist/659.js +1 -0
  25. package/dist/659.js.map +1 -0
  26. package/dist/685.js +1 -0
  27. package/dist/685.js.map +1 -0
  28. package/dist/704.js +1 -0
  29. package/dist/704.js.map +1 -0
  30. package/dist/737.js +2 -0
  31. package/dist/737.js.LICENSE.txt +38 -0
  32. package/dist/737.js.map +1 -0
  33. package/dist/773.js +1 -0
  34. package/dist/773.js.map +1 -0
  35. package/dist/848.js +1 -0
  36. package/dist/848.js.map +1 -0
  37. package/dist/92.js +2 -0
  38. package/dist/92.js.LICENSE.txt +9 -0
  39. package/dist/92.js.map +1 -0
  40. package/dist/99.js +1 -1
  41. package/dist/main.js +1 -1
  42. package/dist/main.js.map +1 -1
  43. package/dist/pih-esm-commons-app.js +1 -1
  44. package/dist/pih-esm-commons-app.js.buildmanifest.json +314 -66
  45. package/dist/pih-esm-commons-app.js.map +1 -1
  46. package/dist/routes.json +1 -1
  47. package/package.json +3 -7
  48. package/src/declarations.d.ts +2 -0
  49. package/src/hooks/useEncounters.ts +22 -0
  50. package/src/hooks/useProgramEnrollment.ts +19 -0
  51. package/src/index.ts +28 -9
  52. package/src/routes.json +58 -9
  53. package/src/service-queues-app/maternal-triage-form.workspace.tsx +111 -0
  54. package/src/service-queues-app/maternal-triage-queue-actions.extension.tsx +132 -0
  55. package/src/service-queues-app/maternal-triage-queue-actions.resource.ts +80 -0
  56. package/src/service-queues-app/maternal-trial-queue-actions.scss +14 -0
  57. package/src/service-queues-app/types.ts +58 -0
  58. package/src/ward-app/o2-iframe.component.tsx +86 -0
  59. package/src/ward-app/o2-iframe.scss +20 -0
  60. package/src/ward-app/o2-pregnancy-infant-dashboard.extension.tsx +87 -0
  61. package/src/ward-app/o2-pregnancy-infant-dashboard.scss +5 -0
  62. package/src/ward-app/o2-visit-summary-action-button.component.tsx +17 -0
  63. package/src/ward-app/o2-visit-summary-workspace.component.tsx +28 -23
  64. package/src/ward-app/o2-vital-signs-action-button.component.tsx +17 -0
  65. package/src/ward-app/o2-vital-signs-workspace.component.tsx +61 -0
  66. package/src/ward-app/types.ts +19 -4
  67. package/translations/en.json +16 -2
  68. package/dist/138.js +0 -1
  69. package/dist/138.js.map +0 -1
  70. package/dist/291.js +0 -1
  71. package/dist/291.js.map +0 -1
  72. package/dist/39.js +0 -1
  73. package/dist/39.js.map +0 -1
  74. package/dist/641.js +0 -1
  75. package/dist/641.js.map +0 -1
  76. package/dist/831.js +0 -2
  77. package/dist/831.js.LICENSE.txt +0 -5
  78. package/dist/831.js.map +0 -1
  79. package/dist/90.js +0 -1
  80. package/dist/90.js.map +0 -1
  81. package/src/ward-app/o2-visit-summary-action-button.extension.tsx +0 -18
  82. package/src/ward-app/o2-visit-summary-workspace.scss +0 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pih/esm-commons-app",
3
- "version": "2.1.1-pre.9",
3
+ "version": "2.1.1-pre.93",
4
4
  "description": "An app to define extensions to be slotted into other apps that are not PIH specific.",
5
5
  "browser": "dist/pih-esm-commons-app.js",
6
6
  "main": "src/index.ts",
@@ -18,7 +18,7 @@
18
18
  "test:watch": "cross-env TZ=UTC jest --watch --config jest.config.js --color",
19
19
  "coverage": "yarn test --coverage",
20
20
  "typescript": "tsc",
21
- "extract-translations": "i18next 'src/**/*.component.tsx'"
21
+ "extract-translations": "i18next 'src/**/*.component.tsx' 'src/**/*.extension.tsx' 'src/**/*modal.tsx' 'src/**/*.workspace.tsx' 'src/index.ts' --config ../../tools/i18next-parser.config.js"
22
22
  },
23
23
  "browserslist": [
24
24
  "extends browserslist-config-openmrs"
@@ -38,18 +38,14 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@babel/runtime": "^7.24.0",
41
- "@carbon/react": "~1.37.0",
42
41
  "moment": "^2.30.1",
43
42
  "react-dates": "^21.8.0",
44
43
  "webpack": "^5.74.0"
45
44
  },
46
45
  "peerDependencies": {
47
46
  "@openmrs/esm-framework": "5.x",
48
- "i18next": "^19.0.0",
49
47
  "react": "18.x",
50
- "react-i18next": "11.x",
51
- "react-router-dom": "^6.x",
52
- "swr": "2.x"
48
+ "react-i18next": "16.x"
53
49
  },
54
50
  "devDependencies": {
55
51
  "webpack": "^5.74.0"
@@ -0,0 +1,2 @@
1
+ declare module '*.scss';
2
+ declare module '*.module.scss';
@@ -0,0 +1,22 @@
1
+ import { restBaseUrl, useOpenmrsFetchAll } from '@openmrs/esm-framework';
2
+ import { type Encounter } from '../service-queues-app/types';
3
+
4
+ interface EncounterSearchParams {
5
+ patient: string;
6
+ visit?: string;
7
+ encounterType?: string;
8
+ }
9
+
10
+ export function useEncounters(params: EncounterSearchParams) {
11
+ const url = `${restBaseUrl}/encounter?`;
12
+ const searchParams = new URLSearchParams();
13
+ searchParams.append('patient', params.patient);
14
+ if (params.visit) {
15
+ searchParams.append('visit', params.visit);
16
+ }
17
+ if (params.encounterType) {
18
+ searchParams.append('encounterType', params.encounterType);
19
+ }
20
+
21
+ return useOpenmrsFetchAll<Encounter>(url + searchParams.toString());
22
+ }
@@ -0,0 +1,19 @@
1
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import useSWR from 'swr';
3
+ const customRepresentation = `custom:(uuid,display,program,dateEnrolled,dateCompleted,location:(uuid,display))`;
4
+
5
+ export interface PatientProgram {
6
+ uuid: string;
7
+ program: {
8
+ uuid: string;
9
+ };
10
+ }
11
+
12
+ export const useActivePatientEnrollment = (patientUuid: string) => {
13
+ const result = useSWR<{ data: { results: Array<PatientProgram> } }>(
14
+ patientUuid ? `${restBaseUrl}/programenrollment?patient=${patientUuid}&v=${customRepresentation}` : null,
15
+ openmrsFetch,
16
+ );
17
+
18
+ return result;
19
+ };
package/src/index.ts CHANGED
@@ -8,23 +8,42 @@
8
8
  import { getAsyncLifecycle } from '@openmrs/esm-framework';
9
9
 
10
10
  const moduleName = '@pih/esm-commons-app';
11
- const options = {
12
- featureName: 'commons',
13
- moduleName,
14
- };
15
11
 
16
12
  export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
17
13
 
18
- // export const root = getAsyncLifecycle(() => import('./root.component'), options);
19
-
20
14
  export const o2VisitSummaryWorkspaceSideRailIcon = getAsyncLifecycle(
21
- () => import('./ward-app/o2-visit-summary-action-button.extension'),
22
- options,
15
+ () => import('./ward-app/o2-visit-summary-action-button.component'),
16
+ { featureName: 'o2VisitSummaryWorkspaceSideRailIcon', moduleName },
23
17
  );
24
18
 
25
19
  export const o2VisitSummaryWorkspace = getAsyncLifecycle(
26
20
  () => import('./ward-app/o2-visit-summary-workspace.component'),
27
- options,
21
+ { featureName: 'o2VisitSummaryWorkspace', moduleName },
22
+ );
23
+
24
+ export const o2VitalSignsWorkspaceSideRailIcon = getAsyncLifecycle(
25
+ () => import('./ward-app/o2-vital-signs-action-button.component'),
26
+ { featureName: 'o2VitalSignsWorkspaceSideRailIcon', moduleName },
27
+ );
28
+
29
+ export const o2VitalSignsWorkspace = getAsyncLifecycle(() => import('./ward-app/o2-vital-signs-workspace.component'), {
30
+ featureName: 'o2VitalSignsWorkspace',
31
+ moduleName,
32
+ });
33
+
34
+ export const o2PregnancyInfantDashboard = getAsyncLifecycle(
35
+ () => import('./ward-app/o2-pregnancy-infant-dashboard.extension'),
36
+ { featureName: 'o2PregnancyInfantDashboard', moduleName },
37
+ );
38
+
39
+ export const maternalTriageFormWorkspace = getAsyncLifecycle(
40
+ () => import('./service-queues-app/maternal-triage-form.workspace'),
41
+ { featureName: 'maternalTriageFormWorkspace', moduleName },
42
+ );
43
+
44
+ export const triageWaitingQueueActions = getAsyncLifecycle(
45
+ () => import('./service-queues-app/maternal-triage-queue-actions.extension'),
46
+ { featureName: 'triageWaitingQueueActions', moduleName },
28
47
  );
29
48
 
30
49
  export function startupApp() {}
package/src/routes.json CHANGED
@@ -1,23 +1,72 @@
1
1
  {
2
2
  "$schema": "https://json.openmrs.org/routes.schema.json",
3
3
  "pages": [
4
+ {
5
+ "component": "root",
6
+ "route": "appointments"
7
+ },
8
+ {
9
+ "component": "root",
10
+ "route": "service-queues"
11
+ },
12
+ {
13
+ "component": "root",
14
+ "route": "dispensing2"
15
+ },
16
+ {
17
+ "component": "root",
18
+ "route": "ward"
19
+ }
4
20
  ],
5
21
  "extensions": [
6
22
  {
7
- "name": "o2-visit-summary-workspace-siderail-button",
8
- "component": "o2VisitSummaryWorkspaceSideRailIcon",
9
- "slot": "action-menu-ward-patient-items-slot"
23
+ "name": "o2-pregnancy-infant-dashboard",
24
+ "component": "o2PregnancyInfantDashboard",
25
+ "slot": "ward-patient-workspace-content-slot"
26
+ },
27
+ {
28
+ "name": "triage-waiting-queue-actions",
29
+ "component": "triageWaitingQueueActions",
30
+ "slot": "queue-table-triage-waiting-queue-actions-slot"
10
31
  }
11
32
  ],
12
- "workspaces": [
33
+ "workspaces2": [
13
34
  {
14
35
  "name": "o2-visit-summary-workspace",
15
36
  "component": "o2VisitSummaryWorkspace",
16
- "title": "visitSummary",
17
- "type": "o2-visit-summary",
18
- "sidebarFamily": "ward-patient",
19
- "hasOwnSidebar": true,
20
- "width": "extra-wide"
37
+ "window": "o2-visit-summary-window"
38
+ },
39
+ {
40
+ "name": "o2-vital-signs-workspace",
41
+ "component": "o2VitalSignsWorkspace",
42
+ "window": "o2-vital-signs-window"
43
+ },
44
+ {
45
+ "name": "maternal-triage-form-workspace",
46
+ "component": "maternalTriageFormWorkspace",
47
+ "window": "maternal-triage-form-window"
48
+ }
49
+ ],
50
+ "workspaceWindows2": [
51
+ {
52
+ "name": "o2-visit-summary-window",
53
+ "icon": "o2VisitSummaryWorkspaceSideRailIcon",
54
+ "group": "ward-patient",
55
+ "width": "extra-wide",
56
+ "canMaximize": true
57
+ },
58
+ {
59
+ "name": "o2-vital-signs-window",
60
+ "icon": "o2VitalSignsWorkspaceSideRailIcon",
61
+ "group": "ward-patient",
62
+ "width": "extra-wide",
63
+ "canMaximize": true
64
+ },
65
+ {
66
+ "name": "maternal-triage-form-window",
67
+ "group": "service-queues",
68
+ "width": "extra-wide",
69
+ "canMaximize": true
21
70
  }
22
71
  ]
23
72
  }
@@ -0,0 +1,111 @@
1
+ import { type Patient, showSnackbar, Workspace2, type Workspace2DefinitionProps } from '@openmrs/esm-framework';
2
+ import React, { useEffect } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import O2IFrame from '../ward-app/o2-iframe.component';
5
+ import { updateQueueEntry, useMutateQueueEntries } from './maternal-triage-queue-actions.resource';
6
+ import { type QueueEntry } from './types';
7
+ import { useEncounters } from '../hooks/useEncounters';
8
+ import { Loading } from '@carbon/react';
9
+ import { InlineNotification } from '@carbon/react';
10
+
11
+ interface MaternalTriageFormWorkspaceProps {
12
+ queueEntry: QueueEntry;
13
+ patient: Patient;
14
+ }
15
+
16
+ const MATERNAL_TRIAGE_FORM_ENCOUNTER_TYPE = '41911448-71a1-43d7-bba8-dc86339850da';
17
+
18
+ /**
19
+ * Workspace to display the Maternal Triage HTML Form, rendered in a iframe
20
+ */
21
+ const MaternalTriageFormWorkspace: React.FC<Workspace2DefinitionProps<MaternalTriageFormWorkspaceProps>> = ({
22
+ workspaceProps: { queueEntry, patient },
23
+ closeWorkspace,
24
+ }) => {
25
+ const { t } = useTranslation();
26
+ const { mutateQueueEntries } = useMutateQueueEntries();
27
+ const {
28
+ data: filledOutTriageForms,
29
+ isLoading,
30
+ error,
31
+ } = useEncounters({
32
+ patient: patient.uuid,
33
+ visit: queueEntry.visit.uuid,
34
+ encounterType: MATERNAL_TRIAGE_FORM_ENCOUNTER_TYPE,
35
+ });
36
+
37
+ useEffect(() => {
38
+ const onMessage = async (event: MessageEvent) => {
39
+ if (event.data == 'triageFormSubmitted') {
40
+ const endQueueEntry = () => {
41
+ return updateQueueEntry(queueEntry.uuid, {
42
+ endedAt: new Date().toISOString(),
43
+ });
44
+ };
45
+
46
+ await endQueueEntry();
47
+ await mutateQueueEntries();
48
+ closeWorkspace({ discardUnsavedChanges: true });
49
+ showSnackbar({
50
+ isLowContrast: true,
51
+ kind: 'success',
52
+ title: t('triageFormSubmitted', 'Triage form successfully submitted for {{patient}}.', {
53
+ patient: patient.person.display,
54
+ }),
55
+ });
56
+ }
57
+ };
58
+
59
+ window.addEventListener('message', onMessage);
60
+ return () => window.removeEventListener('message', onMessage);
61
+ }, []);
62
+
63
+ const patientUuid = patient.uuid;
64
+ const visitUuid = queueEntry.visit.uuid;
65
+
66
+ const elementsToHide = [
67
+ 'header',
68
+ '#breadcrumbs',
69
+
70
+ // prevent O2 success toast from showing; After submitting form for a patient,
71
+ // the success toast for that patient shows when opening form for another patient
72
+ '.toast-type-success',
73
+ // UHM-8822: remove Cancel button from the triage form
74
+ '.cancel',
75
+ ];
76
+
77
+ const customJavaScript = `
78
+ htmlForm.setSuccessFunction(() => window.top.postMessage('triageFormSubmitted'))
79
+ `;
80
+
81
+ if (isLoading) {
82
+ return <Loading withOverlay={false} small />;
83
+ } else if (error) {
84
+ return (
85
+ <InlineNotification
86
+ kind="error"
87
+ lowContrast={true}
88
+ hideCloseButton={true}
89
+ title={t('errorLoadingPatientForm', 'Error loading patient form')}
90
+ />
91
+ );
92
+ } else {
93
+ // If patient does not have triage form filled out already, we load a new one,
94
+ // else, we load the last filled out form to edit
95
+ const src =
96
+ filledOutTriageForms.length == 0
97
+ ? `${window.openmrsBase}/htmlformentryui/htmlform/enterHtmlFormWithStandardUi.page?patientId=${patientUuid}&visitId=${visitUuid}&definitionUiResource=file:configuration/pih/htmlforms/triage.xml&returnUrl=%2Fopenmrs%2Fcoreapps%2Fclinicianfacing%2Fpatient.page%3FpatientId%3D${patientUuid}%26`
98
+ : `${window.openmrsBase}/htmlformentryui/htmlform/editHtmlFormWithStandardUi.page?patientId=${patientUuid}&encounterId=${filledOutTriageForms[filledOutTriageForms.length - 1].uuid}`;
99
+
100
+ return (
101
+ <Workspace2
102
+ title={t('maternalTriageForm', 'Maternal triage form')}
103
+ hasUnsavedChanges={true} // assume there are unsaved changes to prevent accidental closure
104
+ >
105
+ <O2IFrame key={patientUuid} src={src} elementsToHide={elementsToHide} customJavaScript={customJavaScript} />
106
+ </Workspace2>
107
+ );
108
+ }
109
+ };
110
+
111
+ export default MaternalTriageFormWorkspace;
@@ -0,0 +1,132 @@
1
+ import { Button, OverflowMenu, OverflowMenuItem } from '@carbon/react';
2
+ import { isDesktop, launchWorkspace2, showModal, useConfig, useLayoutType } from '@openmrs/esm-framework';
3
+ import React from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+ import styles from './maternal-trial-queue-actions.scss';
6
+ import { type QueueEntry } from './types';
7
+ import { transitionQueueEntry, useMutateQueueEntries } from './maternal-triage-queue-actions.resource';
8
+
9
+ // types taken from esm-service-queues-app
10
+ interface QueueTableCellComponentProps {
11
+ queueEntry: QueueEntry;
12
+ }
13
+
14
+ interface ConfigObject {
15
+ concepts: {
16
+ defaultTransitionStatus: string;
17
+ };
18
+ // other fields not shown
19
+ }
20
+
21
+ /**
22
+ * This extension provides an extra "Triage" action, along with the other standard actions for
23
+ * queue entries in the queues table. The Triage action opens the maternal triage form, and also
24
+ * has the side effect of putting the patient's queue entry into the "in service" status, if they have
25
+ * not yet already
26
+ * @param param0
27
+ * @returns
28
+ */
29
+ const MaternalTriageQueueActions: React.FC<QueueTableCellComponentProps> = ({ queueEntry }) => {
30
+ const { t } = useTranslation();
31
+ const layout = useLayoutType();
32
+
33
+ const { mutateQueueEntries } = useMutateQueueEntries();
34
+ const { concepts } = useConfig<ConfigObject>({ externalModuleName: '@openmrs/esm-service-queues-app' });
35
+ const inServiceStatus = concepts.defaultTransitionStatus;
36
+
37
+ const { patient } = queueEntry;
38
+
39
+ return (
40
+ <div className={styles.actionsCell}>
41
+ <Button
42
+ kind="ghost"
43
+ aria-label={t('triage', 'Triage')}
44
+ onClick={async () => {
45
+ if (queueEntry.status.uuid !== inServiceStatus) {
46
+ const res = await transitionQueueEntry({
47
+ queueEntryToTransition: queueEntry.uuid,
48
+ newStatus: inServiceStatus,
49
+ });
50
+ mutateQueueEntries();
51
+ const updatedQueueEntry = { ...res.data, visit: queueEntry.visit };
52
+ launchWorkspace2('maternal-triage-form-workspace', { queueEntry: updatedQueueEntry, patient });
53
+ } else {
54
+ launchWorkspace2('maternal-triage-form-workspace', { queueEntry, patient });
55
+ }
56
+ }}
57
+ size={isDesktop(layout) ? 'sm' : 'lg'}>
58
+ {t('triage', 'Triage')}
59
+ </Button>
60
+
61
+ <OverflowMenu aria-label="Actions menu" size={isDesktop(layout) ? 'sm' : 'lg'} align="left" flipped>
62
+ <OverflowMenuItem
63
+ className={styles.menuItem}
64
+ aria-label={t('transition', 'Transition')}
65
+ hasDivider
66
+ onClick={() => {
67
+ const dispose = showModal('transition-queue-entry-modal', {
68
+ closeModal: () => dispose(),
69
+ queueEntry,
70
+ });
71
+ }}
72
+ itemText={t('transition', 'Transition')}
73
+ />
74
+ <OverflowMenuItem
75
+ className={styles.menuItem}
76
+ aria-label={t('edit', 'Edit')}
77
+ hasDivider
78
+ onClick={() => {
79
+ const dispose = showModal('edit-queue-entry-modal', {
80
+ closeModal: () => dispose(),
81
+ queueEntry,
82
+ });
83
+ }}
84
+ itemText={t('edit', 'Edit')}
85
+ />
86
+ <OverflowMenuItem
87
+ className={styles.menuItem}
88
+ aria-label={t('removePatient', 'Remove patient')}
89
+ hasDivider
90
+ onClick={() => {
91
+ const dispose = showModal('remove-queue-entry-modal', {
92
+ closeModal: () => dispose(),
93
+ queueEntry,
94
+ });
95
+ }}
96
+ itemText={t('removePatient', 'Remove patient')}
97
+ />
98
+ {queueEntry.previousQueueEntry == null ? (
99
+ <OverflowMenuItem
100
+ className={styles.menuItem}
101
+ aria-label={t('delete', 'Delete')}
102
+ hasDivider
103
+ isDelete
104
+ onClick={() => {
105
+ const dispose = showModal('delete-queue-entry-modal', {
106
+ closeModal: () => dispose(),
107
+ queueEntry,
108
+ });
109
+ }}
110
+ itemText={t('delete', 'Delete')}
111
+ />
112
+ ) : (
113
+ <OverflowMenuItem
114
+ className={styles.menuItem}
115
+ aria-label={t('undoTransition', 'Undo transition')}
116
+ hasDivider
117
+ isDelete
118
+ onClick={() => {
119
+ const dispose = showModal('undo-transition-queue-entry-modal', {
120
+ closeModal: () => dispose(),
121
+ queueEntry,
122
+ });
123
+ }}
124
+ itemText={t('undoTransition', 'Undo transition')}
125
+ />
126
+ )}
127
+ </OverflowMenu>
128
+ </div>
129
+ );
130
+ };
131
+
132
+ export default MaternalTriageQueueActions;
@@ -0,0 +1,80 @@
1
+ import { type Concept, type FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import { useSWRConfig } from 'swr';
3
+ import { type QueueEntry } from './types';
4
+
5
+ // Hooks here copied from esm-service-queues-app
6
+
7
+ export function useMutateQueueEntries() {
8
+ const { mutate } = useSWRConfig();
9
+
10
+ return {
11
+ mutateQueueEntries: () => {
12
+ return mutate((key) => {
13
+ return (
14
+ typeof key === 'string' &&
15
+ (key.includes(`${restBaseUrl}/queue-entry`) || key.includes(`${restBaseUrl}/visit-queue-entry`))
16
+ );
17
+ }).then(() => {
18
+ window.dispatchEvent(new CustomEvent('queue-entry-updated'));
19
+ });
20
+ },
21
+ };
22
+ }
23
+
24
+ interface TransitionQueueEntryParams {
25
+ queueEntryToTransition: string;
26
+ transitionDate?: string;
27
+ newQueue?: string;
28
+ newStatus?: string;
29
+ newPriority?: string;
30
+ newPriorityComment?: string;
31
+ }
32
+
33
+ /**
34
+ * A transition is defined as an action that ends a current queue entry and immediately starts a new one
35
+ * with (slightly) different values. For now, this could be used to transition the queue entry's status,
36
+ * priority or queue. This allows us to keep a history of queue entries through a patient's visit.
37
+ * Note that there are some use cases (like RDE or data correction) where a transition is NOT appropriate.
38
+ * @param params
39
+ * @param abortController
40
+ * @returns
41
+ */
42
+ export function transitionQueueEntry(
43
+ params: TransitionQueueEntryParams,
44
+ abortController?: AbortController,
45
+ ): Promise<FetchResponse<QueueEntry>> {
46
+ return openmrsFetch(`${restBaseUrl}/queue-entry/transition`, {
47
+ method: 'POST',
48
+ headers: {
49
+ 'Content-Type': 'application/json',
50
+ },
51
+ signal: abortController?.signal,
52
+ body: params,
53
+ });
54
+ }
55
+
56
+ interface UpdateQueueEntryParams {
57
+ status?: Concept;
58
+ priority?: Concept;
59
+ priorityComment?: string;
60
+ sortWeight?: number;
61
+ startedAt?: string;
62
+ endedAt?: string;
63
+ loationWaitingFor?: Location;
64
+ providerWaitingFor?: Location;
65
+ }
66
+
67
+ export function updateQueueEntry(
68
+ queueEntryUuid: string,
69
+ params: UpdateQueueEntryParams,
70
+ abortController?: AbortController,
71
+ ) {
72
+ return openmrsFetch(`${restBaseUrl}/queue-entry/${queueEntryUuid}`, {
73
+ method: 'POST',
74
+ headers: {
75
+ 'Content-Type': 'application/json',
76
+ },
77
+ signal: abortController?.signal,
78
+ body: params,
79
+ });
80
+ }
@@ -0,0 +1,14 @@
1
+ .actionCellContainer {
2
+ white-space: nowrap;
3
+ }
4
+
5
+ .menuItem {
6
+ max-width: none;
7
+ }
8
+
9
+ .actionsCell {
10
+ display: flex;
11
+ justify-content: flex-end;
12
+ height: 100%;
13
+ align-items: center;
14
+ }
@@ -0,0 +1,58 @@
1
+ import { type Concept, type OpenmrsResource, type Patient, type Visit } from '@openmrs/esm-framework';
2
+
3
+ export interface Queue {
4
+ uuid: string;
5
+ display: string;
6
+ name: string;
7
+ description: string;
8
+ location: Location;
9
+ service: Concept;
10
+ allowedPriorities: Array<Concept>;
11
+ allowedStatuses: Array<Concept>;
12
+ }
13
+
14
+ export interface QueueEntry {
15
+ uuid: string;
16
+ display: string;
17
+ endedAt: string;
18
+ locationWaitingFor: Location;
19
+ patient: Patient;
20
+ priority: Concept;
21
+ priorityComment: string | null;
22
+ providerWaitingFor: Provider;
23
+ queue: Queue;
24
+ startedAt: string;
25
+ status: Concept;
26
+ visit: Visit;
27
+ sortWeight: number;
28
+ queueComingFrom: Queue;
29
+ previousQueueEntry: QueueEntry;
30
+ }
31
+
32
+ export interface Provider extends OpenmrsResource {}
33
+
34
+ export interface Encounter {
35
+ uuid: string;
36
+ encounterDateTime: string;
37
+ encounterProviders: Array<{
38
+ uuid: string;
39
+ display: string;
40
+ encounterRole: {
41
+ uuid: string;
42
+ display: string;
43
+ };
44
+ provider: {
45
+ uuid: string;
46
+ person: {
47
+ uuid: string;
48
+ display: string;
49
+ };
50
+ };
51
+ }>;
52
+ encounterType: {
53
+ uuid: string;
54
+ display: string;
55
+ };
56
+ obs: Array<OpenmrsResource>;
57
+ orders: Array<OpenmrsResource>;
58
+ }