From d4377e07c4ed9b52d587f4497fc7e18859a9cbe1 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Tue, 6 May 2025 20:57:49 +0300 Subject: [PATCH 01/35] Printing Patient Identifier template should use backend API --- .../src/config-schema.ts | 65 ------- packages/esm-patient-banner-app/src/index.ts | 11 +- .../patient-detail.component.tsx | 147 --------------- ...tifier-sticker-action-button.component.tsx | 13 +- .../print-identifier-sticker-modal.test.tsx | 131 -------------- .../print-identifier-sticker.modal.tsx | 168 ------------------ .../print-identifier-sticker.resource.ts | 46 ----- .../print-identifier-sticker.scss | 88 --------- .../esm-patient-banner-app/src/routes.json | 13 -- 9 files changed, 14 insertions(+), 668 deletions(-) delete mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx delete mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-modal.test.tsx delete mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.modal.tsx delete mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.resource.ts delete mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.scss diff --git a/packages/esm-patient-banner-app/src/config-schema.ts b/packages/esm-patient-banner-app/src/config-schema.ts index cf780704f9..1d41ba22e6 100644 --- a/packages/esm-patient-banner-app/src/config-schema.ts +++ b/packages/esm-patient-banner-app/src/config-schema.ts @@ -12,58 +12,6 @@ export const configSchema = { '14d4f066-15f5-102d-96e4-000c29c2a5d7', ], }, - printPatientSticker: { - header: { - _type: Type.Object, - _description: 'Configuration properties for patient identifier stickers', - showBarcode: { - _type: Type.Boolean, - _description: 'Whether to display a barcode on the patient sticker', - }, - showLogo: { - _type: Type.Boolean, - _description: 'Whether to display a logo on the patient sticker', - }, - logo: { - _type: Type.String, - _description: 'The URL of the logo to display in the patient sticker', - }, - _default: { - showBarcode: true, - showLogo: true, - logo: '', - }, - }, - fields: { - _type: Type.Array, - _elements: { - _type: Type.String, - }, - _description: 'Patient demographics to include in the patient sticker printout', - _default: ['name', 'dob', 'gender', 'identifier', 'age', 'contact', 'address'], - }, - 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', - }, - printScale: { - _type: Type.String, - _description: - 'Set the scale for the printed content. A value between 0 and 1 shrinks the content, while a value greater than 1 enlarges it. The scale must be greater than 0.', - _default: '1', - }, - identifiersToDisplay: { - _type: Type.Array, - _elements: { - _type: Type.UUID, - }, - _description: - 'List of UUIDs of patient identifier types to include on the patient sticker. If empty, all identifiers will be displayed.', - _default: [], - }, - }, useRelationshipNameLink: { _type: Type.Boolean, _description: "Whether to use the relationship name as a link to the associated person's patient chart.", @@ -71,20 +19,7 @@ export const configSchema = { }, }; -export type AllowedPatientFields = 'address' | 'age' | 'contact' | 'dob' | 'gender' | 'identifier' | 'name'; - export interface ConfigObject { contactAttributeTypes: Array; - printPatientSticker: { - header: { - showBarcode: boolean; - showLogo: boolean; - logo: string; - }; - fields: Array; - pageSize: string; - printScale: string; - identifiersToDisplay: Array; - }; useRelationshipNameLink: boolean; } diff --git a/packages/esm-patient-banner-app/src/index.ts b/packages/esm-patient-banner-app/src/index.ts index 9da2558d6d..f02f8a1698 100644 --- a/packages/esm-patient-banner-app/src/index.ts +++ b/packages/esm-patient-banner-app/src/index.ts @@ -3,6 +3,7 @@ import { getAsyncLifecycle, getSyncLifecycle, messageOmrsServiceWorker, + registerFeatureFlag, restBaseUrl, } from '@openmrs/esm-framework'; import { configSchema } from './config-schema'; @@ -25,6 +26,11 @@ export function startupApp() { pattern: `.+${restBaseUrl}/relationship.+`, }); + registerFeatureFlag( + 'print-patient-identifier-sticker', + 'Print patient identifier sticker', + 'Features to support printing a patient identifier sticker', + ); defineConfigSchema(moduleName, configSchema); } @@ -34,11 +40,6 @@ export const deceasedPatientTag = getSyncLifecycle(deceasedPatientTagComponent, export const patientBanner = getSyncLifecycle(patientBannerComponent, options); -export const printIdentifierStickerModal = getAsyncLifecycle( - () => import('./print-identifier-sticker/print-identifier-sticker.modal'), - options, -); - export const printIdentifierStickerActionButton = getAsyncLifecycle( () => import('./print-identifier-sticker/print-identifier-sticker-action-button.component'), { 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 deleted file mode 100644 index ffa4086033..0000000000 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/patient-detail.component.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import React from 'react'; -import dayjs from 'dayjs'; -import { useTranslation } from 'react-i18next'; -import { age, type CoreTranslationKey, getCoreTranslation, getPatientName, useConfig } from '@openmrs/esm-framework'; -import { type ConfigObject } from '../config-schema'; -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} -
- ))} -
- ); -}; - -export const PatientContact: React.FC = ({ patient }) => { - const { t } = useTranslation(); - - if (!patient?.telecom?.length) { - 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/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 8ccaaf6f06..f40852d21a 100644 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -1,7 +1,7 @@ import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; -import { showModal, useFeatureFlag } from '@openmrs/esm-framework'; +import { useFeatureFlag } from '@openmrs/esm-framework'; import styles from './action-button.scss'; interface PrintIdentifierStickerOverflowMenuItemProps { @@ -13,10 +13,13 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC { - const dispose = showModal('print-identifier-sticker-modal', { - closeModal: () => dispose(), - patient, - }); + if (patient?.id) { + const url = `${window.openmrsBase}/ws/module/commonreports/patientIdSticker?patientUuid=${patient?.id}`; + const anchor = document.createElement('a'); + anchor.setAttribute('href', url); + anchor.click(); + anchor.remove(); + } }, [patient]); if (!patient || !canPrintPatientIdentifierSticker) { 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 deleted file mode 100644 index 25133c1f0d..0000000000 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-modal.test.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import React from 'react'; -import Barcode from 'react-barcode'; -import userEvent from '@testing-library/user-event'; -import { render, screen } from '@testing-library/react'; -import { useReactToPrint } from 'react-to-print'; -import { age, getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework'; -import { mockFhirPatient } from '__mocks__'; -import { type ConfigObject, configSchema } from '../config-schema'; -import { getByTextWithMarkup } from 'tools'; -import PrintIdentifierSticker from './print-identifier-sticker.modal'; - -const mockedCloseModal = jest.fn(); -const mockedUseConfig = jest.mocked(useConfig); -const mockedUseReactToPrint = jest.mocked(useReactToPrint); - -const defaultConfig: ConfigObject = getDefaultsFromConfigSchema(configSchema); - -jest.mock('react-to-print', () => ({ - ...jest.requireActual('react-to-print'), - useReactToPrint: jest.fn(), -})); - -jest.mock('react-barcode', () => jest.fn().mockReturnValue(
    )); - -describe('PrintIdentifierStickerModal', () => { - beforeEach(() => { - mockedUseConfig.mockReturnValue(getDefaultsFromConfigSchema(configSchema)); - }); - - it('renders the print modal', async () => { - const user = userEvent.setup(); - 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(mockedCloseModal).toHaveBeenCalledTimes(1); - - await user.click(printButton); - expect(mockHandlePrint).toHaveBeenCalledTimes(1); - }); - - it('renders a barcode if enabled via config', async () => { - 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', - format: 'CODE39', - textAlign: 'center', - textPosition: 'bottom', - fontSize: 16, - }, - {}, - ); - expect(screen.getByTestId('openmrs-logo')).toBeInTheDocument(); - }); - - it("should not render a barcode if it's disabled via config", async () => { - 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('renders a custom implementation logo if passed via config', () => { - 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'); - }); - - it("renders the patient's details in the print modal", () => { - renderPrintIdentifierStickerModal(); - - expect(getByTextWithMarkup(/Joshua Johnson/i)).toBeInTheDocument(); - expect(getByTextWithMarkup(/\+255777053243/i)).toBeInTheDocument(); - expect(getByTextWithMarkup(/100008E/i)).toBeInTheDocument(); - expect(getByTextWithMarkup(age(mockFhirPatient.birthDate))).toBeInTheDocument(); - }); -}); - -function renderPrintIdentifierStickerModal() { - return render(); -} 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 deleted file mode 100644 index fe631be05c..0000000000 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.modal.tsx +++ /dev/null @@ -1,168 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; -import Barcode from 'react-barcode'; -import { useTranslation } from 'react-i18next'; -import { useReactToPrint } from 'react-to-print'; -import { Button, InlineLoading, ModalBody, ModalFooter, ModalHeader } from '@carbon/react'; -import { getPatientName, showSnackbar, useConfig, getCoreTranslation } from '@openmrs/esm-framework'; -import { type ConfigObject } from '../config-schema'; -import { defaultBarcodeParams, getPatientField } from './print-identifier-sticker.resource'; -import styles from './print-identifier-sticker.scss'; - -interface PrintIdentifierStickerProps { - closeModal: () => void; - patient: fhir.Patient; -} - -interface PrintComponentProps extends Partial { - patient: fhir.Patient; -} - -const PrintIdentifierSticker: React.FC = ({ closeModal, patient }) => { - const { t } = useTranslation(); - const { printPatientSticker } = useConfig(); - const { pageSize, printScale = '1' } = printPatientSticker ?? {}; - const contentToPrintRef = useRef(null); - const onBeforeGetContentResolve = useRef<() => void | null>(null); - const [isPrinting, setIsPrinting] = useState(false); - const headerTitle = t('patientIdentifierSticker', 'Patient identifier sticker'); - - useEffect(() => { - if (isPrinting && onBeforeGetContentResolve.current) { - onBeforeGetContentResolve.current(); - } - }, [isPrinting]); - - const handleBeforeGetContent = useCallback( - () => - new Promise((resolve) => { - if (patient && headerTitle) { - onBeforeGetContentResolve.current = resolve; - setIsPrinting(true); - } - }), - [headerTitle, patient], - ); - - const handleAfterPrint = useCallback(() => { - onBeforeGetContentResolve.current = null; - setIsPrinting(false); - closeModal(); - }, [closeModal]); - - const handlePrintError = useCallback((errorLocation, error) => { - onBeforeGetContentResolve.current = null; - - showSnackbar({ - isLowContrast: false, - kind: 'error', - title: getCoreTranslation('printError', 'Print error'), - subtitle: - getCoreTranslation('printErrorExplainer', 'An error occurred in "{{errorLocation}}": ', { errorLocation }) + - error, - }); - - setIsPrinting(false); - }, []); - - const handleInitiatePrint = useCallback( - (printWindow: HTMLIFrameElement | null): Promise => { - return new Promise((resolve) => { - if (printWindow) { - const printContent = printWindow.contentDocument || printWindow.contentWindow?.document; - if (printContent) { - printContent.documentElement.style.setProperty('--print-scale', printScale); - printWindow.contentWindow?.print(); - resolve(); - } - } - }); - }, - [printScale], - ); - - const handlePrint = useReactToPrint({ - content: () => contentToPrintRef.current, - documentTitle: `${getPatientName(patient)} - ${headerTitle}`, - onAfterPrint: handleAfterPrint, - onBeforeGetContent: handleBeforeGetContent, - onPrintError: handlePrintError, - print: handleInitiatePrint, - copyStyles: true, - }); - - return ( - <> - - -
    - - -
    -
    - - - - - - ); -}; - -const PrintComponent = ({ patient }: PrintComponentProps) => { - const { printPatientSticker } = useConfig(); - const primaryIdentifierValue = patient?.identifier?.find((identifier) => identifier.use === 'official')?.value; - return ( -
    -
    - {printPatientSticker?.header?.showBarcode && ( - - )} - {printPatientSticker?.header?.showLogo && ( -
    - -
    - )} -
    - {printPatientSticker.fields.map((field) => { - const Component = getPatientField(field); - return ; - })} -
    - ); -}; - -const ImplementationLogo: React.FC = () => { - const { t } = useTranslation(); - const { printPatientSticker } = useConfig(); - - return printPatientSticker?.header?.logo ? ( - {t('implementationLogo', - ) : ( - // TODO: Figure out why #omrs-logo-full-mono sprite is not working - - - - ); -}; - -export default PrintIdentifierSticker; 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 deleted file mode 100644 index ef32c1272e..0000000000 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.resource.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { type Options } from 'react-barcode'; -import { type AllowedPatientFields } from '../config-schema'; -import { - PatientAddress, - PatientAge, - PatientContact, - type PatientDetailProps, - PatientDob, - PatientGender, - PatientIdentifier, - PatientName, -} from './patient-detail.component'; - -export const defaultBarcodeParams: Options = { - width: 2, - format: 'CODE39', - 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; - case 'contact': - return PatientContact; - case 'address': - return PatientAddress; - default: - console.error(`Invalid patient field: ${field}`); - return null; - } -} diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.scss b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.scss deleted file mode 100644 index f6dd205b2a..0000000000 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker.scss +++ /dev/null @@ -1,88 +0,0 @@ -@use '@carbon/layout'; -@use '@carbon/type'; -@use '@openmrs/esm-styleguide/src/vars' as *; - -.stickerContainer { - padding: layout.$spacing-03 layout.$spacing-05; -} - -.documentHeader { - display: flex; - justify-content: space-between; - align-items: center; - border-bottom: 1px solid $brand-01; - margin-bottom: layout.$spacing-05; -} - -.row { - margin: layout.$spacing-03 0 0; - display: flex; - flex-flow: row wrap; - gap: layout.$spacing-05; -} - -.gridRow { - padding: 0px; - display: flex; - flex-direction: row; - justify-content: space-between; - - div { - margin-left: 0px; - margin-bottom: 5px; - } -} - -.patientName { - font-size: layout.$spacing-06; - font-weight: bolder; - margin-bottom: 5px; -} - -.button { - :global(.cds--inline-loading) { - min-height: layout.$spacing-05 !important; - } -} - -.detailsGrid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: layout.$spacing-03 0; - margin-top: layout.$spacing-03; -} - -.loader { - :global(.cds--inline-loading__text) { - @include type.type-style('body-01'); - } -} - -.strong { - @include type.type-style('heading-04'); - font-weight: 700; - margin-inline-end: layout.$spacing-03; -} - -.patientDetail { - @include type.type-style('heading-03'); -} - -.implementationLogo { - width: 40%; -} - -@media print { - html, - body { - height: 100vh; - margin: 0 !important; - padding: 0 !important; - overflow: hidden; - } - - .stickerContainer { - transform: scale(var(--print-scale)); - transform-origin: left top; - } -} diff --git a/packages/esm-patient-banner-app/src/routes.json b/packages/esm-patient-banner-app/src/routes.json index 6f54188a2b..e932823db2 100644 --- a/packages/esm-patient-banner-app/src/routes.json +++ b/packages/esm-patient-banner-app/src/routes.json @@ -32,18 +32,5 @@ "online": true, "offline": true } - ], - "modals": [ - { - "name": "print-identifier-sticker-modal", - "component": "printIdentifierStickerModal" - } - ], - "featureFlags": [ - { - "description": "Features to support printing a patient identifier sticker", - "flagName": "print-patient-identifier-sticker", - "label": "Print patient identifier sticker" - } ] } From c835d2a3872bbc3095501d2b1cec8e5397a983e4 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Thu, 8 May 2025 14:18:33 +0300 Subject: [PATCH 02/35] allow printing sticker without download to local machine --- ...tifier-sticker-action-button.component.tsx | 133 ++++++++++++++++-- .../translations/en.json | 10 +- 2 files changed, 123 insertions(+), 20 deletions(-) diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index f40852d21a..38e51ddc27 100644 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -1,27 +1,133 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useState, useRef, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; -import { useFeatureFlag } from '@openmrs/esm-framework'; +import { useFeatureFlag, showSnackbar, getCoreTranslation } from '@openmrs/esm-framework'; import styles from './action-button.scss'; interface PrintIdentifierStickerOverflowMenuItemProps { patient: fhir.Patient; } +const useSickerPdfPrinter = () => { + const iframeRef = useRef(null); + const [isPrinting, setIsPrinting] = useState(false); + + const printPdf = useCallback((url: string) => { + return new Promise((resolve, reject) => { + setIsPrinting(true); + + if (!iframeRef.current) { + const iframe = document.createElement('iframe'); + iframe.name = 'pdfPrinterFrame'; + iframe.style.position = 'fixed'; + iframe.style.width = '0'; + iframe.style.height = '0'; + iframe.style.border = 'none'; + iframe.style.visibility = 'hidden'; + iframeRef.current = iframe; + document.body.appendChild(iframe); + } + + const iframe = iframeRef.current; + + const handleLoad = () => { + try { + const contentWindow = iframe.contentWindow; + + if (!contentWindow) { + throw new Error('Failed to access print window'); + } + + contentWindow.focus(); + contentWindow.print(); + + if (isSameOrigin(url)) { + contentWindow.addEventListener('afterprint', handlePrintComplete); + } else { + // For cross-origin, we'll assume printing is immediate + // and rely on the browser's print dialog behavior + handlePrintComplete(); + } + } catch (error) { + handlePrintError(error); + } + }; + + const handlePrintComplete = () => { + cleanup(); + resolve(); + }; + + const handlePrintError = (error: unknown) => { + cleanup(); + reject(error instanceof Error ? error : new Error('Printing failed')); + }; + + const cleanup = () => { + iframe.onload = null; + iframe.onerror = null; + setIsPrinting(false); + + // Remove event listener if same-origin + if (iframe.contentWindow && isSameOrigin(url)) { + try { + iframe.contentWindow.removeEventListener('afterprint', handlePrintComplete); + } catch { + // Ignore cross-origin errors + } + } + }; + + iframe.onload = handleLoad; + iframe.onerror = () => handlePrintError(new Error('Failed to load PDF')); + iframe.src = url; + }); + }, []); + + const isSameOrigin = (url: string) => { + try { + return new URL(url).origin === window.location.origin; + } catch { + return false; + } + }; + + useEffect(() => { + return () => { + if (iframeRef.current) { + document.body.removeChild(iframeRef.current); + } + }; + }, []); + + return { printPdf, isPrinting }; +}; + const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { const { t } = useTranslation(); const canPrintPatientIdentifierSticker = useFeatureFlag('print-patient-identifier-sticker'); + const { printPdf, isPrinting } = useSickerPdfPrinter(); - const handleLaunchModal = useCallback(() => { - if (patient?.id) { - const url = `${window.openmrsBase}/ws/module/commonreports/patientIdSticker?patientUuid=${patient?.id}`; - const anchor = document.createElement('a'); - anchor.setAttribute('href', url); - anchor.click(); - anchor.remove(); + const getPdfUrl = useCallback(() => { + if (!patient?.id) { + throw new Error('Patient ID not found'); } + return `${window.openmrsBase}/ws/module/commonreports/patientIdSticker?patientUuid=${patient.id}`; }, [patient]); + const handlePrint = useCallback(async () => { + try { + const pdfUrl = getPdfUrl(); + await printPdf(pdfUrl); + } catch (error) { + showSnackbar({ + kind: 'error', + title: getCoreTranslation('printError', 'Print Error'), + subtitle: getCoreTranslation('printErrorExplainer', '', { errorLocation: error?.message }), + }); + } + }, [getPdfUrl, printPdf]); + if (!patient || !canPrintPatientIdentifierSticker) { return null; } @@ -29,8 +135,13 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC ); }; diff --git a/packages/esm-patient-banner-app/translations/en.json b/packages/esm-patient-banner-app/translations/en.json index d6f528ff35..a21571c7d0 100644 --- a/packages/esm-patient-banner-app/translations/en.json +++ b/packages/esm-patient-banner-app/translations/en.json @@ -9,16 +9,8 @@ "deceased": "Deceased", "district": "District", "from_lower": "from", - "implementationLogo": "Implementation logo", - "patientAge": "Age:", - "patientDateOfBirthWithSeparator": "Date of birth:", - "patientGenderWithSeparator": "Gender:", - "patientIdentifierSticker": "Patient identifier sticker", - "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", - "stateProvince": "State", - "telephoneNumberWithSeparator": "Telephone number:" + "stateProvince": "State" } From fe11571f88a40faea98105c7b2a46269940c5e4b Mon Sep 17 00:00:00 2001 From: jnsereko Date: Tue, 13 May 2025 08:58:57 +0300 Subject: [PATCH 03/35] Move Patient Identifier Sticker logic to a new esm --- packages/esm-patient-banner-app/src/index.ts | 13 ---- .../esm-patient-banner-app/src/routes.json | 7 --- .../esm-patient-label-printing-app/README.md | 3 + .../jest.config.js | 3 + .../package.json | 52 ++++++++++++++++ .../src/config-schema.ts | 5 ++ .../src/hooks/useSickerPdfPrinter.ts} | 55 +---------------- .../src/index.ts | 40 +++++++++++++ .../action-button.scss | 0 ...tifier-sticker-action-button.component.tsx | 56 +++++++++++++++++ .../src/routes.json | 16 +++++ .../src/types/index.ts | 60 +++++++++++++++++++ .../tsconfig.json | 4 ++ .../webpack.config.js | 1 + yarn.lock | 15 +++++ 15 files changed, 256 insertions(+), 74 deletions(-) create mode 100644 packages/esm-patient-label-printing-app/README.md create mode 100644 packages/esm-patient-label-printing-app/jest.config.js create mode 100644 packages/esm-patient-label-printing-app/package.json create mode 100644 packages/esm-patient-label-printing-app/src/config-schema.ts rename packages/{esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx => esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts} (58%) create mode 100644 packages/esm-patient-label-printing-app/src/index.ts rename packages/{esm-patient-banner-app => esm-patient-label-printing-app}/src/print-identifier-sticker/action-button.scss (100%) create mode 100644 packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx create mode 100644 packages/esm-patient-label-printing-app/src/routes.json create mode 100644 packages/esm-patient-label-printing-app/src/types/index.ts create mode 100644 packages/esm-patient-label-printing-app/tsconfig.json create mode 100644 packages/esm-patient-label-printing-app/webpack.config.js diff --git a/packages/esm-patient-banner-app/src/index.ts b/packages/esm-patient-banner-app/src/index.ts index f02f8a1698..49f9174bd9 100644 --- a/packages/esm-patient-banner-app/src/index.ts +++ b/packages/esm-patient-banner-app/src/index.ts @@ -26,11 +26,6 @@ export function startupApp() { pattern: `.+${restBaseUrl}/relationship.+`, }); - registerFeatureFlag( - 'print-patient-identifier-sticker', - 'Print patient identifier sticker', - 'Features to support printing a patient identifier sticker', - ); defineConfigSchema(moduleName, configSchema); } @@ -40,14 +35,6 @@ export const deceasedPatientTag = getSyncLifecycle(deceasedPatientTagComponent, export const patientBanner = getSyncLifecycle(patientBannerComponent, 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/routes.json b/packages/esm-patient-banner-app/src/routes.json index e932823db2..678dced63d 100644 --- a/packages/esm-patient-banner-app/src/routes.json +++ b/packages/esm-patient-banner-app/src/routes.json @@ -24,13 +24,6 @@ "component": "patientBanner", "online": true, "offline": true - }, - { - "name": "print-identifier-sticker-button", - "slot": "patient-actions-slot", - "component": "printIdentifierStickerActionButton", - "online": true, - "offline": true } ] } diff --git a/packages/esm-patient-label-printing-app/README.md b/packages/esm-patient-label-printing-app/README.md new file mode 100644 index 0000000000..08f737c492 --- /dev/null +++ b/packages/esm-patient-label-printing-app/README.md @@ -0,0 +1,3 @@ +# esm-patient-label-printing-app + +Patient Label Printing microfrontend is designed to provide a flexible and extensible printing mechanism that can be easily integrated into multiple contexts within the application. Its core architecture will support print actions in diverse scenarios, such as patient management apps like Queues, clerical views, and billing interfaces, enabling quick and standardized print functionality for various document types including patient records, receipts, and other critical documents. diff --git a/packages/esm-patient-label-printing-app/jest.config.js b/packages/esm-patient-label-printing-app/jest.config.js new file mode 100644 index 0000000000..0352f6214c --- /dev/null +++ b/packages/esm-patient-label-printing-app/jest.config.js @@ -0,0 +1,3 @@ +const rootConfig = require('../../jest.config.js'); + +module.exports = rootConfig; diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json new file mode 100644 index 0000000000..8f98a58638 --- /dev/null +++ b/packages/esm-patient-label-printing-app/package.json @@ -0,0 +1,52 @@ +{ + "name": "@openmrs/esm-patient-label-printing-app", + "version": "10.1.0", + "license": "MPL-2.0", + "description": "Patient Label Printing for the OpenMRS SPA", + "browser": "dist/openmrs-esm-patient-label-printing-app.js", + "main": "src/index.ts", + "source": true, + "scripts": { + "start": "openmrs develop", + "serve": "webpack serve --mode=development", + "debug": "npm run serve", + "build": "webpack --mode production --color", + "analyze": "webpack --mode=production --env analyze=true", + "lint": "cross-env eslint src --ext tsx,ts --fix --max-warnings=0", + "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' 'src/**/*.modal.tsx' 'src/**/*.extension.tsx' 'src/**/*.workspace.tsx' 'src/**/*.hook.tsx' 'src/index.ts' --config ../../tools/i18next-parser.config.js" + }, + "browserslist": [ + "extends browserslist-config-openmrs" + ], + "keywords": [ + "openmrs" + ], + "homepage": "https://github.com/openmrs/openmrs-esm-patient-chart#readme", + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/openmrs/openmrs-esm-patient-chart.git" + }, + "bugs": { + "url": "https://github.com/openmrs/openmrs-esm-patient-chart/issues" + }, + "dependencies": { + "@carbon/react": "^1.76.0" + }, + "peerDependencies": { + "@openmrs/esm-framework": "6.x", + "@openmrs/esm-patient-common-lib": "10.x", + "react": "18.x", + "react-i18next": "11.x", + "react-router-dom": "6.x" + }, + "devDependencies": { + "webpack": "^5.94.0" + } +} diff --git a/packages/esm-patient-label-printing-app/src/config-schema.ts b/packages/esm-patient-label-printing-app/src/config-schema.ts new file mode 100644 index 0000000000..a0ebada034 --- /dev/null +++ b/packages/esm-patient-label-printing-app/src/config-schema.ts @@ -0,0 +1,5 @@ +import { Type } from '@openmrs/esm-framework'; + +export const configSchema = {}; + +export interface ConfigObject {} diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts similarity index 58% rename from packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx rename to packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts index 38e51ddc27..9291d0aa62 100644 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts @@ -1,12 +1,4 @@ -import React, { useCallback, useState, useRef, useEffect } from 'react'; -import { useTranslation } from 'react-i18next'; -import { OverflowMenuItem } from '@carbon/react'; -import { useFeatureFlag, showSnackbar, getCoreTranslation } from '@openmrs/esm-framework'; -import styles from './action-button.scss'; - -interface PrintIdentifierStickerOverflowMenuItemProps { - patient: fhir.Patient; -} +import { useCallback, useEffect, useRef, useState } from 'react'; const useSickerPdfPrinter = () => { const iframeRef = useRef(null); @@ -102,48 +94,3 @@ const useSickerPdfPrinter = () => { return { printPdf, isPrinting }; }; - -const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { - const { t } = useTranslation(); - const canPrintPatientIdentifierSticker = useFeatureFlag('print-patient-identifier-sticker'); - const { printPdf, isPrinting } = useSickerPdfPrinter(); - - const getPdfUrl = useCallback(() => { - if (!patient?.id) { - throw new Error('Patient ID not found'); - } - return `${window.openmrsBase}/ws/module/commonreports/patientIdSticker?patientUuid=${patient.id}`; - }, [patient]); - - const handlePrint = useCallback(async () => { - try { - const pdfUrl = getPdfUrl(); - await printPdf(pdfUrl); - } catch (error) { - showSnackbar({ - kind: 'error', - title: getCoreTranslation('printError', 'Print Error'), - subtitle: getCoreTranslation('printErrorExplainer', '', { errorLocation: error?.message }), - }); - } - }, [getPdfUrl, printPdf]); - - if (!patient || !canPrintPatientIdentifierSticker) { - return null; - } - - return ( - - ); -}; - -export default PrintIdentifierStickerOverflowMenuItem; diff --git a/packages/esm-patient-label-printing-app/src/index.ts b/packages/esm-patient-label-printing-app/src/index.ts new file mode 100644 index 0000000000..e725600687 --- /dev/null +++ b/packages/esm-patient-label-printing-app/src/index.ts @@ -0,0 +1,40 @@ +import { + defineConfigSchema, + getAsyncLifecycle, + getSyncLifecycle, + messageOmrsServiceWorker, + registerFeatureFlag, + restBaseUrl, +} from '@openmrs/esm-framework'; +import { configSchema } from './config-schema'; + +const moduleName = '@openmrs/esm-patient-label-printing-app'; + +const options = { + featureName: 'patient-banner', + moduleName, +}; + +export const importTranslation = require.context('../translations', false, /.json$/, 'lazy'); + +export function startupApp() { + messageOmrsServiceWorker({ + type: 'registerDynamicRoute', + pattern: `.+${restBaseUrl}/relationship.+`, + }); + + registerFeatureFlag( + 'print-patient-identifier-sticker', + 'Print patient identifier sticker', + 'Features to support printing a patient identifier sticker', + ); + defineConfigSchema(moduleName, configSchema); +} + +// export const printIdentifierStickerActionButton = getAsyncLifecycle( +// () => import('./print-identifier-sticker/print-identifier-sticker-action-button.component'), +// { +// featureName: 'patient-actions-slot-print-identifier-sticker-button', +// moduleName, +// }, +// ); diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/action-button.scss similarity index 100% rename from packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss rename to packages/esm-patient-label-printing-app/src/print-identifier-sticker/action-button.scss diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx new file mode 100644 index 0000000000..694af93fe8 --- /dev/null +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -0,0 +1,56 @@ +import React, { useCallback, useState, useRef, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; +import { OverflowMenuItem } from '@carbon/react'; +import { useFeatureFlag, showSnackbar, getCoreTranslation } from '@openmrs/esm-framework'; +import styles from './action-button.scss'; + +interface PrintIdentifierStickerOverflowMenuItemProps { + patient: fhir.Patient; +} + +const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { + const canPrintPatientIdentifierSticker = useFeatureFlag('print-patient-identifier-sticker'); + const { printPdf, isPrinting } = useSickerPdfPrinter(); + + const getPdfUrl = useCallback(() => { + if (!patient?.id) { + throw new Error('Patient ID not found'); + } + return `${window.openmrsBase}/ws/module/commonreports/patientIdSticker?patientUuid=${patient.id}`; + }, [patient]); + + const handlePrint = useCallback(async () => { + try { + const pdfUrl = getPdfUrl(); + await printPdf(pdfUrl); + } catch (error) { + showSnackbar({ + kind: 'error', + title: getCoreTranslation('printError', 'Print Error'), + subtitle: getCoreTranslation('printErrorExplainer', '', { errorLocation: error?.message }), + }); + } + }, [getPdfUrl, printPdf]); + + if (!patient || !canPrintPatientIdentifierSticker) { + return null; + } + + return ( + + ); +}; + +export default PrintIdentifierStickerOverflowMenuItem; +function useSickerPdfPrinter(): { printPdf: any; isPrinting: any } { + throw new Error('Function not implemented.'); +} diff --git a/packages/esm-patient-label-printing-app/src/routes.json b/packages/esm-patient-label-printing-app/src/routes.json new file mode 100644 index 0000000000..bfbbe7bc51 --- /dev/null +++ b/packages/esm-patient-label-printing-app/src/routes.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json.openmrs.org/routes.schema.json", + "backendDependencies": { + "webservices.rest": "^2.2.0", + "commonreports": "^1.5.0" + }, + "extensions": [ + { + "name": "print-identifier-sticker-button", + "slot": "patient-actions-slot", + "component": "printIdentifierStickerActionButton", + "online": true, + "offline": true + } + ] +} diff --git a/packages/esm-patient-label-printing-app/src/types/index.ts b/packages/esm-patient-label-printing-app/src/types/index.ts new file mode 100644 index 0000000000..079535d9d0 --- /dev/null +++ b/packages/esm-patient-label-printing-app/src/types/index.ts @@ -0,0 +1,60 @@ +// import { type OpenmrsResource } from '@openmrs/esm-framework'; + +// export interface Location { +// uuid: string; +// display?: string; +// name?: string; +// } + +// export interface VisitType { +// uuid: string; +// display: string; +// name?: string; +// } + +// export interface Patient { +// uuid: string; +// display: string; +// identifiers: Array; +// person: Person; +// } + +// export interface Person { +// age: number; +// attributes: Array; +// birthDate: string; +// gender: string; +// display: string; +// preferredAddress: OpenmrsResource; +// uuid: string; +// dead?: boolean; +// deathDate?: Date; +// type?: string; +// } + +// export interface Attribute { +// attributeType: OpenmrsResource; +// display: string; +// uuid: string; +// value: string | number; +// } + +// export interface PersonFetchResponse { +// person: { uuid: string; dead: boolean; deathDate: Date; type: string }; +// } + +// export interface CohortMemberResponse { +// results: Array; +// } +// interface CohortMember { +// uuid: string; +// patient: OpenmrsResource; +// cohort: Cohort; +// } + +// interface Cohort { +// uuid: string; +// name: string; +// startDate: string; +// endDate: string; +// } diff --git a/packages/esm-patient-label-printing-app/tsconfig.json b/packages/esm-patient-label-printing-app/tsconfig.json new file mode 100644 index 0000000000..29fd6726f2 --- /dev/null +++ b/packages/esm-patient-label-printing-app/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*", "../../tools/setup-tests.ts"], +} diff --git a/packages/esm-patient-label-printing-app/webpack.config.js b/packages/esm-patient-label-printing-app/webpack.config.js new file mode 100644 index 0000000000..2c74029c85 --- /dev/null +++ b/packages/esm-patient-label-printing-app/webpack.config.js @@ -0,0 +1 @@ +module.exports = require('openmrs/default-webpack-config'); diff --git a/yarn.lock b/yarn.lock index 25302c95e2..e93c02d869 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5021,6 +5021,21 @@ __metadata: languageName: unknown linkType: soft +"@openmrs/esm-patient-label-printing-app@workspace:packages/esm-patient-label-printing-app": + version: 0.0.0-use.local + resolution: "@openmrs/esm-patient-label-printing-app@workspace:packages/esm-patient-label-printing-app" + dependencies: + "@carbon/react": "npm:^1.76.0" + webpack: "npm:^5.94.0" + peerDependencies: + "@openmrs/esm-framework": 6.x + "@openmrs/esm-patient-common-lib": 10.x + react: 18.x + react-i18next: 11.x + react-router-dom: 6.x + languageName: unknown + linkType: soft + "@openmrs/esm-patient-lists-app@workspace:packages/esm-patient-lists-app": version: 0.0.0-use.local resolution: "@openmrs/esm-patient-lists-app@workspace:packages/esm-patient-lists-app" From 9aa7b96cace28021235eeb1e761f30bd8515944e Mon Sep 17 00:00:00 2001 From: jnsereko Date: Tue, 13 May 2025 13:34:29 +0300 Subject: [PATCH 04/35] add translations --- packages/esm-patient-banner-app/src/index.ts | 9 +- .../src/hooks/useSickerPdfPrinter.ts | 139 +++++++++--------- ...tifier-sticker-action-button.component.tsx | 11 +- .../src/types/index.ts | 60 -------- .../translations/en.json | 6 + 5 files changed, 84 insertions(+), 141 deletions(-) delete mode 100644 packages/esm-patient-label-printing-app/src/types/index.ts create mode 100644 packages/esm-patient-label-printing-app/translations/en.json diff --git a/packages/esm-patient-banner-app/src/index.ts b/packages/esm-patient-banner-app/src/index.ts index 49f9174bd9..51a377693a 100644 --- a/packages/esm-patient-banner-app/src/index.ts +++ b/packages/esm-patient-banner-app/src/index.ts @@ -1,11 +1,4 @@ -import { - defineConfigSchema, - getAsyncLifecycle, - getSyncLifecycle, - messageOmrsServiceWorker, - registerFeatureFlag, - restBaseUrl, -} from '@openmrs/esm-framework'; +import { defineConfigSchema, getSyncLifecycle, messageOmrsServiceWorker, restBaseUrl } from '@openmrs/esm-framework'; import { configSchema } from './config-schema'; import deceasedPatientTagComponent from './banner-tags/deceased-patient-tag.extension'; import patientBannerComponent from './banner/patient-banner.component'; diff --git a/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts b/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts index 9291d0aa62..d0937013a8 100644 --- a/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts +++ b/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts @@ -1,80 +1,85 @@ import { useCallback, useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; -const useSickerPdfPrinter = () => { +export const useSickerPdfPrinter = () => { + const { t } = useTranslation(); const iframeRef = useRef(null); const [isPrinting, setIsPrinting] = useState(false); - const printPdf = useCallback((url: string) => { - return new Promise((resolve, reject) => { - setIsPrinting(true); - - if (!iframeRef.current) { - const iframe = document.createElement('iframe'); - iframe.name = 'pdfPrinterFrame'; - iframe.style.position = 'fixed'; - iframe.style.width = '0'; - iframe.style.height = '0'; - iframe.style.border = 'none'; - iframe.style.visibility = 'hidden'; - iframeRef.current = iframe; - document.body.appendChild(iframe); - } - - const iframe = iframeRef.current; - - const handleLoad = () => { - try { - const contentWindow = iframe.contentWindow; - - if (!contentWindow) { - throw new Error('Failed to access print window'); - } - - contentWindow.focus(); - contentWindow.print(); - - if (isSameOrigin(url)) { - contentWindow.addEventListener('afterprint', handlePrintComplete); - } else { - // For cross-origin, we'll assume printing is immediate - // and rely on the browser's print dialog behavior - handlePrintComplete(); - } - } catch (error) { - handlePrintError(error); + const printPdf = useCallback( + (url: string) => { + return new Promise((resolve, reject) => { + setIsPrinting(true); + + if (!iframeRef.current) { + const iframe = document.createElement('iframe'); + iframe.name = 'pdfPrinterFrame'; + iframe.style.position = 'fixed'; + iframe.style.width = '0'; + iframe.style.height = '0'; + iframe.style.border = 'none'; + iframe.style.visibility = 'hidden'; + iframeRef.current = iframe; + document.body.appendChild(iframe); } - }; - - const handlePrintComplete = () => { - cleanup(); - resolve(); - }; - const handlePrintError = (error: unknown) => { - cleanup(); - reject(error instanceof Error ? error : new Error('Printing failed')); - }; + const iframe = iframeRef.current; - const cleanup = () => { - iframe.onload = null; - iframe.onerror = null; - setIsPrinting(false); - - // Remove event listener if same-origin - if (iframe.contentWindow && isSameOrigin(url)) { + const handleLoad = () => { try { - iframe.contentWindow.removeEventListener('afterprint', handlePrintComplete); - } catch { - // Ignore cross-origin errors + const contentWindow = iframe.contentWindow; + + if (!contentWindow) { + throw new Error(t('failedToAccessPrintWindow', 'Failed to access print window')); + } + + contentWindow.focus(); + contentWindow.print(); + + if (isSameOrigin(url)) { + contentWindow.addEventListener('afterprint', handlePrintComplete); + } else { + // For cross-origin, we'll assume printing is immediate + // and rely on the browser's print dialog behavior + handlePrintComplete(); + } + } catch (error) { + handlePrintError(error); } - } - }; - - iframe.onload = handleLoad; - iframe.onerror = () => handlePrintError(new Error('Failed to load PDF')); - iframe.src = url; - }); - }, []); + }; + + const handlePrintComplete = () => { + cleanup(); + resolve(); + }; + + const handlePrintError = (error: unknown) => { + cleanup(); + reject(error instanceof Error ? error : new Error(t('printingFailed', 'Printing failed'))); + }; + + const cleanup = () => { + iframe.onload = null; + iframe.onerror = null; + setIsPrinting(false); + + // Remove event listener if same-origin + if (iframe.contentWindow && isSameOrigin(url)) { + try { + iframe.contentWindow.removeEventListener('afterprint', handlePrintComplete); + } catch { + // Ignore cross-origin errors + } + } + }; + + iframe.onload = handleLoad; + iframe.onerror = () => handlePrintError(new Error(t('failedToLoadPDF', 'Failed to load PDF'))); + iframe.src = url; + }); + }, + [t], + ); const isSameOrigin = (url: string) => { try { diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 694af93fe8..2889c1083f 100644 --- a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -1,23 +1,25 @@ -import React, { useCallback, useState, useRef, useEffect } from 'react'; +import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; import { useFeatureFlag, showSnackbar, getCoreTranslation } from '@openmrs/esm-framework'; import styles from './action-button.scss'; +import { useSickerPdfPrinter } from '../hooks/useSickerPdfPrinter'; interface PrintIdentifierStickerOverflowMenuItemProps { patient: fhir.Patient; } const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { + const { t } = useTranslation(); const canPrintPatientIdentifierSticker = useFeatureFlag('print-patient-identifier-sticker'); const { printPdf, isPrinting } = useSickerPdfPrinter(); const getPdfUrl = useCallback(() => { if (!patient?.id) { - throw new Error('Patient ID not found'); + throw new Error(t('patientIdNotFound', 'Patient ID not found')); } return `${window.openmrsBase}/ws/module/commonreports/patientIdSticker?patientUuid=${patient.id}`; - }, [patient]); + }, [patient.id, t]); const handlePrint = useCallback(async () => { try { @@ -51,6 +53,3 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC; -// person: Person; -// } - -// export interface Person { -// age: number; -// attributes: Array; -// birthDate: string; -// gender: string; -// display: string; -// preferredAddress: OpenmrsResource; -// uuid: string; -// dead?: boolean; -// deathDate?: Date; -// type?: string; -// } - -// export interface Attribute { -// attributeType: OpenmrsResource; -// display: string; -// uuid: string; -// value: string | number; -// } - -// export interface PersonFetchResponse { -// person: { uuid: string; dead: boolean; deathDate: Date; type: string }; -// } - -// export interface CohortMemberResponse { -// results: Array; -// } -// interface CohortMember { -// uuid: string; -// patient: OpenmrsResource; -// cohort: Cohort; -// } - -// interface Cohort { -// uuid: string; -// name: string; -// startDate: string; -// endDate: string; -// } diff --git a/packages/esm-patient-label-printing-app/translations/en.json b/packages/esm-patient-label-printing-app/translations/en.json new file mode 100644 index 0000000000..d615be88f6 --- /dev/null +++ b/packages/esm-patient-label-printing-app/translations/en.json @@ -0,0 +1,6 @@ +{ + "failedToAccessPrintWindow": "Failed to access print window", + "failedToLoadPDF": "Failed to load PDF", + "patientIdNotFound": "Patient ID not found", + "printingFailed": "Printing failed" +} From 5cafc05e7e6ff6974503b2998d2c5cdd8871018d Mon Sep 17 00:00:00 2001 From: jnsereko Date: Tue, 13 May 2025 13:38:51 +0300 Subject: [PATCH 05/35] Fix CI --- .../{useSickerPdfPrinter.ts => useSickerPdfPrinter.tsx} | 0 packages/esm-patient-label-printing-app/translations/en.json | 5 +---- 2 files changed, 1 insertion(+), 4 deletions(-) rename packages/esm-patient-label-printing-app/src/hooks/{useSickerPdfPrinter.ts => useSickerPdfPrinter.tsx} (100%) diff --git a/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts b/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.tsx similarity index 100% rename from packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.ts rename to packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.tsx diff --git a/packages/esm-patient-label-printing-app/translations/en.json b/packages/esm-patient-label-printing-app/translations/en.json index d615be88f6..e768524041 100644 --- a/packages/esm-patient-label-printing-app/translations/en.json +++ b/packages/esm-patient-label-printing-app/translations/en.json @@ -1,6 +1,3 @@ { - "failedToAccessPrintWindow": "Failed to access print window", - "failedToLoadPDF": "Failed to load PDF", - "patientIdNotFound": "Patient ID not found", - "printingFailed": "Printing failed" + "patientIdNotFound": "Patient ID not found" } From 91a2998f00b0269a84b750b957e5da75697e2c44 Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Tue, 13 May 2025 13:42:23 +0300 Subject: [PATCH 06/35] Update packages/esm-patient-label-printing-app/README.md Co-authored-by: Dennis Kigen --- packages/esm-patient-label-printing-app/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/README.md b/packages/esm-patient-label-printing-app/README.md index 08f737c492..1a7c2da18e 100644 --- a/packages/esm-patient-label-printing-app/README.md +++ b/packages/esm-patient-label-printing-app/README.md @@ -1,3 +1,3 @@ # esm-patient-label-printing-app -Patient Label Printing microfrontend is designed to provide a flexible and extensible printing mechanism that can be easily integrated into multiple contexts within the application. Its core architecture will support print actions in diverse scenarios, such as patient management apps like Queues, clerical views, and billing interfaces, enabling quick and standardized print functionality for various document types including patient records, receipts, and other critical documents. +The Patient label printing frontend module provides a flexible and extensible printing mechanism that integrates easily into various parts of the application. Its core architecture supports print actions across diverse contexts—such as patient management apps like queues, clerical views, and billing interfaces—enabling fast, standardized printing of documents like patient records, receipts, and other critical materials. From ceae307e7e78fe153417969161aa963aa1290086 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Tue, 13 May 2025 13:56:01 +0300 Subject: [PATCH 07/35] clean code --- .../package.json | 1 - .../src/config-schema.ts | 2 -- ...dfPrinter.tsx => useStickerPdfPrinter.tsx} | 2 +- .../src/index.ts | 20 +++++++------------ ...tifier-sticker-action-button.component.tsx | 4 ++-- .../src/routes.json | 1 - yarn.lock | 1 - 7 files changed, 10 insertions(+), 21 deletions(-) rename packages/esm-patient-label-printing-app/src/hooks/{useSickerPdfPrinter.tsx => useStickerPdfPrinter.tsx} (98%) diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index 8f98a58638..b3f753faf8 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -41,7 +41,6 @@ }, "peerDependencies": { "@openmrs/esm-framework": "6.x", - "@openmrs/esm-patient-common-lib": "10.x", "react": "18.x", "react-i18next": "11.x", "react-router-dom": "6.x" diff --git a/packages/esm-patient-label-printing-app/src/config-schema.ts b/packages/esm-patient-label-printing-app/src/config-schema.ts index a0ebada034..152465255c 100644 --- a/packages/esm-patient-label-printing-app/src/config-schema.ts +++ b/packages/esm-patient-label-printing-app/src/config-schema.ts @@ -1,5 +1,3 @@ -import { Type } from '@openmrs/esm-framework'; - export const configSchema = {}; export interface ConfigObject {} diff --git a/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.tsx b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx similarity index 98% rename from packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.tsx rename to packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx index d0937013a8..97f7855e9a 100644 --- a/packages/esm-patient-label-printing-app/src/hooks/useSickerPdfPrinter.tsx +++ b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -export const useSickerPdfPrinter = () => { +export const useStickerPdfPrinter = () => { const { t } = useTranslation(); const iframeRef = useRef(null); const [isPrinting, setIsPrinting] = useState(false); diff --git a/packages/esm-patient-label-printing-app/src/index.ts b/packages/esm-patient-label-printing-app/src/index.ts index e725600687..b230e805cc 100644 --- a/packages/esm-patient-label-printing-app/src/index.ts +++ b/packages/esm-patient-label-printing-app/src/index.ts @@ -1,7 +1,6 @@ import { defineConfigSchema, getAsyncLifecycle, - getSyncLifecycle, messageOmrsServiceWorker, registerFeatureFlag, restBaseUrl, @@ -10,11 +9,6 @@ import { configSchema } from './config-schema'; const moduleName = '@openmrs/esm-patient-label-printing-app'; -const options = { - featureName: 'patient-banner', - moduleName, -}; - export const importTranslation = require.context('../translations', false, /.json$/, 'lazy'); export function startupApp() { @@ -31,10 +25,10 @@ export function startupApp() { defineConfigSchema(moduleName, configSchema); } -// export const printIdentifierStickerActionButton = getAsyncLifecycle( -// () => import('./print-identifier-sticker/print-identifier-sticker-action-button.component'), -// { -// featureName: 'patient-actions-slot-print-identifier-sticker-button', -// moduleName, -// }, -// ); +export const printIdentifierStickerActionButton = getAsyncLifecycle( + () => import('./print-identifier-sticker/print-identifier-sticker-action-button.component'), + { + featureName: 'patient-actions-slot-print-identifier-sticker-button', + moduleName, + }, +); diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 2889c1083f..a6b70e1ad7 100644 --- a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; import { useFeatureFlag, showSnackbar, getCoreTranslation } from '@openmrs/esm-framework'; import styles from './action-button.scss'; -import { useSickerPdfPrinter } from '../hooks/useSickerPdfPrinter'; +import { useStickerPdfPrinter } from '../hooks/useStickerPdfPrinter'; interface PrintIdentifierStickerOverflowMenuItemProps { patient: fhir.Patient; @@ -12,7 +12,7 @@ interface PrintIdentifierStickerOverflowMenuItemProps { const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { const { t } = useTranslation(); const canPrintPatientIdentifierSticker = useFeatureFlag('print-patient-identifier-sticker'); - const { printPdf, isPrinting } = useSickerPdfPrinter(); + const { printPdf, isPrinting } = useStickerPdfPrinter(); const getPdfUrl = useCallback(() => { if (!patient?.id) { diff --git a/packages/esm-patient-label-printing-app/src/routes.json b/packages/esm-patient-label-printing-app/src/routes.json index bfbbe7bc51..b6687a6fd7 100644 --- a/packages/esm-patient-label-printing-app/src/routes.json +++ b/packages/esm-patient-label-printing-app/src/routes.json @@ -1,7 +1,6 @@ { "$schema": "https://json.openmrs.org/routes.schema.json", "backendDependencies": { - "webservices.rest": "^2.2.0", "commonreports": "^1.5.0" }, "extensions": [ diff --git a/yarn.lock b/yarn.lock index e93c02d869..310a47a637 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5029,7 +5029,6 @@ __metadata: webpack: "npm:^5.94.0" peerDependencies: "@openmrs/esm-framework": 6.x - "@openmrs/esm-patient-common-lib": 10.x react: 18.x react-i18next: 11.x react-router-dom: 6.x From 0bae418271a1b2cc882c86346468b07c7198c0c8 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Tue, 20 May 2025 10:24:14 +0300 Subject: [PATCH 08/35] use patient documents backend module --- .../print-identifier-sticker-action-button.component.tsx | 2 +- packages/esm-patient-label-printing-app/src/routes.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index a6b70e1ad7..26915cb178 100644 --- a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -18,7 +18,7 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC { diff --git a/packages/esm-patient-label-printing-app/src/routes.json b/packages/esm-patient-label-printing-app/src/routes.json index b6687a6fd7..560f40aeac 100644 --- a/packages/esm-patient-label-printing-app/src/routes.json +++ b/packages/esm-patient-label-printing-app/src/routes.json @@ -1,7 +1,7 @@ { "$schema": "https://json.openmrs.org/routes.schema.json", "backendDependencies": { - "commonreports": "^1.5.0" + "patientdocuments": "^1.0.0" }, "extensions": [ { From 82d8b6ff08ed24fa6c889c8664ab168709daddd3 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Mon, 4 Aug 2025 15:43:39 +0300 Subject: [PATCH 09/35] Add ability to enable Sticker by default --- .../src/config-schema.ts | 14 ++++++- .../src/declarations.d.ts | 4 ++ .../src/index.ts | 13 +----- ...tifier-sticker-action-button.component.tsx | 41 +++++++++++-------- .../src/routes.json | 2 +- 5 files changed, 42 insertions(+), 32 deletions(-) create mode 100644 packages/esm-patient-label-printing-app/src/declarations.d.ts diff --git a/packages/esm-patient-label-printing-app/src/config-schema.ts b/packages/esm-patient-label-printing-app/src/config-schema.ts index 152465255c..4c0df275a4 100644 --- a/packages/esm-patient-label-printing-app/src/config-schema.ts +++ b/packages/esm-patient-label-printing-app/src/config-schema.ts @@ -1,3 +1,13 @@ -export const configSchema = {}; +import { Type } from '@openmrs/esm-framework'; -export interface ConfigObject {} +export const configSchema = { + showPrintIdentifierStickerButton: { + _type: Type.Boolean, + _description: "Whether to display the 'Print identifier sticker' button in the patient banner", + _default: false, + }, +}; + +export interface ConfigObject { + showPrintIdentifierStickerButton: boolean; +} diff --git a/packages/esm-patient-label-printing-app/src/declarations.d.ts b/packages/esm-patient-label-printing-app/src/declarations.d.ts new file mode 100644 index 0000000000..2978cbc493 --- /dev/null +++ b/packages/esm-patient-label-printing-app/src/declarations.d.ts @@ -0,0 +1,4 @@ +declare module '*.scss' { + const content: { [className: string]: string }; + export default content; +} diff --git a/packages/esm-patient-label-printing-app/src/index.ts b/packages/esm-patient-label-printing-app/src/index.ts index b230e805cc..97dea66a54 100644 --- a/packages/esm-patient-label-printing-app/src/index.ts +++ b/packages/esm-patient-label-printing-app/src/index.ts @@ -1,10 +1,4 @@ -import { - defineConfigSchema, - getAsyncLifecycle, - messageOmrsServiceWorker, - registerFeatureFlag, - restBaseUrl, -} from '@openmrs/esm-framework'; +import { defineConfigSchema, getAsyncLifecycle, registerFeatureFlag } from '@openmrs/esm-framework'; import { configSchema } from './config-schema'; const moduleName = '@openmrs/esm-patient-label-printing-app'; @@ -12,11 +6,6 @@ const moduleName = '@openmrs/esm-patient-label-printing-app'; export const importTranslation = require.context('../translations', false, /.json$/, 'lazy'); export function startupApp() { - messageOmrsServiceWorker({ - type: 'registerDynamicRoute', - pattern: `.+${restBaseUrl}/relationship.+`, - }); - registerFeatureFlag( 'print-patient-identifier-sticker', 'Print patient identifier sticker', diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 26915cb178..9b10fc3916 100644 --- a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -1,9 +1,10 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; -import { useFeatureFlag, showSnackbar, getCoreTranslation } from '@openmrs/esm-framework'; +import { useFeatureFlag, showSnackbar, getCoreTranslation, useConfig } from '@openmrs/esm-framework'; import styles from './action-button.scss'; import { useStickerPdfPrinter } from '../hooks/useStickerPdfPrinter'; +import type { ConfigObject } from '../config-schema'; interface PrintIdentifierStickerOverflowMenuItemProps { patient: fhir.Patient; @@ -11,44 +12,50 @@ interface PrintIdentifierStickerOverflowMenuItemProps { const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { const { t } = useTranslation(); - const canPrintPatientIdentifierSticker = useFeatureFlag('print-patient-identifier-sticker'); + const { showPrintIdentifierStickerButton } = useConfig(); + const enableStickerFeatureFlag = useFeatureFlag('print-patient-identifier-sticker'); const { printPdf, isPrinting } = useStickerPdfPrinter(); + const isVisible = useMemo(() => { + if (!patient?.id) return false; + return enableStickerFeatureFlag || showPrintIdentifierStickerButton; + }, [enableStickerFeatureFlag, showPrintIdentifierStickerButton, patient?.id]); + const getPdfUrl = useCallback(() => { if (!patient?.id) { throw new Error(t('patientIdNotFound', 'Patient ID not found')); } return `${window.openmrsBase}/ws/module/patientdocuments/patientIdSticker?patientUuid=${patient.id}`; - }, [patient.id, t]); + }, [patient?.id, t]); const handlePrint = useCallback(async () => { + if (isPrinting) return; + try { const pdfUrl = getPdfUrl(); await printPdf(pdfUrl); } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); showSnackbar({ kind: 'error', title: getCoreTranslation('printError', 'Print Error'), - subtitle: getCoreTranslation('printErrorExplainer', '', { errorLocation: error?.message }), + subtitle: getCoreTranslation('printErrorExplainer', '', { errorLocation: errorMessage }), }); } - }, [getPdfUrl, printPdf]); + }, [getPdfUrl, printPdf, isPrinting]); + + const buttonText = useMemo(() => { + return isPrinting + ? getCoreTranslation('printing', 'Printing...') + : getCoreTranslation('printIdentifierSticker', 'Print identifier sticker'); + }, [isPrinting]); - if (!patient || !canPrintPatientIdentifierSticker) { + if (!isVisible) { return null; } return ( - + ); }; diff --git a/packages/esm-patient-label-printing-app/src/routes.json b/packages/esm-patient-label-printing-app/src/routes.json index 560f40aeac..ab573f7f7c 100644 --- a/packages/esm-patient-label-printing-app/src/routes.json +++ b/packages/esm-patient-label-printing-app/src/routes.json @@ -1,7 +1,7 @@ { "$schema": "https://json.openmrs.org/routes.schema.json", "backendDependencies": { - "patientdocuments": "^1.0.0" + "patientdocuments": "^1.0.0-SNAPSHOT" }, "extensions": [ { From 226065c962f3569c0bcf8bdba749d387dd7978bd Mon Sep 17 00:00:00 2001 From: jnsereko Date: Mon, 4 Aug 2025 16:52:46 +0300 Subject: [PATCH 10/35] add lock file --- yarn.lock | 238 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 218 insertions(+), 20 deletions(-) diff --git a/yarn.lock b/yarn.lock index 310a47a637..b89a1f2c8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2034,15 +2034,33 @@ __metadata: languageName: node linkType: hard -"@carbon/feature-flags@npm:^0.31.0": - version: 0.31.0 - resolution: "@carbon/feature-flags@npm:0.31.0" +"@carbon/colors@npm:^11.37.0": + version: 11.37.0 + resolution: "@carbon/colors@npm:11.37.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.5.0" + checksum: 10/85ac7e42fd743c809dd309080ed6ba01dcf1a2f90bafab99e2dbe5f93dec28a3ae4728202941ecfdbdeccd1899c0ee7f029bce08943cb07ff419832773c69cbf + languageName: node + linkType: hard + +"@carbon/feature-flags@npm:^0.27.0": + version: 0.27.0 + resolution: "@carbon/feature-flags@npm:0.27.0" dependencies: "@ibm/telemetry-js": "npm:^1.5.0" checksum: 10/fe7ec8f7f338535811c2852606b6b2ac19382857f2881867137d1cc530df6fa0a8b33bf6c367ec5c88899421a851cbe34425479d4b229ec20c8c838313c0700d languageName: node linkType: hard +"@carbon/feature-flags@npm:^0.29.0": + version: 0.29.0 + resolution: "@carbon/feature-flags@npm:0.29.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.5.0" + checksum: 10/00d2fda8418693b86ba856304ef518c58cdd25304ce8c33f1dae52bd6ee51c0c4a680ec36195112ddc55b775dfbfb1677b57bcb19c53c28db23f5c8713260cec + languageName: node + linkType: hard + "@carbon/feature-flags@npm:^0.9.0": version: 0.9.0 resolution: "@carbon/feature-flags@npm:0.9.0" @@ -2082,27 +2100,89 @@ __metadata: languageName: node linkType: hard -"@carbon/layout@npm:^11.42.0, @carbon/layout@npm:^11.7.0": - version: 11.42.0 - resolution: "@carbon/layout@npm:11.42.0" +"@carbon/icons-react@npm:^11.64.0": + version: 11.64.0 + resolution: "@carbon/icons-react@npm:11.64.0" + dependencies: + "@carbon/icon-helpers": "npm:^10.63.0" + "@ibm/telemetry-js": "npm:^1.5.0" + prop-types: "npm:^15.8.1" + peerDependencies: + react: ">=16" + checksum: 10/c33515176542cf812b6e732f865cf5c665836eaba79cc3114f13c52de95b3b81b4b6d5e5256511c842205d5dbb0fec5f3b2e7190ed089fd3f7c1bfc8e881e129 + languageName: node + linkType: hard + +"@carbon/layout@npm:^11.35.0, @carbon/layout@npm:^11.7.0": + version: 11.35.0 + resolution: "@carbon/layout@npm:11.35.0" dependencies: "@ibm/telemetry-js": "npm:^1.5.0" checksum: 10/bf038bfab3d9e0a161a69c7ac48afc47bd96332eef90f4d33eb2cc325427bd4020bfcbef4c8301c5f39583959796145473143b4dd78702091285f247e7262f05 languageName: node linkType: hard -"@carbon/motion@npm:^11.36.0, @carbon/motion@npm:^11.5.0": - version: 11.36.0 - resolution: "@carbon/motion@npm:11.36.0" +"@carbon/layout@npm:^11.38.0": + version: 11.38.0 + resolution: "@carbon/layout@npm:11.38.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.5.0" + checksum: 10/f7be0cf0cf7585e8472eee827e9d2c3e908188c56c2a2ac8a86f71f981d7f280a445d9037cbd5b91f658bc2cfb4e0184887304635240423ffa01bad02a8845f3 + languageName: node + linkType: hard + +"@carbon/motion@npm:^11.29.0, @carbon/motion@npm:^11.5.0": + version: 11.29.0 + resolution: "@carbon/motion@npm:11.29.0" dependencies: "@ibm/telemetry-js": "npm:^1.5.0" checksum: 10/b20f42cff7950bc3e1e0add0ce31330574c6a4b21b6c8597156c1a31007654bdbe63439f019f07dc59a2ed60e70c7c7215c0f78cd4de06bada0777e8d2e3bff8 languageName: node linkType: hard -"@carbon/react@npm:^1.83.0, @carbon/react@npm:^1.92.1": - version: 1.92.1 - resolution: "@carbon/react@npm:1.92.1" +"@carbon/motion@npm:^11.32.0": + version: 11.32.0 + resolution: "@carbon/motion@npm:11.32.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.5.0" + checksum: 10/8b6ce5b4cb496d734daad8b73dd2e290efeab52b29217fe9ee79d9e85aa599f9bf147d6588d011c56f278065941f3f40cec0c6a94c84d8942233e915f35ee44d + languageName: node + linkType: hard + +"@carbon/react@npm:^1.76.0": + version: 1.88.0 + resolution: "@carbon/react@npm:1.88.0" + dependencies: + "@babel/runtime": "npm:^7.27.3" + "@carbon/feature-flags": "npm:^0.29.0" + "@carbon/icons-react": "npm:^11.64.0" + "@carbon/layout": "npm:^11.38.0" + "@carbon/styles": "npm:^1.87.0" + "@carbon/utilities": "npm:^0.7.0" + "@floating-ui/react": "npm:^0.27.4" + "@ibm/telemetry-js": "npm:^1.5.0" + classnames: "npm:2.5.1" + copy-to-clipboard: "npm:^3.3.1" + downshift: "npm:9.0.9" + es-toolkit: "npm:^1.27.0" + flatpickr: "npm:4.6.13" + invariant: "npm:^2.2.3" + prop-types: "npm:^15.8.1" + react-fast-compare: "npm:^3.2.2" + tabbable: "npm:^6.2.0" + window-or-global: "npm:^1.0.1" + peerDependencies: + react: ^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0 + react-dom: ^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0 + react-is: ^16.13.1 || ^17.0.2 || ^18.3.1 || ^19.0.0 + sass: ^1.33.0 + checksum: 10/03fed67eba0f04606a1ffa3ffb981219e6c1b04501d10988d27776ae63d1307a4b6dd57718a4498524539e7004354993b73ddf450fd7cadea484be31d7c4d3f6 + languageName: node + linkType: hard + +"@carbon/react@npm:^1.83.0": + version: 1.84.0 + resolution: "@carbon/react@npm:1.84.0" dependencies: "@babel/runtime": "npm:^7.27.3" "@carbon/feature-flags": "npm:^0.31.0" @@ -2161,6 +2241,36 @@ __metadata: languageName: node linkType: hard +"@carbon/styles@npm:^1.87.0": + version: 1.87.0 + resolution: "@carbon/styles@npm:1.87.0" + dependencies: + "@carbon/colors": "npm:^11.37.0" + "@carbon/feature-flags": "npm:^0.29.0" + "@carbon/grid": "npm:^11.40.0" + "@carbon/layout": "npm:^11.38.0" + "@carbon/motion": "npm:^11.32.0" + "@carbon/themes": "npm:^11.57.0" + "@carbon/type": "npm:^11.44.0" + "@ibm/plex": "npm:6.0.0-next.6" + "@ibm/plex-mono": "npm:0.0.3-alpha.0" + "@ibm/plex-sans": "npm:0.0.3-alpha.0" + "@ibm/plex-sans-arabic": "npm:0.0.3-alpha.0" + "@ibm/plex-sans-devanagari": "npm:0.0.3-alpha.0" + "@ibm/plex-sans-hebrew": "npm:0.0.3-alpha.0" + "@ibm/plex-sans-thai": "npm:0.0.3-alpha.0" + "@ibm/plex-sans-thai-looped": "npm:0.0.3-alpha.0" + "@ibm/plex-serif": "npm:0.0.3-alpha.0" + "@ibm/telemetry-js": "npm:^1.5.0" + peerDependencies: + sass: ^1.33.0 + peerDependenciesMeta: + sass: + optional: true + checksum: 10/8f4468876ba6a81ecf35c138793a350ebaf17451bbc268cc507acd8f92fd0f885dd14c5ddc2fdf5880a9e0d13f3f49cdd24acea5a446a03adf700e6cb3c456a3 + languageName: node + linkType: hard + "@carbon/styles@npm:~1.14.0": version: 1.14.0 resolution: "@carbon/styles@npm:1.14.0" @@ -2192,9 +2302,22 @@ __metadata: languageName: node linkType: hard -"@carbon/type@npm:^11.10.0, @carbon/type@npm:^11.48.0": - version: 11.48.0 - resolution: "@carbon/type@npm:11.48.0" +"@carbon/themes@npm:^11.57.0": + version: 11.57.0 + resolution: "@carbon/themes@npm:11.57.0" + dependencies: + "@carbon/colors": "npm:^11.37.0" + "@carbon/layout": "npm:^11.38.0" + "@carbon/type": "npm:^11.44.0" + "@ibm/telemetry-js": "npm:^1.5.0" + color: "npm:^4.0.0" + checksum: 10/2622bf2cadc9e616316ec33781785e25c7b41273a56e26a81e747a8a9412351a0672adb014793aedba95591d5e0c4400fb5a1795a659502dc2ce944c3208ed37 + languageName: node + linkType: hard + +"@carbon/type@npm:^11.10.0, @carbon/type@npm:^11.41.0": + version: 11.41.0 + resolution: "@carbon/type@npm:11.41.0" dependencies: "@carbon/grid": "npm:^11.44.0" "@carbon/layout": "npm:^11.42.0" @@ -2203,9 +2326,20 @@ __metadata: languageName: node linkType: hard -"@carbon/utilities@npm:^0.10.0": - version: 0.10.0 - resolution: "@carbon/utilities@npm:0.10.0" +"@carbon/type@npm:^11.44.0": + version: 11.44.0 + resolution: "@carbon/type@npm:11.44.0" + dependencies: + "@carbon/grid": "npm:^11.40.0" + "@carbon/layout": "npm:^11.38.0" + "@ibm/telemetry-js": "npm:^1.5.0" + checksum: 10/cf68583c418a4a68396a6a66ba366de7eb80563e921865471f2b12ff8dff5aa8c20e6822b7f259e6b64d32a6f0ffdc59115006970b317dfddd7acaa3392960c3 + languageName: node + linkType: hard + +"@carbon/utilities@npm:^0.7.0": + version: 0.7.0 + resolution: "@carbon/utilities@npm:0.7.0" dependencies: "@ibm/telemetry-js": "npm:^1.6.1" "@internationalized/number": "npm:^3.6.1" @@ -8374,7 +8508,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5, @types/estree@npm:^1.0.6": +"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 @@ -9625,6 +9759,15 @@ __metadata: languageName: node linkType: hard +"acorn-import-phases@npm:^1.0.3": + version: 1.0.4 + resolution: "acorn-import-phases@npm:1.0.4" + peerDependencies: + acorn: ^8.14.0 + checksum: 10/471050ac7d9b61909c837b426de9eeef2958997f6277ad7dea88d5894fd9b3245d8ed4a225c2ca44f814dbb20688009db7a80e525e8196fc9e98c5285b66161d + languageName: node + linkType: hard + "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -9641,7 +9784,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.14.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": +"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -13503,6 +13646,16 @@ __metadata: languageName: node linkType: hard +"enhanced-resolve@npm:^5.17.2": + version: 5.18.2 + resolution: "enhanced-resolve@npm:5.18.2" + dependencies: + graceful-fs: "npm:^4.2.4" + tapable: "npm:^2.2.0" + checksum: 10/d1b517c908b69d1afbf87b476bbe7dd8d1daf11070127b9ec4f8553f0c6020d30f79103c938776645d569e954e4e04c326f408d2ea3820ade71e72798fb7d36f + languageName: node + linkType: hard + "enquirer@npm:~2.3.6": version: 2.3.6 resolution: "enquirer@npm:2.3.6" @@ -26162,6 +26315,13 @@ __metadata: languageName: node linkType: hard +"webpack-sources@npm:^3.3.3": + version: 3.3.3 + resolution: "webpack-sources@npm:3.3.3" + checksum: 10/ec5d72607e8068467370abccbfff855c596c098baedbe9d198a557ccf198e8546a322836a6f74241492576adba06100286592993a62b63196832cdb53c8bae91 + languageName: node + linkType: hard + "webpack-stats-plugin@npm:^1.1.3": version: 1.1.3 resolution: "webpack-stats-plugin@npm:1.1.3" @@ -26221,6 +26381,44 @@ __metadata: languageName: node linkType: hard +"webpack@npm:^5.94.0": + version: 5.101.0 + resolution: "webpack@npm:5.101.0" + dependencies: + "@types/eslint-scope": "npm:^3.7.7" + "@types/estree": "npm:^1.0.8" + "@types/json-schema": "npm:^7.0.15" + "@webassemblyjs/ast": "npm:^1.14.1" + "@webassemblyjs/wasm-edit": "npm:^1.14.1" + "@webassemblyjs/wasm-parser": "npm:^1.14.1" + acorn: "npm:^8.15.0" + acorn-import-phases: "npm:^1.0.3" + browserslist: "npm:^4.24.0" + chrome-trace-event: "npm:^1.0.2" + enhanced-resolve: "npm:^5.17.2" + es-module-lexer: "npm:^1.2.1" + eslint-scope: "npm:5.1.1" + events: "npm:^3.2.0" + glob-to-regexp: "npm:^0.4.1" + graceful-fs: "npm:^4.2.11" + json-parse-even-better-errors: "npm:^2.3.1" + loader-runner: "npm:^4.2.0" + mime-types: "npm:^2.1.27" + neo-async: "npm:^2.6.2" + schema-utils: "npm:^4.3.2" + tapable: "npm:^2.1.1" + terser-webpack-plugin: "npm:^5.3.11" + watchpack: "npm:^2.4.1" + webpack-sources: "npm:^3.3.3" + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: 10/edeb24a88cbe96902c601bc1292cd344d27c89c5eceb187f4e9936c8a17356c62b23a5dc441c12b16e62bb6c40804bd10d691135c638398f921760f2dba6a761 + languageName: node + linkType: hard + "webpack@npm:^5.99.9": version: 5.99.9 resolution: "webpack@npm:5.99.9" From 776c6d1118fad5e768765e9c2ce037c0629bf634 Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:59:18 +0300 Subject: [PATCH 11/35] Update packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx Co-authored-by: Samuel Male --- .../src/hooks/useStickerPdfPrinter.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx index 97f7855e9a..bcb151fed7 100644 --- a/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx +++ b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx @@ -14,11 +14,13 @@ export const useStickerPdfPrinter = () => { if (!iframeRef.current) { const iframe = document.createElement('iframe'); iframe.name = 'pdfPrinterFrame'; - iframe.style.position = 'fixed'; - iframe.style.width = '0'; - iframe.style.height = '0'; - iframe.style.border = 'none'; - iframe.style.visibility = 'hidden'; + Object.assign(iframe.style, { + position: 'fixed', + width: '0', + height: '0', + border: 'none', + visibility: 'hidden' + }); iframeRef.current = iframe; document.body.appendChild(iframe); } From 0363a19d2842b1b4fb0ac70210a76bffb5b2cd89 Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:59:42 +0300 Subject: [PATCH 12/35] Update packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx Co-authored-by: Samuel Male --- .../print-identifier-sticker-action-button.component.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 9b10fc3916..da886e8da1 100644 --- a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -32,8 +32,7 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC Date: Mon, 6 Oct 2025 23:41:41 +0300 Subject: [PATCH 13/35] (chore) Bump OpenMRS dependencies and fix tests Bumps `@openmrs/esm-framework` and the OpenMRS CLI to `8.0.1-pre.3397` and fixes tests that were failing due to changes in the Carbon DataTable component. --- yarn.lock | 131 ++++++++---------------------------------------------- 1 file changed, 18 insertions(+), 113 deletions(-) diff --git a/yarn.lock b/yarn.lock index b89a1f2c8b..fc9233719e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2034,18 +2034,9 @@ __metadata: languageName: node linkType: hard -"@carbon/colors@npm:^11.37.0": - version: 11.37.0 - resolution: "@carbon/colors@npm:11.37.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/85ac7e42fd743c809dd309080ed6ba01dcf1a2f90bafab99e2dbe5f93dec28a3ae4728202941ecfdbdeccd1899c0ee7f029bce08943cb07ff419832773c69cbf - languageName: node - linkType: hard - -"@carbon/feature-flags@npm:^0.27.0": - version: 0.27.0 - resolution: "@carbon/feature-flags@npm:0.27.0" +"@carbon/feature-flags@npm:^0.31.0": + version: 0.31.0 + resolution: "@carbon/feature-flags@npm:0.31.0" dependencies: "@ibm/telemetry-js": "npm:^1.5.0" checksum: 10/fe7ec8f7f338535811c2852606b6b2ac19382857f2881867137d1cc530df6fa0a8b33bf6c367ec5c88899421a851cbe34425479d4b229ec20c8c838313c0700d @@ -2100,89 +2091,27 @@ __metadata: languageName: node linkType: hard -"@carbon/icons-react@npm:^11.64.0": - version: 11.64.0 - resolution: "@carbon/icons-react@npm:11.64.0" - dependencies: - "@carbon/icon-helpers": "npm:^10.63.0" - "@ibm/telemetry-js": "npm:^1.5.0" - prop-types: "npm:^15.8.1" - peerDependencies: - react: ">=16" - checksum: 10/c33515176542cf812b6e732f865cf5c665836eaba79cc3114f13c52de95b3b81b4b6d5e5256511c842205d5dbb0fec5f3b2e7190ed089fd3f7c1bfc8e881e129 - languageName: node - linkType: hard - -"@carbon/layout@npm:^11.35.0, @carbon/layout@npm:^11.7.0": - version: 11.35.0 - resolution: "@carbon/layout@npm:11.35.0" +"@carbon/layout@npm:^11.42.0, @carbon/layout@npm:^11.7.0": + version: 11.42.0 + resolution: "@carbon/layout@npm:11.42.0" dependencies: "@ibm/telemetry-js": "npm:^1.5.0" checksum: 10/bf038bfab3d9e0a161a69c7ac48afc47bd96332eef90f4d33eb2cc325427bd4020bfcbef4c8301c5f39583959796145473143b4dd78702091285f247e7262f05 languageName: node linkType: hard -"@carbon/layout@npm:^11.38.0": - version: 11.38.0 - resolution: "@carbon/layout@npm:11.38.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/f7be0cf0cf7585e8472eee827e9d2c3e908188c56c2a2ac8a86f71f981d7f280a445d9037cbd5b91f658bc2cfb4e0184887304635240423ffa01bad02a8845f3 - languageName: node - linkType: hard - -"@carbon/motion@npm:^11.29.0, @carbon/motion@npm:^11.5.0": - version: 11.29.0 - resolution: "@carbon/motion@npm:11.29.0" +"@carbon/motion@npm:^11.36.0, @carbon/motion@npm:^11.5.0": + version: 11.36.0 + resolution: "@carbon/motion@npm:11.36.0" dependencies: "@ibm/telemetry-js": "npm:^1.5.0" checksum: 10/b20f42cff7950bc3e1e0add0ce31330574c6a4b21b6c8597156c1a31007654bdbe63439f019f07dc59a2ed60e70c7c7215c0f78cd4de06bada0777e8d2e3bff8 languageName: node linkType: hard -"@carbon/motion@npm:^11.32.0": - version: 11.32.0 - resolution: "@carbon/motion@npm:11.32.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/8b6ce5b4cb496d734daad8b73dd2e290efeab52b29217fe9ee79d9e85aa599f9bf147d6588d011c56f278065941f3f40cec0c6a94c84d8942233e915f35ee44d - languageName: node - linkType: hard - -"@carbon/react@npm:^1.76.0": - version: 1.88.0 - resolution: "@carbon/react@npm:1.88.0" - dependencies: - "@babel/runtime": "npm:^7.27.3" - "@carbon/feature-flags": "npm:^0.29.0" - "@carbon/icons-react": "npm:^11.64.0" - "@carbon/layout": "npm:^11.38.0" - "@carbon/styles": "npm:^1.87.0" - "@carbon/utilities": "npm:^0.7.0" - "@floating-ui/react": "npm:^0.27.4" - "@ibm/telemetry-js": "npm:^1.5.0" - classnames: "npm:2.5.1" - copy-to-clipboard: "npm:^3.3.1" - downshift: "npm:9.0.9" - es-toolkit: "npm:^1.27.0" - flatpickr: "npm:4.6.13" - invariant: "npm:^2.2.3" - prop-types: "npm:^15.8.1" - react-fast-compare: "npm:^3.2.2" - tabbable: "npm:^6.2.0" - window-or-global: "npm:^1.0.1" - peerDependencies: - react: ^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0 - react-dom: ^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0 - react-is: ^16.13.1 || ^17.0.2 || ^18.3.1 || ^19.0.0 - sass: ^1.33.0 - checksum: 10/03fed67eba0f04606a1ffa3ffb981219e6c1b04501d10988d27776ae63d1307a4b6dd57718a4498524539e7004354993b73ddf450fd7cadea484be31d7c4d3f6 - languageName: node - linkType: hard - -"@carbon/react@npm:^1.83.0": - version: 1.84.0 - resolution: "@carbon/react@npm:1.84.0" +"@carbon/react@npm:^1.83.0, @carbon/react@npm:^1.92.1": + version: 1.92.1 + resolution: "@carbon/react@npm:1.92.1" dependencies: "@babel/runtime": "npm:^7.27.3" "@carbon/feature-flags": "npm:^0.31.0" @@ -2302,22 +2231,9 @@ __metadata: languageName: node linkType: hard -"@carbon/themes@npm:^11.57.0": - version: 11.57.0 - resolution: "@carbon/themes@npm:11.57.0" - dependencies: - "@carbon/colors": "npm:^11.37.0" - "@carbon/layout": "npm:^11.38.0" - "@carbon/type": "npm:^11.44.0" - "@ibm/telemetry-js": "npm:^1.5.0" - color: "npm:^4.0.0" - checksum: 10/2622bf2cadc9e616316ec33781785e25c7b41273a56e26a81e747a8a9412351a0672adb014793aedba95591d5e0c4400fb5a1795a659502dc2ce944c3208ed37 - languageName: node - linkType: hard - -"@carbon/type@npm:^11.10.0, @carbon/type@npm:^11.41.0": - version: 11.41.0 - resolution: "@carbon/type@npm:11.41.0" +"@carbon/type@npm:^11.10.0, @carbon/type@npm:^11.48.0": + version: 11.48.0 + resolution: "@carbon/type@npm:11.48.0" dependencies: "@carbon/grid": "npm:^11.44.0" "@carbon/layout": "npm:^11.42.0" @@ -2326,20 +2242,9 @@ __metadata: languageName: node linkType: hard -"@carbon/type@npm:^11.44.0": - version: 11.44.0 - resolution: "@carbon/type@npm:11.44.0" - dependencies: - "@carbon/grid": "npm:^11.40.0" - "@carbon/layout": "npm:^11.38.0" - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/cf68583c418a4a68396a6a66ba366de7eb80563e921865471f2b12ff8dff5aa8c20e6822b7f259e6b64d32a6f0ffdc59115006970b317dfddd7acaa3392960c3 - languageName: node - linkType: hard - -"@carbon/utilities@npm:^0.7.0": - version: 0.7.0 - resolution: "@carbon/utilities@npm:0.7.0" +"@carbon/utilities@npm:^0.10.0": + version: 0.10.0 + resolution: "@carbon/utilities@npm:0.10.0" dependencies: "@ibm/telemetry-js": "npm:^1.6.1" "@internationalized/number": "npm:^3.6.1" From b666b4e5428e829275ebcca53005213424ccce31 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Tue, 14 Oct 2025 16:32:04 +0300 Subject: [PATCH 14/35] rebase, update the Patient Id Sticker rest API and remove feature flag --- .../action-button.scss | 3 + ...tifier-sticker-action-button.component.tsx | 34 +++ .../package.json | 2 +- .../src/hooks/useStickerPdfPrinter.tsx | 17 +- .../src/index.ts | 9 +- ...tifier-sticker-action-button.component.tsx | 7 +- yarn.lock | 196 ++++++++++++++---- 7 files changed, 208 insertions(+), 60 deletions(-) create mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss create mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx 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/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx new file mode 100644 index 0000000000..5b2e65ffed --- /dev/null +++ b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -0,0 +1,34 @@ +import React, { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { OverflowMenuItem } from '@carbon/react'; +import { showModal, useFeatureFlag } from '@openmrs/esm-framework'; +import styles from './action-button.scss'; + +interface PrintIdentifierStickerOverflowMenuItemProps { + patient: fhir.Patient; +} + +const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { + const { t } = useTranslation(); + + const handleLaunchModal = useCallback(() => { + const dispose = showModal('print-identifier-sticker-modal', { + closeModal: () => dispose(), + patient, + }); + }, [patient]); + + if (!patient) { + return null; + } + + return ( + + ); +}; + +export default PrintIdentifierStickerOverflowMenuItem; diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index b3f753faf8..43d255a5ba 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -1,5 +1,5 @@ { - "name": "@openmrs/esm-patient-label-printing-app", + "name": "@openmrs/esm-patient-printing-app", "version": "10.1.0", "license": "MPL-2.0", "description": "Patient Label Printing for the OpenMRS SPA", diff --git a/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx index bcb151fed7..442f73899a 100644 --- a/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx +++ b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx @@ -15,12 +15,12 @@ export const useStickerPdfPrinter = () => { const iframe = document.createElement('iframe'); iframe.name = 'pdfPrinterFrame'; Object.assign(iframe.style, { - position: 'fixed', - width: '0', - height: '0', - border: 'none', - visibility: 'hidden' - }); + position: 'fixed', + width: '0', + height: '0', + border: 'none', + visibility: 'hidden', + }); iframeRef.current = iframe; document.body.appendChild(iframe); } @@ -43,7 +43,9 @@ export const useStickerPdfPrinter = () => { } else { // For cross-origin, we'll assume printing is immediate // and rely on the browser's print dialog behavior - handlePrintComplete(); + setTimeout(() => { + handlePrintComplete(); + }, 1000); } } catch (error) { handlePrintError(error); @@ -95,6 +97,7 @@ export const useStickerPdfPrinter = () => { return () => { if (iframeRef.current) { document.body.removeChild(iframeRef.current); + iframeRef.current = null; } }; }, []); diff --git a/packages/esm-patient-label-printing-app/src/index.ts b/packages/esm-patient-label-printing-app/src/index.ts index 97dea66a54..7b7a198fa9 100644 --- a/packages/esm-patient-label-printing-app/src/index.ts +++ b/packages/esm-patient-label-printing-app/src/index.ts @@ -1,16 +1,11 @@ -import { defineConfigSchema, getAsyncLifecycle, registerFeatureFlag } from '@openmrs/esm-framework'; +import { defineConfigSchema, getAsyncLifecycle } from '@openmrs/esm-framework'; import { configSchema } from './config-schema'; -const moduleName = '@openmrs/esm-patient-label-printing-app'; +const moduleName = '@openmrs/esm-patient-printing-app'; export const importTranslation = require.context('../translations', false, /.json$/, 'lazy'); export function startupApp() { - registerFeatureFlag( - 'print-patient-identifier-sticker', - 'Print patient identifier sticker', - 'Features to support printing a patient identifier sticker', - ); defineConfigSchema(moduleName, configSchema); } diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index da886e8da1..4e7859b763 100644 --- a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -13,19 +13,18 @@ interface PrintIdentifierStickerOverflowMenuItemProps { const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { const { t } = useTranslation(); const { showPrintIdentifierStickerButton } = useConfig(); - const enableStickerFeatureFlag = useFeatureFlag('print-patient-identifier-sticker'); const { printPdf, isPrinting } = useStickerPdfPrinter(); const isVisible = useMemo(() => { if (!patient?.id) return false; - return enableStickerFeatureFlag || showPrintIdentifierStickerButton; - }, [enableStickerFeatureFlag, showPrintIdentifierStickerButton, patient?.id]); + return showPrintIdentifierStickerButton; + }, [showPrintIdentifierStickerButton, patient?.id]); const getPdfUrl = useCallback(() => { if (!patient?.id) { throw new Error(t('patientIdNotFound', 'Patient ID not found')); } - return `${window.openmrsBase}/ws/module/patientdocuments/patientIdSticker?patientUuid=${patient.id}`; + return `${window.openmrsBase}/ws/rest/v1/patientdocuments/patientIdSticker?patientUuid=${patient.id}`; }, [patient?.id, t]); const handlePrint = useCallback(async () => { diff --git a/yarn.lock b/yarn.lock index fc9233719e..05b2bc3d95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2034,21 +2034,21 @@ __metadata: languageName: node linkType: hard -"@carbon/feature-flags@npm:^0.31.0": - version: 0.31.0 - resolution: "@carbon/feature-flags@npm:0.31.0" +"@carbon/colors@npm:^11.42.0": + version: 11.42.0 + resolution: "@carbon/colors@npm:11.42.0" dependencies: "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/fe7ec8f7f338535811c2852606b6b2ac19382857f2881867137d1cc530df6fa0a8b33bf6c367ec5c88899421a851cbe34425479d4b229ec20c8c838313c0700d + checksum: 10/7cb9303515f4b90a9fd9cb8398a5ba01bb18341eacd6dc7465fad8fe6eedf21daf90657eccecd3874978f5e2f74ed960b87d6c31f0e2c8a595886a2d48bdaa5c languageName: node linkType: hard -"@carbon/feature-flags@npm:^0.29.0": - version: 0.29.0 - resolution: "@carbon/feature-flags@npm:0.29.0" +"@carbon/feature-flags@npm:^0.31.0": + version: 0.31.0 + resolution: "@carbon/feature-flags@npm:0.31.0" dependencies: "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/00d2fda8418693b86ba856304ef518c58cdd25304ce8c33f1dae52bd6ee51c0c4a680ec36195112ddc55b775dfbfb1677b57bcb19c53c28db23f5c8713260cec + checksum: 10/fe7ec8f7f338535811c2852606b6b2ac19382857f2881867137d1cc530df6fa0a8b33bf6c367ec5c88899421a851cbe34425479d4b229ec20c8c838313c0700d languageName: node linkType: hard @@ -2091,6 +2091,19 @@ __metadata: languageName: node linkType: hard +"@carbon/icons-react@npm:^11.69.0": + version: 11.69.0 + resolution: "@carbon/icons-react@npm:11.69.0" + dependencies: + "@carbon/icon-helpers": "npm:^10.68.0" + "@ibm/telemetry-js": "npm:^1.5.0" + prop-types: "npm:^15.8.1" + peerDependencies: + react: ">=16" + checksum: 10/5485fdbf44416096988f0741db694efcb14b9ec394177f930fb10b1385eb6fd073354392cbc8e308bab2c1bcc9415873ea8799b938117d5c2f4bc498bc29f9b4 + languageName: node + linkType: hard + "@carbon/layout@npm:^11.42.0, @carbon/layout@npm:^11.7.0": version: 11.42.0 resolution: "@carbon/layout@npm:11.42.0" @@ -2100,6 +2113,15 @@ __metadata: languageName: node linkType: hard +"@carbon/layout@npm:^11.43.0": + version: 11.43.0 + resolution: "@carbon/layout@npm:11.43.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.5.0" + checksum: 10/cfa0d56ac88f025a5cdb7f76b71b3969cc8ddcd3c55e8d2373fc67099b0bee45da176905974dbcbe7e994e3f01d39964f49f27c2cb2b975070ae82954cbd966a + languageName: node + linkType: hard + "@carbon/motion@npm:^11.36.0, @carbon/motion@npm:^11.5.0": version: 11.36.0 resolution: "@carbon/motion@npm:11.36.0" @@ -2109,6 +2131,46 @@ __metadata: languageName: node linkType: hard +"@carbon/motion@npm:^11.37.0": + version: 11.37.0 + resolution: "@carbon/motion@npm:11.37.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.5.0" + checksum: 10/a97962dcda0596e1a523ffabe5dbcd8e2ed694cc0c94b6b919e8b59adb4745b82fd263af51094d826a44ce9bda20c5e5391370cc765209cea96ce0b1921e5bb0 + languageName: node + linkType: hard + +"@carbon/react@npm:^1.76.0": + version: 1.93.0 + resolution: "@carbon/react@npm:1.93.0" + dependencies: + "@babel/runtime": "npm:^7.27.3" + "@carbon/feature-flags": "npm:^0.31.0" + "@carbon/icons-react": "npm:^11.69.0" + "@carbon/layout": "npm:^11.43.0" + "@carbon/styles": "npm:^1.92.0" + "@carbon/utilities": "npm:^0.11.0" + "@floating-ui/react": "npm:^0.27.4" + "@ibm/telemetry-js": "npm:^1.5.0" + classnames: "npm:2.5.1" + copy-to-clipboard: "npm:^3.3.1" + downshift: "npm:9.0.10" + es-toolkit: "npm:^1.27.0" + flatpickr: "npm:4.6.13" + invariant: "npm:^2.2.3" + prop-types: "npm:^15.8.1" + react-fast-compare: "npm:^3.2.2" + tabbable: "npm:^6.2.0" + window-or-global: "npm:^1.0.1" + peerDependencies: + react: ^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0 + react-dom: ^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0 + react-is: ^16.13.1 || ^17.0.2 || ^18.3.1 || ^19.0.0 + sass: ^1.33.0 + checksum: 10/52e29504569f24b757c475b7d51cc007a2dbd379a83197850512ed2ca4ec3d7c8b91a6f9b2e951da59865fc29d274fb60218ef3f9969b13bd57768ec9eee7337 + languageName: node + linkType: hard + "@carbon/react@npm:^1.83.0, @carbon/react@npm:^1.92.1": version: 1.92.1 resolution: "@carbon/react@npm:1.92.1" @@ -2170,33 +2232,33 @@ __metadata: languageName: node linkType: hard -"@carbon/styles@npm:^1.87.0": - version: 1.87.0 - resolution: "@carbon/styles@npm:1.87.0" +"@carbon/styles@npm:^1.92.0": + version: 1.92.0 + resolution: "@carbon/styles@npm:1.92.0" dependencies: - "@carbon/colors": "npm:^11.37.0" - "@carbon/feature-flags": "npm:^0.29.0" - "@carbon/grid": "npm:^11.40.0" - "@carbon/layout": "npm:^11.38.0" - "@carbon/motion": "npm:^11.32.0" - "@carbon/themes": "npm:^11.57.0" - "@carbon/type": "npm:^11.44.0" + "@carbon/colors": "npm:^11.42.0" + "@carbon/feature-flags": "npm:^0.31.0" + "@carbon/grid": "npm:^11.45.0" + "@carbon/layout": "npm:^11.43.0" + "@carbon/motion": "npm:^11.37.0" + "@carbon/themes": "npm:^11.62.0" + "@carbon/type": "npm:^11.49.0" "@ibm/plex": "npm:6.0.0-next.6" - "@ibm/plex-mono": "npm:0.0.3-alpha.0" - "@ibm/plex-sans": "npm:0.0.3-alpha.0" - "@ibm/plex-sans-arabic": "npm:0.0.3-alpha.0" - "@ibm/plex-sans-devanagari": "npm:0.0.3-alpha.0" - "@ibm/plex-sans-hebrew": "npm:0.0.3-alpha.0" - "@ibm/plex-sans-thai": "npm:0.0.3-alpha.0" - "@ibm/plex-sans-thai-looped": "npm:0.0.3-alpha.0" - "@ibm/plex-serif": "npm:0.0.3-alpha.0" + "@ibm/plex-mono": "npm:1.1.0" + "@ibm/plex-sans": "npm:1.1.0" + "@ibm/plex-sans-arabic": "npm:1.1.0" + "@ibm/plex-sans-devanagari": "npm:1.1.0" + "@ibm/plex-sans-hebrew": "npm:1.1.0" + "@ibm/plex-sans-thai": "npm:1.1.0" + "@ibm/plex-sans-thai-looped": "npm:1.1.0" + "@ibm/plex-serif": "npm:1.1.0" "@ibm/telemetry-js": "npm:^1.5.0" peerDependencies: sass: ^1.33.0 peerDependenciesMeta: sass: optional: true - checksum: 10/8f4468876ba6a81ecf35c138793a350ebaf17451bbc268cc507acd8f92fd0f885dd14c5ddc2fdf5880a9e0d13f3f49cdd24acea5a446a03adf700e6cb3c456a3 + checksum: 10/5f306bd4bc58838e4d2032efa7de42407f49bdde2992389e3f518a22d08ed26b41665e5bce7a8921570e4ca39d0e903ebe38c86591ec20cc965dac0aa0bbca87 languageName: node linkType: hard @@ -2231,6 +2293,19 @@ __metadata: languageName: node linkType: hard +"@carbon/themes@npm:^11.62.0": + version: 11.62.0 + resolution: "@carbon/themes@npm:11.62.0" + dependencies: + "@carbon/colors": "npm:^11.42.0" + "@carbon/layout": "npm:^11.43.0" + "@carbon/type": "npm:^11.49.0" + "@ibm/telemetry-js": "npm:^1.5.0" + color: "npm:^4.0.0" + checksum: 10/c3f739bd69a522c5d4b00bbaed4cadd04a5956d5a5be22cb7e79a36417e3f428ef1d0e597325546698429042c011a55e77d2c95b122b74b6e2bbb3c491ece0cd + languageName: node + linkType: hard + "@carbon/type@npm:^11.10.0, @carbon/type@npm:^11.48.0": version: 11.48.0 resolution: "@carbon/type@npm:11.48.0" @@ -2242,6 +2317,17 @@ __metadata: languageName: node linkType: hard +"@carbon/type@npm:^11.49.0": + version: 11.49.0 + resolution: "@carbon/type@npm:11.49.0" + dependencies: + "@carbon/grid": "npm:^11.45.0" + "@carbon/layout": "npm:^11.43.0" + "@ibm/telemetry-js": "npm:^1.5.0" + checksum: 10/3d4d4ddaaf1917a2d08829a7b9d3f979a9693821e90947cf4daa10f41d8dc923b58726aceb41822f1bca316c2f834f95f474b38dc361c4c6f1f6483c605eb0e4 + languageName: node + linkType: hard + "@carbon/utilities@npm:^0.10.0": version: 0.10.0 resolution: "@carbon/utilities@npm:0.10.0" @@ -2252,6 +2338,16 @@ __metadata: languageName: node linkType: hard +"@carbon/utilities@npm:^0.11.0": + version: 0.11.0 + resolution: "@carbon/utilities@npm:0.11.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.6.1" + "@internationalized/number": "npm:^3.6.1" + checksum: 10/2b79d4a83357c62f165e31017ad005801d7310ad99ef0e150105bb8b0cabc8c5cec602e26a8e38c270d111f01cc347d893ca6d8dac42e5fda37cb722e90c3718 + languageName: node + linkType: hard + "@carbon/utils-position@npm:^1.3.0": version: 1.3.0 resolution: "@carbon/utils-position@npm:1.3.0" @@ -3082,6 +3178,15 @@ __metadata: languageName: node linkType: hard +"@ibm/plex-sans-hebrew@npm:1.1.0": + version: 1.1.0 + resolution: "@ibm/plex-sans-hebrew@npm:1.1.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.6.1" + checksum: 10/46f02a068b5e3455e5d46bec5e0f8b273b9e26f78a3e9d27899a554d0c398a146be97a14d9992ca46c29257e21949372fa77fc99b132fc9e5c792eb96774e3b8 + languageName: node + linkType: hard + "@ibm/plex-sans-thai-looped@npm:1.1.0": version: 1.1.0 resolution: "@ibm/plex-sans-thai-looped@npm:1.1.0" @@ -3098,6 +3203,15 @@ __metadata: languageName: node linkType: hard +"@ibm/plex-sans-thai@npm:1.1.0": + version: 1.1.0 + resolution: "@ibm/plex-sans-thai@npm:1.1.0" + dependencies: + "@ibm/telemetry-js": "npm:^1.6.1" + checksum: 10/bad059292389005ae4aab29d5f900035229f12340e42f105b22ef75ca7b7ab93b4a8991df7dfa15af62abcf1f83d1d476db8ecc077ca134d698ce1774a569610 + languageName: node + linkType: hard + "@ibm/plex-sans@npm:1.1.0": version: 1.1.0 resolution: "@ibm/plex-sans@npm:1.1.0" @@ -5060,20 +5174,6 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-patient-label-printing-app@workspace:packages/esm-patient-label-printing-app": - version: 0.0.0-use.local - resolution: "@openmrs/esm-patient-label-printing-app@workspace:packages/esm-patient-label-printing-app" - dependencies: - "@carbon/react": "npm:^1.76.0" - webpack: "npm:^5.94.0" - peerDependencies: - "@openmrs/esm-framework": 6.x - react: 18.x - react-i18next: 11.x - react-router-dom: 6.x - languageName: unknown - linkType: soft - "@openmrs/esm-patient-lists-app@workspace:packages/esm-patient-lists-app": version: 0.0.0-use.local resolution: "@openmrs/esm-patient-lists-app@workspace:packages/esm-patient-lists-app" @@ -5152,6 +5252,20 @@ __metadata: languageName: unknown linkType: soft +"@openmrs/esm-patient-printing-app@workspace:packages/esm-patient-label-printing-app": + version: 0.0.0-use.local + resolution: "@openmrs/esm-patient-printing-app@workspace:packages/esm-patient-label-printing-app" + dependencies: + "@carbon/react": "npm:^1.76.0" + webpack: "npm:^5.94.0" + peerDependencies: + "@openmrs/esm-framework": 6.x + react: 18.x + react-i18next: 11.x + react-router-dom: 6.x + languageName: unknown + linkType: soft + "@openmrs/esm-patient-programs-app@workspace:packages/esm-patient-programs-app": version: 0.0.0-use.local resolution: "@openmrs/esm-patient-programs-app@workspace:packages/esm-patient-programs-app" From 65f200a59362975ddfbbb469b1b5ea57609bbfa6 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Wed, 15 Oct 2025 12:09:43 +0300 Subject: [PATCH 15/35] rebase, remove feature flag and update API --- packages/esm-patient-banner-app/translations/en.json | 1 + .../README.md | 2 +- .../jest.config.js | 0 .../package.json | 2 +- .../src/config-schema.ts | 2 +- .../src/declarations.d.ts | 0 .../src/hooks/useStickerPdfPrinter.tsx | 0 .../src/index.ts | 0 .../src/print-identifier-sticker/action-button.scss | 0 .../print-identifier-sticker-action-button.component.tsx | 0 .../src/routes.json | 0 .../translations/en.json | 0 .../tsconfig.json | 0 .../webpack.config.js | 0 yarn.lock | 4 ++-- 15 files changed, 6 insertions(+), 5 deletions(-) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/README.md (92%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/jest.config.js (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/package.json (96%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/src/config-schema.ts (94%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/src/declarations.d.ts (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/src/hooks/useStickerPdfPrinter.tsx (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/src/index.ts (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/src/print-identifier-sticker/action-button.scss (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/src/routes.json (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/translations/en.json (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/tsconfig.json (100%) rename packages/{esm-patient-label-printing-app => esm-patient-printing-app}/webpack.config.js (100%) diff --git a/packages/esm-patient-banner-app/translations/en.json b/packages/esm-patient-banner-app/translations/en.json index a21571c7d0..49d123c707 100644 --- a/packages/esm-patient-banner-app/translations/en.json +++ b/packages/esm-patient-banner-app/translations/en.json @@ -10,6 +10,7 @@ "district": "District", "from_lower": "from", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State" diff --git a/packages/esm-patient-label-printing-app/README.md b/packages/esm-patient-printing-app/README.md similarity index 92% rename from packages/esm-patient-label-printing-app/README.md rename to packages/esm-patient-printing-app/README.md index 1a7c2da18e..fd10fe0d02 100644 --- a/packages/esm-patient-label-printing-app/README.md +++ b/packages/esm-patient-printing-app/README.md @@ -1,3 +1,3 @@ -# esm-patient-label-printing-app +# esm-patient-printing-app The Patient label printing frontend module provides a flexible and extensible printing mechanism that integrates easily into various parts of the application. Its core architecture supports print actions across diverse contexts—such as patient management apps like queues, clerical views, and billing interfaces—enabling fast, standardized printing of documents like patient records, receipts, and other critical materials. diff --git a/packages/esm-patient-label-printing-app/jest.config.js b/packages/esm-patient-printing-app/jest.config.js similarity index 100% rename from packages/esm-patient-label-printing-app/jest.config.js rename to packages/esm-patient-printing-app/jest.config.js diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-printing-app/package.json similarity index 96% rename from packages/esm-patient-label-printing-app/package.json rename to packages/esm-patient-printing-app/package.json index 43d255a5ba..2db3486195 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-printing-app/package.json @@ -3,7 +3,7 @@ "version": "10.1.0", "license": "MPL-2.0", "description": "Patient Label Printing for the OpenMRS SPA", - "browser": "dist/openmrs-esm-patient-label-printing-app.js", + "browser": "dist/openmrs-esm-patient-printing-app.js", "main": "src/index.ts", "source": true, "scripts": { diff --git a/packages/esm-patient-label-printing-app/src/config-schema.ts b/packages/esm-patient-printing-app/src/config-schema.ts similarity index 94% rename from packages/esm-patient-label-printing-app/src/config-schema.ts rename to packages/esm-patient-printing-app/src/config-schema.ts index 4c0df275a4..773297715e 100644 --- a/packages/esm-patient-label-printing-app/src/config-schema.ts +++ b/packages/esm-patient-printing-app/src/config-schema.ts @@ -4,7 +4,7 @@ export const configSchema = { showPrintIdentifierStickerButton: { _type: Type.Boolean, _description: "Whether to display the 'Print identifier sticker' button in the patient banner", - _default: false, + _default: true, }, }; diff --git a/packages/esm-patient-label-printing-app/src/declarations.d.ts b/packages/esm-patient-printing-app/src/declarations.d.ts similarity index 100% rename from packages/esm-patient-label-printing-app/src/declarations.d.ts rename to packages/esm-patient-printing-app/src/declarations.d.ts diff --git a/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx b/packages/esm-patient-printing-app/src/hooks/useStickerPdfPrinter.tsx similarity index 100% rename from packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx rename to packages/esm-patient-printing-app/src/hooks/useStickerPdfPrinter.tsx diff --git a/packages/esm-patient-label-printing-app/src/index.ts b/packages/esm-patient-printing-app/src/index.ts similarity index 100% rename from packages/esm-patient-label-printing-app/src/index.ts rename to packages/esm-patient-printing-app/src/index.ts diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/action-button.scss b/packages/esm-patient-printing-app/src/print-identifier-sticker/action-button.scss similarity index 100% rename from packages/esm-patient-label-printing-app/src/print-identifier-sticker/action-button.scss rename to packages/esm-patient-printing-app/src/print-identifier-sticker/action-button.scss diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx similarity index 100% rename from packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx rename to packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx diff --git a/packages/esm-patient-label-printing-app/src/routes.json b/packages/esm-patient-printing-app/src/routes.json similarity index 100% rename from packages/esm-patient-label-printing-app/src/routes.json rename to packages/esm-patient-printing-app/src/routes.json diff --git a/packages/esm-patient-label-printing-app/translations/en.json b/packages/esm-patient-printing-app/translations/en.json similarity index 100% rename from packages/esm-patient-label-printing-app/translations/en.json rename to packages/esm-patient-printing-app/translations/en.json diff --git a/packages/esm-patient-label-printing-app/tsconfig.json b/packages/esm-patient-printing-app/tsconfig.json similarity index 100% rename from packages/esm-patient-label-printing-app/tsconfig.json rename to packages/esm-patient-printing-app/tsconfig.json diff --git a/packages/esm-patient-label-printing-app/webpack.config.js b/packages/esm-patient-printing-app/webpack.config.js similarity index 100% rename from packages/esm-patient-label-printing-app/webpack.config.js rename to packages/esm-patient-printing-app/webpack.config.js diff --git a/yarn.lock b/yarn.lock index 05b2bc3d95..c888608c31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5252,9 +5252,9 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-patient-printing-app@workspace:packages/esm-patient-label-printing-app": +"@openmrs/esm-patient-printing-app@workspace:packages/esm-patient-printing-app": version: 0.0.0-use.local - resolution: "@openmrs/esm-patient-printing-app@workspace:packages/esm-patient-label-printing-app" + resolution: "@openmrs/esm-patient-printing-app@workspace:packages/esm-patient-printing-app" dependencies: "@carbon/react": "npm:^1.76.0" webpack: "npm:^5.94.0" From 3b75a6bfb91672db181e587d73d6adc38d60a862 Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Thu, 16 Oct 2025 09:46:54 +0300 Subject: [PATCH 16/35] Update packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx Co-authored-by: Dennis Kigen --- .../print-identifier-sticker-action-button.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 4e7859b763..4a8347174d 100644 --- a/packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; -import { useFeatureFlag, showSnackbar, getCoreTranslation, useConfig } from '@openmrs/esm-framework'; +import { showSnackbar, getCoreTranslation, useConfig } from '@openmrs/esm-framework'; import styles from './action-button.scss'; import { useStickerPdfPrinter } from '../hooks/useStickerPdfPrinter'; import type { ConfigObject } from '../config-schema'; From 38ca6d097a529fcb2edf82088b485044bb0aa9fb Mon Sep 17 00:00:00 2001 From: jnsereko Date: Thu, 23 Oct 2025 14:38:56 +0300 Subject: [PATCH 17/35] update webpack, printing hook and rename app --- packages/esm-form-entry-app/package.json | 2 +- ...tifier-sticker-action-button.component.tsx | 34 -------- .../translations/am.json | 1 - .../translations/ar.json | 1 - .../translations/ar_SY.json | 1 - .../translations/bn.json | 1 - .../translations/de.json | 1 - .../translations/en.json | 1 - .../translations/en_US.json | 1 - .../translations/es.json | 1 - .../translations/es_MX.json | 1 - .../translations/fr.json | 1 - .../translations/he.json | 1 - .../translations/hi.json | 1 - .../translations/hi_IN.json | 1 - .../translations/id.json | 1 - .../translations/it.json | 1 - .../translations/ka.json | 1 - .../translations/km.json | 1 - .../translations/ku.json | 1 - .../translations/ky.json | 1 - .../translations/lg.json | 1 - .../translations/ne.json | 1 - .../translations/pl.json | 1 - .../translations/pt.json | 1 - .../translations/pt_BR.json | 1 - .../translations/qu.json | 1 - .../translations/ro_RO.json | 1 - .../translations/ru_RU.json | 1 - .../translations/si.json | 1 - .../translations/sw.json | 1 - .../translations/sw_KE.json | 1 - .../translations/tr.json | 1 - .../translations/tr_TR.json | 1 - .../translations/uk.json | 1 - .../translations/uz.json | 1 - .../translations/uz@Latn.json | 1 - .../translations/uz_UZ.json | 1 - .../translations/vi.json | 1 - .../translations/zh.json | 1 - .../translations/zh_CN.json | 1 - .../README.md | 2 +- .../jest.config.js | 0 .../package.json | 4 +- .../src/config-schema.ts | 0 .../src/declarations.d.ts | 0 .../src/hooks/useStickerPdfPrinter.tsx | 70 ++++++++++++---- .../src/index.ts | 2 +- .../action-button.scss | 0 ...tifier-sticker-action-button.component.tsx | 6 +- .../src/routes.json | 0 .../translations/en.json | 0 .../tsconfig.json | 0 .../webpack.config.js | 0 .../action-button.scss | 3 - yarn.lock | 83 +++++-------------- 56 files changed, 81 insertions(+), 164 deletions(-) delete mode 100644 packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/README.md (92%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/jest.config.js (100%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/package.json (93%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/src/config-schema.ts (100%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/src/declarations.d.ts (100%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/src/hooks/useStickerPdfPrinter.tsx (55%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/src/index.ts (90%) rename packages/{esm-patient-banner-app => esm-patient-label-printing-app}/src/print-identifier-sticker/action-button.scss (100%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx (85%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/src/routes.json (100%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/translations/en.json (100%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/tsconfig.json (100%) rename packages/{esm-patient-printing-app => esm-patient-label-printing-app}/webpack.config.js (100%) delete mode 100644 packages/esm-patient-printing-app/src/print-identifier-sticker/action-button.scss diff --git a/packages/esm-form-entry-app/package.json b/packages/esm-form-entry-app/package.json index ec5b85f21b..c59b480b43 100644 --- a/packages/esm-form-entry-app/package.json +++ b/packages/esm-form-entry-app/package.json @@ -100,7 +100,7 @@ "rxjs": "^7.5.0", "rxjs-compat": "^6.6.7", "style-loader": "2.x", - "webpack": "~5.94.0" + "webpack": "~5.99.9" }, "installConfig": { "hoistingLimits": "dependencies" diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx deleted file mode 100644 index 5b2e65ffed..0000000000 --- a/packages/esm-patient-banner-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; -import { OverflowMenuItem } from '@carbon/react'; -import { showModal, useFeatureFlag } from '@openmrs/esm-framework'; -import styles from './action-button.scss'; - -interface PrintIdentifierStickerOverflowMenuItemProps { - patient: fhir.Patient; -} - -const PrintIdentifierStickerOverflowMenuItem: React.FC = ({ patient }) => { - const { t } = useTranslation(); - - const handleLaunchModal = useCallback(() => { - const dispose = showModal('print-identifier-sticker-modal', { - closeModal: () => dispose(), - patient, - }); - }, [patient]); - - if (!patient) { - return null; - } - - return ( - - ); -}; - -export default PrintIdentifierStickerOverflowMenuItem; diff --git a/packages/esm-patient-banner-app/translations/am.json b/packages/esm-patient-banner-app/translations/am.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/am.json +++ b/packages/esm-patient-banner-app/translations/am.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/ar.json b/packages/esm-patient-banner-app/translations/ar.json index 60b75bd039..ae99a24010 100644 --- a/packages/esm-patient-banner-app/translations/ar.json +++ b/packages/esm-patient-banner-app/translations/ar.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "ملصق تعريف المريض", "patientNameWithSeparator": "اسم المريض", "postalCode": "الرمز البريدي", - "printIdentifierSticker": "ملصق تعريف المريض", "started": "Started", "state": "الولاية", "stateProvince": "الولاية", diff --git a/packages/esm-patient-banner-app/translations/ar_SY.json b/packages/esm-patient-banner-app/translations/ar_SY.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/ar_SY.json +++ b/packages/esm-patient-banner-app/translations/ar_SY.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/bn.json b/packages/esm-patient-banner-app/translations/bn.json index 587de5fe1f..f08b8b7b31 100644 --- a/packages/esm-patient-banner-app/translations/bn.json +++ b/packages/esm-patient-banner-app/translations/bn.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "রোগীর নাম:", "postalCode": "পোস্টাল কোড", - "printIdentifierSticker": "Print identifier sticker", "started": "শুরু হয়েছে", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/de.json b/packages/esm-patient-banner-app/translations/de.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/de.json +++ b/packages/esm-patient-banner-app/translations/de.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/en.json b/packages/esm-patient-banner-app/translations/en.json index 49d123c707..a21571c7d0 100644 --- a/packages/esm-patient-banner-app/translations/en.json +++ b/packages/esm-patient-banner-app/translations/en.json @@ -10,7 +10,6 @@ "district": "District", "from_lower": "from", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State" diff --git a/packages/esm-patient-banner-app/translations/en_US.json b/packages/esm-patient-banner-app/translations/en_US.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/en_US.json +++ b/packages/esm-patient-banner-app/translations/en_US.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/es.json b/packages/esm-patient-banner-app/translations/es.json index ac494483ea..847decf45e 100644 --- a/packages/esm-patient-banner-app/translations/es.json +++ b/packages/esm-patient-banner-app/translations/es.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Sticker de identificación del paciente", "patientNameWithSeparator": "Nombre del paciente:", "postalCode": "Código postal", - "printIdentifierSticker": "Imprimir sticker de identificación", "started": "Iniciado", "state": "Estado", "stateProvince": "Estado", diff --git a/packages/esm-patient-banner-app/translations/es_MX.json b/packages/esm-patient-banner-app/translations/es_MX.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/es_MX.json +++ b/packages/esm-patient-banner-app/translations/es_MX.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/fr.json b/packages/esm-patient-banner-app/translations/fr.json index e9e306a6c1..ad4e7f99fe 100644 --- a/packages/esm-patient-banner-app/translations/fr.json +++ b/packages/esm-patient-banner-app/translations/fr.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Autocollant d'identification du patient", "patientNameWithSeparator": "Nom du patient :", "postalCode": "Code postal", - "printIdentifierSticker": "Imprimer l'autocollant d'identification", "started": "Démarré", "state": "État", "stateProvince": "État", diff --git a/packages/esm-patient-banner-app/translations/he.json b/packages/esm-patient-banner-app/translations/he.json index c1c54a67d0..ea68986414 100644 --- a/packages/esm-patient-banner-app/translations/he.json +++ b/packages/esm-patient-banner-app/translations/he.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "שם המטופל/ת:", "postalCode": "מיקוד", - "printIdentifierSticker": "הדפסת מדבקת זיהוי", "started": "Started", "state": "מדינה", "stateProvince": "מדינה", diff --git a/packages/esm-patient-banner-app/translations/hi.json b/packages/esm-patient-banner-app/translations/hi.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/hi.json +++ b/packages/esm-patient-banner-app/translations/hi.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/hi_IN.json b/packages/esm-patient-banner-app/translations/hi_IN.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/hi_IN.json +++ b/packages/esm-patient-banner-app/translations/hi_IN.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/id.json b/packages/esm-patient-banner-app/translations/id.json index 75d1cdb25e..8829082552 100644 --- a/packages/esm-patient-banner-app/translations/id.json +++ b/packages/esm-patient-banner-app/translations/id.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Stiker identitas pasien", "patientNameWithSeparator": "Nama pasien:", "postalCode": "Kode pos", - "printIdentifierSticker": "Cetak stiker identitas", "started": "Dimulai", "state": "Provinsi", "stateProvince": "Provinsi", diff --git a/packages/esm-patient-banner-app/translations/it.json b/packages/esm-patient-banner-app/translations/it.json index 96b7635651..18bba93c5b 100644 --- a/packages/esm-patient-banner-app/translations/it.json +++ b/packages/esm-patient-banner-app/translations/it.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Etichetta identificativa del paziente", "patientNameWithSeparator": "Nome del paziente:", "postalCode": "Codice postale", - "printIdentifierSticker": "Stampa etichetta identificativa", "started": "Iniziato", "state": "Stato", "stateProvince": "Stato", diff --git a/packages/esm-patient-banner-app/translations/ka.json b/packages/esm-patient-banner-app/translations/ka.json index 2f8cdb7e04..b6b128bd69 100644 --- a/packages/esm-patient-banner-app/translations/ka.json +++ b/packages/esm-patient-banner-app/translations/ka.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "პაკეტის იდენტიფიკატორი ეტიკეტი", "patientNameWithSeparator": "პაციენტის სახელი:", "postalCode": "საფოსტო კოდი", - "printIdentifierSticker": "იდენტიფიკატორი ეტიკეტის დაბეჭდვა", "started": "დაწყებულია", "state": "შტატი", "stateProvince": "შტატი", diff --git a/packages/esm-patient-banner-app/translations/km.json b/packages/esm-patient-banner-app/translations/km.json index 3c53df1521..92a025b04e 100644 --- a/packages/esm-patient-banner-app/translations/km.json +++ b/packages/esm-patient-banner-app/translations/km.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "លេខកូដតំបន់", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "រដ្ឋ", "stateProvince": "រដ្ឋ", diff --git a/packages/esm-patient-banner-app/translations/ku.json b/packages/esm-patient-banner-app/translations/ku.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/ku.json +++ b/packages/esm-patient-banner-app/translations/ku.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/ky.json b/packages/esm-patient-banner-app/translations/ky.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/ky.json +++ b/packages/esm-patient-banner-app/translations/ky.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/lg.json b/packages/esm-patient-banner-app/translations/lg.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/lg.json +++ b/packages/esm-patient-banner-app/translations/lg.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/ne.json b/packages/esm-patient-banner-app/translations/ne.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/ne.json +++ b/packages/esm-patient-banner-app/translations/ne.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/pl.json b/packages/esm-patient-banner-app/translations/pl.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/pl.json +++ b/packages/esm-patient-banner-app/translations/pl.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/pt.json b/packages/esm-patient-banner-app/translations/pt.json index 5a0b17e8cc..43bfd0f44c 100644 --- a/packages/esm-patient-banner-app/translations/pt.json +++ b/packages/esm-patient-banner-app/translations/pt.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Etiqueta de Identificador do Utente", "patientNameWithSeparator": "Nome do utente:", "postalCode": "Caixa postal", - "printIdentifierSticker": "Imprimir etiqueta do identificador", "started": "Started", "state": "Estado", "stateProvince": "Estado", diff --git a/packages/esm-patient-banner-app/translations/pt_BR.json b/packages/esm-patient-banner-app/translations/pt_BR.json index 5cbf7e2113..60ead8b7f3 100644 --- a/packages/esm-patient-banner-app/translations/pt_BR.json +++ b/packages/esm-patient-banner-app/translations/pt_BR.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Etiqueta de identificação do Paciente", "patientNameWithSeparator": "Nome do Paciente:", "postalCode": "Código postal CEP", - "printIdentifierSticker": "Imprimir etiqueta de identificação", "started": "Iniciado", "state": "Estado", "stateProvince": "Estado", diff --git a/packages/esm-patient-banner-app/translations/qu.json b/packages/esm-patient-banner-app/translations/qu.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/qu.json +++ b/packages/esm-patient-banner-app/translations/qu.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/ro_RO.json b/packages/esm-patient-banner-app/translations/ro_RO.json index ec789dfb6b..e2184ad215 100644 --- a/packages/esm-patient-banner-app/translations/ro_RO.json +++ b/packages/esm-patient-banner-app/translations/ro_RO.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Etichetă identificare pacient", "patientNameWithSeparator": "Nume pacient:", "postalCode": "Cod poștal", - "printIdentifierSticker": "Printează etichetă identificare", "started": "Început", "state": "Stat", "stateProvince": "Stat/Provincie", diff --git a/packages/esm-patient-banner-app/translations/ru_RU.json b/packages/esm-patient-banner-app/translations/ru_RU.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/ru_RU.json +++ b/packages/esm-patient-banner-app/translations/ru_RU.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/si.json b/packages/esm-patient-banner-app/translations/si.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/si.json +++ b/packages/esm-patient-banner-app/translations/si.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/sw.json b/packages/esm-patient-banner-app/translations/sw.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/sw.json +++ b/packages/esm-patient-banner-app/translations/sw.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/sw_KE.json b/packages/esm-patient-banner-app/translations/sw_KE.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/sw_KE.json +++ b/packages/esm-patient-banner-app/translations/sw_KE.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/tr.json b/packages/esm-patient-banner-app/translations/tr.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/tr.json +++ b/packages/esm-patient-banner-app/translations/tr.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/tr_TR.json b/packages/esm-patient-banner-app/translations/tr_TR.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/tr_TR.json +++ b/packages/esm-patient-banner-app/translations/tr_TR.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/uk.json b/packages/esm-patient-banner-app/translations/uk.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/uk.json +++ b/packages/esm-patient-banner-app/translations/uk.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/uz.json b/packages/esm-patient-banner-app/translations/uz.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/uz.json +++ b/packages/esm-patient-banner-app/translations/uz.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/uz@Latn.json b/packages/esm-patient-banner-app/translations/uz@Latn.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/uz@Latn.json +++ b/packages/esm-patient-banner-app/translations/uz@Latn.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/uz_UZ.json b/packages/esm-patient-banner-app/translations/uz_UZ.json index d6f528ff35..b6a77bf8a5 100644 --- a/packages/esm-patient-banner-app/translations/uz_UZ.json +++ b/packages/esm-patient-banner-app/translations/uz_UZ.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/vi.json b/packages/esm-patient-banner-app/translations/vi.json index 59f68f52a1..7bc66a156a 100644 --- a/packages/esm-patient-banner-app/translations/vi.json +++ b/packages/esm-patient-banner-app/translations/vi.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "Nhãn dán nhận dạng bệnh nhân", "patientNameWithSeparator": "Tên bệnh nhân:", "postalCode": "Mã bưu chính", - "printIdentifierSticker": "In nhãn dán nhận dạng", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/zh.json b/packages/esm-patient-banner-app/translations/zh.json index 0c64edf158..78017acf90 100644 --- a/packages/esm-patient-banner-app/translations/zh.json +++ b/packages/esm-patient-banner-app/translations/zh.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "患者标识符贴纸", "patientNameWithSeparator": "Patient name:", "postalCode": "邮政编码", - "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "省份", "stateProvince": "省份", diff --git a/packages/esm-patient-banner-app/translations/zh_CN.json b/packages/esm-patient-banner-app/translations/zh_CN.json index ccf3392b3c..49a2e956ca 100644 --- a/packages/esm-patient-banner-app/translations/zh_CN.json +++ b/packages/esm-patient-banner-app/translations/zh_CN.json @@ -16,7 +16,6 @@ "patientIdentifierSticker": "患者标识符标签", "patientNameWithSeparator": "患者姓名:", "postalCode": "邮政编码", - "printIdentifierSticker": "患者标识符标签", "started": "已开始", "state": "省份", "stateProvince": "省份", diff --git a/packages/esm-patient-printing-app/README.md b/packages/esm-patient-label-printing-app/README.md similarity index 92% rename from packages/esm-patient-printing-app/README.md rename to packages/esm-patient-label-printing-app/README.md index fd10fe0d02..1a7c2da18e 100644 --- a/packages/esm-patient-printing-app/README.md +++ b/packages/esm-patient-label-printing-app/README.md @@ -1,3 +1,3 @@ -# esm-patient-printing-app +# esm-patient-label-printing-app The Patient label printing frontend module provides a flexible and extensible printing mechanism that integrates easily into various parts of the application. Its core architecture supports print actions across diverse contexts—such as patient management apps like queues, clerical views, and billing interfaces—enabling fast, standardized printing of documents like patient records, receipts, and other critical materials. diff --git a/packages/esm-patient-printing-app/jest.config.js b/packages/esm-patient-label-printing-app/jest.config.js similarity index 100% rename from packages/esm-patient-printing-app/jest.config.js rename to packages/esm-patient-label-printing-app/jest.config.js diff --git a/packages/esm-patient-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json similarity index 93% rename from packages/esm-patient-printing-app/package.json rename to packages/esm-patient-label-printing-app/package.json index 2db3486195..b3f753faf8 100644 --- a/packages/esm-patient-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -1,9 +1,9 @@ { - "name": "@openmrs/esm-patient-printing-app", + "name": "@openmrs/esm-patient-label-printing-app", "version": "10.1.0", "license": "MPL-2.0", "description": "Patient Label Printing for the OpenMRS SPA", - "browser": "dist/openmrs-esm-patient-printing-app.js", + "browser": "dist/openmrs-esm-patient-label-printing-app.js", "main": "src/index.ts", "source": true, "scripts": { diff --git a/packages/esm-patient-printing-app/src/config-schema.ts b/packages/esm-patient-label-printing-app/src/config-schema.ts similarity index 100% rename from packages/esm-patient-printing-app/src/config-schema.ts rename to packages/esm-patient-label-printing-app/src/config-schema.ts diff --git a/packages/esm-patient-printing-app/src/declarations.d.ts b/packages/esm-patient-label-printing-app/src/declarations.d.ts similarity index 100% rename from packages/esm-patient-printing-app/src/declarations.d.ts rename to packages/esm-patient-label-printing-app/src/declarations.d.ts diff --git a/packages/esm-patient-printing-app/src/hooks/useStickerPdfPrinter.tsx b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx similarity index 55% rename from packages/esm-patient-printing-app/src/hooks/useStickerPdfPrinter.tsx rename to packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx index 442f73899a..f6456e31af 100644 --- a/packages/esm-patient-printing-app/src/hooks/useStickerPdfPrinter.tsx +++ b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx @@ -3,29 +3,39 @@ import { useTranslation } from 'react-i18next'; export const useStickerPdfPrinter = () => { const { t } = useTranslation(); - const iframeRef = useRef(null); + const iframeRef = useRef(null); const [isPrinting, setIsPrinting] = useState(false); + const cleanupRef = useRef<(() => void) | null>(null); const printPdf = useCallback( (url: string) => { + if (isPrinting) { + return Promise.reject(new Error(t('printInProgress', 'Print already in progress'))); + } + return new Promise((resolve, reject) => { setIsPrinting(true); + const sameOrigin = isSameOrigin(url); + if (!iframeRef.current) { const iframe = document.createElement('iframe'); iframe.name = 'pdfPrinterFrame'; + iframe.setAttribute('aria-hidden', 'true'); Object.assign(iframe.style, { position: 'fixed', width: '0', height: '0', border: 'none', visibility: 'hidden', + pointerEvents: 'none', }); iframeRef.current = iframe; document.body.appendChild(iframe); } const iframe = iframeRef.current; + let printCompleted = false; const handleLoad = () => { try { @@ -38,17 +48,32 @@ export const useStickerPdfPrinter = () => { contentWindow.focus(); contentWindow.print(); - if (isSameOrigin(url)) { - contentWindow.addEventListener('afterprint', handlePrintComplete); + if (sameOrigin) { + // Use afterprint event for same-origin + const afterPrintHandler = () => { + if (!printCompleted) { + printCompleted = true; + handlePrintComplete(); + } + }; + contentWindow.addEventListener('afterprint', afterPrintHandler); + + cleanupRef.current = () => { + contentWindow.removeEventListener('afterprint', afterPrintHandler); + }; } else { - // For cross-origin, we'll assume printing is immediate - // and rely on the browser's print dialog behavior setTimeout(() => { - handlePrintComplete(); - }, 1000); + if (!printCompleted) { + printCompleted = true; + handlePrintComplete(); + } + }, 500); } } catch (error) { - handlePrintError(error); + if (!printCompleted) { + printCompleted = true; + handlePrintError(error); + } } }; @@ -65,29 +90,32 @@ export const useStickerPdfPrinter = () => { const cleanup = () => { iframe.onload = null; iframe.onerror = null; - setIsPrinting(false); - // Remove event listener if same-origin - if (iframe.contentWindow && isSameOrigin(url)) { + if (cleanupRef.current) { try { - iframe.contentWindow.removeEventListener('afterprint', handlePrintComplete); + cleanupRef.current(); } catch { - // Ignore cross-origin errors + // Ignore cleanup errors } + cleanupRef.current = null; } + + setIsPrinting(false); }; iframe.onload = handleLoad; iframe.onerror = () => handlePrintError(new Error(t('failedToLoadPDF', 'Failed to load PDF'))); + iframe.src = url; }); }, - [t], + [t, isPrinting], ); - const isSameOrigin = (url: string) => { + const isSameOrigin = (url: string): boolean => { try { - return new URL(url).origin === window.location.origin; + const urlObj = new URL(url, window.location.href); + return urlObj.origin === window.location.origin; } catch { return false; } @@ -95,7 +123,15 @@ export const useStickerPdfPrinter = () => { useEffect(() => { return () => { - if (iframeRef.current) { + if (cleanupRef.current) { + try { + cleanupRef.current(); + } catch { + // Ignore cleanup errors + } + } + + if (iframeRef.current && document.body.contains(iframeRef.current)) { document.body.removeChild(iframeRef.current); iframeRef.current = null; } diff --git a/packages/esm-patient-printing-app/src/index.ts b/packages/esm-patient-label-printing-app/src/index.ts similarity index 90% rename from packages/esm-patient-printing-app/src/index.ts rename to packages/esm-patient-label-printing-app/src/index.ts index 7b7a198fa9..f357c6bbbe 100644 --- a/packages/esm-patient-printing-app/src/index.ts +++ b/packages/esm-patient-label-printing-app/src/index.ts @@ -1,7 +1,7 @@ import { defineConfigSchema, getAsyncLifecycle } from '@openmrs/esm-framework'; import { configSchema } from './config-schema'; -const moduleName = '@openmrs/esm-patient-printing-app'; +const moduleName = '@openmrs/esm-patient-label-printing-app'; export const importTranslation = require.context('../translations', false, /.json$/, 'lazy'); diff --git a/packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/action-button.scss similarity index 100% rename from packages/esm-patient-banner-app/src/print-identifier-sticker/action-button.scss rename to packages/esm-patient-label-printing-app/src/print-identifier-sticker/action-button.scss diff --git a/packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx similarity index 85% rename from packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx rename to packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 4a8347174d..563db920c3 100644 --- a/packages/esm-patient-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; -import { showSnackbar, getCoreTranslation, useConfig } from '@openmrs/esm-framework'; +import { showSnackbar, getCoreTranslation, useConfig, UserHasAccess } from '@openmrs/esm-framework'; import styles from './action-button.scss'; import { useStickerPdfPrinter } from '../hooks/useStickerPdfPrinter'; import type { ConfigObject } from '../config-schema'; @@ -53,7 +53,9 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC + + + ); }; diff --git a/packages/esm-patient-printing-app/src/routes.json b/packages/esm-patient-label-printing-app/src/routes.json similarity index 100% rename from packages/esm-patient-printing-app/src/routes.json rename to packages/esm-patient-label-printing-app/src/routes.json diff --git a/packages/esm-patient-printing-app/translations/en.json b/packages/esm-patient-label-printing-app/translations/en.json similarity index 100% rename from packages/esm-patient-printing-app/translations/en.json rename to packages/esm-patient-label-printing-app/translations/en.json diff --git a/packages/esm-patient-printing-app/tsconfig.json b/packages/esm-patient-label-printing-app/tsconfig.json similarity index 100% rename from packages/esm-patient-printing-app/tsconfig.json rename to packages/esm-patient-label-printing-app/tsconfig.json diff --git a/packages/esm-patient-printing-app/webpack.config.js b/packages/esm-patient-label-printing-app/webpack.config.js similarity index 100% rename from packages/esm-patient-printing-app/webpack.config.js rename to packages/esm-patient-label-printing-app/webpack.config.js diff --git a/packages/esm-patient-printing-app/src/print-identifier-sticker/action-button.scss b/packages/esm-patient-printing-app/src/print-identifier-sticker/action-button.scss deleted file mode 100644 index 2a7fdf7d6c..0000000000 --- a/packages/esm-patient-printing-app/src/print-identifier-sticker/action-button.scss +++ /dev/null @@ -1,3 +0,0 @@ -.menuitem { - max-width: none; -} diff --git a/yarn.lock b/yarn.lock index c888608c31..fe155608c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4818,7 +4818,7 @@ __metadata: tree-model: "npm:^1.0.7" tslib: "npm:^2.4.1" uuid: "npm:^8.3.2" - webpack: "npm:~5.94.0" + webpack: "npm:~5.99.9" zone.js: "npm:~0.14.8" peerDependencies: "@openmrs/esm-framework": 8.x @@ -5174,6 +5174,20 @@ __metadata: languageName: unknown linkType: soft +"@openmrs/esm-patient-label-printing-app@workspace:packages/esm-patient-label-printing-app": + version: 0.0.0-use.local + resolution: "@openmrs/esm-patient-label-printing-app@workspace:packages/esm-patient-label-printing-app" + dependencies: + "@carbon/react": "npm:^1.76.0" + webpack: "npm:^5.94.0" + peerDependencies: + "@openmrs/esm-framework": 6.x + react: 18.x + react-i18next: 11.x + react-router-dom: 6.x + languageName: unknown + linkType: soft + "@openmrs/esm-patient-lists-app@workspace:packages/esm-patient-lists-app": version: 0.0.0-use.local resolution: "@openmrs/esm-patient-lists-app@workspace:packages/esm-patient-lists-app" @@ -5252,20 +5266,6 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-patient-printing-app@workspace:packages/esm-patient-printing-app": - version: 0.0.0-use.local - resolution: "@openmrs/esm-patient-printing-app@workspace:packages/esm-patient-printing-app" - dependencies: - "@carbon/react": "npm:^1.76.0" - webpack: "npm:^5.94.0" - peerDependencies: - "@openmrs/esm-framework": 6.x - react: 18.x - react-i18next: 11.x - react-router-dom: 6.x - languageName: unknown - linkType: soft - "@openmrs/esm-patient-programs-app@workspace:packages/esm-patient-programs-app": version: 0.0.0-use.local resolution: "@openmrs/esm-patient-programs-app@workspace:packages/esm-patient-programs-app" @@ -9493,7 +9493,7 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/ast@npm:1.14.1, @webassemblyjs/ast@npm:^1.11.5, @webassemblyjs/ast@npm:^1.12.1, @webassemblyjs/ast@npm:^1.14.1": +"@webassemblyjs/ast@npm:1.14.1, @webassemblyjs/ast@npm:^1.11.5, @webassemblyjs/ast@npm:^1.14.1": version: 1.14.1 resolution: "@webassemblyjs/ast@npm:1.14.1" dependencies: @@ -9579,7 +9579,7 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/wasm-edit@npm:^1.11.5, @webassemblyjs/wasm-edit@npm:^1.12.1, @webassemblyjs/wasm-edit@npm:^1.14.1": +"@webassemblyjs/wasm-edit@npm:^1.11.5, @webassemblyjs/wasm-edit@npm:^1.14.1": version: 1.14.1 resolution: "@webassemblyjs/wasm-edit@npm:1.14.1" dependencies: @@ -9620,7 +9620,7 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/wasm-parser@npm:1.14.1, @webassemblyjs/wasm-parser@npm:^1.11.5, @webassemblyjs/wasm-parser@npm:^1.12.1, @webassemblyjs/wasm-parser@npm:^1.14.1": +"@webassemblyjs/wasm-parser@npm:1.14.1, @webassemblyjs/wasm-parser@npm:^1.11.5, @webassemblyjs/wasm-parser@npm:^1.14.1": version: 1.14.1 resolution: "@webassemblyjs/wasm-parser@npm:1.14.1" dependencies: @@ -9769,15 +9769,6 @@ __metadata: languageName: node linkType: hard -"acorn-import-attributes@npm:^1.9.5": - version: 1.9.5 - resolution: "acorn-import-attributes@npm:1.9.5" - peerDependencies: - acorn: ^8 - checksum: 10/8bfbfbb6e2467b9b47abb4d095df717ab64fce2525da65eabee073e85e7975fb3a176b6c8bba17c99a7d8ede283a10a590272304eb54a93c4aa1af9790d47a8b - languageName: node - linkType: hard - "acorn-import-phases@npm:^1.0.3": version: 1.0.4 resolution: "acorn-import-phases@npm:1.0.4" @@ -26438,7 +26429,7 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5.99.9": +"webpack@npm:^5.99.9, webpack@npm:~5.99.9": version: 5.99.9 resolution: "webpack@npm:5.99.9" dependencies: @@ -26475,42 +26466,6 @@ __metadata: languageName: node linkType: hard -"webpack@npm:~5.94.0": - version: 5.94.0 - resolution: "webpack@npm:5.94.0" - dependencies: - "@types/estree": "npm:^1.0.5" - "@webassemblyjs/ast": "npm:^1.12.1" - "@webassemblyjs/wasm-edit": "npm:^1.12.1" - "@webassemblyjs/wasm-parser": "npm:^1.12.1" - acorn: "npm:^8.7.1" - acorn-import-attributes: "npm:^1.9.5" - browserslist: "npm:^4.21.10" - chrome-trace-event: "npm:^1.0.2" - enhanced-resolve: "npm:^5.17.1" - es-module-lexer: "npm:^1.2.1" - eslint-scope: "npm:5.1.1" - events: "npm:^3.2.0" - glob-to-regexp: "npm:^0.4.1" - graceful-fs: "npm:^4.2.11" - json-parse-even-better-errors: "npm:^2.3.1" - loader-runner: "npm:^4.2.0" - mime-types: "npm:^2.1.27" - neo-async: "npm:^2.6.2" - schema-utils: "npm:^3.2.0" - tapable: "npm:^2.1.1" - terser-webpack-plugin: "npm:^5.3.10" - watchpack: "npm:^2.4.1" - webpack-sources: "npm:^3.2.3" - peerDependenciesMeta: - webpack-cli: - optional: true - bin: - webpack: bin/webpack.js - checksum: 10/648449c5fbbb0839814116e3b2b044ac6c75a7ba272435155ddeb1e64dfaa2f8079be3adfbb691f648b69900756ce0f6fb73beab0ced3cf5e0fd46868b4593a6 - languageName: node - linkType: hard - "websocket-driver@npm:>=0.5.1, websocket-driver@npm:^0.7.4": version: 0.7.4 resolution: "websocket-driver@npm:0.7.4" From 9529c2535ac27292b33a613bc0ce4dcdfa69fcf2 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Thu, 23 Oct 2025 15:36:42 +0300 Subject: [PATCH 18/35] update lock file --- yarn.lock | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/yarn.lock b/yarn.lock index fe155608c1..6175011c28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2069,29 +2069,26 @@ __metadata: languageName: node linkType: hard -"@carbon/icon-helpers@npm:^10.68.0": - version: 10.68.0 - resolution: "@carbon/icon-helpers@npm:10.68.0" +"@carbon/grid@npm:^11.45.0": + version: 11.45.0 + resolution: "@carbon/grid@npm:11.45.0" dependencies: + "@carbon/layout": "npm:^11.43.0" "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/51fde0042e379ce6c7ff1f98db02a73031040cddea4f10282ee4eaf17da5442c01807f6a9bbcee8686defc561018489fb2d562c8eeb5e1fa45e0f9e72e45e603 + checksum: 10/1edce30dab10f971869806fa0fa31c67fbae9b94e06be6fbeabc5db41ed6b2543a86743e7a874a34c4cd34da3678809a34eba21cd3963cef3d6e2a1e13d5e0fa languageName: node linkType: hard -"@carbon/icons-react@npm:^11.64.0, @carbon/icons-react@npm:^11.68.0": - version: 11.69.0 - resolution: "@carbon/icons-react@npm:11.69.0" +"@carbon/icon-helpers@npm:^10.68.0": + version: 10.68.0 + resolution: "@carbon/icon-helpers@npm:10.68.0" dependencies: - "@carbon/icon-helpers": "npm:^10.68.0" "@ibm/telemetry-js": "npm:^1.5.0" - prop-types: "npm:^15.8.1" - peerDependencies: - react: ">=16" - checksum: 10/5485fdbf44416096988f0741db694efcb14b9ec394177f930fb10b1385eb6fd073354392cbc8e308bab2c1bcc9415873ea8799b938117d5c2f4bc498bc29f9b4 + checksum: 10/51fde0042e379ce6c7ff1f98db02a73031040cddea4f10282ee4eaf17da5442c01807f6a9bbcee8686defc561018489fb2d562c8eeb5e1fa45e0f9e72e45e603 languageName: node linkType: hard -"@carbon/icons-react@npm:^11.69.0": +"@carbon/icons-react@npm:^11.64.0, @carbon/icons-react@npm:^11.68.0, @carbon/icons-react@npm:^11.69.0": version: 11.69.0 resolution: "@carbon/icons-react@npm:11.69.0" dependencies: @@ -4806,7 +4803,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:^8.0.1-pre.3439" protractor: "npm:~7.0.0" reflect-metadata: "npm:^0.1.13" rxjs: "npm:^7.5.0" @@ -5015,7 +5012,7 @@ __metadata: resolution: "@openmrs/esm-patient-chart@workspace:." dependencies: "@hookform/resolvers": "npm:^3.3.1" - "@openmrs/esm-framework": "npm:next" + "@openmrs/esm-framework": "npm:^8.0.1-pre.3439" "@playwright/test": "npm:^1.51.1" "@swc/cli": "npm:^0.1.62" "@swc/core": "npm:^1.3.89" @@ -5055,7 +5052,7 @@ __metadata: jest-environment-jsdom: "npm:^29.7.0" lint-staged: "npm:^14.0.1" lodash: "npm:^4.17.21" - openmrs: "npm:next" + openmrs: "npm:^8.0.1-pre.3439" prettier: "npm:^3.0.3" react: "npm:^18.3.1" react-barcode: "npm:^1.5.3" From fc30c630e92a29bee4b319f8d3e8b7b40db5d59b Mon Sep 17 00:00:00 2001 From: jnsereko Date: Thu, 23 Oct 2025 15:42:21 +0300 Subject: [PATCH 19/35] update lock file --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6175011c28..8fa903f5c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4803,7 +4803,7 @@ __metadata: ngx-bootstrap: "npm:^12.0.0" ngx-build-plus: "npm:^17.0.0" ngx-webcam: "npm:^0.4.1" - openmrs: "npm:^8.0.1-pre.3439" + openmrs: "npm:next" protractor: "npm:~7.0.0" reflect-metadata: "npm:^0.1.13" rxjs: "npm:^7.5.0" @@ -5012,7 +5012,7 @@ __metadata: resolution: "@openmrs/esm-patient-chart@workspace:." dependencies: "@hookform/resolvers": "npm:^3.3.1" - "@openmrs/esm-framework": "npm:^8.0.1-pre.3439" + "@openmrs/esm-framework": "npm:next" "@playwright/test": "npm:^1.51.1" "@swc/cli": "npm:^0.1.62" "@swc/core": "npm:^1.3.89" @@ -5052,7 +5052,7 @@ __metadata: jest-environment-jsdom: "npm:^29.7.0" lint-staged: "npm:^14.0.1" lodash: "npm:^4.17.21" - openmrs: "npm:^8.0.1-pre.3439" + openmrs: "npm:next" prettier: "npm:^3.0.3" react: "npm:^18.3.1" react-barcode: "npm:^1.5.3" From 25308f03ccc247d8ebcbecf65282b7e9e8b33d0f Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Fri, 24 Oct 2025 11:33:33 +0300 Subject: [PATCH 20/35] Update packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx Co-authored-by: Dennis Kigen --- .../print-identifier-sticker-action-button.component.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 563db920c3..3007a76736 100644 --- a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -24,7 +24,7 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC { From be62675bd71493dd79c0de8bdd982b76720358e0 Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Fri, 24 Oct 2025 11:34:40 +0300 Subject: [PATCH 21/35] Update packages/esm-patient-label-printing-app/package.json Co-authored-by: Dennis Kigen --- packages/esm-patient-label-printing-app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index b3f753faf8..df8c9d2687 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -2,7 +2,7 @@ "name": "@openmrs/esm-patient-label-printing-app", "version": "10.1.0", "license": "MPL-2.0", - "description": "Patient Label Printing for the OpenMRS SPA", + "description": "Patient Label Printing frontend module for O3", "browser": "dist/openmrs-esm-patient-label-printing-app.js", "main": "src/index.ts", "source": true, From af1c81c343ed86c26983938ecb8733c3caac2205 Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Fri, 24 Oct 2025 11:34:57 +0300 Subject: [PATCH 22/35] Update packages/esm-patient-label-printing-app/package.json Co-authored-by: Dennis Kigen --- packages/esm-patient-label-printing-app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index df8c9d2687..1d7457fbe0 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -1,6 +1,6 @@ { "name": "@openmrs/esm-patient-label-printing-app", - "version": "10.1.0", + "version": "11.3.0", "license": "MPL-2.0", "description": "Patient Label Printing frontend module for O3", "browser": "dist/openmrs-esm-patient-label-printing-app.js", From 68acde33a4b31d56cf9379df595c9a0e8de5240a Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Fri, 24 Oct 2025 11:35:11 +0300 Subject: [PATCH 23/35] Update packages/esm-patient-label-printing-app/package.json Co-authored-by: Dennis Kigen --- packages/esm-patient-label-printing-app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index 1d7457fbe0..b9e80e0540 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -37,7 +37,7 @@ "url": "https://github.com/openmrs/openmrs-esm-patient-chart/issues" }, "dependencies": { - "@carbon/react": "^1.76.0" + "@carbon/react": "^1.83.0", }, "peerDependencies": { "@openmrs/esm-framework": "6.x", From 02601c6fb65b36c019e33525a3ecfd84f64ef098 Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Fri, 24 Oct 2025 11:35:25 +0300 Subject: [PATCH 24/35] Update packages/esm-patient-label-printing-app/package.json Co-authored-by: Dennis Kigen --- packages/esm-patient-label-printing-app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index b9e80e0540..4674839b2f 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -42,7 +42,7 @@ "peerDependencies": { "@openmrs/esm-framework": "6.x", "react": "18.x", - "react-i18next": "11.x", + "react-i18next": "16.x", "react-router-dom": "6.x" }, "devDependencies": { From b10f8e8c98cb5f81fe078ddcdbff52aa7ab0fc0a Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Fri, 24 Oct 2025 11:35:39 +0300 Subject: [PATCH 25/35] Update packages/esm-patient-label-printing-app/package.json Co-authored-by: Dennis Kigen --- packages/esm-patient-label-printing-app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index 4674839b2f..09a69d58a5 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -40,7 +40,7 @@ "@carbon/react": "^1.83.0", }, "peerDependencies": { - "@openmrs/esm-framework": "6.x", + "@openmrs/esm-framework": "8.x", "react": "18.x", "react-i18next": "16.x", "react-router-dom": "6.x" From 7c0a5d760a40e27cb5a827fc65822d083c63cfea Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Fri, 24 Oct 2025 11:35:55 +0300 Subject: [PATCH 26/35] Update packages/esm-patient-label-printing-app/package.json Co-authored-by: Dennis Kigen --- packages/esm-patient-label-printing-app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index 09a69d58a5..10a5e64ae1 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -46,6 +46,6 @@ "react-router-dom": "6.x" }, "devDependencies": { - "webpack": "^5.94.0" + "webpack": "^5.99.9" } } From 06a14f48f951dde46cff8d376162545570f1dc27 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Mon, 27 Oct 2025 14:07:11 +0300 Subject: [PATCH 27/35] remove translation changes in non-en files --- .../translations/am.json | 1 + .../translations/ar.json | 1 + .../translations/ar_SY.json | 1 + .../translations/bn.json | 1 + .../translations/de.json | 1 + .../translations/en_US.json | 1 + .../translations/es.json | 1 + .../translations/es_MX.json | 1 + .../translations/fr.json | 1 + .../translations/he.json | 1 + .../translations/hi.json | 1 + .../translations/hi_IN.json | 1 + .../translations/id.json | 1 + .../translations/it.json | 1 + .../translations/ka.json | 1 + .../translations/km.json | 1 + .../translations/ku.json | 1 + .../translations/ky.json | 1 + .../translations/lg.json | 1 + .../translations/ne.json | 1 + .../translations/pl.json | 1 + .../translations/pt.json | 1 + .../translations/pt_BR.json | 1 + .../translations/qu.json | 1 + .../translations/ro_RO.json | 1 + .../translations/ru_RU.json | 1 + .../translations/si.json | 1 + .../translations/sw.json | 1 + .../translations/sw_KE.json | 1 + .../translations/tr.json | 1 + .../translations/tr_TR.json | 1 + .../translations/uk.json | 1 + .../translations/uz.json | 1 + .../translations/uz@Latn.json | 1 + .../translations/uz_UZ.json | 1 + .../translations/vi.json | 1 + .../translations/zh.json | 1 + .../translations/zh_CN.json | 1 + .../package.json | 2 +- ...tifier-sticker-action-button.component.tsx | 6 +- ...int-identifier-sticker-action-button.scss} | 0 yarn.lock | 228 +----------------- 42 files changed, 49 insertions(+), 225 deletions(-) rename packages/esm-patient-label-printing-app/src/print-identifier-sticker/{action-button.scss => print-identifier-sticker-action-button.scss} (100%) diff --git a/packages/esm-patient-banner-app/translations/am.json b/packages/esm-patient-banner-app/translations/am.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/am.json +++ b/packages/esm-patient-banner-app/translations/am.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/ar.json b/packages/esm-patient-banner-app/translations/ar.json index ae99a24010..60b75bd039 100644 --- a/packages/esm-patient-banner-app/translations/ar.json +++ b/packages/esm-patient-banner-app/translations/ar.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "ملصق تعريف المريض", "patientNameWithSeparator": "اسم المريض", "postalCode": "الرمز البريدي", + "printIdentifierSticker": "ملصق تعريف المريض", "started": "Started", "state": "الولاية", "stateProvince": "الولاية", diff --git a/packages/esm-patient-banner-app/translations/ar_SY.json b/packages/esm-patient-banner-app/translations/ar_SY.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/ar_SY.json +++ b/packages/esm-patient-banner-app/translations/ar_SY.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/bn.json b/packages/esm-patient-banner-app/translations/bn.json index f08b8b7b31..587de5fe1f 100644 --- a/packages/esm-patient-banner-app/translations/bn.json +++ b/packages/esm-patient-banner-app/translations/bn.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "রোগীর নাম:", "postalCode": "পোস্টাল কোড", + "printIdentifierSticker": "Print identifier sticker", "started": "শুরু হয়েছে", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/de.json b/packages/esm-patient-banner-app/translations/de.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/de.json +++ b/packages/esm-patient-banner-app/translations/de.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/en_US.json b/packages/esm-patient-banner-app/translations/en_US.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/en_US.json +++ b/packages/esm-patient-banner-app/translations/en_US.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/es.json b/packages/esm-patient-banner-app/translations/es.json index 847decf45e..ac494483ea 100644 --- a/packages/esm-patient-banner-app/translations/es.json +++ b/packages/esm-patient-banner-app/translations/es.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Sticker de identificación del paciente", "patientNameWithSeparator": "Nombre del paciente:", "postalCode": "Código postal", + "printIdentifierSticker": "Imprimir sticker de identificación", "started": "Iniciado", "state": "Estado", "stateProvince": "Estado", diff --git a/packages/esm-patient-banner-app/translations/es_MX.json b/packages/esm-patient-banner-app/translations/es_MX.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/es_MX.json +++ b/packages/esm-patient-banner-app/translations/es_MX.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/fr.json b/packages/esm-patient-banner-app/translations/fr.json index ad4e7f99fe..e9e306a6c1 100644 --- a/packages/esm-patient-banner-app/translations/fr.json +++ b/packages/esm-patient-banner-app/translations/fr.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Autocollant d'identification du patient", "patientNameWithSeparator": "Nom du patient :", "postalCode": "Code postal", + "printIdentifierSticker": "Imprimer l'autocollant d'identification", "started": "Démarré", "state": "État", "stateProvince": "État", diff --git a/packages/esm-patient-banner-app/translations/he.json b/packages/esm-patient-banner-app/translations/he.json index ea68986414..c1c54a67d0 100644 --- a/packages/esm-patient-banner-app/translations/he.json +++ b/packages/esm-patient-banner-app/translations/he.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "שם המטופל/ת:", "postalCode": "מיקוד", + "printIdentifierSticker": "הדפסת מדבקת זיהוי", "started": "Started", "state": "מדינה", "stateProvince": "מדינה", diff --git a/packages/esm-patient-banner-app/translations/hi.json b/packages/esm-patient-banner-app/translations/hi.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/hi.json +++ b/packages/esm-patient-banner-app/translations/hi.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/hi_IN.json b/packages/esm-patient-banner-app/translations/hi_IN.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/hi_IN.json +++ b/packages/esm-patient-banner-app/translations/hi_IN.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/id.json b/packages/esm-patient-banner-app/translations/id.json index 8829082552..75d1cdb25e 100644 --- a/packages/esm-patient-banner-app/translations/id.json +++ b/packages/esm-patient-banner-app/translations/id.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Stiker identitas pasien", "patientNameWithSeparator": "Nama pasien:", "postalCode": "Kode pos", + "printIdentifierSticker": "Cetak stiker identitas", "started": "Dimulai", "state": "Provinsi", "stateProvince": "Provinsi", diff --git a/packages/esm-patient-banner-app/translations/it.json b/packages/esm-patient-banner-app/translations/it.json index 18bba93c5b..96b7635651 100644 --- a/packages/esm-patient-banner-app/translations/it.json +++ b/packages/esm-patient-banner-app/translations/it.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Etichetta identificativa del paziente", "patientNameWithSeparator": "Nome del paziente:", "postalCode": "Codice postale", + "printIdentifierSticker": "Stampa etichetta identificativa", "started": "Iniziato", "state": "Stato", "stateProvince": "Stato", diff --git a/packages/esm-patient-banner-app/translations/ka.json b/packages/esm-patient-banner-app/translations/ka.json index b6b128bd69..2f8cdb7e04 100644 --- a/packages/esm-patient-banner-app/translations/ka.json +++ b/packages/esm-patient-banner-app/translations/ka.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "პაკეტის იდენტიფიკატორი ეტიკეტი", "patientNameWithSeparator": "პაციენტის სახელი:", "postalCode": "საფოსტო კოდი", + "printIdentifierSticker": "იდენტიფიკატორი ეტიკეტის დაბეჭდვა", "started": "დაწყებულია", "state": "შტატი", "stateProvince": "შტატი", diff --git a/packages/esm-patient-banner-app/translations/km.json b/packages/esm-patient-banner-app/translations/km.json index 92a025b04e..3c53df1521 100644 --- a/packages/esm-patient-banner-app/translations/km.json +++ b/packages/esm-patient-banner-app/translations/km.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "លេខកូដតំបន់", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "រដ្ឋ", "stateProvince": "រដ្ឋ", diff --git a/packages/esm-patient-banner-app/translations/ku.json b/packages/esm-patient-banner-app/translations/ku.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/ku.json +++ b/packages/esm-patient-banner-app/translations/ku.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/ky.json b/packages/esm-patient-banner-app/translations/ky.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/ky.json +++ b/packages/esm-patient-banner-app/translations/ky.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/lg.json b/packages/esm-patient-banner-app/translations/lg.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/lg.json +++ b/packages/esm-patient-banner-app/translations/lg.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/ne.json b/packages/esm-patient-banner-app/translations/ne.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/ne.json +++ b/packages/esm-patient-banner-app/translations/ne.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/pl.json b/packages/esm-patient-banner-app/translations/pl.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/pl.json +++ b/packages/esm-patient-banner-app/translations/pl.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/pt.json b/packages/esm-patient-banner-app/translations/pt.json index 43bfd0f44c..5a0b17e8cc 100644 --- a/packages/esm-patient-banner-app/translations/pt.json +++ b/packages/esm-patient-banner-app/translations/pt.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Etiqueta de Identificador do Utente", "patientNameWithSeparator": "Nome do utente:", "postalCode": "Caixa postal", + "printIdentifierSticker": "Imprimir etiqueta do identificador", "started": "Started", "state": "Estado", "stateProvince": "Estado", diff --git a/packages/esm-patient-banner-app/translations/pt_BR.json b/packages/esm-patient-banner-app/translations/pt_BR.json index 60ead8b7f3..5cbf7e2113 100644 --- a/packages/esm-patient-banner-app/translations/pt_BR.json +++ b/packages/esm-patient-banner-app/translations/pt_BR.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Etiqueta de identificação do Paciente", "patientNameWithSeparator": "Nome do Paciente:", "postalCode": "Código postal CEP", + "printIdentifierSticker": "Imprimir etiqueta de identificação", "started": "Iniciado", "state": "Estado", "stateProvince": "Estado", diff --git a/packages/esm-patient-banner-app/translations/qu.json b/packages/esm-patient-banner-app/translations/qu.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/qu.json +++ b/packages/esm-patient-banner-app/translations/qu.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/ro_RO.json b/packages/esm-patient-banner-app/translations/ro_RO.json index e2184ad215..ec789dfb6b 100644 --- a/packages/esm-patient-banner-app/translations/ro_RO.json +++ b/packages/esm-patient-banner-app/translations/ro_RO.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Etichetă identificare pacient", "patientNameWithSeparator": "Nume pacient:", "postalCode": "Cod poștal", + "printIdentifierSticker": "Printează etichetă identificare", "started": "Început", "state": "Stat", "stateProvince": "Stat/Provincie", diff --git a/packages/esm-patient-banner-app/translations/ru_RU.json b/packages/esm-patient-banner-app/translations/ru_RU.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/ru_RU.json +++ b/packages/esm-patient-banner-app/translations/ru_RU.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/si.json b/packages/esm-patient-banner-app/translations/si.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/si.json +++ b/packages/esm-patient-banner-app/translations/si.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/sw.json b/packages/esm-patient-banner-app/translations/sw.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/sw.json +++ b/packages/esm-patient-banner-app/translations/sw.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/sw_KE.json b/packages/esm-patient-banner-app/translations/sw_KE.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/sw_KE.json +++ b/packages/esm-patient-banner-app/translations/sw_KE.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/tr.json b/packages/esm-patient-banner-app/translations/tr.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/tr.json +++ b/packages/esm-patient-banner-app/translations/tr.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/tr_TR.json b/packages/esm-patient-banner-app/translations/tr_TR.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/tr_TR.json +++ b/packages/esm-patient-banner-app/translations/tr_TR.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/uk.json b/packages/esm-patient-banner-app/translations/uk.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/uk.json +++ b/packages/esm-patient-banner-app/translations/uk.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/uz.json b/packages/esm-patient-banner-app/translations/uz.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/uz.json +++ b/packages/esm-patient-banner-app/translations/uz.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/uz@Latn.json b/packages/esm-patient-banner-app/translations/uz@Latn.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/uz@Latn.json +++ b/packages/esm-patient-banner-app/translations/uz@Latn.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/uz_UZ.json b/packages/esm-patient-banner-app/translations/uz_UZ.json index b6a77bf8a5..d6f528ff35 100644 --- a/packages/esm-patient-banner-app/translations/uz_UZ.json +++ b/packages/esm-patient-banner-app/translations/uz_UZ.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Patient identifier sticker", "patientNameWithSeparator": "Patient name:", "postalCode": "Postal code", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/vi.json b/packages/esm-patient-banner-app/translations/vi.json index 7bc66a156a..59f68f52a1 100644 --- a/packages/esm-patient-banner-app/translations/vi.json +++ b/packages/esm-patient-banner-app/translations/vi.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "Nhãn dán nhận dạng bệnh nhân", "patientNameWithSeparator": "Tên bệnh nhân:", "postalCode": "Mã bưu chính", + "printIdentifierSticker": "In nhãn dán nhận dạng", "started": "Started", "state": "State", "stateProvince": "State", diff --git a/packages/esm-patient-banner-app/translations/zh.json b/packages/esm-patient-banner-app/translations/zh.json index 78017acf90..0c64edf158 100644 --- a/packages/esm-patient-banner-app/translations/zh.json +++ b/packages/esm-patient-banner-app/translations/zh.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "患者标识符贴纸", "patientNameWithSeparator": "Patient name:", "postalCode": "邮政编码", + "printIdentifierSticker": "Print identifier sticker", "started": "Started", "state": "省份", "stateProvince": "省份", diff --git a/packages/esm-patient-banner-app/translations/zh_CN.json b/packages/esm-patient-banner-app/translations/zh_CN.json index 49a2e956ca..ccf3392b3c 100644 --- a/packages/esm-patient-banner-app/translations/zh_CN.json +++ b/packages/esm-patient-banner-app/translations/zh_CN.json @@ -16,6 +16,7 @@ "patientIdentifierSticker": "患者标识符标签", "patientNameWithSeparator": "患者姓名:", "postalCode": "邮政编码", + "printIdentifierSticker": "患者标识符标签", "started": "已开始", "state": "省份", "stateProvince": "省份", diff --git a/packages/esm-patient-label-printing-app/package.json b/packages/esm-patient-label-printing-app/package.json index 10a5e64ae1..5514fed7c9 100644 --- a/packages/esm-patient-label-printing-app/package.json +++ b/packages/esm-patient-label-printing-app/package.json @@ -37,7 +37,7 @@ "url": "https://github.com/openmrs/openmrs-esm-patient-chart/issues" }, "dependencies": { - "@carbon/react": "^1.83.0", + "@carbon/react": "^1.83.0" }, "peerDependencies": { "@openmrs/esm-framework": "8.x", diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx index 3007a76736..505ec35692 100644 --- a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.component.tsx @@ -1,8 +1,8 @@ import React, { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem } from '@carbon/react'; -import { showSnackbar, getCoreTranslation, useConfig, UserHasAccess } from '@openmrs/esm-framework'; -import styles from './action-button.scss'; +import { showSnackbar, getCoreTranslation, useConfig, UserHasAccess, restBaseUrl } from '@openmrs/esm-framework'; +import styles from './print-identifier-sticker-action-button.scss'; import { useStickerPdfPrinter } from '../hooks/useStickerPdfPrinter'; import type { ConfigObject } from '../config-schema'; @@ -24,7 +24,7 @@ const PrintIdentifierStickerOverflowMenuItem: React.FC { diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/action-button.scss b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.scss similarity index 100% rename from packages/esm-patient-label-printing-app/src/print-identifier-sticker/action-button.scss rename to packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.scss diff --git a/yarn.lock b/yarn.lock index 8fa903f5c2..5c6e97859b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2034,15 +2034,6 @@ __metadata: languageName: node linkType: hard -"@carbon/colors@npm:^11.42.0": - version: 11.42.0 - resolution: "@carbon/colors@npm:11.42.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/7cb9303515f4b90a9fd9cb8398a5ba01bb18341eacd6dc7465fad8fe6eedf21daf90657eccecd3874978f5e2f74ed960b87d6c31f0e2c8a595886a2d48bdaa5c - languageName: node - linkType: hard - "@carbon/feature-flags@npm:^0.31.0": version: 0.31.0 resolution: "@carbon/feature-flags@npm:0.31.0" @@ -2069,16 +2060,6 @@ __metadata: languageName: node linkType: hard -"@carbon/grid@npm:^11.45.0": - version: 11.45.0 - resolution: "@carbon/grid@npm:11.45.0" - dependencies: - "@carbon/layout": "npm:^11.43.0" - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/1edce30dab10f971869806fa0fa31c67fbae9b94e06be6fbeabc5db41ed6b2543a86743e7a874a34c4cd34da3678809a34eba21cd3963cef3d6e2a1e13d5e0fa - languageName: node - linkType: hard - "@carbon/icon-helpers@npm:^10.68.0": version: 10.68.0 resolution: "@carbon/icon-helpers@npm:10.68.0" @@ -2088,7 +2069,7 @@ __metadata: languageName: node linkType: hard -"@carbon/icons-react@npm:^11.64.0, @carbon/icons-react@npm:^11.68.0, @carbon/icons-react@npm:^11.69.0": +"@carbon/icons-react@npm:^11.64.0, @carbon/icons-react@npm:^11.68.0": version: 11.69.0 resolution: "@carbon/icons-react@npm:11.69.0" dependencies: @@ -2110,15 +2091,6 @@ __metadata: languageName: node linkType: hard -"@carbon/layout@npm:^11.43.0": - version: 11.43.0 - resolution: "@carbon/layout@npm:11.43.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/cfa0d56ac88f025a5cdb7f76b71b3969cc8ddcd3c55e8d2373fc67099b0bee45da176905974dbcbe7e994e3f01d39964f49f27c2cb2b975070ae82954cbd966a - languageName: node - linkType: hard - "@carbon/motion@npm:^11.36.0, @carbon/motion@npm:^11.5.0": version: 11.36.0 resolution: "@carbon/motion@npm:11.36.0" @@ -2128,46 +2100,6 @@ __metadata: languageName: node linkType: hard -"@carbon/motion@npm:^11.37.0": - version: 11.37.0 - resolution: "@carbon/motion@npm:11.37.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/a97962dcda0596e1a523ffabe5dbcd8e2ed694cc0c94b6b919e8b59adb4745b82fd263af51094d826a44ce9bda20c5e5391370cc765209cea96ce0b1921e5bb0 - languageName: node - linkType: hard - -"@carbon/react@npm:^1.76.0": - version: 1.93.0 - resolution: "@carbon/react@npm:1.93.0" - dependencies: - "@babel/runtime": "npm:^7.27.3" - "@carbon/feature-flags": "npm:^0.31.0" - "@carbon/icons-react": "npm:^11.69.0" - "@carbon/layout": "npm:^11.43.0" - "@carbon/styles": "npm:^1.92.0" - "@carbon/utilities": "npm:^0.11.0" - "@floating-ui/react": "npm:^0.27.4" - "@ibm/telemetry-js": "npm:^1.5.0" - classnames: "npm:2.5.1" - copy-to-clipboard: "npm:^3.3.1" - downshift: "npm:9.0.10" - es-toolkit: "npm:^1.27.0" - flatpickr: "npm:4.6.13" - invariant: "npm:^2.2.3" - prop-types: "npm:^15.8.1" - react-fast-compare: "npm:^3.2.2" - tabbable: "npm:^6.2.0" - window-or-global: "npm:^1.0.1" - peerDependencies: - react: ^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0 - react-dom: ^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0 - react-is: ^16.13.1 || ^17.0.2 || ^18.3.1 || ^19.0.0 - sass: ^1.33.0 - checksum: 10/52e29504569f24b757c475b7d51cc007a2dbd379a83197850512ed2ca4ec3d7c8b91a6f9b2e951da59865fc29d274fb60218ef3f9969b13bd57768ec9eee7337 - languageName: node - linkType: hard - "@carbon/react@npm:^1.83.0, @carbon/react@npm:^1.92.1": version: 1.92.1 resolution: "@carbon/react@npm:1.92.1" @@ -2229,36 +2161,6 @@ __metadata: languageName: node linkType: hard -"@carbon/styles@npm:^1.92.0": - version: 1.92.0 - resolution: "@carbon/styles@npm:1.92.0" - dependencies: - "@carbon/colors": "npm:^11.42.0" - "@carbon/feature-flags": "npm:^0.31.0" - "@carbon/grid": "npm:^11.45.0" - "@carbon/layout": "npm:^11.43.0" - "@carbon/motion": "npm:^11.37.0" - "@carbon/themes": "npm:^11.62.0" - "@carbon/type": "npm:^11.49.0" - "@ibm/plex": "npm:6.0.0-next.6" - "@ibm/plex-mono": "npm:1.1.0" - "@ibm/plex-sans": "npm:1.1.0" - "@ibm/plex-sans-arabic": "npm:1.1.0" - "@ibm/plex-sans-devanagari": "npm:1.1.0" - "@ibm/plex-sans-hebrew": "npm:1.1.0" - "@ibm/plex-sans-thai": "npm:1.1.0" - "@ibm/plex-sans-thai-looped": "npm:1.1.0" - "@ibm/plex-serif": "npm:1.1.0" - "@ibm/telemetry-js": "npm:^1.5.0" - peerDependencies: - sass: ^1.33.0 - peerDependenciesMeta: - sass: - optional: true - checksum: 10/5f306bd4bc58838e4d2032efa7de42407f49bdde2992389e3f518a22d08ed26b41665e5bce7a8921570e4ca39d0e903ebe38c86591ec20cc965dac0aa0bbca87 - languageName: node - linkType: hard - "@carbon/styles@npm:~1.14.0": version: 1.14.0 resolution: "@carbon/styles@npm:1.14.0" @@ -2290,19 +2192,6 @@ __metadata: languageName: node linkType: hard -"@carbon/themes@npm:^11.62.0": - version: 11.62.0 - resolution: "@carbon/themes@npm:11.62.0" - dependencies: - "@carbon/colors": "npm:^11.42.0" - "@carbon/layout": "npm:^11.43.0" - "@carbon/type": "npm:^11.49.0" - "@ibm/telemetry-js": "npm:^1.5.0" - color: "npm:^4.0.0" - checksum: 10/c3f739bd69a522c5d4b00bbaed4cadd04a5956d5a5be22cb7e79a36417e3f428ef1d0e597325546698429042c011a55e77d2c95b122b74b6e2bbb3c491ece0cd - languageName: node - linkType: hard - "@carbon/type@npm:^11.10.0, @carbon/type@npm:^11.48.0": version: 11.48.0 resolution: "@carbon/type@npm:11.48.0" @@ -2314,17 +2203,6 @@ __metadata: languageName: node linkType: hard -"@carbon/type@npm:^11.49.0": - version: 11.49.0 - resolution: "@carbon/type@npm:11.49.0" - dependencies: - "@carbon/grid": "npm:^11.45.0" - "@carbon/layout": "npm:^11.43.0" - "@ibm/telemetry-js": "npm:^1.5.0" - checksum: 10/3d4d4ddaaf1917a2d08829a7b9d3f979a9693821e90947cf4daa10f41d8dc923b58726aceb41822f1bca316c2f834f95f474b38dc361c4c6f1f6483c605eb0e4 - languageName: node - linkType: hard - "@carbon/utilities@npm:^0.10.0": version: 0.10.0 resolution: "@carbon/utilities@npm:0.10.0" @@ -2335,16 +2213,6 @@ __metadata: languageName: node linkType: hard -"@carbon/utilities@npm:^0.11.0": - version: 0.11.0 - resolution: "@carbon/utilities@npm:0.11.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.6.1" - "@internationalized/number": "npm:^3.6.1" - checksum: 10/2b79d4a83357c62f165e31017ad005801d7310ad99ef0e150105bb8b0cabc8c5cec602e26a8e38c270d111f01cc347d893ca6d8dac42e5fda37cb722e90c3718 - languageName: node - linkType: hard - "@carbon/utils-position@npm:^1.3.0": version: 1.3.0 resolution: "@carbon/utils-position@npm:1.3.0" @@ -3175,15 +3043,6 @@ __metadata: languageName: node linkType: hard -"@ibm/plex-sans-hebrew@npm:1.1.0": - version: 1.1.0 - resolution: "@ibm/plex-sans-hebrew@npm:1.1.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.6.1" - checksum: 10/46f02a068b5e3455e5d46bec5e0f8b273b9e26f78a3e9d27899a554d0c398a146be97a14d9992ca46c29257e21949372fa77fc99b132fc9e5c792eb96774e3b8 - languageName: node - linkType: hard - "@ibm/plex-sans-thai-looped@npm:1.1.0": version: 1.1.0 resolution: "@ibm/plex-sans-thai-looped@npm:1.1.0" @@ -3200,15 +3059,6 @@ __metadata: languageName: node linkType: hard -"@ibm/plex-sans-thai@npm:1.1.0": - version: 1.1.0 - resolution: "@ibm/plex-sans-thai@npm:1.1.0" - dependencies: - "@ibm/telemetry-js": "npm:^1.6.1" - checksum: 10/bad059292389005ae4aab29d5f900035229f12340e42f105b22ef75ca7b7ab93b4a8991df7dfa15af62abcf1f83d1d476db8ecc077ca134d698ce1774a569610 - languageName: node - linkType: hard - "@ibm/plex-sans@npm:1.1.0": version: 1.1.0 resolution: "@ibm/plex-sans@npm:1.1.0" @@ -5175,12 +5025,12 @@ __metadata: version: 0.0.0-use.local resolution: "@openmrs/esm-patient-label-printing-app@workspace:packages/esm-patient-label-printing-app" dependencies: - "@carbon/react": "npm:^1.76.0" - webpack: "npm:^5.94.0" + "@carbon/react": "npm:^1.83.0" + webpack: "npm:^5.99.9" peerDependencies: - "@openmrs/esm-framework": 6.x + "@openmrs/esm-framework": 8.x react: 18.x - react-i18next: 11.x + react-i18next: 16.x react-router-dom: 6.x languageName: unknown linkType: soft @@ -8524,7 +8374,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": +"@types/estree@npm:*, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.5, @types/estree@npm:^1.0.6": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 @@ -9766,15 +9616,6 @@ __metadata: languageName: node linkType: hard -"acorn-import-phases@npm:^1.0.3": - version: 1.0.4 - resolution: "acorn-import-phases@npm:1.0.4" - peerDependencies: - acorn: ^8.14.0 - checksum: 10/471050ac7d9b61909c837b426de9eeef2958997f6277ad7dea88d5894fd9b3245d8ed4a225c2ca44f814dbb20688009db7a80e525e8196fc9e98c5285b66161d - languageName: node - linkType: hard - "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -9791,7 +9632,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.14.0, acorn@npm:^8.15.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": +"acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.14.0, acorn@npm:^8.7.1, acorn@npm:^8.8.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.15.0 resolution: "acorn@npm:8.15.0" bin: @@ -13653,16 +13494,6 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.17.2": - version: 5.18.2 - resolution: "enhanced-resolve@npm:5.18.2" - dependencies: - graceful-fs: "npm:^4.2.4" - tapable: "npm:^2.2.0" - checksum: 10/d1b517c908b69d1afbf87b476bbe7dd8d1daf11070127b9ec4f8553f0c6020d30f79103c938776645d569e954e4e04c326f408d2ea3820ade71e72798fb7d36f - languageName: node - linkType: hard - "enquirer@npm:~2.3.6": version: 2.3.6 resolution: "enquirer@npm:2.3.6" @@ -26322,13 +26153,6 @@ __metadata: languageName: node linkType: hard -"webpack-sources@npm:^3.3.3": - version: 3.3.3 - resolution: "webpack-sources@npm:3.3.3" - checksum: 10/ec5d72607e8068467370abccbfff855c596c098baedbe9d198a557ccf198e8546a322836a6f74241492576adba06100286592993a62b63196832cdb53c8bae91 - languageName: node - linkType: hard - "webpack-stats-plugin@npm:^1.1.3": version: 1.1.3 resolution: "webpack-stats-plugin@npm:1.1.3" @@ -26388,44 +26212,6 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5.94.0": - version: 5.101.0 - resolution: "webpack@npm:5.101.0" - dependencies: - "@types/eslint-scope": "npm:^3.7.7" - "@types/estree": "npm:^1.0.8" - "@types/json-schema": "npm:^7.0.15" - "@webassemblyjs/ast": "npm:^1.14.1" - "@webassemblyjs/wasm-edit": "npm:^1.14.1" - "@webassemblyjs/wasm-parser": "npm:^1.14.1" - acorn: "npm:^8.15.0" - acorn-import-phases: "npm:^1.0.3" - browserslist: "npm:^4.24.0" - chrome-trace-event: "npm:^1.0.2" - enhanced-resolve: "npm:^5.17.2" - es-module-lexer: "npm:^1.2.1" - eslint-scope: "npm:5.1.1" - events: "npm:^3.2.0" - glob-to-regexp: "npm:^0.4.1" - graceful-fs: "npm:^4.2.11" - json-parse-even-better-errors: "npm:^2.3.1" - loader-runner: "npm:^4.2.0" - mime-types: "npm:^2.1.27" - neo-async: "npm:^2.6.2" - schema-utils: "npm:^4.3.2" - tapable: "npm:^2.1.1" - terser-webpack-plugin: "npm:^5.3.11" - watchpack: "npm:^2.4.1" - webpack-sources: "npm:^3.3.3" - peerDependenciesMeta: - webpack-cli: - optional: true - bin: - webpack: bin/webpack.js - checksum: 10/edeb24a88cbe96902c601bc1292cd344d27c89c5eceb187f4e9936c8a17356c62b23a5dc441c12b16e62bb6c40804bd10d691135c638398f921760f2dba6a761 - languageName: node - linkType: hard - "webpack@npm:^5.99.9, webpack@npm:~5.99.9": version: 5.99.9 resolution: "webpack@npm:5.99.9" From 247d708ccd7711bd5fc7eac517e6690c7521ac20 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Mon, 27 Oct 2025 14:41:50 +0300 Subject: [PATCH 28/35] Trigger CI/CD pipeline From f7f67d64f8d679c2925d28aada09a8ff6850b46a Mon Sep 17 00:00:00 2001 From: jnsereko Date: Mon, 27 Oct 2025 15:38:37 +0300 Subject: [PATCH 29/35] reset form entry webpack to 5.94 to fix CI --- packages/esm-form-entry-app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-form-entry-app/package.json b/packages/esm-form-entry-app/package.json index c59b480b43..ec5b85f21b 100644 --- a/packages/esm-form-entry-app/package.json +++ b/packages/esm-form-entry-app/package.json @@ -100,7 +100,7 @@ "rxjs": "^7.5.0", "rxjs-compat": "^6.6.7", "style-loader": "2.x", - "webpack": "~5.99.9" + "webpack": "~5.94.0" }, "installConfig": { "hoistingLimits": "dependencies" From 11b726e3379aa58b2ae2f9ee8b37f95aeb58e537 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Mon, 27 Oct 2025 16:42:16 +0300 Subject: [PATCH 30/35] add lock file --- yarn.lock | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5c6e97859b..1ac633d8b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4665,7 +4665,7 @@ __metadata: tree-model: "npm:^1.0.7" tslib: "npm:^2.4.1" uuid: "npm:^8.3.2" - webpack: "npm:~5.99.9" + webpack: "npm:~5.94.0" zone.js: "npm:~0.14.8" peerDependencies: "@openmrs/esm-framework": 8.x @@ -9340,7 +9340,7 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/ast@npm:1.14.1, @webassemblyjs/ast@npm:^1.11.5, @webassemblyjs/ast@npm:^1.14.1": +"@webassemblyjs/ast@npm:1.14.1, @webassemblyjs/ast@npm:^1.11.5, @webassemblyjs/ast@npm:^1.12.1, @webassemblyjs/ast@npm:^1.14.1": version: 1.14.1 resolution: "@webassemblyjs/ast@npm:1.14.1" dependencies: @@ -9426,7 +9426,7 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/wasm-edit@npm:^1.11.5, @webassemblyjs/wasm-edit@npm:^1.14.1": +"@webassemblyjs/wasm-edit@npm:^1.11.5, @webassemblyjs/wasm-edit@npm:^1.12.1, @webassemblyjs/wasm-edit@npm:^1.14.1": version: 1.14.1 resolution: "@webassemblyjs/wasm-edit@npm:1.14.1" dependencies: @@ -9467,7 +9467,7 @@ __metadata: languageName: node linkType: hard -"@webassemblyjs/wasm-parser@npm:1.14.1, @webassemblyjs/wasm-parser@npm:^1.11.5, @webassemblyjs/wasm-parser@npm:^1.14.1": +"@webassemblyjs/wasm-parser@npm:1.14.1, @webassemblyjs/wasm-parser@npm:^1.11.5, @webassemblyjs/wasm-parser@npm:^1.12.1, @webassemblyjs/wasm-parser@npm:^1.14.1": version: 1.14.1 resolution: "@webassemblyjs/wasm-parser@npm:1.14.1" dependencies: @@ -9616,6 +9616,15 @@ __metadata: languageName: node linkType: hard +"acorn-import-attributes@npm:^1.9.5": + version: 1.9.5 + resolution: "acorn-import-attributes@npm:1.9.5" + peerDependencies: + acorn: ^8 + checksum: 10/8bfbfbb6e2467b9b47abb4d095df717ab64fce2525da65eabee073e85e7975fb3a176b6c8bba17c99a7d8ede283a10a590272304eb54a93c4aa1af9790d47a8b + languageName: node + linkType: hard + "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -26212,7 +26221,7 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5.99.9, webpack@npm:~5.99.9": +"webpack@npm:^5.99.9": version: 5.99.9 resolution: "webpack@npm:5.99.9" dependencies: @@ -26249,6 +26258,42 @@ __metadata: languageName: node linkType: hard +"webpack@npm:~5.94.0": + version: 5.94.0 + resolution: "webpack@npm:5.94.0" + dependencies: + "@types/estree": "npm:^1.0.5" + "@webassemblyjs/ast": "npm:^1.12.1" + "@webassemblyjs/wasm-edit": "npm:^1.12.1" + "@webassemblyjs/wasm-parser": "npm:^1.12.1" + acorn: "npm:^8.7.1" + acorn-import-attributes: "npm:^1.9.5" + browserslist: "npm:^4.21.10" + chrome-trace-event: "npm:^1.0.2" + enhanced-resolve: "npm:^5.17.1" + es-module-lexer: "npm:^1.2.1" + eslint-scope: "npm:5.1.1" + events: "npm:^3.2.0" + glob-to-regexp: "npm:^0.4.1" + graceful-fs: "npm:^4.2.11" + json-parse-even-better-errors: "npm:^2.3.1" + loader-runner: "npm:^4.2.0" + mime-types: "npm:^2.1.27" + neo-async: "npm:^2.6.2" + schema-utils: "npm:^3.2.0" + tapable: "npm:^2.1.1" + terser-webpack-plugin: "npm:^5.3.10" + watchpack: "npm:^2.4.1" + webpack-sources: "npm:^3.2.3" + peerDependenciesMeta: + webpack-cli: + optional: true + bin: + webpack: bin/webpack.js + checksum: 10/648449c5fbbb0839814116e3b2b044ac6c75a7ba272435155ddeb1e64dfaa2f8079be3adfbb691f648b69900756ce0f6fb73beab0ced3cf5e0fd46868b4593a6 + languageName: node + linkType: hard + "websocket-driver@npm:>=0.5.1, websocket-driver@npm:^0.7.4": version: 0.7.4 resolution: "websocket-driver@npm:0.7.4" From dbf688c4295dc1242275e7729c775b1f24308e84 Mon Sep 17 00:00:00 2001 From: jnsereko <58003327+jnsereko@users.noreply.github.com> Date: Wed, 29 Oct 2025 08:13:12 +0300 Subject: [PATCH 31/35] Update packages/esm-patient-label-printing-app/src/config-schema.ts Co-authored-by: Dennis Kigen --- packages/esm-patient-label-printing-app/src/config-schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/esm-patient-label-printing-app/src/config-schema.ts b/packages/esm-patient-label-printing-app/src/config-schema.ts index 773297715e..4c0df275a4 100644 --- a/packages/esm-patient-label-printing-app/src/config-schema.ts +++ b/packages/esm-patient-label-printing-app/src/config-schema.ts @@ -4,7 +4,7 @@ export const configSchema = { showPrintIdentifierStickerButton: { _type: Type.Boolean, _description: "Whether to display the 'Print identifier sticker' button in the patient banner", - _default: true, + _default: false, }, }; From 97d46fb880c53c567130f7ccc523c6078ef27a55 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Wed, 29 Oct 2025 10:47:53 +0300 Subject: [PATCH 32/35] simplify PDF printer hook logic and cleanup --- .../src/hooks/useStickerPdfPrinter.tsx | 107 +++++------------- 1 file changed, 29 insertions(+), 78 deletions(-) diff --git a/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx index f6456e31af..43a0500238 100644 --- a/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx +++ b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.tsx @@ -5,7 +5,6 @@ export const useStickerPdfPrinter = () => { const { t } = useTranslation(); const iframeRef = useRef(null); const [isPrinting, setIsPrinting] = useState(false); - const cleanupRef = useRef<(() => void) | null>(null); const printPdf = useCallback( (url: string) => { @@ -13,11 +12,9 @@ export const useStickerPdfPrinter = () => { return Promise.reject(new Error(t('printInProgress', 'Print already in progress'))); } - return new Promise((resolve, reject) => { + return new Promise((resolve) => { setIsPrinting(true); - const sameOrigin = isSameOrigin(url); - if (!iframeRef.current) { const iframe = document.createElement('iframe'); iframe.name = 'pdfPrinterFrame'; @@ -35,105 +32,59 @@ export const useStickerPdfPrinter = () => { } const iframe = iframeRef.current; - let printCompleted = false; + let hasClosed = false; const handleLoad = () => { try { const contentWindow = iframe.contentWindow; + if (!contentWindow) throw new Error('No content window'); + + const cleanup = () => { + if (hasClosed) return; + hasClosed = true; + setIsPrinting(false); + resolve(); + }; - if (!contentWindow) { - throw new Error(t('failedToAccessPrintWindow', 'Failed to access print window')); + try { + contentWindow.addEventListener('afterprint', cleanup, { once: true }); + } catch (e) { + // Cross-origin, use polling fallback } contentWindow.focus(); contentWindow.print(); - if (sameOrigin) { - // Use afterprint event for same-origin - const afterPrintHandler = () => { - if (!printCompleted) { - printCompleted = true; - handlePrintComplete(); - } - }; - contentWindow.addEventListener('afterprint', afterPrintHandler); + let wasFocused = false; + const pollInterval = setInterval(() => { + const hasFocus = document.hasFocus(); + if (hasFocus && wasFocused) cleanup(); + if (!hasFocus) wasFocused = true; + }, 250); - cleanupRef.current = () => { - contentWindow.removeEventListener('afterprint', afterPrintHandler); - }; - } else { - setTimeout(() => { - if (!printCompleted) { - printCompleted = true; - handlePrintComplete(); - } - }, 500); - } + setTimeout(cleanup, 30000); + setTimeout(() => clearInterval(pollInterval), 30000); } catch (error) { - if (!printCompleted) { - printCompleted = true; - handlePrintError(error); - } + setIsPrinting(false); + resolve(); } }; - const handlePrintComplete = () => { - cleanup(); - resolve(); - }; - - const handlePrintError = (error: unknown) => { - cleanup(); - reject(error instanceof Error ? error : new Error(t('printingFailed', 'Printing failed'))); - }; - - const cleanup = () => { - iframe.onload = null; - iframe.onerror = null; - - if (cleanupRef.current) { - try { - cleanupRef.current(); - } catch { - // Ignore cleanup errors - } - cleanupRef.current = null; - } - + iframe.onload = handleLoad; + iframe.onerror = () => { setIsPrinting(false); + resolve(); }; - - iframe.onload = handleLoad; - iframe.onerror = () => handlePrintError(new Error(t('failedToLoadPDF', 'Failed to load PDF'))); - iframe.src = url; }); }, [t, isPrinting], ); - const isSameOrigin = (url: string): boolean => { - try { - const urlObj = new URL(url, window.location.href); - return urlObj.origin === window.location.origin; - } catch { - return false; - } - }; - useEffect(() => { return () => { - if (cleanupRef.current) { - try { - cleanupRef.current(); - } catch { - // Ignore cleanup errors - } - } - - if (iframeRef.current && document.body.contains(iframeRef.current)) { - document.body.removeChild(iframeRef.current); - iframeRef.current = null; + if (iframeRef.current?.parentNode) { + iframeRef.current.parentNode.removeChild(iframeRef.current); } }; }, []); From 5649405adfc1f4c9519b931b07013fad85337644 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Mon, 27 Oct 2025 14:41:50 +0300 Subject: [PATCH 33/35] Trigger CI/CD pipeline From 612f063356afba92e07e90a05b06426883a5a178 Mon Sep 17 00:00:00 2001 From: jnsereko Date: Mon, 27 Oct 2025 14:41:50 +0300 Subject: [PATCH 34/35] Trigger CI/CD pipeline From 8f383aac079bd13371226dbde5eb27e6115cafe9 Mon Sep 17 00:00:00 2001 From: Dennis Kigen Date: Thu, 20 Nov 2025 21:57:11 +0300 Subject: [PATCH 35/35] Improve label printing test coverage - Remove unnecessary setAttribute spy from PDF printer hook test - Add privilege verification test for print identifier button - Ensure UserHasAccess component is properly tested --- .../src/hooks/useStickerPdfPrinter.test.tsx | 237 ++++++++++++++++++ ...-identifier-sticker-action-button.test.tsx | 127 ++++++++++ 2 files changed, 364 insertions(+) create mode 100644 packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.test.tsx create mode 100644 packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.test.tsx diff --git a/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.test.tsx b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.test.tsx new file mode 100644 index 0000000000..95f29b2790 --- /dev/null +++ b/packages/esm-patient-label-printing-app/src/hooks/useStickerPdfPrinter.test.tsx @@ -0,0 +1,237 @@ +import { act, renderHook, waitFor } from '@testing-library/react'; +import { useStickerPdfPrinter } from './useStickerPdfPrinter'; + +describe('useStickerPdfPrinter', () => { + let mockContentWindow: any; + let afterPrintHandler: (() => void) | null = null; + + beforeEach(() => { + afterPrintHandler = null; + + // Create a mock contentWindow with all required methods + mockContentWindow = { + print: jest.fn(), + focus: jest.fn(), + addEventListener: jest.fn((event: string, handler: () => void) => { + if (event === 'afterprint') { + afterPrintHandler = handler; + } + }), + }; + + // Mock HTMLIFrameElement.prototype.contentWindow to return our mock + Object.defineProperty(HTMLIFrameElement.prototype, 'contentWindow', { + configurable: true, + get: () => mockContentWindow, + }); + + Object.defineProperty(HTMLIFrameElement.prototype, 'src', { + configurable: true, + set: function (value) { + this._src = value; + // Trigger onload asynchronously to simulate real behavior + if (this.onload) { + Promise.resolve().then(() => { + if (this.onload) { + this.onload({} as Event); + } + }); + } + }, + get: function () { + return this._src; + }, + }); + + // Mock document.hasFocus to support the polling mechanism + document.hasFocus = jest.fn().mockReturnValue(false); + }); + + afterEach(() => { + jest.restoreAllMocks(); + jest.useRealTimers(); + afterPrintHandler = null; + }); + + const waitForIframeLoad = () => { + // Wait for next tick to allow iframe onload to trigger + return new Promise((resolve) => setTimeout(resolve, 0)); + }; + + const triggerPrintCompletion = () => { + // Simulate the print dialog closing by triggering afterprint event + if (afterPrintHandler) { + afterPrintHandler(); + } + }; + + it('should provide printPdf function and isPrinting state', () => { + const { result } = renderHook(() => useStickerPdfPrinter()); + + expect(result.current.isPrinting).toBe(false); + expect(typeof result.current.printPdf).toBe('function'); + }); + + it('should set isPrinting to true when printing starts', () => { + const { result } = renderHook(() => useStickerPdfPrinter()); + + act(() => { + result.current.printPdf('http://example.com/test.pdf'); + }); + + expect(result.current.isPrinting).toBe(true); + }); + + it('should reject concurrent print requests with an error', async () => { + const { result } = renderHook(() => useStickerPdfPrinter()); + + act(() => { + result.current.printPdf('http://example.com/test.pdf'); + }); + + await expect(result.current.printPdf('http://example.com/test2.pdf')).rejects.toThrow('Print already in progress'); + }); + + it('should reset isPrinting to false when printing completes', async () => { + const { result } = renderHook(() => useStickerPdfPrinter()); + + act(() => { + result.current.printPdf('http://example.com/test.pdf'); + }); + + expect(result.current.isPrinting).toBe(true); + + // Wait for iframe to load + await act(async () => { + await waitForIframeLoad(); + }); + + // Simulate print completion + act(() => { + triggerPrintCompletion(); + }); + + await waitFor(() => { + expect(result.current.isPrinting).toBe(false); + }); + }); + + it('should return a promise that resolves when printing completes', async () => { + const { result } = renderHook(() => useStickerPdfPrinter()); + + let resolved = false; + let printPromise: Promise; + + act(() => { + printPromise = result.current.printPdf('http://example.com/test.pdf').then(() => { + resolved = true; + }); + }); + + expect(resolved).toBe(false); + + // Wait for iframe to load + await act(async () => { + await waitForIframeLoad(); + }); + + // Simulate print completion + act(() => { + triggerPrintCompletion(); + }); + + await waitFor(() => { + expect(resolved).toBe(true); + }); + + await printPromise!; + }); + + it('should allow printing again after previous print completes', async () => { + const { result } = renderHook(() => useStickerPdfPrinter()); + + // First print + act(() => { + result.current.printPdf('http://example.com/test1.pdf'); + }); + + await act(async () => { + await waitForIframeLoad(); + }); + + act(() => { + triggerPrintCompletion(); + }); + + await waitFor(() => { + expect(result.current.isPrinting).toBe(false); + }); + + // Second print should succeed + act(() => { + result.current.printPdf('http://example.com/test2.pdf'); + }); + + expect(result.current.isPrinting).toBe(true); + + await act(async () => { + await waitForIframeLoad(); + }); + + act(() => { + triggerPrintCompletion(); + }); + + await waitFor(() => { + expect(result.current.isPrinting).toBe(false); + }); + }); + + it('should reset isPrinting after timeout when print cannot be detected as complete', async () => { + jest.useFakeTimers(); + const { result } = renderHook(() => useStickerPdfPrinter()); + + act(() => { + result.current.printPdf('http://example.com/test.pdf'); + }); + + expect(result.current.isPrinting).toBe(true); + + // Fast-forward time to trigger iframe load, then advance past timeout + // The iframe onload will be triggered via Promise.resolve() which needs runAllTimers + await act(async () => { + await jest.runAllTimersAsync(); + }); + + // Verify timeout mechanism resets isPrinting (afterprint never fired) + expect(result.current.isPrinting).toBe(false); + }); + + it('should handle errors gracefully and reset isPrinting state', async () => { + // Mock contentWindow to return null to simulate an error + Object.defineProperty(HTMLIFrameElement.prototype, 'contentWindow', { + configurable: true, + get: () => null, + }); + + const { result } = renderHook(() => useStickerPdfPrinter()); + + let resolved = false; + act(() => { + result.current.printPdf('http://example.com/test.pdf').then(() => { + resolved = true; + }); + }); + + // Wait for iframe to attempt loading and trigger error path + await act(async () => { + await waitForIframeLoad(); + }); + + await waitFor(() => { + expect(result.current.isPrinting).toBe(false); + }); + + expect(resolved).toBe(true); + }); +}); diff --git a/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.test.tsx b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.test.tsx new file mode 100644 index 0000000000..4e6a061404 --- /dev/null +++ b/packages/esm-patient-label-printing-app/src/print-identifier-sticker/print-identifier-sticker-action-button.test.tsx @@ -0,0 +1,127 @@ +import React from 'react'; +import userEvent from '@testing-library/user-event'; +import { screen } from '@testing-library/react'; +import { getDefaultsFromConfigSchema, showSnackbar, useConfig, UserHasAccess } from '@openmrs/esm-framework'; +import { mockFhirPatient } from '__mocks__'; +import { renderWithSwr } from 'tools'; +import { useStickerPdfPrinter } from '../hooks/useStickerPdfPrinter'; +import { configSchema, type ConfigObject } from '../config-schema'; +import PrintIdentifierStickerOverflowMenuItem from './print-identifier-sticker-action-button.component'; + +jest.mock('../hooks/useStickerPdfPrinter'); +jest.mock('@openmrs/esm-framework', () => ({ + ...jest.requireActual('@openmrs/esm-framework'), + UserHasAccess: jest.fn(({ children }) => children), +})); + +const mockUseConfig = jest.mocked(useConfig); +const mockShowSnackbar = jest.mocked(showSnackbar); +const mockUseStickerPdfPrinter = jest.mocked(useStickerPdfPrinter); +const mockUserHasAccess = jest.mocked(UserHasAccess); +const mockPrintPdf = jest.fn(); + +describe('PrintIdentifierStickerOverflowMenuItem', () => { + beforeEach(() => { + mockUseConfig.mockReturnValue({ + ...getDefaultsFromConfigSchema(configSchema), + showPrintIdentifierStickerButton: true, + } as ConfigObject); + mockPrintPdf.mockResolvedValue(undefined); + mockUseStickerPdfPrinter.mockReturnValue({ + printPdf: mockPrintPdf, + isPrinting: false, + }); + }); + + it('renders the print button when enabled in config', () => { + renderWithSwr(); + + expect(screen.getByRole('menuitem', { name: /print identifier sticker/i })).toBeInTheDocument(); + }); + + it('does not render the button when disabled in config', () => { + mockUseConfig.mockReturnValue({ + ...getDefaultsFromConfigSchema(configSchema), + showPrintIdentifierStickerButton: false, + } as ConfigObject); + + renderWithSwr(); + + expect(screen.queryByRole('menuitem', { name: /print identifier sticker/i })).not.toBeInTheDocument(); + }); + + it('does not render the button when patient ID is missing', () => { + const patientWithoutId = { ...mockFhirPatient, id: undefined } as fhir.Patient; + + renderWithSwr(); + + expect(screen.queryByRole('menuitem', { name: /print identifier sticker/i })).not.toBeInTheDocument(); + }); + + it('triggers print when button is clicked', async () => { + const user = userEvent.setup(); + renderWithSwr(); + + const printButton = screen.getByRole('menuitem', { name: /print identifier sticker/i }); + await user.click(printButton); + + expect(mockPrintPdf).toHaveBeenCalledTimes(1); + expect(mockPrintPdf).toHaveBeenCalledWith(expect.stringContaining(mockFhirPatient.id)); + }); + + it('shows error notification when print fails', async () => { + const user = userEvent.setup(); + const errorMessage = 'Network error'; + mockPrintPdf.mockRejectedValueOnce(new Error(errorMessage)); + + renderWithSwr(); + + const printButton = screen.getByRole('menuitem', { name: /print identifier sticker/i }); + await user.click(printButton); + + expect(mockShowSnackbar).toHaveBeenCalledWith({ + kind: 'error', + title: 'Print error', + subtitle: expect.stringContaining(errorMessage), + }); + }); + + it('shows loading state when printing', () => { + mockUseStickerPdfPrinter.mockReturnValue({ + printPdf: mockPrintPdf, + isPrinting: true, + }); + + renderWithSwr(); + + const printButton = screen.getByRole('menuitem', { name: /printing/i }); + expect(printButton).toBeInTheDocument(); + expect(printButton).toBeDisabled(); + }); + + it('prevents multiple print calls when already printing', async () => { + const user = userEvent.setup(); + mockUseStickerPdfPrinter.mockReturnValue({ + printPdf: mockPrintPdf, + isPrinting: true, + }); + + renderWithSwr(); + + const printButton = screen.getByRole('menuitem', { name: /printing/i }); + await user.click(printButton); + + expect(mockPrintPdf).not.toHaveBeenCalled(); + }); + + it('checks for the correct privilege when rendering', () => { + renderWithSwr(); + + expect(mockUserHasAccess).toHaveBeenCalledWith( + expect.objectContaining({ + privilege: 'App: Can generate a Patient Identity Sticker', + }), + expect.anything(), + ); + }); +});