diff --git a/packages/esm-patient-chart-app/src/workspace/workspace-window.component.tsx b/packages/esm-patient-chart-app/src/workspace/workspace-window.component.tsx index 6861d736c7..0946d77d08 100644 --- a/packages/esm-patient-chart-app/src/workspace/workspace-window.component.tsx +++ b/packages/esm-patient-chart-app/src/workspace/workspace-window.component.tsx @@ -72,7 +72,7 @@ const WorkspaceWindow: React.FC = () => { onClick={toggleWindowState} size="lg" > - {maximized ? : } + {maximized ? : } )} {canHide ? ( diff --git a/packages/esm-patient-common-lib/src/workspaces/workspaces.test.ts b/packages/esm-patient-common-lib/src/workspaces/workspaces.test.ts index 66f526f0b9..af7821a093 100644 --- a/packages/esm-patient-common-lib/src/workspaces/workspaces.test.ts +++ b/packages/esm-patient-common-lib/src/workspaces/workspaces.test.ts @@ -28,13 +28,15 @@ describe('workspace system', () => { test('registering, launching, and closing a workspace', () => { const store = getWorkspaceStore(); + const mockedOnCloseWorkspace = jest.fn(); registerWorkspace({ name: 'allergies', title: 'Allergies', load: jest.fn() }); - launchPatientWorkspace('allergies', { foo: true }); + launchPatientWorkspace('allergies', { foo: true, onCloseWorkspace: mockedOnCloseWorkspace }); expect(store.getState().openWorkspaces.length).toEqual(1); const allergies = store.getState().openWorkspaces[0]; expect(allergies.name).toBe('allergies'); expect(allergies.additionalProps['foo']).toBe(true); allergies.closeWorkspace(); + expect(mockedOnCloseWorkspace).toHaveBeenCalled(); expect(store.getState().openWorkspaces.length).toEqual(0); }); @@ -304,11 +306,14 @@ describe('workspace system', () => { test('respects promptBeforeClosing function', () => { const store = getWorkspaceStore(); + const mockedOnCloseWorkspace = jest.fn(); registerWorkspace({ name: 'hiv', title: 'HIV', load: jest.fn() }); registerWorkspace({ name: 'diabetes', title: 'Diabetes', load: jest.fn() }); launchPatientWorkspace('hiv'); store.getState().openWorkspaces[0].promptBeforeClosing(() => false); - launchPatientWorkspace('diabetes'); + launchPatientWorkspace('diabetes', { + onCloseWorkspace: mockedOnCloseWorkspace, + }); expect(store.getState().prompt).toBeNull(); expect(store.getState().openWorkspaces[0].name).toBe('diabetes'); store.getState().openWorkspaces[0].promptBeforeClosing(() => true); @@ -316,6 +321,8 @@ describe('workspace system', () => { expect(store.getState().openWorkspaces[0].name).toBe('diabetes'); expect(store.getState().prompt.title).toBe('You have unsaved changes'); store.getState().prompt.onConfirm(); + // Should call the `onCloseWorkspace` function if passed + expect(mockedOnCloseWorkspace).toHaveBeenCalled(); expect(store.getState().openWorkspaces[0].name).toBe('hiv'); }); @@ -343,8 +350,11 @@ describe('workspace system', () => { test('respects promptBeforeClosing function before closing workspace, with unsaved changes', () => { const store = getWorkspaceStore(); + const mockedOnCloseWorkspace = jest.fn(); registerWorkspace({ name: 'hiv', title: 'HIV', load: jest.fn() }); - launchPatientWorkspace('hiv'); + launchPatientWorkspace('hiv', { + onCloseWorkspace: mockedOnCloseWorkspace, + }); store.getState().openWorkspaces[0].promptBeforeClosing(() => true); store.getState().openWorkspaces[0].closeWorkspace(false); expect(store.getState().prompt.title).toBe('Unsaved Changes'); @@ -353,6 +363,9 @@ describe('workspace system', () => { ); expect(store.getState().prompt.confirmText).toBe('Discard'); store.getState().prompt.onConfirm(); + expect(store.getState().prompt).toBeNull(); + // Should call the `onCloseWorkspace` function if passed + expect(mockedOnCloseWorkspace).toHaveBeenCalled(); expect(store.getState().openWorkspaces.length).toBe(0); }); }); diff --git a/packages/esm-patient-common-lib/src/workspaces/workspaces.ts b/packages/esm-patient-common-lib/src/workspaces/workspaces.ts index c865568c03..496353d3d3 100644 --- a/packages/esm-patient-common-lib/src/workspaces/workspaces.ts +++ b/packages/esm-patient-common-lib/src/workspaces/workspaces.ts @@ -41,6 +41,12 @@ export interface WorkspaceRegistration { preferredWindowSize?: WorkspaceWindowState; } +interface WorkspaceAdditionalProps { + workspaceTitle?: string; + onCloseWorkspace?: () => void; + [x: string]: any; +} + let registeredWorkspaces: Record = {}; /** @@ -154,12 +160,12 @@ function promptBeforeLaunchingWorkspace( * @param name The name of the workspace to launch * @param additionalProps Props to pass to the workspace component being launched */ -export function launchPatientWorkspace(name: string, additionalProps?: object) { +export function launchPatientWorkspace(name: string, additionalProps?: WorkspaceAdditionalProps) { const store = getWorkspaceStore(); const workspace = getWorkspaceRegistration(name); const newWorkspace = { ...workspace, - closeWorkspace: (ignoreChanges = true) => closeWorkspace(name, ignoreChanges), + closeWorkspace: (ignoreChanges = true) => closeWorkspace(name, ignoreChanges, additionalProps?.onCloseWorkspace), promptBeforeClosing: (testFcn) => promptBeforeClosing(name, testFcn), additionalProps, }; @@ -239,9 +245,27 @@ export function cancelPrompt() { store.setState({ ...state, prompt: null }); } -export function closeWorkspace(name: string, ignoreChanges: boolean) { +export function closeWorkspace(name: string, ignoreChanges: boolean, onCloseWorkspace?: () => void) { const store = getWorkspaceStore(); const promptCheckFcn = getPromptBeforeClosingFcn(name); + const updateStoreWithClosedWorkspace = () => { + const state = store.getState(); + const newOpenWorkspaces = state.openWorkspaces.filter((w) => w.name !== name); + + store.setState({ + ...state, + prompt: null, + openWorkspaces: newOpenWorkspaces, + }); + + if (onCloseWorkspace && typeof onCloseWorkspace === 'function') { + try { + onCloseWorkspace(); + } catch (e) { + console.error(`Custom 'onCloseWorkspace' for workspace ${name} caused an error`, e); + } + } + }; if (!ignoreChanges && promptCheckFcn && promptCheckFcn()) { const prompt: Prompt = { title: translateFrom('@openmrs/esm-patient-chart-app', 'unsavedChangesTitleText', 'Unsaved Changes'), @@ -251,15 +275,13 @@ export function closeWorkspace(name: string, ignoreChanges: boolean) { `You have unsaved changes in the side panel. Do you want to discard these changes?`, ), onConfirm: () => { - const state = store.getState(); - store.setState({ ...state, prompt: null, openWorkspaces: state.openWorkspaces.filter((w) => w.name != name) }); + updateStoreWithClosedWorkspace(); }, confirmText: translateFrom('@openmrs/esm-patient-chart-app', 'discard', 'Discard'), }; store.setState({ ...store.getState(), prompt }); } else { - const state = store.getState(); - store.setState({ ...state, openWorkspaces: state.openWorkspaces.filter((w) => w.name != name) }); + updateStoreWithClosedWorkspace(); } } diff --git a/packages/esm-patient-medications-app/src/drug-order-basket-panel/drug-order-basket-panel.extension.tsx b/packages/esm-patient-medications-app/src/drug-order-basket-panel/drug-order-basket-panel.extension.tsx index 7b12ad2f9b..69e2a92a9f 100644 --- a/packages/esm-patient-medications-app/src/drug-order-basket-panel/drug-order-basket-panel.extension.tsx +++ b/packages/esm-patient-medications-app/src/drug-order-basket-panel/drug-order-basket-panel.extension.tsx @@ -55,8 +55,14 @@ export default function DrugOrderBasketPanelExtension() { }; }, [orders]); + const onClose = useCallback(() => { + launchPatientWorkspace('order-basket'); + }, []); + const openDrugSearch = () => { - launchPatientWorkspace('add-drug-order'); + launchPatientWorkspace('add-drug-order', { + onCloseWorkspace: onClose, + }); }; const openDrugForm = (order: DrugOrderBasketItem) => {