Skip to content

Commit

Permalink
(feat) UHM-8240 Create O2 Visit Summary workspace for Ward App
Browse files Browse the repository at this point in the history
  • Loading branch information
chibongho committed Nov 19, 2024
1 parent 56d4e9c commit 4059c2e
Show file tree
Hide file tree
Showing 21 changed files with 310 additions and 42 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = {
'@openmrs/esm-framework': '@openmrs/esm-framework/mock',
'^dexie$': require.resolve('dexie'),
'^lodash-es/(.*)$': 'lodash/$1',
'lodash-es': 'lodash',
'^react-i18next$': path.resolve(__dirname, 'react-i18next.js'),
'^uuid$': path.resolve(__dirname, 'node_modules', 'uuid', 'dist', 'index.js'),
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"react-dom": "^18.2.0",
"rxjs": "^6.6.7",
"swc-loader": "^0.2.6",
"turbo": "^1.12.5",
"turbo": "^2.2.3",
"typescript": "^4.9.5",
"webpack": "^5.90.3",
"webpack-cli": "^4.10.0"
Expand Down
1 change: 1 addition & 0 deletions packages/esm-commons-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This ESM is not really an app (for now). It is a place to define extensions to be slotted into other apps that are not PIH specific (e.g. the ward app).
51 changes: 51 additions & 0 deletions packages/esm-commons-app/__mocks__/react-i18next.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/** At present, this entire mock is boilerplate. */

const React = require('react');
const reactI18next = require('react-i18next');

const hasChildren = (node) => node && (node.children || (node.props && node.props.children));

const getChildren = (node) => (node && node.children ? node.children : node.props && node.props.children);

const renderNodes = (reactNodes) => {
if (typeof reactNodes === 'string') {
return reactNodes;
}

return Object.keys(reactNodes).map((key, i) => {
const child = reactNodes[key];
const isElement = React.isValidElement(child);

if (typeof child === 'string') {
return child;
}
if (hasChildren(child)) {
const inner = renderNodes(getChildren(child));
return React.cloneElement(child, { ...child.props, key: i }, inner);
}
if (typeof child === 'object' && !isElement) {
return Object.keys(child).reduce((str, childKey) => `${str}${child[childKey]}`, '');
}

return child;
});
};

const useMock = [(k) => k, {}];
useMock.t = (k, o) => (o && o.defaultValue) || (typeof o === 'string' ? o : k);
useMock.i18n = {};

module.exports = {
// this mock makes sure any components using the translate HoC receive the t function as a prop
Trans: ({ children }) => renderNodes(children),
Translation: ({ children }) => children((k) => k, { i18n: {} }),
useTranslation: () => useMock,

// mock if needed
I18nextProvider: reactI18next.I18nextProvider,
initReactI18next: reactI18next.initReactI18next,
setDefaults: reactI18next.setDefaults,
getDefaults: reactI18next.getDefaults,
setI18n: reactI18next.setI18n,
getI18n: reactI18next.getI18n,
};
3 changes: 3 additions & 0 deletions packages/esm-commons-app/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const rootConfig = require('../../jest.config.js');

module.exports = rootConfig;
57 changes: 57 additions & 0 deletions packages/esm-commons-app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "@pih/esm-commons-app",
"version": "2.1.0",
"description": "An app to define extensions to be slotted into other apps that are not PIH specific.",
"browser": "dist/pih-esm-commons-app.js",
"main": "src/index.ts",
"source": true,
"license": "MPL-2.0",
"homepage": "https://github.com/PIH/openmrs-esm-pihemr#readme",
"scripts": {
"start": "openmrs develop",
"serve": "webpack serve --mode=development",
"debug": "npm run serve",
"build": "webpack --mode production",
"analyze": "webpack --mode=production --env.analyze=true",
"lint": "cross-env eslint src --ext ts,tsx",
"test": "cross-env TZ=UTC jest --config jest.config.js --verbose false --passWithNoTests --color",
"test:watch": "cross-env TZ=UTC jest --watch --config jest.config.js --color",
"coverage": "yarn test --coverage",
"typescript": "tsc",
"extract-translations": "i18next 'src/**/*.component.tsx'"
},
"browserslist": [
"extends browserslist-config-openmrs"
],
"keywords": [
"openmrs"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/PIH/openmrs-esm-pihemr.git"
},
"bugs": {
"url": "https://github.com/PIH/openmrs-esm-pihemr/issues"
},
"dependencies": {
"@babel/runtime": "^7.24.0",
"@carbon/react": "~1.37.0",
"moment": "^2.30.1",
"react-dates": "^21.8.0",
"webpack": "^5.74.0"
},
"peerDependencies": {
"@openmrs/esm-framework": "5.x",
"i18next": "^19.0.0",
"react": "18.x",
"react-i18next": "11.x",
"react-router-dom": "^6.x",
"swr": "2.x"
},
"devDependencies": {
"webpack": "^5.74.0"
}
}
30 changes: 30 additions & 0 deletions packages/esm-commons-app/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* This is the entrypoint file of the application. It communicates the
* important features of this microfrontend to the app shell. It
* connects the app shell to the React application(s) that make up this
* microfrontend.
*/

import { getAsyncLifecycle } from '@openmrs/esm-framework';

const moduleName = '@pih/esm-commons-app';
const options = {
featureName: 'commons',
moduleName,
};

export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');

