From a603a438198582795ca13c7effdc5fb1f5f799d4 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Mon, 2 Sep 2024 14:02:28 +0530 Subject: [PATCH 01/10] New print sticker implemented with modified configuration --- package.json | 1 + .../print-identifier-sticker-modal.test.tsx | 7 +- .../patient-detail.component.tsx | 93 +++++++++++++ .../print-identifier-sticker-modal.test.tsx | 67 ++++++++++ .../print-identifier-sticker.modal.tsx | 122 ++++++------------ .../print-identifier-sticker.resource.ts | 39 ++++++ .../print-identifier-sticker.scss | 16 +++ .../src/config-schema.ts | 53 +++++--- packages/esm-patient-banner-app/src/index.ts | 2 +- .../translations/en.json | 2 +- yarn.lock | 13 ++ 11 files changed, 309 insertions(+), 106 deletions(-) create mode 100644 packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx create mode 100644 packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker-modal.test.tsx rename packages/esm-patient-banner-app/src/banner-tags/{ => print-identifier-sticker}/print-identifier-sticker.modal.tsx (54%) create mode 100644 packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.resource.ts rename packages/esm-patient-banner-app/src/banner-tags/{ => print-identifier-sticker}/print-identifier-sticker.scss (78%) diff --git a/package.json b/package.json index 6d9ba91dd9..34b20bffe0 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "dependencies": { "@hookform/resolvers": "^3.3.1", "classnames": "^2.3.2", + "react-barcode": "^1.5.3", "react-hook-form": "^7.46.2", "react-to-print": "^2.14.13", "zod": "^3.22.2" diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker-modal.test.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker-modal.test.tsx index 9092801ae8..844ae54b02 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker-modal.test.tsx +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker-modal.test.tsx @@ -5,7 +5,7 @@ import { useReactToPrint } from 'react-to-print'; import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; import { configSchema, type ConfigObject } from '../config-schema'; import { mockPatient } from 'tools'; -import PrintIdentifierSticker from './print-identifier-sticker.modal'; +import PrintIdentifierSticker from './print-identifier-sticker/print-identifier-sticker.modal'; const mockCloseModal = jest.fn(); const mockUseReactToPrint = jest.mocked(useReactToPrint); @@ -22,7 +22,10 @@ jest.mock('react-to-print', () => { mockUseConfig.mockReturnValue({ ...getDefaultsFromConfigSchema(configSchema), - printIdentifierStickerFields: ['name', 'identifier', 'age', 'dateOfBirth', 'gender'], + // @ts-ignore + printPatientSticker: { + fields: ['name', 'identifier', 'age', 'dob', 'gender'], + }, }); describe('PrintIdentifierSticker', () => { diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx new file mode 100644 index 0000000000..dce807251b --- /dev/null +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx @@ -0,0 +1,93 @@ +import React from 'react'; +import { age, getCoreTranslation, getPatientName, useConfig } from '@openmrs/esm-framework'; +import dayjs from 'dayjs'; +import { type ConfigObject } from '../../config-schema'; +import { useTranslation } from 'react-i18next'; +import styles from './print-identifier-sticker.scss'; + +export interface PatientDetailProps { + patient: fhir.Patient; +} + +export const PatientName: React.FC = ({ patient }) => { + const { t } = useTranslation(); + return ( +
+ + {t('patientNameWithSeparator', 'Patient name:')} + + {getPatientName(patient)} +
+ ); +}; + +export const PatientAge: React.FC = ({ patient }) => { + const { t } = useTranslation(); + return ( +
+ + {t('patientAge', 'Age:')} + + {age(patient.birthDate)} +
+ ); +}; + +export const PatientDob: React.FC = ({ patient }) => { + const { t } = useTranslation(); + return ( +
+ + {t('patientDateOfBirthWithSeparator', 'Date of birth:')} + + {dayjs(patient.birthDate).format('DD-MM-YYYY')} +
+ ); +}; + +export const PatientGender: React.FC = ({ patient }) => { + const { t } = useTranslation(); + const getGender = (gender: string): string => { + switch (gender) { + case 'male': + return getCoreTranslation('male', 'Male'); + case 'female': + return getCoreTranslation('female', 'Female'); + case 'other': + return getCoreTranslation('other', 'Other'); + case 'unknown': + return getCoreTranslation('unknown', 'Unknown'); + default: + return gender; + } + }; + return ( +
+ + {t('patientGenderWithSeparator', 'Gender:')} + + {getGender(patient.gender)} +
+ ); +}; + +export const PatientIdentifier: React.FC = ({ patient }) => { + const { printPatientSticker } = useConfig(); + const { identifiersToDisplay } = printPatientSticker ?? {}; + const patientIdentifiers = + (identifiersToDisplay ?? []).length === 0 + ? patient.identifier + : patient.identifier?.filter((identifier) => identifiersToDisplay.includes(identifier.type.coding[0].code)); + return ( +
+ {patientIdentifiers?.map((identifier) => ( +
+ + {identifier.type.text}: + + {identifier.value} +
+ ))} +
+ ); +}; diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker-modal.test.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker-modal.test.tsx new file mode 100644 index 0000000000..81e3f0bed3 --- /dev/null +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker-modal.test.tsx @@ -0,0 +1,67 @@ +import React from 'react'; +import userEvent from '@testing-library/user-event'; +import { render, screen } from '@testing-library/react'; +import { useReactToPrint } from 'react-to-print'; +import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; +import { configSchema, type ConfigObject } from '../../config-schema'; +import { mockPatient } from 'tools'; +import PrintIdentifierSticker from './print-identifier-sticker.modal'; + +const mockCloseModal = jest.fn(); +const mockUseReactToPrint = jest.mocked(useReactToPrint); +const mockUseConfig = jest.mocked(useConfig); + +jest.mock('react-to-print', () => { + const originalModule = jest.requireActual('react-to-print'); + + return { + ...originalModule, + useReactToPrint: jest.fn(), + }; +}); + +mockUseConfig.mockReturnValue({ + ...getDefaultsFromConfigSchema(configSchema), + // @ts-ignore + printPatientSticker: { + fields: ['name', 'identifier', 'age', 'dob', 'gender'], + }, +}); + +describe('PrintIdentifierSticker', () => { + test('renders the component', () => { + render(); + + expect(screen.getByText(/Print Identifier Sticker/i)).toBeInTheDocument(); + expect(screen.getByText('John Wilson')).toBeInTheDocument(); + expect(screen.getByText('100GEJ')).toBeInTheDocument(); + expect(screen.getByText('1972-04-04')).toBeInTheDocument(); + }); + + test('calls closeModal when cancel button is clicked', async () => { + const user = userEvent.setup(); + + render(); + + const cancelButton = screen.getByRole('button', { name: /Cancel/i }); + expect(cancelButton).toBeInTheDocument(); + + await user.click(cancelButton); + expect(mockCloseModal).toHaveBeenCalled(); + }); + + test('calls the print function when print button is clicked', async () => { + const handlePrint = jest.fn(); + mockUseReactToPrint.mockReturnValue(handlePrint); + + const user = userEvent.setup(); + + render(); + + const printButton = screen.getByRole('button', { name: /Print/i }); + expect(printButton).toBeInTheDocument(); + + await user.click(printButton); + expect(handlePrint).toHaveBeenCalled(); + }); +}); diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker.modal.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx similarity index 54% rename from packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker.modal.tsx rename to packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx index 47dac29857..e00b0fa6cd 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker.modal.tsx +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx @@ -2,33 +2,21 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation, type TFunction } from 'react-i18next'; import { useReactToPrint } from 'react-to-print'; import { Button, InlineLoading, ModalBody, ModalFooter, ModalHeader } from '@carbon/react'; -import { age, getPatientName, showSnackbar, useConfig, getCoreTranslation } from '@openmrs/esm-framework'; -import { type ConfigObject } from '../config-schema'; +import { age, getPatientName, showSnackbar, useConfig, getCoreTranslation, usePatient } from '@openmrs/esm-framework'; +import { type ConfigObject } from '../../config-schema'; import styles from './print-identifier-sticker.scss'; +import Barcode from 'react-barcode'; +import { defaultBarcodeParams, getPatientField } from './print-identifier-sticker.resource'; interface PrintIdentifierStickerProps { closeModal: () => void; patient: fhir.Patient; } -interface PrintComponentProps extends Partial { - patientDetails: { - address?: fhir.Address[]; - age?: string; - dateOfBirth?: string; - gender?: string; - id?: string; - identifiers?: fhir.Identifier[]; - name?: string; - photo?: fhir.Attachment[]; - }; - t: TFunction; -} - const PrintIdentifierSticker: React.FC = ({ closeModal, patient }) => { const { t } = useTranslation(); - const { printIdentifierStickerFields, printIdentifierStickerSize, excludePatientIdentifierCodeTypes } = - useConfig(); + const { printPatientSticker } = useConfig(); + const { pageSize } = printPatientSticker ?? {}; const contentToPrintRef = useRef(null); const onBeforeGetContentResolve = useRef<() => void | null>(null); const [isPrinting, setIsPrinting] = useState(false); @@ -40,43 +28,6 @@ const PrintIdentifierSticker: React.FC = ({ closeMo } }, [isPrinting]); - const patientDetails = useMemo(() => { - if (!patient) { - return {}; - } - - const getGender = (gender: string): string => { - switch (gender) { - case 'male': - return getCoreTranslation('male', 'Male'); - case 'female': - return getCoreTranslation('female', 'Female'); - case 'other': - return getCoreTranslation('other', 'Other'); - case 'unknown': - return getCoreTranslation('unknown', 'Unknown'); - default: - return gender; - } - }; - - const identifiers = - patient.identifier?.filter( - (identifier) => !excludePatientIdentifierCodeTypes?.uuids.includes(identifier.type.coding[0].code), - ) ?? []; - - return { - address: patient.address, - age: age(patient.birthDate), - dateOfBirth: patient.birthDate, - gender: getGender(patient.gender), - id: patient.id, - identifiers: [...identifiers], - name: patient ? getPatientName(patient) : '', - photo: patient.photo, - }; - }, [excludePatientIdentifierCodeTypes?.uuids, patient]); - const handleBeforeGetContent = useCallback( () => new Promise((resolve) => { @@ -91,8 +42,8 @@ const PrintIdentifierSticker: React.FC = ({ closeMo const handleAfterPrint = useCallback(() => { onBeforeGetContentResolve.current = null; setIsPrinting(false); - closeModal(); - }, [closeModal]); + // closeModal(); + }, []); const handlePrintError = useCallback((errorLocation, error) => { onBeforeGetContentResolve.current = null; @@ -111,10 +62,11 @@ const PrintIdentifierSticker: React.FC = ({ closeMo const handlePrint = useReactToPrint({ content: () => contentToPrintRef.current, - documentTitle: `${patientDetails.name} - ${headerTitle}`, + documentTitle: `${getPatientName(patient)} - ${headerTitle}`, onAfterPrint: handleAfterPrint, onBeforeGetContent: handleBeforeGetContent, onPrintError: handlePrintError, + copyStyles: true, }); return ( @@ -128,15 +80,11 @@ const PrintIdentifierSticker: React.FC = ({ closeMo - + @@ -155,30 +103,38 @@ const PrintIdentifierSticker: React.FC = ({ closeMo ); }; -const PrintComponent = ({ patientDetails, printIdentifierStickerFields, t }: PrintComponentProps) => { +interface PrintComponentProps extends Partial { + patient: fhir.Patient; +} + +const PrintComponent = ({ patient }: PrintComponentProps) => { + const { t } = useTranslation(); + const { printPatientSticker } = useConfig(); return (
- {printIdentifierStickerFields.includes('name') &&
{patientDetails.name}
} -
- {patientDetails.identifiers.map((identifier) => { - return ( -

- {identifier?.type?.text}: {identifier?.value} -

- ); - })} -

- {getCoreTranslation('sex', 'Sex')}: {patientDetails.gender} -

-

- {t('dob', 'DOB')}: {patientDetails.dateOfBirth} -

-

- {getCoreTranslation('age', 'Age')}: {patientDetails.age} -

+
+ +
+ {printPatientSticker.fields.map((field) => { + const Component = getPatientField(field); + return ; + })}
); }; +const ImplementationLogo: React.FC = () => { + const { t } = useTranslation(); + const { printPatientSticker } = useConfig(); + return printPatientSticker.logo ? ( + {printPatientSticker.logo} + ) : ( + + {t('openmrsLogo', 'OpenMRS logo')} + + + ); +}; + export default PrintIdentifierSticker; diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.resource.ts b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.resource.ts new file mode 100644 index 0000000000..4986e74b50 --- /dev/null +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.resource.ts @@ -0,0 +1,39 @@ +import { type Options } from 'react-barcode'; +import { type AllowedPatientFields } from '../../config-schema'; +import { + PatientAge, + type PatientDetailProps, + PatientDob, + PatientGender, + PatientIdentifier, + PatientName, +} from './patient-detail.component'; + +export const defaultBarcodeParams: Options = { + width: 2, + background: '#f4f4f4', + displayValue: true, + renderer: 'img', + font: 'IBM Plex Sans', + textAlign: 'center', + textPosition: 'bottom', + fontSize: 16, +}; + +export function getPatientField(field: AllowedPatientFields): React.FC { + switch (field) { + case 'name': + return PatientName; + case 'age': + return PatientAge; + case 'dob': + return PatientDob; + case 'gender': + return PatientGender; + case 'identifier': + return PatientIdentifier; + default: + console.error(`Invalid patient field: ${field}`); + return null; + } +} diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker.scss b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.scss similarity index 78% rename from packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker.scss rename to packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.scss index 08e0962fdf..524b7162d7 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker.scss +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.scss @@ -5,6 +5,12 @@ padding: layout.$spacing-03 layout.$spacing-05; } +.documentHeader { + display: flex; + justify-content: space-between; + align-items: center; +} + .row { margin: layout.$spacing-03 0 0; display: flex; @@ -49,6 +55,16 @@ } } +.strong { + @include type.type-style('heading-06'); + font-weight: 700; + margin-right: layout.$spacing-03; +} + +.patientDetail { + @include type.type-style('heading-05'); +} + @media print { html, body { diff --git a/packages/esm-patient-banner-app/src/config-schema.ts b/packages/esm-patient-banner-app/src/config-schema.ts index 93c5d5e005..161855ce78 100644 --- a/packages/esm-patient-banner-app/src/config-schema.ts +++ b/packages/esm-patient-banner-app/src/config-schema.ts @@ -1,4 +1,5 @@ import { Type } from '@openmrs/esm-framework'; +import _default from 'react-hook-form/dist/logic/appendErrors'; export const configSchema = { contactAttributeTypes: { @@ -12,42 +13,56 @@ export const configSchema = { _type: Type.UUID, }, }, - excludePatientIdentifierCodeTypes: { - uuids: { + + printPatientSticker: { + enabled: { + _type: Type.Boolean, + _description: 'Whether to enable the print patient sticker feature', + _default: true, + }, + fields: { + _type: Type.Array, + _description: 'Patient demographics to include in the patient sticker printout', + _default: ['name', 'dob', 'gender', 'identifier', 'age'], + }, + pageSize: { + _type: Type.String, + _description: + 'Specifies the paper size for printing the sticker. You can define the size using units (e.g., mm, in) or named sizes (e.g., "148mm 210mm", "A1", "A2", "A4", "A5").', + _default: 'A4', + }, + identifiersToDisplay: { _type: Type.Array, - _description: 'List of UUIDs of patient identifier types to exclude from rendering in the patient banner', + _description: + 'List of UUIDs of patient identifier types to exclude from rendering in the patient banner. If empty, all identifiers will be displayed.', _default: [], _elements: { _type: Type.UUID, }, }, - }, - printIdentifierStickerFields: { - _type: Type.Array, - _description: 'Patient demographics to include in the identifier sticker printout', - _default: ['age', 'dateOfBirth', 'gender', 'identifier', 'name'], - _elements: { + logo: { _type: Type.String, + _description: 'The URL of the logo to display in the patient sticker', + _default: '', }, }, - printIdentifierStickerSize: { - _type: Type.String, - _description: - 'Specifies the paper size for printing the sticker. You can define the size using units (e.g., mm, in) or named sizes (e.g., "148mm 210mm", "A1", "A2", "A4", "A5").', - _default: '4in 6in', - }, useRelationshipNameLink: { _type: Type.Boolean, _description: "Whether to use the relationship name as a link to the associated person's patient chart.", _default: false, }, }; + +export type AllowedPatientFields = 'name' | 'dob' | 'gender' | 'identifier' | 'age'; + export interface ConfigObject { contactAttributeTypes: Array; - excludePatientIdentifierCodeTypes: { - uuids: Array; + printPatientSticker: { + enabled: boolean; + fields: Array; + pageSize: string; + identifiersToDisplay: Array; + logo: string; }; - printIdentifierStickerFields: Array; - printIdentifierStickerSize: string; useRelationshipNameLink: boolean; } diff --git a/packages/esm-patient-banner-app/src/index.ts b/packages/esm-patient-banner-app/src/index.ts index 8a538bfbd1..12c537126c 100644 --- a/packages/esm-patient-banner-app/src/index.ts +++ b/packages/esm-patient-banner-app/src/index.ts @@ -35,7 +35,7 @@ export const deceasedPatientTag = getSyncLifecycle(deceasedPatientTagComponent, export const patientBanner = getSyncLifecycle(patientBannerComponent, options); export const printIdentifierStickerModal = getAsyncLifecycle( - () => import('./banner-tags/print-identifier-sticker.modal'), + () => import('./banner-tags/print-identifier-sticker/print-identifier-sticker.modal'), options, ); diff --git a/packages/esm-patient-banner-app/translations/en.json b/packages/esm-patient-banner-app/translations/en.json index c96dacfc21..3870023a35 100644 --- a/packages/esm-patient-banner-app/translations/en.json +++ b/packages/esm-patient-banner-app/translations/en.json @@ -6,7 +6,7 @@ "country": "Country", "countyDistrict": "District", "district": "District", - "dob": "DOB", + "openmrsLogo": "OpenMRS logo", "patientIdentifierSticker": "Patient identifier sticker", "postalCode": "Postal code", "state": "State", diff --git a/yarn.lock b/yarn.lock index 0a476de993..3864f60334 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5997,6 +5997,7 @@ __metadata: openmrs: "npm:next" prettier: "npm:^3.0.3" react: "npm:^18.3.1" + react-barcode: "npm:^1.5.3" react-dom: "npm:^18.3.1" react-hook-form: "npm:^7.46.2" react-i18next: "npm:^11.18.6" @@ -22352,6 +22353,18 @@ __metadata: languageName: node linkType: hard +"react-barcode@npm:^1.5.3": + version: 1.5.3 + resolution: "react-barcode@npm:1.5.3" + dependencies: + jsbarcode: "npm:^3.8.0" + prop-types: "npm:^15.6.2" + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: 10/1c1953c6e64fad12cf60f6be82a138849c5d8f0267b7aac1077662b86e58637192282d4a22d745f947c1ae168f058fe1a53f3111a00ba34d4d53657ebb1118c1 + languageName: node + linkType: hard + "react-dom@npm:^18.1.0, react-dom@npm:^18.2.0, react-dom@npm:^18.3.1": version: 18.3.1 resolution: "react-dom@npm:18.3.1" From 4ea8854d9090e110eb5a5b17692abae3df123d18 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Mon, 2 Sep 2024 14:02:50 +0530 Subject: [PATCH 02/10] Updated translations --- packages/esm-patient-banner-app/translations/en.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/esm-patient-banner-app/translations/en.json b/packages/esm-patient-banner-app/translations/en.json index 3870023a35..504a0e6725 100644 --- a/packages/esm-patient-banner-app/translations/en.json +++ b/packages/esm-patient-banner-app/translations/en.json @@ -7,7 +7,11 @@ "countyDistrict": "District", "district": "District", "openmrsLogo": "OpenMRS logo", + "patientAge": "Age:", + "patientDateOfBirthWithSeparator": "Date of birth:", + "patientGenderWithSeparator": "Gender:", "patientIdentifierSticker": "Patient identifier sticker", + "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", "state": "State", "stateProvince": "State" From 994ad9cb6f52d724a224df9f18eb5b01f8bac4c3 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Mon, 2 Sep 2024 14:10:27 +0530 Subject: [PATCH 03/10] Add svg for OpenMRS logo --- .../print-identifier-sticker.modal.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx index e00b0fa6cd..42ff46f53b 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx @@ -130,9 +130,12 @@ const ImplementationLogo: React.FC = () => { return printPatientSticker.logo ? ( {printPatientSticker.logo} ) : ( - - {t('openmrsLogo', 'OpenMRS logo')} - + + ); }; From 5ed4643a36f2a9680231a1b5932e19730627ed02 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Mon, 2 Sep 2024 14:35:15 +0530 Subject: [PATCH 04/10] Update config for printing identifier sticker --- .../print-identifier-sticker.modal.tsx | 8 +++-- .../src/config-schema.ts | 33 +++++++++++++++---- .../translations/en.json | 1 - 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx index 42ff46f53b..2c3841fcf9 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx @@ -110,10 +110,11 @@ interface PrintComponentProps extends Partial { const PrintComponent = ({ patient }: PrintComponentProps) => { const { t } = useTranslation(); const { printPatientSticker } = useConfig(); + const primaryIdentifierValue = patient?.identifier?.find((identifier) => identifier.use === 'official')?.value; return (
- +
{printPatientSticker.fields.map((field) => { @@ -127,8 +128,9 @@ const PrintComponent = ({ patient }: PrintComponentProps) => { const ImplementationLogo: React.FC = () => { const { t } = useTranslation(); const { printPatientSticker } = useConfig(); - return printPatientSticker.logo ? ( - {printPatientSticker.logo} + + return printPatientSticker?.header?.logo ? ( + {printPatientSticker?.header?.logo} ) : ( ; printPatientSticker: { enabled: boolean; + header: { + showBarcode: boolean; + showLogo: boolean; + logo: string; + }; fields: Array; pageSize: string; identifiersToDisplay: Array; - logo: string; }; useRelationshipNameLink: boolean; } diff --git a/packages/esm-patient-banner-app/translations/en.json b/packages/esm-patient-banner-app/translations/en.json index 504a0e6725..0222e742af 100644 --- a/packages/esm-patient-banner-app/translations/en.json +++ b/packages/esm-patient-banner-app/translations/en.json @@ -6,7 +6,6 @@ "country": "Country", "countyDistrict": "District", "district": "District", - "openmrsLogo": "OpenMRS logo", "patientAge": "Age:", "patientDateOfBirthWithSeparator": "Date of birth:", "patientGenderWithSeparator": "Gender:", From 374f7173d912bc8e9e5d7f5dd5155c496658bf96 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Wed, 18 Sep 2024 22:43:29 +0530 Subject: [PATCH 05/10] Added fields for contact and address, and finalize the designs --- .../patient-detail.component.tsx | 56 ++++++++++++++++++- .../print-identifier-sticker.modal.tsx | 12 +++- .../print-identifier-sticker.resource.ts | 6 ++ .../print-identifier-sticker.scss | 13 ++++- .../src/config-schema.ts | 36 ++++++------ yarn.lock | 7 +++ 6 files changed, 105 insertions(+), 25 deletions(-) diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx index dce807251b..09f0dcfe22 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { age, getCoreTranslation, getPatientName, useConfig } from '@openmrs/esm-framework'; +import { age, type CoreTranslationKey, getCoreTranslation, getPatientName, useConfig } from '@openmrs/esm-framework'; import dayjs from 'dayjs'; import { type ConfigObject } from '../../config-schema'; import { useTranslation } from 'react-i18next'; @@ -91,3 +91,57 @@ export const PatientIdentifier: React.FC = ({ patient }) =>
); }; + +export const PatientContact: React.FC = ({ patient }) => { + const { t } = useTranslation(); + + if (patient.telecom.length == 0) { + return null; + } + + return ( +
+ + {t('telephoneNumberWithSeparator', 'Telephone number:')} + + {patient.telecom[0]?.value} +
+ ); +}; + +export const PatientAddress: React.FC = ({ patient }) => { + const address = patient?.address?.find((a) => a.use === 'home'); + const getAddressKey = (url: string) => url.split('#')[1]; + + return ( + <> + {address ? ( + Object.entries(address) + .filter(([key]) => key !== 'id' && key !== 'use') + .map(([key, value]) => + key === 'extension' ? ( + address.extension?.[0]?.extension?.map((add, i) => ( +
+ + {getCoreTranslation( + getAddressKey(add.url) as CoreTranslationKey, + getAddressKey(add.url) as CoreTranslationKey, + )} + : + + {add.valueString} +
+ )) + ) : ( +
+ {getCoreTranslation(key as CoreTranslationKey, key)}: + {value} +
+ ), + ) + ) : ( +
  • --
  • + )} + + ); +}; diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx index 2c3841fcf9..dce02881a0 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx @@ -114,8 +114,14 @@ const PrintComponent = ({ patient }: PrintComponentProps) => { return (
    - - + {printPatientSticker?.header?.showBarcode && ( + + )} + {printPatientSticker?.header?.showLogo && ( +
    + +
    + )}
    {printPatientSticker.fields.map((field) => { const Component = getPatientField(field); @@ -130,7 +136,7 @@ const ImplementationLogo: React.FC = () => { const { printPatientSticker } = useConfig(); return printPatientSticker?.header?.logo ? ( - {printPatientSticker?.header?.logo} + implementation-logo ) : ( ; diff --git a/yarn.lock b/yarn.lock index 3864f60334..42d7d12c8e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18185,6 +18185,13 @@ __metadata: languageName: node linkType: hard +"jsbarcode@npm:^3.8.0": + version: 3.11.6 + resolution: "jsbarcode@npm:3.11.6" + checksum: 10/4dcf9f675e799741c89fa4941a97147a1c01575d792a186d8f1f8ad6b949d9d78fa658b0c9321ec1fa2c9ec0aa9784ac1181632357585114ecd74e9a3a08c979 + languageName: node + linkType: hard + "jsbn@npm:1.1.0": version: 1.1.0 resolution: "jsbn@npm:1.1.0" From efdabba1283fa8f705967aa8938fd064b6c94c31 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Wed, 18 Sep 2024 22:44:12 +0530 Subject: [PATCH 06/10] Updated translations --- packages/esm-patient-banner-app/translations/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/esm-patient-banner-app/translations/en.json b/packages/esm-patient-banner-app/translations/en.json index 0222e742af..9063d36550 100644 --- a/packages/esm-patient-banner-app/translations/en.json +++ b/packages/esm-patient-banner-app/translations/en.json @@ -13,5 +13,6 @@ "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", "state": "State", - "stateProvince": "State" + "stateProvince": "State", + "telephoneNumberWithSeparator": "Telephone number:" } From 6e35a62f803a033d9b8dad54403f1f2023090429 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Thu, 19 Sep 2024 17:04:45 +0530 Subject: [PATCH 07/10] Added tests for print patient identifier sticker --- __mocks__/patient.mock.ts | 323 ++++++++++++++++++ .../print-identifier-sticker-modal.test.tsx | 67 ---- .../print-identifier-sticker-modal.test.tsx | 159 ++++++--- .../print-identifier-sticker.modal.tsx | 2 +- 4 files changed, 429 insertions(+), 122 deletions(-) create mode 100644 __mocks__/patient.mock.ts delete mode 100644 packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker-modal.test.tsx diff --git a/__mocks__/patient.mock.ts b/__mocks__/patient.mock.ts new file mode 100644 index 0000000000..14535779f3 --- /dev/null +++ b/__mocks__/patient.mock.ts @@ -0,0 +1,323 @@ +export const mockFhirPatient: fhir.Patient = { + resourceType: 'Patient', + id: 'bfa09dac-ec9e-47c1-9ad3-e3ebdd5d722d', + meta: { + versionId: '1719312976000', + lastUpdated: '2024-06-25T10:56:16.000+00:00', + }, + text: { + status: 'generated', + div: '
    Id:bfa09dac-ec9e-47c1-9ad3-e3ebdd5d722d
    Identifier:
    100008E
    Active:true
    Name: Joshua JOHNSON
    Telecom: +255777053243
    Gender:MALE
    Birth Date:25/09/2019
    Deceased:false
    Address:Wakiso Kayunga Uganda
    ', + }, + identifier: [ + { + id: 'fc6b122a-05bd-4128-8577-7efd8c87cda5', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/patient/identifier#location', + valueReference: { + reference: 'Location/736b08f9-94d6-4b50-ad58-6bc69b9cbfb8', + // type: 'Location', + display: 'Ward 50', + }, + }, + ], + use: 'official', + type: { + coding: [ + { + code: '05a29f94-c0ed-11e2-94be-8c13b969e334', + }, + ], + text: 'OpenMRS ID', + }, + value: '100008E', + }, + ], + active: true, + name: [ + { + id: '67ac67de-aac4-43b3-a0d4-677578a01047', + text: 'Joshua Johnson', + family: 'Johnson', + given: ['Joshua'], + }, + ], + telecom: [ + { + id: 'f3f3c756-d8f1-42ce-8d32-eefe2a86c306', + value: '+255777053243', + }, + ], + gender: 'male', + birthDate: '2019-09-25', + deceasedBoolean: false, + address: [ + { + id: '1e9df4ab-0c73-4f99-b0bd-c2ddc239619b', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Nansana', + }, + ], + }, + ], + use: 'home', + city: 'Wakiso', + state: 'Kayunga', + postalCode: '00000', + country: 'Uganda', + }, + { + id: '93167c61-81da-48e1-8a6d-91640a55ed73', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: '7befd893-a7ed-4080-986a-db5f5d38fda4', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: 'c0a87353-ab2c-4c39-ae7b-13e992206916', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: 'b1c92fab-8002-48ed-a1e1-72ab942d12da', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: 'c85af135-28a4-483d-864d-d97751c21ebd', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: 'a6a15f40-5cc8-47c0-89ee-8cc39d2c73f5', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: '72f199fa-f569-42fb-8f5a-bc1c7bed7bb8', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: '4e0251d4-c00e-4167-ad3e-077c485aa7ec', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: '1b932ad6-d50a-4c57-a3cf-0fee5b3226fa', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: '90c59f5a-2cb4-405f-8c2b-0b5d2746d5ae', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Address16442', + }, + ], + }, + ], + use: 'old', + city: 'City6442', + state: 'State6442', + postalCode: '20839', + country: 'Country6442', + }, + { + id: '810f3756-cb30-4fd8-a729-f6c1a5847312', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Nansana', + }, + ], + }, + ], + use: 'old', + city: 'Wakiso', + state: 'Kayunga', + postalCode: '00000', + country: 'Uganda', + }, + { + id: '72d21a40-c872-4b99-ac2a-f7b179c4aff2', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Nansana', + }, + ], + }, + ], + use: 'old', + city: 'Wakiso', + state: 'Kayunga', + postalCode: '00000', + country: 'Uganda', + }, + { + id: '6f7781b2-4b4d-4c69-bde0-98127712aa76', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address', + extension: [ + { + url: 'http://fhir.openmrs.org/ext/address#address1', + valueString: 'Nansana', + }, + ], + }, + ], + use: 'old', + city: 'Wakiso', + state: 'Kayunga', + postalCode: '00000', + country: 'Uganda', + }, + ], +}; diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker-modal.test.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker-modal.test.tsx deleted file mode 100644 index 844ae54b02..0000000000 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker-modal.test.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React from 'react'; -import userEvent from '@testing-library/user-event'; -import { render, screen } from '@testing-library/react'; -import { useReactToPrint } from 'react-to-print'; -import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; -import { configSchema, type ConfigObject } from '../config-schema'; -import { mockPatient } from 'tools'; -import PrintIdentifierSticker from './print-identifier-sticker/print-identifier-sticker.modal'; - -const mockCloseModal = jest.fn(); -const mockUseReactToPrint = jest.mocked(useReactToPrint); -const mockUseConfig = jest.mocked(useConfig); - -jest.mock('react-to-print', () => { - const originalModule = jest.requireActual('react-to-print'); - - return { - ...originalModule, - useReactToPrint: jest.fn(), - }; -}); - -mockUseConfig.mockReturnValue({ - ...getDefaultsFromConfigSchema(configSchema), - // @ts-ignore - printPatientSticker: { - fields: ['name', 'identifier', 'age', 'dob', 'gender'], - }, -}); - -describe('PrintIdentifierSticker', () => { - test('renders the component', () => { - render(); - - expect(screen.getByText(/Print Identifier Sticker/i)).toBeInTheDocument(); - expect(screen.getByText('John Wilson')).toBeInTheDocument(); - expect(screen.getByText('100GEJ')).toBeInTheDocument(); - expect(screen.getByText('1972-04-04')).toBeInTheDocument(); - }); - - test('calls closeModal when cancel button is clicked', async () => { - const user = userEvent.setup(); - - render(); - - const cancelButton = screen.getByRole('button', { name: /Cancel/i }); - expect(cancelButton).toBeInTheDocument(); - - await user.click(cancelButton); - expect(mockCloseModal).toHaveBeenCalled(); - }); - - test('calls the print function when print button is clicked', async () => { - const handlePrint = jest.fn(); - mockUseReactToPrint.mockReturnValue(handlePrint); - - const user = userEvent.setup(); - - render(); - - const printButton = screen.getByRole('button', { name: /Print/i }); - expect(printButton).toBeInTheDocument(); - - await user.click(printButton); - expect(handlePrint).toHaveBeenCalled(); - }); -}); diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker-modal.test.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker-modal.test.tsx index 81e3f0bed3..d600ad3dee 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker-modal.test.tsx +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker-modal.test.tsx @@ -1,67 +1,118 @@ import React from 'react'; -import userEvent from '@testing-library/user-event'; import { render, screen } from '@testing-library/react'; -import { useReactToPrint } from 'react-to-print'; -import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; -import { configSchema, type ConfigObject } from '../../config-schema'; -import { mockPatient } from 'tools'; import PrintIdentifierSticker from './print-identifier-sticker.modal'; +import { mockFhirPatient } from '../../../../../__mocks__/patient.mock'; +import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; +import { type ConfigObject, configSchema } from '../../config-schema'; +import { useReactToPrint } from 'react-to-print'; +import userEvent from '@testing-library/user-event'; +import Barcode from 'react-barcode'; +import { getByTextWithMarkup } from 'tools'; -const mockCloseModal = jest.fn(); -const mockUseReactToPrint = jest.mocked(useReactToPrint); -const mockUseConfig = jest.mocked(useConfig); - -jest.mock('react-to-print', () => { - const originalModule = jest.requireActual('react-to-print'); - - return { - ...originalModule, - useReactToPrint: jest.fn(), - }; -}); - -mockUseConfig.mockReturnValue({ - ...getDefaultsFromConfigSchema(configSchema), - // @ts-ignore - printPatientSticker: { - fields: ['name', 'identifier', 'age', 'dob', 'gender'], - }, -}); +const mockedCloseModal = jest.fn(); +const mockedUseConfig = jest + .mocked(useConfig) + .mockResolvedValue(getDefaultsFromConfigSchema(configSchema)); +jest.mock('react-to-print', () => ({ + ...jest.requireActual('react-to-print'), + useReactToPrint: jest.fn(), +})); +const mockedUseReactToPrint = jest.mocked(useReactToPrint); -describe('PrintIdentifierSticker', () => { - test('renders the component', () => { - render(); +jest.mock('react-barcode', () => jest.fn().mockReturnValue(
    )); - expect(screen.getByText(/Print Identifier Sticker/i)).toBeInTheDocument(); - expect(screen.getByText('John Wilson')).toBeInTheDocument(); - expect(screen.getByText('100GEJ')).toBeInTheDocument(); - expect(screen.getByText('1972-04-04')).toBeInTheDocument(); +describe('Testing PrintIdentifierStickerModal', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockedUseConfig.mockReturnValue(getDefaultsFromConfigSchema(configSchema)); }); - - test('calls closeModal when cancel button is clicked', async () => { + it('should render PrintIdentifierStickerModal', async () => { const user = userEvent.setup(); - - render(); - - const cancelButton = screen.getByRole('button', { name: /Cancel/i }); - expect(cancelButton).toBeInTheDocument(); - + const mockHandlePrint = jest.fn(); + mockedUseReactToPrint.mockReturnValue(mockHandlePrint); + renderPrintIdentifierStickerModal(); + expect(screen.getByText(/print identifier sticker/i)).toBeInTheDocument(); + const printButton = screen.getByRole('button', { name: /print/i }); + const cancelButton = screen.getByRole('button', { name: /cancel/i }); await user.click(cancelButton); - expect(mockCloseModal).toHaveBeenCalled(); + expect(mockedCloseModal).toHaveBeenCalled(); + await user.click(printButton); + expect(mockHandlePrint).toHaveBeenCalled(); + }); + it('should render barcode if enabled via config', async () => { + const defaultConfig = getDefaultsFromConfigSchema(configSchema) as ConfigObject; + mockedUseConfig.mockReturnValue({ + ...defaultConfig, + printPatientSticker: { + ...defaultConfig.printPatientSticker, + header: { + showBarcode: true, + showLogo: true, + logo: '', + }, + }, + }); + renderPrintIdentifierStickerModal(); + expect(screen.getByTestId('barcode')).toBeInTheDocument(); + expect(Barcode).toHaveBeenCalledWith( + { + value: '100008E', + width: 2, + background: '#f4f4f4', + displayValue: true, + renderer: 'img', + font: 'IBM Plex Sans', + textAlign: 'center', + textPosition: 'bottom', + fontSize: 16, + }, + {}, + ); + expect(screen.getByTestId('openmrs-logo')).toBeInTheDocument(); + }); + it("should not render barcode if it's disabled via config", async () => { + const defaultConfig = getDefaultsFromConfigSchema(configSchema) as ConfigObject; + mockedUseConfig.mockReturnValue({ + ...defaultConfig, + printPatientSticker: { + ...defaultConfig.printPatientSticker, + header: { + showBarcode: false, + showLogo: false, + logo: '', + }, + }, + }); + renderPrintIdentifierStickerModal(); + expect(screen.queryByTestId('barcode')).not.toBeInTheDocument(); + expect(screen.queryByTestId('openmrs-logo')).not.toBeInTheDocument(); + }); + it('should render implementation logo if passed via config', () => { + const defaultConfig = getDefaultsFromConfigSchema(configSchema) as ConfigObject; + mockedUseConfig.mockReturnValue({ + ...defaultConfig, + printPatientSticker: { + ...defaultConfig.printPatientSticker, + header: { + showBarcode: true, + showLogo: true, + logo: '/openmrs/spa/logo.png', + }, + }, + }); + renderPrintIdentifierStickerModal(); + expect(screen.getByRole('img')).toHaveAttribute('src', '/openmrs/spa/logo.png'); }); - test('calls the print function when print button is clicked', async () => { - const handlePrint = jest.fn(); - mockUseReactToPrint.mockReturnValue(handlePrint); - - const user = userEvent.setup(); - - render(); - - const printButton = screen.getByRole('button', { name: /Print/i }); - expect(printButton).toBeInTheDocument(); - - await user.click(printButton); - expect(handlePrint).toHaveBeenCalled(); + it('should render patient details', () => { + renderPrintIdentifierStickerModal(); + expect(getByTextWithMarkup(/Joshua Johnson/i)).toBeInTheDocument(); + expect(getByTextWithMarkup(/\+255777053243/i)).toBeInTheDocument(); + expect(getByTextWithMarkup(/100008E/i)).toBeInTheDocument(); + expect(getByTextWithMarkup(/4 yrs, 11 mths/i)).toBeInTheDocument(); }); }); + +function renderPrintIdentifierStickerModal() { + return render(); +} diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx index dce02881a0..86912af776 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx +++ b/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/print-identifier-sticker.modal.tsx @@ -138,7 +138,7 @@ const ImplementationLogo: React.FC = () => { return printPatientSticker?.header?.logo ? ( implementation-logo ) : ( - + Date: Thu, 19 Sep 2024 17:59:17 +0530 Subject: [PATCH 08/10] Remove print identifier sticker feature flag --- packages/esm-form-entry-app/package.json | 2 +- packages/esm-patient-banner-app/src/index.ts | 10 +- .../action-button.scss | 3 + .../patient-detail.component.tsx | 2 +- ...ifier-sticker-action-button.component.tsx} | 14 +- .../print-identifier-sticker-modal.test.tsx | 4 +- .../print-identifier-sticker.modal.tsx | 2 +- .../print-identifier-sticker.resource.ts | 2 +- .../print-identifier-sticker.scss | 0 .../esm-patient-banner-app/src/routes.json | 7 + packages/esm-patient-chart-app/src/index.ts | 11 - .../esm-patient-chart-app/src/routes.json | 7 - yarn.lock | 214 +++++++++--------- 13 files changed, 141 insertions(+), 137 deletions(-) create mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss rename packages/esm-patient-banner-app/src/{banner-tags => }/print-identifier-sticker/patient-detail.component.tsx (98%) rename packages/{esm-patient-chart-app/src/actions-buttons/print-identifier-sticker.component.tsx => esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx} (67%) rename packages/esm-patient-banner-app/src/{banner-tags => }/print-identifier-sticker/print-identifier-sticker-modal.test.tsx (96%) rename packages/esm-patient-banner-app/src/{banner-tags => }/print-identifier-sticker/print-identifier-sticker.modal.tsx (99%) rename packages/esm-patient-banner-app/src/{banner-tags => }/print-identifier-sticker/print-identifier-sticker.resource.ts (93%) rename packages/esm-patient-banner-app/src/{banner-tags => }/print-identifier-sticker/print-identifier-sticker.scss (100%) diff --git a/packages/esm-form-entry-app/package.json b/packages/esm-form-entry-app/package.json index 1ce81394ed..6712e130cf 100644 --- a/packages/esm-form-entry-app/package.json +++ b/packages/esm-form-entry-app/package.json @@ -94,7 +94,7 @@ "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "^2.1.0", "ngx-build-plus": "^17.0.0", - "openmrs": "next", + "openmrs": "^5.8.2-pre.2324", "protractor": "~7.0.0", "rxjs": "^7.8.0", "style-loader": "2.x", diff --git a/packages/esm-patient-banner-app/src/index.ts b/packages/esm-patient-banner-app/src/index.ts index 12c537126c..9da2558d6d 100644 --- a/packages/esm-patient-banner-app/src/index.ts +++ b/packages/esm-patient-banner-app/src/index.ts @@ -35,10 +35,18 @@ export const deceasedPatientTag = getSyncLifecycle(deceasedPatientTagComponent, export const patientBanner = getSyncLifecycle(patientBannerComponent, options); export const printIdentifierStickerModal = getAsyncLifecycle( - () => import('./banner-tags/print-identifier-sticker/print-identifier-sticker.modal'), + () => import('./print-identifier-sticker/print-identifier-sticker.modal'), options, ); +export const printIdentifierStickerActionButton = getAsyncLifecycle( + () => import('./print-identifier-sticker/print-identifier-sticker-action-button.component'), + { + featureName: 'patient-actions-slot-print-identifier-sticker-button', + moduleName, + }, +); + /* The translations for built-in address fields are kept here in patient-banner. This comment ensures that they are included in the translations files. diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss b/packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss new file mode 100644 index 0000000000..2a7fdf7d6c --- /dev/null +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss @@ -0,0 +1,3 @@ +.menuitem { + max-width: none; +} diff --git a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx similarity index 98% rename from packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx rename to packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx index 09f0dcfe22..8e5adf3370 100644 --- a/packages/esm-patient-banner-app/src/banner-tags/print-identifier-sticker/patient-detail.component.tsx +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { age, type CoreTranslationKey, getCoreTranslation, getPatientName, useConfig } from '@openmrs/esm-framework'; import dayjs from 'dayjs'; -import { type ConfigObject } from '../../config-schema'; +import { type ConfigObject } from '../config-schema'; import { useTranslation } from 'react-i18next'; import styles from './print-identifier-sticker.scss'; diff --git a/packages/esm-patient-chart-app/src/actions-buttons/print-identifier-sticker.component.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx similarity index 67% rename from packages/esm-patient-chart-app/src/actions-buttons/print-identifier-sticker.component.tsx rename to packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 8ccaaf6f06..0e68234203 100644 --- a/packages/esm-patient-chart-app/src/actions-buttons/print-identifier-sticker.component.tsx +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -1,16 +1,20 @@ import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; -import { showModal, useFeatureFlag } from '@openmrs/esm-framework'; +import { showModal, useConfig, useFeatureFlag, usePatient } from '@openmrs/esm-framework'; import styles from './action-button.scss'; +import type { ConfigObject } from '../config-schema'; interface PrintIdentifierStickerOverflowMenuItemProps { - patient: fhir.Patient; + patientUuid: string; } -const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { +const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ + patientUuid, +}) => { const { t } = useTranslation(); - const canPrintPatientIdentifierSticker = useFeatureFlag('print-patient-identifier-sticker'); + const { printPatientSticker } = useConfig(); + const { patient } = usePatient(patientUuid); const handleLaunchModal = useCallback(() => { const dispose = showModal('print-identifier-sticker-modal', { @@ -19,7 +23,7 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC import('./visit/visits-widget/active-visit-buttons/active-visit-buttons'), { featureName: 'active-visit-actions', moduleName }, diff --git a/packages/esm-patient-chart-app/src/routes.json b/packages/esm-patient-chart-app/src/routes.json index b006461f43..71fde6684e 100644 --- a/packages/esm-patient-chart-app/src/routes.json +++ b/packages/esm-patient-chart-app/src/routes.json @@ -70,13 +70,6 @@ "online": true, "offline": true }, - { - "name": "print-identifier-sticker-button", - "slot": "patient-actions-slot", - "component": "printIdentifierStickerActionButton", - "online": true, - "offline": true - }, { "name": "add-past-visit-button", "slot": "patient-search-actions-slot", diff --git a/yarn.lock b/yarn.lock index 42d7d12c8e..12479e9a6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5516,9 +5516,9 @@ __metadata: languageName: node linkType: hard -"@openmrs/esm-api@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-api@npm:5.8.2-pre.2361" +"@openmrs/esm-api@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-api@npm:5.8.2-pre.2369" dependencies: "@types/fhir": "npm:0.0.31" lodash-es: "npm:^4.17.21" @@ -5527,17 +5527,17 @@ __metadata: "@openmrs/esm-error-handling": 5.x "@openmrs/esm-navigation": 5.x "@openmrs/esm-offline": 5.x - checksum: 10/b4b531ca8efe645fc33215b4b0f36394a18524e986df4dc31514bfacf9faa8e25e0a2311a2ae41f17fd9c5507f16baee2c2cb328774237173f3b57ab358603a1 + checksum: 10/cf66b24879c3a4c754c59fea05de33628cba06a44ecb57b58da8dc673ff298fbf7953af4e36f0088cdad62b00d9fbf7e95cf2ee493c5422c17eb272d28f4a4d8 languageName: node linkType: hard -"@openmrs/esm-app-shell@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-app-shell@npm:5.8.2-pre.2361" +"@openmrs/esm-app-shell@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-app-shell@npm:5.8.2-pre.2369" dependencies: "@carbon/react": "npm:~1.37.0" - "@openmrs/esm-framework": "npm:5.8.2-pre.2361" - "@openmrs/esm-styleguide": "npm:5.8.2-pre.2361" + "@openmrs/esm-framework": "npm:5.8.2-pre.2369" + "@openmrs/esm-styleguide": "npm:5.8.2-pre.2369" dayjs: "npm:^1.10.4" dexie: "npm:^3.0.3" html-webpack-plugin: "npm:^5.5.0" @@ -5562,13 +5562,13 @@ __metadata: workbox-strategies: "npm:^6.1.5" workbox-webpack-plugin: "npm:^6.1.5" workbox-window: "npm:^6.1.5" - checksum: 10/a71536c158c46b8e166bb4f77b7bf24c89d261c4a6611d96fcf181c9e040e6892125603684a1aa7f8b5deff19953a2514d1d62f5ea28890ca9455592fbd083ad + checksum: 10/994a0de0e78c2b6dcfe328afb4359f9e7f20434809c1ae0af4d5fe85ef3918403d2e9ca787f7c7ef546c09cb26b35fd341ed0175f22d81bf2e52dc3d74eb8e16 languageName: node linkType: hard -"@openmrs/esm-config@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-config@npm:5.8.2-pre.2361" +"@openmrs/esm-config@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-config@npm:5.8.2-pre.2369" dependencies: ramda: "npm:^0.26.1" peerDependencies: @@ -5576,44 +5576,44 @@ __metadata: "@openmrs/esm-state": 5.x "@openmrs/esm-utils": 5.x single-spa: 5.x - checksum: 10/0e3184227ab66a8ddd93c0c24e5822f0ca205b8421129f8d635b24e0befa213f95750d8346411aca74a17ef9fee75006e414b570c282d59fc13f95081f942720 + checksum: 10/93e73515ff872b26506d24176f9aa5b97a1c5d38860c41dcc1572975d5e2fb36e19750a3ecbc0149601cb926be886b0d9a714f9aee3529ace5545e0421182155 languageName: node linkType: hard -"@openmrs/esm-context@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-context@npm:5.8.2-pre.2361" +"@openmrs/esm-context@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-context@npm:5.8.2-pre.2369" dependencies: immer: "npm:^10.0.4" peerDependencies: "@openmrs/esm-globals": 5.x "@openmrs/esm-state": 5.x - checksum: 10/61f1439da8658f41274d391cf41906adbaa5ab55e8955febbf919c840544ec4a60c60e967151fe7ebcc903466a259fd7d2a54b355af703280cb62698e3f48b52 + checksum: 10/3e751c7d458efb6b19f2bda340b5b399af21e6d387d871a4f32922f30790e56183f63d455e44b22c0e99951d66c22da26d518fdfff2f81e703fc669a931b588a languageName: node linkType: hard -"@openmrs/esm-dynamic-loading@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-dynamic-loading@npm:5.8.2-pre.2361" +"@openmrs/esm-dynamic-loading@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-dynamic-loading@npm:5.8.2-pre.2369" peerDependencies: "@openmrs/esm-globals": 5.x "@openmrs/esm-translations": 5.x - checksum: 10/bbb5d1de5b5872ea727957b7754bf171c3d6372736f9b5371adb368860d71ef2c537d7a0e10acf8a3caaa11fb1d1f77004cd7dd07b73e17f101dc450af8c20cd + checksum: 10/762d33106bb2bca285fa239ed97a644e67fb6b68ef03621f6813bb429498a30400e616d440a2186957355b3142236d47128c42dc0fd247ca3e8b7a73d94d2051 languageName: node linkType: hard -"@openmrs/esm-error-handling@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-error-handling@npm:5.8.2-pre.2361" +"@openmrs/esm-error-handling@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-error-handling@npm:5.8.2-pre.2369" peerDependencies: "@openmrs/esm-globals": 5.x - checksum: 10/4a039b47f1c776e3e60d4ecf55154666bb9e077f6122a543c5a2b12c6fd065704fa3ec107e0e0b5e3723dceff56096986a1ac6e3d15183b4a8d436cb1302fc5f + checksum: 10/eaf94898c7860b2218868ec694128027ad40e27975f93088d5e1d7a658d05ddcdc12fd7a93d4641d8c0c265dc584cb359111e1fcf2c016c5fcd70c0fc016269a languageName: node linkType: hard -"@openmrs/esm-expression-evaluator@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-expression-evaluator@npm:5.8.2-pre.2361" +"@openmrs/esm-expression-evaluator@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-expression-evaluator@npm:5.8.2-pre.2369" dependencies: "@jsep-plugin/arrow": "npm:^1.0.5" "@jsep-plugin/new": "npm:^1.0.3" @@ -5622,13 +5622,13 @@ __metadata: "@jsep-plugin/template": "npm:^1.0.4" "@jsep-plugin/ternary": "npm:^1.1.3" jsep: "npm:^1.3.9" - checksum: 10/5f1d014dee476efbb46c3852bc947a5741282bb1c0fa2a94092c2442ae87ab2bf915532d70a8f0e3ffacec15a10d913d052ef0daf5cbf9c4c229dca2a4270445 + checksum: 10/ee9b7b213afbb9db1358a8cc50aca3d4d52dd147bb9170f88da08a46345f5256977065a91c2e37844304c76d368bbcf2ab3e1f678f8dbe909fc7d0bab3656fbb languageName: node linkType: hard -"@openmrs/esm-extensions@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-extensions@npm:5.8.2-pre.2361" +"@openmrs/esm-extensions@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-extensions@npm:5.8.2-pre.2369" dependencies: lodash-es: "npm:^4.17.21" peerDependencies: @@ -5639,20 +5639,20 @@ __metadata: "@openmrs/esm-state": 5.x "@openmrs/esm-utils": 5.x single-spa: 5.x - checksum: 10/dc132b030b7ea22ea1fd01d75bb5d414d015198a6b0683c091c108f665af75d9e7f62674e5885ec2f1fd6eeafcb4a4ab705a8184eca96d6520e40af25a401b2e + checksum: 10/c5c1822f735bd4527405a2c076f5a84c7db7e4b9fb249aeeaaa8f9ac4575cdba7162da062e26a5dd09d8843b926eed201d8c3d4e45ddcf6dc2ba505aaceb99fd languageName: node linkType: hard -"@openmrs/esm-feature-flags@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-feature-flags@npm:5.8.2-pre.2361" +"@openmrs/esm-feature-flags@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-feature-flags@npm:5.8.2-pre.2369" dependencies: ramda: "npm:^0.26.1" peerDependencies: "@openmrs/esm-globals": 5.x "@openmrs/esm-state": 5.x single-spa: 5.x - checksum: 10/201a388ec97f05e19136b37e3a91b69bc1db1e68ca2d11fe52b886d6946c48eba38f1702bbe50b65cff200b94ac6df4be2da95b71698ac81fb8ed2889067bdb6 + checksum: 10/e06e5181e2c22c88c724aeb0dd01d3aacec7d144d185eaaa426a93f495f1c496efe77dd4326b10dc48a422dda6cfbad59e835e1297c679b74b80e830ac6bbf45 languageName: node linkType: hard @@ -5750,7 +5750,7 @@ __metadata: ngx-bootstrap: "npm:^12.0.0" ngx-build-plus: "npm:^17.0.0" ngx-webcam: "npm:^0.4.1" - openmrs: "npm:next" + openmrs: "npm:^5.8.2-pre.2324" protractor: "npm:~7.0.0" reflect-metadata: "npm:^0.1.13" rxjs: "npm:^7.8.0" @@ -5769,27 +5769,27 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-framework@npm:5.8.2-pre.2361, @openmrs/esm-framework@npm:next": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-framework@npm:5.8.2-pre.2361" - dependencies: - "@openmrs/esm-api": "npm:5.8.2-pre.2361" - "@openmrs/esm-config": "npm:5.8.2-pre.2361" - "@openmrs/esm-context": "npm:5.8.2-pre.2361" - "@openmrs/esm-dynamic-loading": "npm:5.8.2-pre.2361" - "@openmrs/esm-error-handling": "npm:5.8.2-pre.2361" - "@openmrs/esm-expression-evaluator": "npm:5.8.2-pre.2361" - "@openmrs/esm-extensions": "npm:5.8.2-pre.2361" - "@openmrs/esm-feature-flags": "npm:5.8.2-pre.2361" - "@openmrs/esm-globals": "npm:5.8.2-pre.2361" - "@openmrs/esm-navigation": "npm:5.8.2-pre.2361" - "@openmrs/esm-offline": "npm:5.8.2-pre.2361" - "@openmrs/esm-react-utils": "npm:5.8.2-pre.2361" - "@openmrs/esm-routes": "npm:5.8.2-pre.2361" - "@openmrs/esm-state": "npm:5.8.2-pre.2361" - "@openmrs/esm-styleguide": "npm:5.8.2-pre.2361" - "@openmrs/esm-translations": "npm:5.8.2-pre.2361" - "@openmrs/esm-utils": "npm:5.8.2-pre.2361" +"@openmrs/esm-framework@npm:5.8.2-pre.2369, @openmrs/esm-framework@npm:next": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-framework@npm:5.8.2-pre.2369" + dependencies: + "@openmrs/esm-api": "npm:5.8.2-pre.2369" + "@openmrs/esm-config": "npm:5.8.2-pre.2369" + "@openmrs/esm-context": "npm:5.8.2-pre.2369" + "@openmrs/esm-dynamic-loading": "npm:5.8.2-pre.2369" + "@openmrs/esm-error-handling": "npm:5.8.2-pre.2369" + "@openmrs/esm-expression-evaluator": "npm:5.8.2-pre.2369" + "@openmrs/esm-extensions": "npm:5.8.2-pre.2369" + "@openmrs/esm-feature-flags": "npm:5.8.2-pre.2369" + "@openmrs/esm-globals": "npm:5.8.2-pre.2369" + "@openmrs/esm-navigation": "npm:5.8.2-pre.2369" + "@openmrs/esm-offline": "npm:5.8.2-pre.2369" + "@openmrs/esm-react-utils": "npm:5.8.2-pre.2369" + "@openmrs/esm-routes": "npm:5.8.2-pre.2369" + "@openmrs/esm-state": "npm:5.8.2-pre.2369" + "@openmrs/esm-styleguide": "npm:5.8.2-pre.2369" + "@openmrs/esm-translations": "npm:5.8.2-pre.2369" + "@openmrs/esm-utils": "npm:5.8.2-pre.2369" dayjs: "npm:^1.10.7" peerDependencies: dayjs: 1.x @@ -5800,7 +5800,7 @@ __metadata: rxjs: 6.x single-spa: 5.x swr: 2.x - checksum: 10/6a5d1942087ea1b9658764c8886abad42dfc0dfb2e8ef79479b5ed093915a1f56531d2ccfd05c82961e329e80be2c1e177c8b7c2aecc6370ac2ebc776bf11e23 + checksum: 10/c90af1d79d535fde43e46ee8cd126004366f264f02cc8377cc7569012345f55926dc6a9b930b2dfb83ba09f9ce189267d0f4ad07fa6b081ce439a1b48ae0d986 languageName: node linkType: hard @@ -5826,31 +5826,31 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-globals@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-globals@npm:5.8.2-pre.2361" +"@openmrs/esm-globals@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-globals@npm:5.8.2-pre.2369" dependencies: "@types/fhir": "npm:0.0.31" peerDependencies: single-spa: 5.x - checksum: 10/02a884d87c054f23ce4f77c9d4f2b2234016e64eedfa1dc24be97ed4201442f2b6f0f08b3a96d5976f65147b89db34dd48be03dd3bd69d3b2dab17a41e96141c + checksum: 10/bd5e3ff2144a961617b97f0c43801d58f90cc675d8e5bb091da78a18119cbcfb03e328013489f4833f7e5378e44dc8130786a7734a0db0576ded0d8246c5d1cd languageName: node linkType: hard -"@openmrs/esm-navigation@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-navigation@npm:5.8.2-pre.2361" +"@openmrs/esm-navigation@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-navigation@npm:5.8.2-pre.2369" dependencies: path-to-regexp: "npm:6.1.0" peerDependencies: "@openmrs/esm-state": 5.x - checksum: 10/c564aa323cdb97d7009ba10c57c7aefc9d4af2e29a82494c80fdc361f46b26ed901c10127322bc5ba5d26efed81d7a9e6c52a5a716e50f53a1a26b9ecfe9d2ea + checksum: 10/2cefa7bf31cc0377b0b8bd489962fc31c7bd429b08831bc1bd45e0050e445b944fdada6076fc95f98d15c03ad23c5f9d6b24d4a45582dbe382825c2422b90949 languageName: node linkType: hard -"@openmrs/esm-offline@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-offline@npm:5.8.2-pre.2361" +"@openmrs/esm-offline@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-offline@npm:5.8.2-pre.2369" dependencies: dexie: "npm:^3.0.3" lodash-es: "npm:^4.17.21" @@ -5861,7 +5861,7 @@ __metadata: "@openmrs/esm-globals": 5.x "@openmrs/esm-state": 5.x rxjs: 6.x - checksum: 10/2aa6c34ca56e5e1a3a01a41cc4587e65596edeae89e397aed24b06e1bc43b01175152c55574a64d7473f341659768348744452b165222054c9548e6e4c8f8ff8 + checksum: 10/c1d67e084ea12c553fdf1ce0df845e329126b9aa84ac76353593e8b865c4f9e892972c5dd563f520ea4a2645326a64b901070db14cff161173166d27fe8853c8 languageName: node linkType: hard @@ -6255,9 +6255,9 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-react-utils@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-react-utils@npm:5.8.2-pre.2361" +"@openmrs/esm-react-utils@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-react-utils@npm:5.8.2-pre.2369" dependencies: lodash-es: "npm:^4.17.21" single-spa-react: "npm:^6.0.0" @@ -6278,13 +6278,13 @@ __metadata: react-i18next: 11.x rxjs: 6.x swr: 2.x - checksum: 10/38115ba811c3d84893ee4c7c5f4c1995186955605df09371e15638018787fa2c7f4ce105a5dc84a7f1893067f1db85de9dd2e65071d067245b96d4cb6d242924 + checksum: 10/0f353a5659b9d94f0a03e7763fbf662c1bb01bb9f3b4ea49349d03b7e297035e4aeef1d92118cc4077eb9e8b63f2fe68f7ab122d2745aae1f789969d490269cb languageName: node linkType: hard -"@openmrs/esm-routes@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-routes@npm:5.8.2-pre.2361" +"@openmrs/esm-routes@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-routes@npm:5.8.2-pre.2369" peerDependencies: "@openmrs/esm-config": 5.x "@openmrs/esm-dynamic-loading": 5.x @@ -6293,24 +6293,24 @@ __metadata: "@openmrs/esm-globals": 5.x "@openmrs/esm-utils": 5.x single-spa: 6.x - checksum: 10/6dfbb3d04e452069151be9f697fbe8009b3c8abb1781c41395a353ad586d663351cd86ab81488798bfa82873862cd75ec5a4b0ec80cef5c1c8c4e2ea663b5482 + checksum: 10/38614f62f3910da5e103057972692d41e5fb8d2d4b694c9d93fd3d9699d2fd03ae1bb7b65bf5f7a6c5980f0c9b724a0306be51ed0481ce26e13a6de13fcf56f6 languageName: node linkType: hard -"@openmrs/esm-state@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-state@npm:5.8.2-pre.2361" +"@openmrs/esm-state@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-state@npm:5.8.2-pre.2369" dependencies: zustand: "npm:^4.5.5" peerDependencies: "@openmrs/esm-globals": 5.x - checksum: 10/63dfca465e114a9b564f2c7ff2c3537ae43cec0bada501f95e87873893b9e47757b349e6b70783e2dc200c47e85d7bc603dffe7a051b8ebf81c608f4eef1cf31 + checksum: 10/4329348f7b35fd6a6bf9580d8cfb45663b810af0e7043eee04aaa925248068579f469af3fde339657882fabd187b5a499ad077319c17e080ea6b06d3f0ffd6ba languageName: node linkType: hard -"@openmrs/esm-styleguide@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-styleguide@npm:5.8.2-pre.2361" +"@openmrs/esm-styleguide@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-styleguide@npm:5.8.2-pre.2369" dependencies: "@carbon/charts": "npm:^1.12.0" "@carbon/react": "npm:~1.37.0" @@ -6334,24 +6334,24 @@ __metadata: react-dom: 18.x react-i18next: 11.x rxjs: 6.x - checksum: 10/392807bda113efaa23d0c32fde4eb9cf37ef2320cc35290dd918de826002d739539b60b811ef72d5551c0940f3c6c8d61807c2f8bfc5b65b61561768d43908af + checksum: 10/6279a3098d1b677379400012bc838c4d2313081f6e57c06ca114bdc25030532a750d9bd368913b258a85ab269ec871c46f275f1a9fd36d4f0b1ba366d19b29d9 languageName: node linkType: hard -"@openmrs/esm-translations@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-translations@npm:5.8.2-pre.2361" +"@openmrs/esm-translations@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-translations@npm:5.8.2-pre.2369" dependencies: i18next: "npm:21.10.0" peerDependencies: i18next: 21.x - checksum: 10/c4be2be5d5828a8a36a917e5c69879647dd514417ace8a46ab8c67ae2ad60113ab8cd9daf85883b17cd6be7eb6dabca45e3a96118f8b2ba81d538bf04619c00e + checksum: 10/ce3babb0f655d4f2b407595b0816489a959d0d16bd863daf51c49fdd40dd7347164c82423dbd01617b2027a31faf1f95555e2c394da2b3d37dcbaf2fddb34e23 languageName: node linkType: hard -"@openmrs/esm-utils@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/esm-utils@npm:5.8.2-pre.2361" +"@openmrs/esm-utils@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/esm-utils@npm:5.8.2-pre.2369" dependencies: "@formatjs/intl-durationformat": "npm:^0.2.4" "@internationalized/date": "npm:^3.5.5" @@ -6361,7 +6361,7 @@ __metadata: dayjs: 1.x i18next: 21.x rxjs: 6.x - checksum: 10/fba0b545bf4e3e9ebafbc92987b83a92bea43adc4594c98e3c02aa3dbb93c12169286fa4a332762374ca919a98d76947ac638d1020d31878b35efd32a3f5fea2 + checksum: 10/22d3e463a911848547f88b3934285421e7fddbdbc6a8869437fee3911561c57d6e6e239641cd8f03db6bee5047382b967b8ab3bae2514d59273e5d01fc01acb1 languageName: node linkType: hard @@ -6412,9 +6412,9 @@ __metadata: languageName: node linkType: hard -"@openmrs/webpack-config@npm:5.8.2-pre.2361": - version: 5.8.2-pre.2361 - resolution: "@openmrs/webpack-config@npm:5.8.2-pre.2361" +"@openmrs/webpack-config@npm:5.8.2-pre.2369": + version: 5.8.2-pre.2369 + resolution: "@openmrs/webpack-config@npm:5.8.2-pre.2369" dependencies: "@swc/core": "npm:^1.3.58" clean-webpack-plugin: "npm:^4.0.0" @@ -6432,7 +6432,7 @@ __metadata: webpack-stats-plugin: "npm:^1.0.3" peerDependencies: webpack: 5.x - checksum: 10/d0b443ca6a22a1a4391e77c1e19da5c4ac7c443275d75c69fede25d99e16fab0e910bd70fd032636d73da922fe9bd2217fbdfea288a339b2459bf6e0e9273608 + checksum: 10/cbc1fbb09c627bb5330c26822c5a0cc859e78f12ebf4c527d6367b3cd89b82c5cd1b98db3a9ced7dcd52af6d678c0ba79a10aed42fd43df321f4ae3b4fbce739 languageName: node linkType: hard @@ -20672,12 +20672,12 @@ __metadata: languageName: node linkType: hard -"openmrs@npm:next": - version: 5.8.2-pre.2361 - resolution: "openmrs@npm:5.8.2-pre.2361" +"openmrs@npm:^5.8.2-pre.2324, openmrs@npm:next": + version: 5.8.2-pre.2369 + resolution: "openmrs@npm:5.8.2-pre.2369" dependencies: - "@openmrs/esm-app-shell": "npm:5.8.2-pre.2361" - "@openmrs/webpack-config": "npm:5.8.2-pre.2361" + "@openmrs/esm-app-shell": "npm:5.8.2-pre.2369" + "@openmrs/webpack-config": "npm:5.8.2-pre.2369" "@pnpm/npm-conf": "npm:^2.1.0" "@swc/core": "npm:^1.3.58" autoprefixer: "npm:^10.4.20" @@ -20716,7 +20716,7 @@ __metadata: yargs: "npm:^17.6.2" bin: openmrs: ./dist/cli.js - checksum: 10/4a2f4940d486dd59ad9d447eaa78d9a901c6b2cc778130870cbd982563bdcb7aa8d876ab140450de11abb57a55b5c7f01272d593281cf890f9c82862da20da7d + checksum: 10/f2ac023ed7f6353454164385a74dae5c07950758986fa46b10453d820edb0e1e840516f1481e94d69a5bc959f46efbf7fd60791ef2a4cf6789fd14b74b64f9b9 languageName: node linkType: hard From 1655c0d8ae1de882709f8fdfd90390a96a6e9239 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Thu, 19 Sep 2024 18:16:43 +0530 Subject: [PATCH 09/10] Updated translations --- packages/esm-patient-banner-app/translations/en.json | 1 + packages/esm-patient-chart-app/translations/en.json | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-banner-app/translations/en.json b/packages/esm-patient-banner-app/translations/en.json index 9063d36550..d69ea42ead 100644 --- a/packages/esm-patient-banner-app/translations/en.json +++ b/packages/esm-patient-banner-app/translations/en.json @@ -12,6 +12,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "state": "State", "stateProvince": "State", "telephoneNumberWithSeparator": "Telephone number:" diff --git a/packages/esm-patient-chart-app/translations/en.json b/packages/esm-patient-chart-app/translations/en.json index e9fc6e9069..43f57a82d1 100644 --- a/packages/esm-patient-chart-app/translations/en.json +++ b/packages/esm-patient-chart-app/translations/en.json @@ -118,7 +118,6 @@ "pastVisitErrorText": "Past visit error", "pastVisits": "Past visits", "Patient Summary": "Patient summary", - "printIdentifierSticker": "Print identifier sticker", "program": "Program", "provider": "Provider", "quantity": "Quantity", From edee1d38abb25cd334bc3c5e0f997ddc4270a982 Mon Sep 17 00:00:00 2001 From: Vineet Sharma Date: Wed, 2 Oct 2024 11:48:31 +0530 Subject: [PATCH 10/10] Review changes --- packages/esm-patient-banner-app/src/config-schema.ts | 4 ++-- .../src/print-identifier-sticker/patient-detail.component.tsx | 4 ++-- .../print-identifier-sticker-modal.test.tsx | 4 ++-- .../print-identifier-sticker.modal.tsx | 4 ++-- .../print-identifier-sticker.resource.ts | 1 + 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/esm-patient-banner-app/src/config-schema.ts b/packages/esm-patient-banner-app/src/config-schema.ts index 88de883e52..c2c2824518 100644 --- a/packages/esm-patient-banner-app/src/config-schema.ts +++ b/packages/esm-patient-banner-app/src/config-schema.ts @@ -1,5 +1,4 @@ import { Type } from '@openmrs/esm-framework'; -import _default from 'react-hook-form/dist/logic/appendErrors'; export const configSchema = { contactAttributeTypes: { @@ -21,7 +20,8 @@ export const configSchema = { }, header: { _type: Type.Object, - _description: 'The header to display on the patient sticker', + _description: + 'Configuration properties for the patient sticker headerConfiguration properties for the patient sticker header', showBarcode: { _type: Type.Boolean, _description: 'Whether to display a barcode on the patient sticker', diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx index 8e5adf3370..48193d1129 100644 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx @@ -95,7 +95,7 @@ export const PatientIdentifier: React.FC = ({ patient }) => export const PatientContact: React.FC = ({ patient }) => { const { t } = useTranslation(); - if (patient.telecom.length == 0) { + if (!patient?.telecom?.length) { return null; } @@ -104,7 +104,7 @@ export const PatientContact: React.FC = ({ patient }) => { {t('telephoneNumberWithSeparator', 'Telephone number:')} - {patient.telecom[0]?.value} + {patient.telecom?.[0]?.value}
    ); }; diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-modal.test.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-modal.test.tsx index 45f99631c2..527e3c3cee 100644 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-modal.test.tsx +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-modal.test.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import PrintIdentifierSticker from './print-identifier-sticker.modal'; import { mockFhirPatient } from '../../../../__mocks__/patient.mock'; -import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; +import { age, getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; import { type ConfigObject, configSchema } from '../config-schema'; import { useReactToPrint } from 'react-to-print'; import userEvent from '@testing-library/user-event'; @@ -109,7 +109,7 @@ describe('Testing PrintIdentifierStickerModal', () => { expect(getByTextWithMarkup(/Joshua Johnson/i)).toBeInTheDocument(); expect(getByTextWithMarkup(/\+255777053243/i)).toBeInTheDocument(); expect(getByTextWithMarkup(/100008E/i)).toBeInTheDocument(); - expect(getByTextWithMarkup(/4 yrs, 11 mths/i)).toBeInTheDocument(); + expect(getByTextWithMarkup(age(mockFhirPatient.birthDate))).toBeInTheDocument(); }); }); diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.modal.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.modal.tsx index ee0e9bcdb7..317b167cc1 100644 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.modal.tsx +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.modal.tsx @@ -42,8 +42,8 @@ const PrintIdentifierSticker: React.FC = ({ closeMo const handleAfterPrint = useCallback(() => { onBeforeGetContentResolve.current = null; setIsPrinting(false); - // closeModal(); - }, []); + closeModal(); + }, [closeModal]); const handlePrintError = useCallback((errorLocation, error) => { onBeforeGetContentResolve.current = null; diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.resource.ts b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.resource.ts index 721742265f..ef32c1272e 100644 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.resource.ts +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.resource.ts @@ -13,6 +13,7 @@ import { export const defaultBarcodeParams: Options = { width: 2, + format: 'CODE39', background: '#f4f4f4', displayValue: true, renderer: 'img',