Skip to content

Commit

Permalink
Merge pull request #1 from PIH/UHM-8240
Browse files Browse the repository at this point in the history
(feat) UHM-8240 Create O2 Visit Summary workspace for Ward App
  • Loading branch information
chibongho authored Nov 19, 2024
2 parents 8a3287e + 3506050 commit a9977f1
Show file tree
Hide file tree
Showing 23 changed files with 2,483 additions and 932 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
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"extract-translations": "turbo extract-translations -- --config ../../tools/i18next-parser.config.js"
},
"devDependencies": {
"@carbon/react": "~1.37.0",
"@openmrs/esm-framework": "next",
"@playwright/test": "^1.42.1",
"@swc/core": "^1.2.203",
"@swc/jest": "^0.2.21",
Expand All @@ -37,19 +39,19 @@
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"i18next": "^19.0.0",
"i18next": "^21.10.0",
"i18next-parser": "^6.6.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^27.0.4",
"jest-cli": "^27.0.4",
"mockdate": "^3.0.5",
"openmrs": "^5.4.0",
"openmrs": "next",
"prettier": "^3.2.5",
"react": "^18.2.0",
"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": "1.0.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');
22 changes: 7 additions & 15 deletions packages/esm-referrals-queue-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,20 @@
},
"dependencies": {
"@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.4.0",
"@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": {
"@openmrs/esm-framework": "^5.4.0",
"i18next": "^19.0.0",
"react": "18.x",
"react-dates": "^21.8.0",
"react-dom": "18.x",
"react-i18next": "11.x",
"rxjs": "6.x",
"single-spa": "^6.x",
"swr": "^2.2.2"
"webpack": "^5.74.0"
}
}
3 changes: 1 addition & 2 deletions packages/esm-referrals-queue-app/src/declarations.d.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
declare module '@carbon/react';
declare module '*.css';
declare module '*.scss';
declare module '@carbon/react';
declare type SideNavProps = {};

type Referral = {
details: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@use '@carbon/react';

.container {
margin-right: auto;
margin-left: auto;
Expand Down
21 changes: 8 additions & 13 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
{
"compilerOptions": {
"esModuleInterop": true,
"module": "esnext",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "react",
"skipLibCheck": true,
"moduleResolution": "node",
"lib": [
"dom",
"es5",
"scripthost",
"es2015",
"es2015.promise",
"es2016.array.include",
"es2018",
"es2020"
"es2022"
],
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"noEmit": true,
"target": "esnext",
"paths": {
"@openmrs/*": ["./node_modules/@openmrs/*"],
"__mocks__": ["./__mocks__"],
"tools": ["./tools"],
}
},
"resolveJsonModule": true,
"skipLibCheck": true,
"target": "esnext",
}
}
Loading

0 comments on commit a9977f1

Please sign in to comment.