// export const root = getAsyncLifecycle(() => import('./root.component'), options);

export const o2VisitSummaryWorkspaceSideRailIcon = getAsyncLifecycle(
() => import('./ward-app/o2-visit-summary-action-button.extension'),
options,
);

export const o2VisitSummaryWorkspace = getAsyncLifecycle(
() => import('./ward-app/o2-visit-summary-workspace.component'),
options,
);

export function startupApp() {}
23 changes: 23 additions & 0 deletions packages/esm-commons-app/src/routes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://json.openmrs.org/routes.schema.json",
"pages": [
],
"extensions": [
{
"name": "o2-visit-summary-workspace-siderail-button",
"component": "o2VisitSummaryWorkspaceSideRailIcon",
"slot": "action-menu-ward-patient-items-slot"
}
],
"workspaces": [
{
"name": "o2-visit-summary-workspace",
"component": "o2VisitSummaryWorkspace",
"title": "visitSummary",
"type": "o2-visit-summary",
"sidebarFamily": "ward-patient",
"hasOwnSidebar": true,
"width": "extra-wide"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ActionMenuButton, launchWorkspace, UserAvatarIcon } from '@openmrs/esm-framework';
import React from 'react';
import { useTranslation } from 'react-i18next';
import type { WardPatientWorkspaceProps } from './types';

export default function WardPatientActionButton() {
const { t } = useTranslation();

return (
<ActionMenuButton
getIcon={(props) => <UserAvatarIcon {...props} />}
label={t('visitSummary', 'Visit summary')}
iconDescription={t('patientVisitSummary', 'Patient visit summary')}
handler={() => launchWorkspace<WardPatientWorkspaceProps>('o2-visit-summary-workspace')}
type={'o2-visit-summary'}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { useCallback, useRef } from 'react';
import { type WardPatientWorkspaceProps } from './types';
import styles from './o2-visit-summary-workspace.scss';

const O2VisitSummaryWorkspace: React.FC<WardPatientWorkspaceProps> = ({ wardPatient }) => {
const { patient, visit } = wardPatient ?? {};
const iframeRef = useRef<HTMLIFrameElement>();

// hide the headers breadcrumbs and visit actions from
const onLoad = useCallback(() => {
const dashboard = iframeRef.current.contentDocument;
const elementsToHide = ['header', '.patient-header', '#breadcrumbs', '.visit-actions', '#choose-another-visit'];

const styleTag = dashboard.createElement('style');
styleTag.innerHTML = elementsToHide.map((e) => `${e} {display: none;}`).join('\n');
dashboard.head.appendChild(styleTag);
}, []);

if (patient && visit) {
const src = `/openmrs/pihcore/visit/visit.page?patient=${patient.uuid}&visit=${visit.uuid}`;
return (
<div className={styles.iframeWrapper}>
<iframe ref={iframeRef} src={src} onLoad={onLoad} className={styles.o2Iframe} />
</div>
);
} else {
return;
}
};

export default O2VisitSummaryWorkspace;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.iframeWrapper {
height: 100%;
width: 100%;
}

.o2Iframe {
height: 100%;
width: 100%;
}
11 changes: 11 additions & 0 deletions packages/esm-commons-app/src/ward-app/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { DefaultWorkspaceProps, Patient, Visit } from '@openmrs/esm-framework';

// a stripped down version of the same type defined in esm-ward-app
export type WardPatient = {
patient: Patient;
visit: Visit;
};

export interface WardPatientWorkspaceProps extends DefaultWorkspaceProps {
wardPatient: WardPatient;
}
4 changes: 4 additions & 0 deletions packages/esm-commons-app/translations/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"patientVisitSummary": "Patient visit summary",
"visitSummary": "Visit summary"
}
4 changes: 4 additions & 0 deletions packages/esm-commons-app/translations/es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"patientVisitSummary": "Patient visit summary",
"visitSummary": "Visit summary"
}
4 changes: 4 additions & 0 deletions packages/esm-commons-app/translations/fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"patientVisitSummary": "Patient visit summary",
"visitSummary": "Visit summary"
}
5 changes: 5 additions & 0 deletions packages/esm-commons-app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"],
"exclude": ["src/**/*.test.tsx"]
}
1 change: 1 addition & 0 deletions packages/esm-commons-app/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('openmrs/default-webpack-config');
9 changes: 4 additions & 5 deletions packages/esm-referrals-queue-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,16 @@
"@babel/runtime": "^7.24.0",
"@carbon/react": "~1.37.0",
"moment": "^2.30.1",
"react-dates": "^21.8.0"
"react-dates": "^21.8.0",
"webpack": "^5.74.0"
},
"peerDependencies": {
"@openmrs/esm-framework": "5.x",
"i18next": "^19.0.0",
"react": "18.x",
"react-dom": "18.x",
"react-i18next": "11.x",
"rxjs": "6.x",
"single-spa": "^6.x",
"swr": "^2.2.2"
"react-router-dom": "^6.x",
"swr": "2.x"
},
"devDependencies": {
"webpack": "^5.74.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

.container {
margin-right: auto;
margin-left: auto;
Expand Down
2 changes: 1 addition & 1 deletion turbo.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://turborepo.org/schema.json",
"pipeline": {
"tasks": {
"build": {
"outputs": ["dist/**"]
},
Expand Down
Loading

0 comments on commit 4059c2e

Please sign in to comment.