diff --git a/packages/esm-form-engine-app/translations/zh.json b/packages/esm-form-engine-app/translations/zh.json new file mode 100644 index 0000000000..bb79ccad1c --- /dev/null +++ b/packages/esm-form-engine-app/translations/zh.json @@ -0,0 +1,8 @@ +{ + "closeThisPanel": "Close this panel", + "errorTitle": "There was an error with this form", + "loading": "Loading", + "or": "or", + "thisList": "this list", + "tryAgainMessage": "Try opening another form from" +} diff --git a/packages/esm-form-engine-app/translations/zh_CN.json b/packages/esm-form-engine-app/translations/zh_CN.json new file mode 100644 index 0000000000..bb79ccad1c --- /dev/null +++ b/packages/esm-form-engine-app/translations/zh_CN.json @@ -0,0 +1,8 @@ +{ + "closeThisPanel": "Close this panel", + "errorTitle": "There was an error with this form", + "loading": "Loading", + "or": "or", + "thisList": "this list", + "tryAgainMessage": "Try opening another form from" +} diff --git a/packages/esm-patient-attachments-app/src/assets/placeholder.svg b/packages/esm-patient-attachments-app/src/assets/placeholder.svg index 9e274ab8c6..e6cc8968b8 100644 --- a/packages/esm-patient-attachments-app/src/assets/placeholder.svg +++ b/packages/esm-patient-attachments-app/src/assets/placeholder.svg @@ -1,6 +1,6 @@ - + - - + + - + \ No newline at end of file diff --git a/packages/esm-patient-attachments-app/src/camera-media-uploader/capture-photo.component.tsx b/packages/esm-patient-attachments-app/src/camera-media-uploader/capture-photo.component.tsx index 0f80b27a62..73e4434e12 100644 --- a/packages/esm-patient-attachments-app/src/camera-media-uploader/capture-photo.component.tsx +++ b/packages/esm-patient-attachments-app/src/camera-media-uploader/capture-photo.component.tsx @@ -4,6 +4,7 @@ import { Button } from '@carbon/react'; import { showModal, toOmrsIsoString } from '@openmrs/esm-framework'; import placeholder from '../assets/placeholder.svg'; import { type UploadedFile } from '../attachments-types'; +import styles from './capture-photo.scss'; export interface CapturePhotoProps { onCapturePhoto(dataUri: string, photoDateTime: string): void; @@ -31,9 +32,9 @@ const CapturePhoto: React.FC = ({ initialState, onCapturePhot return (
-
+
+ diff --git a/packages/esm-patient-attachments-app/src/camera-media-uploader/capture-photo.scss b/packages/esm-patient-attachments-app/src/camera-media-uploader/capture-photo.scss new file mode 100644 index 0000000000..c11b1227ea --- /dev/null +++ b/packages/esm-patient-attachments-app/src/camera-media-uploader/capture-photo.scss @@ -0,0 +1,8 @@ +.buttonCssReset { + max-width: 64px; + padding: 0; + margin: 0; + border: none; + background: none; + cursor: pointer; +} diff --git a/packages/esm-patient-banner-app/src/banner/patient-banner.test.tsx b/packages/esm-patient-banner-app/src/banner/patient-banner.test.tsx index bc1ef838e8..ac1220e9e4 100644 --- a/packages/esm-patient-banner-app/src/banner/patient-banner.test.tsx +++ b/packages/esm-patient-banner-app/src/banner/patient-banner.test.tsx @@ -1,9 +1,12 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import { render, screen } from '@testing-library/react'; -import { useConnectedExtensions } from '@openmrs/esm-framework'; -import { mockPatient } from 'tools'; import PatientBanner from './patient-banner.component'; +import { mockPatient } from 'tools'; +import { defineConfigSchema, useConnectedExtensions } from '@openmrs/esm-framework'; +import { configSchema } from '../config-schema'; + +defineConfigSchema('@openmrs/esm-patient-banner-app', configSchema); class ResizeObserverMock { callback: any; @@ -27,17 +30,10 @@ const testProps = { const mockNavigateTo = jest.fn(); const mockUseConnectedExtensions = useConnectedExtensions as jest.Mock; -jest.mock('@openmrs/esm-framework', () => ({ - ...(jest.requireActual('@openmrs/esm-framework') as any), - useVisit: jest.fn(), - age: jest.fn(), - Breakpoint: { TABLET_MAX: 1023 }, - useConnectedExtensions: jest.fn(() => [{}, {}]), -})); - describe('PatientBanner: ', () => { it('renders information about a patient in a banner above the patient chart', () => { window.ResizeObserver = ResizeObserverMock; + mockUseConnectedExtensions.mockReturnValue([{ id: 'Some action extension' }]); renderPatientBanner(); @@ -53,7 +49,7 @@ describe('PatientBanner: ', () => { expect(screen.getByRole('button', { name: /^Show details$/i })).toBeInTheDocument(); }); - it('shoulld not render actions menu if no actions connected', () => { + it('should not render actions menu if no actions connected', () => { window.ResizeObserver = ResizeObserverMock; mockUseConnectedExtensions.mockReturnValue([]); // override the default mock to one that returns an empty array diff --git a/packages/esm-patient-banner-app/src/config-schema.ts b/packages/esm-patient-banner-app/src/config-schema.ts index 66c69203a9..07e11570ae 100644 --- a/packages/esm-patient-banner-app/src/config-schema.ts +++ b/packages/esm-patient-banner-app/src/config-schema.ts @@ -1,43 +1,34 @@ import { Type } from '@openmrs/esm-framework'; export const configSchema = { - contactAttributeType: { - _type: Type.UUID, - _description: - 'The Uuids of person attribute-type that captures contact information `e.g Next of kin contact details`', + contactAttributeTypes: { + _type: Type.Array, + _description: 'The UUIDs of person attribute types that capture contact information', _default: [], + _elements: { + _type: Type.UUID, + }, }, excludePatientIdentifierCodeTypes: { uuids: { _type: Type.Array, - _description: 'The Uuids of patient identifier types that should be excluded from patient banner.', + _description: 'The UUIDs of patient identifier types that should be excluded from patient banner.', _default: [], - }, - }, - useCustomAddressLabel: { - enabled: { - _type: Type.Boolean, - _description: 'whether to enable using custom address labels', - _default: false, - }, - customAddressLabel: { - _type: Type.Object, - _description: 'custom labels for addresses', - _default: {}, + _elements: { + _type: Type.UUID, + }, }, }, useRelationshipNameLink: { _type: Type.Boolean, - _description: 'Enable the use of a link to the patient chart in relationship names', + _description: "Whether to use the relationship name as a link to the person's patient chart", _default: false, }, }; export interface ConfigObject { - contactAttributeType: Array; - useCustomAddressLabel: { - enabled: boolean; - customAddressLabel: Object; - }; + contactAttributeTypes: Array; + excludePatientIdentifierCodeTypes: Array; + customAddressLabels: Object; useRelationshipNameLink: boolean; } diff --git a/packages/esm-patient-banner-app/src/contact-details/contact-details.component.tsx b/packages/esm-patient-banner-app/src/contact-details/contact-details.component.tsx index 7c6891ea39..478606ddd5 100644 --- a/packages/esm-patient-banner-app/src/contact-details/contact-details.component.tsx +++ b/packages/esm-patient-banner-app/src/contact-details/contact-details.component.tsx @@ -1,12 +1,12 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { InlineLoading } from '@carbon/react'; import { ConfigurableLink, parseDate, useConfig } from '@openmrs/esm-framework'; -import { type ConfigObject } from '../config-schema'; import { useRelationships } from './relationships.resource'; import { usePatientContactAttributes } from '../hooks/usePatientAttributes'; import { usePatientListsForPatient } from '../hooks/usePatientListsForPatient'; import styles from './contact-details.scss'; +import { type ConfigObject } from '../config-schema'; interface ContactDetailsProps { address: Array; @@ -62,10 +62,6 @@ const PatientLists: React.FC<{ patientUuid: string }> = ({ patientUuid }) => { const Address: React.FC<{ address?: fhir.Address }> = ({ address }) => { const { t } = useTranslation(); - const { useCustomAddressLabel } = useConfig(); - const useCustomAddressLabelEnabled = useCustomAddressLabel?.enabled; - const customAddressLabel = useCustomAddressLabel?.customAddressLabel; - const getAddressKey = (url) => url.split('#')[1]; /* DO NOT REMOVE THIS COMMENT UNLESS YOU UNDERSTAND WHY IT IS HERE @@ -90,20 +86,19 @@ const Address: React.FC<{ address?: fhir.Address }> = ({ address }) => { {address ? ( {Object.entries(address) - .filter(([key]) => !['use', 'id'].some((k) => k === key)) + .filter(([key]) => !['use', 'id'].includes(key)) .map(([key, value]) => key === 'extension' ? ( - address?.extension[0]?.extension.map((add, i) => ( -
  • - {useCustomAddressLabelEnabled - ? t(customAddressLabel[getAddressKey(add.url)]) - : t(getAddressKey(add.url))} - : {add.valueString} -
  • - )) + address?.extension[0]?.extension.map((add, i) => { + return ( +
  • + {t(getAddressKey(add.url), getAddressKey(add.url))}: {add.valueString} +
  • + ); + }) ) : (
  • - {useCustomAddressLabelEnabled ? t(customAddressLabel[key]) : t(key)}: {value} + {t(key, key)}: {value}
  • ), )} @@ -121,9 +116,19 @@ const Contact: React.FC<{ telecom: Array; patientUuid: string patientUuid, }) => { const { t } = useTranslation(); - const value = telecom?.length ? telecom[0].value : '--'; const { isLoading, contactAttributes } = usePatientContactAttributes(patientUuid); + const contacts = useMemo( + () => [ + ...telecom?.map((contact) => [t(contact.system, contact.system), contact.value]), + ...contactAttributes?.map((contact) => [ + t(contact.attributeType.display, contact.attributeType.display), + contact.value, + ]), + ], + [telecom, contactAttributes], + ); + return ( <>

    {t('contactDetails', 'Contact Details')}

    @@ -131,16 +136,12 @@ const Contact: React.FC<{ telecom: Array; patientUuid: string ) : (
      - {value ? ( - -
    • {value}
    • - {contactAttributes?.length > 0 && - contactAttributes.map(({ attributeType, value, uuid }) => ( -
    • - {attributeType.display}: {value} -
    • - ))} -
      + {contacts.length ? ( + contacts.map(([label, value], index) => ( +
    • + {label}: {value} +
    • + )) ) : (
    • --
    • )} @@ -153,16 +154,7 @@ const Contact: React.FC<{ telecom: Array; patientUuid: string const Relationships: React.FC<{ patientId: string }> = ({ patientId }) => { const { t } = useTranslation(); const { data: relationships, isLoading } = useRelationships(patientId); - const config = useConfig(); - - const extractName = (display: string) => { - const pattern = /-\s*(.*)$/; - const match = display.match(pattern); - if (match && match.length > 1) { - return match[1].trim(); - } - return display.trim(); - }; + const config = useConfig(); return ( <> @@ -183,7 +175,7 @@ const Relationships: React.FC<{ patientId: string }> = ({ patientId }) => { {r.display} ) : ( -
      {extractName(r.display)}
      +
      {r.name}
      )}
      {r.relationshipType}
      diff --git a/packages/esm-patient-banner-app/src/contact-details/contact-details.test.tsx b/packages/esm-patient-banner-app/src/contact-details/contact-details.test.tsx index 1819102e30..25d6560895 100644 --- a/packages/esm-patient-banner-app/src/contact-details/contact-details.test.tsx +++ b/packages/esm-patient-banner-app/src/contact-details/contact-details.test.tsx @@ -1,14 +1,19 @@ import React from 'react'; import { screen } from '@testing-library/react'; -import { openmrsFetch } from '@openmrs/esm-framework'; import { renderWithSwr, waitForLoadingToFinish } from 'tools'; import { usePatientAttributes, usePatientContactAttributes } from '../hooks/usePatientAttributes'; import { usePatientListsForPatient } from '../hooks/usePatientListsForPatient'; +import { useRelationships } from './relationships.resource'; import ContactDetails from './contact-details.component'; +import { defineConfigSchema } from '@openmrs/esm-framework'; +import { configSchema } from '../config-schema'; + +defineConfigSchema('@openmrs/esm-patient-banner-app', configSchema); const mockedUsePatientAttributes = usePatientAttributes as jest.Mock; const mockedUsePatientContactAttributes = usePatientContactAttributes as jest.Mock; const mockUsePatientListsForPatient = usePatientListsForPatient as jest.Mock; +const mockUseRelationships = useRelationships as jest.Mock; const testProps = { address: [ @@ -21,7 +26,7 @@ const testProps = { use: 'home', }, ], - telecom: [{ value: '+0123456789' }], + telecom: [{ system: 'Cellular', value: '+0123456789' }], patientId: '1111', deceased: false, isTabletViewport: false, @@ -29,25 +34,12 @@ const testProps = { const mockRelationships = [ { - display: 'Amanda is the Sibling of John', + display: '100ADT - Amanda Robinson', + name: 'Amanda Robinson', + relationshipType: 'Sibling', + relativeAge: 24, + relativeUuid: '07006bcb-91d4-4c57-a5f7-49751899d9b5', uuid: '993bc79d-5ca5-4c76-b4b3-adf49e25bd0b', - personA: { - uuid: '07006bcb-91d4-4c57-a5f7-49751899d9b5', - display: '100ADT - Amanda Robinson', - age: 24, - }, - personB: { - uuid: '8673ee4f-e2ab-4077-ba55-4980f408773e', - display: '100GEJ - John Wilson', - age: 49, - }, - relationshipType: { - uuid: '8d91a01c-c2cc-11de-8d13-0010c6dffd0f', - display: 'Sibling/Sibling', - description: 'Relationship between brother/sister, brother/brother, and sister/sister', - aIsToB: 'Sibling', - bIsToA: 'Sibling', - }, }, ]; @@ -89,7 +81,6 @@ const mockCohorts = [ endDate: null, }, ]; -const mockOpenmrsFetch = openmrsFetch as jest.Mock; jest.mock('../hooks/usePatientAttributes', () => ({ usePatientAttributes: jest.fn(), @@ -100,25 +91,46 @@ jest.mock('../hooks/usePatientListsForPatient', () => ({ usePatientListsForPatient: jest.fn(), })); +jest.mock('./relationships.resource', () => ({ + useRelationships: jest.fn(), +})); + describe('ContactDetails', () => { - it("renders the patient's address, contact details, patient lists, and relationships when available", async () => { + afterEach(() => { mockedUsePatientAttributes.mockReturnValue({ isLoading: false, attributes: [], error: null, }); + mockedUsePatientContactAttributes.mockReturnValue({ + isLoading: false, + contactAttributes: [], + }); + mockUsePatientListsForPatient.mockReturnValue({ + isLoading: false, + cohorts: [], + }); + mockUseRelationships.mockReturnValue({ + isLoading: false, + data: [], + }); + }); - mockedUsePatientContactAttributes.mockReturnValueOnce({ + it("renders the patient's address, contact details, patient lists, and relationships when available", async () => { + mockedUsePatientContactAttributes.mockReturnValue({ isLoading: false, contactAttributes: mockPersonAttributes, }); - mockUsePatientListsForPatient.mockReturnValueOnce({ + mockUsePatientListsForPatient.mockReturnValue({ isLoading: false, cohorts: mockCohorts, }); - mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockRelationships } }); + mockUseRelationships.mockReturnValue({ + isLoading: false, + data: mockRelationships, + }); renderContactDetails(); @@ -139,18 +151,15 @@ describe('ContactDetails', () => { }); it('renders the contact details with 2 columns if banner width is small', async () => { - mockedUsePatientAttributes.mockReturnValue({ - isLoading: false, - attributes: [], - error: null, - }); - mockedUsePatientContactAttributes.mockReturnValueOnce({ isLoading: false, contactAttributes: mockPersonAttributes, }); - mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockRelationships } }); + mockUseRelationships.mockReturnValue({ + isLoading: false, + data: mockRelationships, + }); mockUsePatientListsForPatient.mockReturnValueOnce({ isLoading: false, @@ -175,12 +184,6 @@ describe('ContactDetails', () => { }); it('renders the contact details with 4 colummns if banner width is large', async () => { - mockedUsePatientAttributes.mockReturnValue({ - isLoading: false, - attributes: [], - error: null, - }); - mockedUsePatientContactAttributes.mockReturnValueOnce({ isLoading: false, contactAttributes: mockPersonAttributes, @@ -191,7 +194,11 @@ describe('ContactDetails', () => { cohorts: mockCohorts, }); - mockOpenmrsFetch.mockReturnValueOnce({ data: { results: mockRelationships } }); + mockUseRelationships.mockReturnValue({ + isLoading: false, + data: mockRelationships, + }); + const props = { ...testProps, isTabletViewport: false }; const { container } = renderWithSwr(); @@ -210,32 +217,8 @@ describe('ContactDetails', () => { }); it('renders an empty state view when contact details, relations, patient lists and addresses are not available', async () => { - mockedUsePatientAttributes.mockReturnValue({ - isLoading: false, - attributes: [], - error: null, - }); - - mockedUsePatientContactAttributes.mockReturnValueOnce({ - isLoading: false, - contactAttributes: [], - }); - - mockUsePatientListsForPatient.mockReturnValueOnce({ - isLoading: false, - cohorts: [], - }); - - mockOpenmrsFetch.mockReturnValueOnce({ data: { results: [] } }); - renderWithSwr( - , + , ); await waitForLoadingToFinish(); diff --git a/packages/esm-patient-banner-app/src/contact-details/relationships.resource.tsx b/packages/esm-patient-banner-app/src/contact-details/relationships.resource.tsx index daee9045f1..d436306d87 100644 --- a/packages/esm-patient-banner-app/src/contact-details/relationships.resource.tsx +++ b/packages/esm-patient-banner-app/src/contact-details/relationships.resource.tsx @@ -33,6 +33,7 @@ function extractRelationshipData( if (patientIdentifier === r.personA.uuid) { relationshipsData.push({ uuid: r.uuid, + name: extractName(r.personB.display), display: r.personB.display, relativeAge: r.personB.age, relativeUuid: r.personB.uuid, @@ -41,6 +42,7 @@ function extractRelationshipData( } else { relationshipsData.push({ uuid: r.uuid, + name: extractName(r.personA.display), display: r.personA.display, relativeAge: r.personA.age, relativeUuid: r.personA.uuid, @@ -51,12 +53,22 @@ function extractRelationshipData( return relationshipsData; } +const extractName = (display: string) => { + const pattern = /-\s*(.*)$/; + const match = display.match(pattern); + if (match && match.length > 1) { + return match[1].trim(); + } + return display.trim(); +}; + interface RelationshipsResponse { results: Array; } interface ExtractedRelationship { uuid: string; + name: string; display: string; relativeAge: number; relativeUuid: string; diff --git a/packages/esm-patient-banner-app/src/hooks/usePatientAttributes.ts b/packages/esm-patient-banner-app/src/hooks/usePatientAttributes.ts index 6360c7f62f..8d6ac22096 100644 --- a/packages/esm-patient-banner-app/src/hooks/usePatientAttributes.ts +++ b/packages/esm-patient-banner-app/src/hooks/usePatientAttributes.ts @@ -7,13 +7,15 @@ const customRepresentation = 'custom:(uuid,display,identifiers:(identifier,uuid,preferred,location:(uuid,name),identifierType:(uuid,name,format,formatDescription,validator)),person:(uuid,display,gender,birthdate,dead,age,deathDate,birthdateEstimated,causeOfDeath,preferredName:(uuid,preferred,givenName,middleName,familyName),attributes,preferredAddress:(uuid,preferred,address1,address2,cityVillage,longitude,stateProvince,latitude,country,postalCode,countyDistrict,address3,address4,address5,address6,address7)))'; /** - * React hook that takes patientUuid and return Patient Attributes {@link Attribute} - * @param patientUuid Unique Patient identifier - * @returns Object containing `patient-attributes`, `isLoading` loading status, `error` + * React hook for obtaining patient attributes for a given patient {@link Attribute} + * + * If `patientUuid` is null, the hook does nothing. + * + * @param patientUuid The patient's UUID */ -export const usePatientAttributes = (patientUuid: string) => { +export const usePatientAttributes = (patientUuid: string | null) => { const { data, error, isLoading } = useSWRImmutable<{ data: Patient }>( - `/ws/rest/v1/patient/${patientUuid}?v=${customRepresentation}`, + patientUuid ? `/ws/rest/v1/patient/${patientUuid}?v=${customRepresentation}` : null, openmrsFetch, ); @@ -32,10 +34,10 @@ export const usePatientAttributes = (patientUuid: string) => { * @returns Object containing `contactAttribute` {@link Attribute} loading status */ export const usePatientContactAttributes = (patientUuid: string) => { - const { contactAttributeType } = useConfig() as ConfigObject; - const { attributes, isLoading } = usePatientAttributes(patientUuid); - const contactAttributes = attributes?.filter( - ({ attributeType }) => contactAttributeType?.some((uuid) => attributeType?.uuid === uuid), + const { contactAttributeTypes } = useConfig() as ConfigObject; + const { attributes, isLoading } = usePatientAttributes(contactAttributeTypes.length ? patientUuid : null); + const contactAttributes = attributes?.filter(({ attributeType }) => + contactAttributeTypes.includes(attributeType?.uuid), ); return { contactAttributes: contactAttributes ?? [], diff --git a/packages/esm-patient-banner-app/translations/zh_CN.json b/packages/esm-patient-banner-app/translations/zh_CN.json index 5749bafb56..feffc78f8e 100644 --- a/packages/esm-patient-banner-app/translations/zh_CN.json +++ b/packages/esm-patient-banner-app/translations/zh_CN.json @@ -19,8 +19,6 @@ "patientLists": "患者列表", "postalCode": "邮政编码", "relationships": "关系", - "seeMoreLists_one": "查看另外 {{count}} 个列表", - "seeMoreLists_other": "查看另外 {{count}} 个列表", "showDetails": "显示详情", "started": "已开始", "state": "省份", diff --git a/packages/esm-patient-chart-app/src/config-schema.ts b/packages/esm-patient-chart-app/src/config-schema.ts index f5de8e3394..5fb927b715 100644 --- a/packages/esm-patient-chart-app/src/config-schema.ts +++ b/packages/esm-patient-chart-app/src/config-schema.ts @@ -119,7 +119,6 @@ export const esmPatientChartSchema = { _default: false, }, }; - export interface ChartConfig { offlineVisitTypeUuid: string; visitTypeResourceUrl: string; @@ -142,16 +141,3 @@ export interface ChartConfig { }; disableChangingVisitLocation: boolean; } - -export const configSchema = { - contactAttributeType: { - _type: Type.UUID, - _description: - 'The Uuids of person attribute-type that captures contact information `e.g Next of kin contact details`', - _default: [], - }, -}; - -export interface ConfigObject { - contactAttributeType: Array; -} diff --git a/packages/esm-patient-chart-app/src/visit-header/close-button.component.tsx b/packages/esm-patient-chart-app/src/visit-header/close-button.component.tsx new file mode 100644 index 0000000000..c74d025b8a --- /dev/null +++ b/packages/esm-patient-chart-app/src/visit-header/close-button.component.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { HeaderGlobalAction } from '@carbon/react'; +import { CloseFilled } from '@carbon/react/icons'; +import { getHistory, goBackInHistory, navigate, usePatient } from '@openmrs/esm-framework'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import styles from './close-button.scss'; + +export function CloseButton() { + const { t } = useTranslation(); + const { patientUuid } = usePatient(); + + const onClosePatientChart = useCallback(() => { + const history = getHistory(); + // Get the last page the user was on before opening the patient chart by going backward + // through the history until a URL does not include patientUuid + let onCloseTarget = ''; + for (let i = history.length - 1; i >= 0; i--) { + if (!history[i].includes(patientUuid)) { + onCloseTarget = history[i]; + break; + } + } + if (onCloseTarget) { + goBackInHistory({ toUrl: onCloseTarget }); + } else { + navigate({ to: '${openmrsSpaBase}/home' }); + } + }, [patientUuid]); + + return ( + + + + ); +} diff --git a/packages/esm-patient-chart-app/src/visit-header/close-button.scss b/packages/esm-patient-chart-app/src/visit-header/close-button.scss new file mode 100644 index 0000000000..c283e3ad11 --- /dev/null +++ b/packages/esm-patient-chart-app/src/visit-header/close-button.scss @@ -0,0 +1,5 @@ +@import '~@openmrs/esm-styleguide/src/vars'; + +.headerGlobalBarCloseButton { + @include brand-02(background-color); +} \ No newline at end of file diff --git a/packages/esm-patient-chart-app/src/visit-header/visit-header.component.tsx b/packages/esm-patient-chart-app/src/visit-header/visit-header.component.tsx index cf917acb9f..1cbdef46ab 100644 --- a/packages/esm-patient-chart-app/src/visit-header/visit-header.component.tsx +++ b/packages/esm-patient-chart-app/src/visit-header/visit-header.component.tsx @@ -1,7 +1,6 @@ import React, { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Button, Header, HeaderGlobalAction, HeaderGlobalBar, HeaderMenuButton, Tag, Tooltip } from '@carbon/react'; -import { CloseFilled } from '@carbon/react/icons'; +import { Button, Header, HeaderGlobalBar, HeaderMenuButton, Tag, Tooltip } from '@carbon/react'; import { age, ConfigurableLink, @@ -9,7 +8,6 @@ import { useLayoutType, usePatient, useVisit, - navigate, useConfig, showModal, ExtensionSlot, @@ -21,6 +19,7 @@ import { EditQueueEntry } from '../visit/queue-entry/edit-queue-entry.component' import VisitHeaderSideMenu from './visit-header-side-menu.component'; import styles from './visit-header.scss'; import RetrospectiveVisitLabel from './retrospective-visit-label.component'; +import { CloseButton } from './close-button.component'; interface PatientInfoProps { patient: fhir.Patient; @@ -139,10 +138,6 @@ const VisitHeader: React.FC = () => { const toggleSideMenu = useCallback(() => setIsSideMenuExpanded((prevState) => !prevState), []); - const onClosePatientChart = useCallback(() => { - document.referrer === '' ? navigate({ to: `${window.spaBase}/home` }) : window.history.back(); - }, []); - const openModal = useCallback((patientUuid) => { const dispose = showModal('end-visit-dialog', { closeModal: () => dispose(), @@ -198,13 +193,7 @@ const VisitHeader: React.FC = () => { )} )} - - - + diff --git a/packages/esm-patient-chart-app/src/visit-header/visit-header.scss b/packages/esm-patient-chart-app/src/visit-header/visit-header.scss index 7397c78cdc..ef20957847 100644 --- a/packages/esm-patient-chart-app/src/visit-header/visit-header.scss +++ b/packages/esm-patient-chart-app/src/visit-header/visit-header.scss @@ -8,10 +8,6 @@ @include brand-02(background-color); } -.headerGlobalBarCloseButton { - @include brand-02(background-color); -} - .headerName { display: flex; } diff --git a/packages/esm-patient-chart-app/src/visit-header/visit-header.test.tsx b/packages/esm-patient-chart-app/src/visit-header/visit-header.test.tsx index b69f43a189..c520095769 100644 --- a/packages/esm-patient-chart-app/src/visit-header/visit-header.test.tsx +++ b/packages/esm-patient-chart-app/src/visit-header/visit-header.test.tsx @@ -9,6 +9,9 @@ import { useVisit, navigate, showModal, + getHistory, + goBackInHistory, + age, } from '@openmrs/esm-framework'; import { registerWorkspace, launchPatientWorkspace } from '@openmrs/esm-patient-common-lib'; import { mockPatient, mockPatientWithLongName, getByTextWithMarkup } from 'tools'; @@ -19,26 +22,21 @@ const mockUseAssignedExtensions = useAssignedExtensions as jest.Mock; const mockUsePatient = usePatient as jest.Mock; const mockUseVisit = useVisit as jest.Mock; const mockUseLayoutType = useLayoutType as jest.Mock; -const mockExtensionRegistry = {}; const mockShowModal = showModal as jest.Mock; -const mockNavigateBack = jest.fn(); +const mockGetHistory = getHistory as jest.Mock; +const mockGoBackInHistory = goBackInHistory as jest.Mock; jest.mock('@openmrs/esm-framework', () => { const originalModule = jest.requireActual('@openmrs/esm-framework'); return { ...originalModule, - usePatient: jest.fn(), - useAssignedExtensions: jest.fn(), - age: jest.fn(() => 20), + age: jest.fn().mockReturnValue('20'), + getHistory: jest.fn(() => []), + goBackInHistory: jest.fn(), LeftNavMenu: jest.fn().mockImplementation(() =>
      Left Nav Menu
      ), - useVisit: jest.fn(), - registerExtension: (ext) => { - mockExtensionRegistry[ext.name] = ext; - }, - getExtensionRegistration: (name) => mockExtensionRegistry[name], translateFrom: (module, key, defaultValue, options) => defaultValue, + useAssignedExtensions: jest.fn(), useOnClickOutside: jest.fn(), - showModal: jest.fn(), }; }); @@ -47,20 +45,19 @@ jest.mock('@openmrs/esm-patient-common-lib', () => { return { ...originalModule, launchPatientWorkspace: jest.fn(), - navigate: jest.fn(), }; }); describe('Visit Header', () => { beforeEach(() => { - window.history.back = mockNavigateBack; + mockUseAssignedExtensions.mockReturnValue([{ id: 'someId' }]); + mockGoBackInHistory.mockClear(); }); test('should display visit header and left nav bar hamburger icon', async () => { const user = userEvent.setup(); registerWorkspace({ name: 'start-visit-workspace-form', title: 'Start visit', load: jest.fn() }); - mockUseAssignedExtensions.mockReturnValue([{ id: 'someId' }]); mockUsePatient.mockReturnValue({ patient: mockPatient, isLoading: false, @@ -70,7 +67,7 @@ describe('Visit Header', () => { mockUseVisit.mockReturnValue({ isValidating: null, currentVisit: null }); mockUseLayoutType.mockReturnValue('tablet'); - renderVisitHeader(); + render(); const headerBanner = screen.getByRole('banner', { name: /OpenMRS/i }); expect(headerBanner).toBeInTheDocument(); @@ -96,25 +93,10 @@ describe('Visit Header', () => { expect(startVisitButton).toBeInTheDocument(); await user.click(startVisitButton); - expect(launchPatientWorkspace).toHaveBeenCalled(); expect(launchPatientWorkspace).toHaveBeenCalledWith('start-visit-workspace-form'); - - const closeButton = screen.getByRole('button', { name: 'Close' }); - expect(closeButton).toBeInTheDocument(); - - // Should close the visit-header - await user.click(closeButton); - expect(navigate).toHaveBeenCalledWith({ to: '/spa/home' }); - expect(window.history.back).not.toHaveBeenCalled(); - - Object.defineProperty(document, 'referrer', { value: 'some-uuid', configurable: true }); - await user.click(closeButton); - expect(window.history.back).toHaveBeenCalled(); - expect(mockNavigateBack).toHaveBeenCalled(); }); test('should display a truncated name when the patient name is very long', async () => { - mockUseAssignedExtensions.mockReturnValue([{ id: 'someId' }]); mockUsePatient.mockReturnValue({ patient: mockPatientWithLongName, isLoading: false, @@ -124,7 +106,7 @@ describe('Visit Header', () => { mockUseVisit.mockReturnValue({ isValidating: null, currentVisit: null }); mockUseLayoutType.mockReturnValue('desktop'); - renderVisitHeader(); + render(); const longNameText = screen.getByText(/^Some very long given name...$/i); expect(longNameText).toBeInTheDocument(); @@ -133,7 +115,6 @@ describe('Visit Header', () => { it('should be able to show configurable stop visit button and modal to stop current visit', async () => { const user = userEvent.setup(); - mockUseAssignedExtensions.mockReturnValue([{ id: 'someId' }]); mockUsePatient.mockReturnValue({ patient: mockPatientWithLongName, isLoading: false, @@ -143,7 +124,7 @@ describe('Visit Header', () => { mockUseVisit.mockReturnValue({ isValidating: false, currentVisit: mockCurrentVisit }); mockUseLayoutType.mockReturnValue('desktop'); - renderVisitHeader(); + render(); // Should be able to end a visit const endVisitButton = screen.getByRole('button', { name: /End visit/i }); @@ -154,14 +135,33 @@ describe('Visit Header', () => { expect(mockShowModal).toHaveBeenCalledTimes(1); const closeButton = screen.getByRole('button', { name: 'Close' }); - expect(closeButton).toBeInTheDocument(); + await user.click(closeButton); + expect(navigate).toHaveBeenCalled(); + }); - // Should close the visit-header + test('close button should navigate back to before the patient chart', async () => { + const user = userEvent.setup(); + mockGetHistory.mockReturnValue([ + 'https://o3.openmrs.org/openmrs/spa/home', + 'https://o3.openmrs.org/openmrs/spa/patient/1234/chart', + `https://o3.openmrs.org/openmrs/spa/patient/${mockPatient.id}/chart`, + `https://o3.openmrs.org/openmrs/spa/patient/${mockPatient.id}/chart/labs`, + ]); + render(); + const closeButton = screen.getByRole('button', { name: 'Close' }); await user.click(closeButton); - expect(navigate).toHaveBeenCalledWith({ to: '/spa/home' }); + expect(goBackInHistory).toHaveBeenCalledWith({ toUrl: 'https://o3.openmrs.org/openmrs/spa/patient/1234/chart' }); }); -}); -function renderVisitHeader() { - render(); -} + test('close button should navigate to home if no such URL exists in history', async () => { + const user = userEvent.setup(); + render(); + mockGetHistory.mockReturnValue([ + `https://o3.openmrs.org/openmrs/spa/patient/${mockPatient.id}/chart`, + `https://o3.openmrs.org/openmrs/spa/patient/${mockPatient.id}/chart/labs`, + ]); + const closeButton = screen.getByRole('button', { name: 'Close' }); + await user.click(closeButton); + expect(navigate).toHaveBeenCalledWith({ to: '${openmrsSpaBase}/home' }); + }); +}); diff --git a/packages/esm-patient-chart-app/src/workspace/workspace-window.test.tsx b/packages/esm-patient-chart-app/src/workspace/workspace-window.test.tsx index c2a12092d5..6a4dc1654d 100644 --- a/packages/esm-patient-chart-app/src/workspace/workspace-window.test.tsx +++ b/packages/esm-patient-chart-app/src/workspace/workspace-window.test.tsx @@ -19,10 +19,6 @@ jest.mock('@openmrs/esm-framework', () => { return { ...originalModule, isDesktop: jest.fn(), - getExtensionRegistration: (name) => mockExtensionRegistry[name], - registerExtension: (ext) => { - mockExtensionRegistry[ext.name] = ext; - }, translateFrom: (module, key, defaultValue, options) => defaultValue, useBodyScrollLock: jest.fn(), }; diff --git a/packages/esm-patient-chart-app/translations/km.json b/packages/esm-patient-chart-app/translations/km.json index 29ee8d13c4..6659aebee7 100644 --- a/packages/esm-patient-chart-app/translations/km.json +++ b/packages/esm-patient-chart-app/translations/km.json @@ -83,7 +83,7 @@ "markAlive": "សម្គាល់ថានៅរស់", "markAsAlive": "សម្គាល់ថានៅរស់", "markAsDeceased": "តើអ្នកប្រាកដថាចង់សម្គាល់ថាអ្នកជំងឺបានស្លាប់ហើយ?", - "markDeceased": "គូសលើអ្នកជាស្លាប់", + "markDeceased": "កំណត់ត្រាមរណភាព", "markingPatientDeceasedInfoText": "ការសម្គាល់អ្នកជំងឺថាបានស្លាប់ រួចបញ្ចប់ការពិនិត្យអ្នកជំងឺនេះ", "maximize": "អតិបរមា", "medications": "ឱសថ", diff --git a/packages/esm-patient-chart-app/translations/zh.json b/packages/esm-patient-chart-app/translations/zh.json index be1202c4f0..5ee8c27805 100644 --- a/packages/esm-patient-chart-app/translations/zh.json +++ b/packages/esm-patient-chart-app/translations/zh.json @@ -1,136 +1,191 @@ { - "actions": "操作", - "activeFormWarning": "工作区中有一个正在进行中的表单", + "addAPastVisit": "Add a past visit", "addPastVisit": "添加历史就诊", "addPastVisitText": "您可以添加或更新一个历史就诊,请选择以下选项之一继续。", - "address": "地址", "all": "全部", "allEncounters": "所有问诊", + "Allergies dashboard": "Allergies dashboard", + "appointmentEdited": "Appointment edited", + "Appointments dashboard": "Appointments dashboard", + "appointmentUpdate": "Upcoming appointment updated successfully", + "Attachments dashboard": "Attachments dashboard", "cancel": "取消", - "cancelActiveVisit": "取消活动就诊", + "cancelActiveVisitConfirmation": "Are you sure you want to cancel this active visit?", + "cancellingVisit": "Cancelling visit", "cancelVisit": "取消就诊", - "cancelVisitError": "取消活动就诊时出现错误", - "cancelVisitWarningMessage": "取消此次就诊将删除所有相关的问诊记录", + "cancelVisitExplainerMessage": "Cancelling this visit will delete its associated encounters", "causeOfDeath": "死亡原因", + "causeOfDeath_title": "Cause of Death", "checkFilters": "检查上方的筛选条件", - "chooseService": "选择服务", - "chooseStatus": "选择状态", "close": "关闭", - "configurePriorities": "请配置优先级以继续。", - "configureServices": "请配置服务以继续。", - "configureStatuses": "请配置状态以继续。", + "Conditions dashboard": "Conditions dashboard", "confirm": "确认", "confirmDeceased": "确认已故", + "confirmDeletingVisitTextWithStartAndEndDate": "Are you sure you want to delete {{visit}} which started {{visitStartDate}} and ended {{visitEndDate}}?", "confirmMarkAsAlive": "您确定要将患者标记为存活吗?", - "contactDetails": "联系方式", + "confirmModifyingVisitDateToAccomodateEncounter": "The encounter date falls outside the designated visit date range. Would you like to modify the visit date to accommodate the new encounter date?", + "currentVisit": "Current Visit", "date": "日期", "dateAndTime": "日期&时间", - "dateAndTimeOfVisit": "就诊日期和时间", "dateOfDeath": "死亡日期", + "delete": "Delete", + "deleteEncounter": "Delete Encounter", + "deleteEncounterConfirmationText": "Are you sure you want to delete this encounter? This action can't be undone.", "deleteThisEncounter": "删除此次问诊", + "deleteVisit": "Delete visit", + "deleteVisitDialogHeader": "Are you sure you want to delete this visit?", + "deletingVisit": "Deleting visit", + "deletingVisitWillDeleteEncounters": "Deleting this visit will delete all associated encounters.", "diagnoses": "诊断", "discard": "放弃", "dose": "剂量", - "edit": "编辑", - "editEncounter": "编辑这次问诊", "editPastVisit": "编辑历史就诊", - "editQueueEntryStatusTooltip": "编辑", "editThisEncounter": "编辑这次问诊", + "editThisVisit": "Edit this visit", + "editVisitDetails": "Edit visit details", + "emptyStateText": "There are no {{displayText}} to display for this patient", + "encounterDeleted": "Encounter deleted", "encounters": "问诊", - "Encounters": "问诊", + "encounters_title": "Encounters", "encounterType": "问诊类型", "end": "End", - "endActiveVisit": "结束活动就诊", + "endActiveVisitConfirmation": "Are you sure you want to end this active visit?", "endDate": "End date", + "endDate_title": "End Date", "endVisit": "结束就诊", - "endVisitError": "结束当前就诊时出现错误", - "endVisitWarningMessage": "结束此次就诊后,您将无法为该患者填写另一个问诊记录表。", + "endVisit_title": "End Visit", + "endVisitExplainerMessage": "Ending this visit means that you will no longer be able to add encounters to it. If you need to add an encounter, you can create a new visit for this patient or edit a past one.", + "error": "Error", + "errorCancellingVisit": "Error cancelling active visit", + "errorCopy": "Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.", + "errorDeletingVisit": "Error deleting visit", + "errorEndingVisit": "Error ending visit", + "errorOccuredDeletingVisit": "An error occured when deleting visit", + "errorUpdatingVisitDetails": "Error updating visit details", + "errorWhenRestoringVisit": "Error occured when restoring {{visit}}", + "failedDeleting": "couldn't be deleted", + "failedToLoadCurrentVisit": "Failed loading current visit", "female": "女性", "fieldRequired": "此字段为必填项", "filterByEncounterType": "按问诊类型筛选", + "form": "Form name", + "Forms & Notes dashboard": "Forms & Notes dashboard", "goToThisEncounter": "前往这次问诊", "hide": "隐藏", "indication": "Indication", + "invalidTimeFormat": "Invalid time format", + "invalidVisitStartDate": "Start date needs to be on or before {{firstEncounterDatetime}}", + "invalidVisitStopDate": "Visit stop date time cannot be on or before visit start date time", "loading": "加载中", - "loadVisitInfo": "加载就诊信息", + "loadingVisit": "Loading current visit...", "location": "地点", "male": "男性", "markAlive": "标记存活", "markAsAlive": "标记为存活", "markAsDeceased": "您确定要将患者标记为已故吗?", + "markDeceased": "Mark deceased", "markingPatientDeceasedInfoText": "标记患者为已故将结束该患者的所有活动就诊", "maximize": "最大化", "medications": "药物清单", + "Medications dashboard": "Medications dashboard", "minimize": "最小化", "missingVisitType": "就诊类型缺失", + "modifyVisitDate": "Modify visit date", + "movePatient": "Move patient", + "movePatientToNextService": "Move patient to next service", "name": "Name", "no": "No", "noActiveVisit": "当前没有活动的就诊", + "noActiveVisitMessage": "active visit", + "noActiveVisitNoRDEText": "You can't add data to the patient chart without an active visit. Would you like to start a new visit?", "noActiveVisitText": "您无法在没有活动就诊的情况下向患者图表添加数据,请选择以下选项之一以继续。", "noDiagnosesFound": "未找到诊断", "noEncountersFound": "未找到问诊记录", "noEncountersToDisplay": "没有可显示的问诊记录", - "noMedicationsFound": "未找到药物清单", - "noNotesFound": "No notes found", "noObservationsFound": "未找到观察记录", - "noPrioritiesConfigured": "未配置优先级", - "noServicesConfigured": "未配置服务", - "noStatusesConfigured": "未配置状态", "notes": "Notes", + "Offline Actions dashboard": "Offline Actions dashboard", "openAnyway": "Open anyway", "optional": "可选的", "orderDurationAndUnit": "for {duration} {durationUnit}", "orderIndefiniteDuration": "无限期", "other": "其他", + "paginationItemsCount_other": "{{pageItemsCount}} / {{count}} items", + "paginationPageText_other": "of {{count}} pages", + "partOfFormDidntLoad": "Part of the form did not load", "pastVisitErrorText": "历史就诊错误", "pastVisits": "历史就诊", - "priority": "优先级", + "Patient Summary": "Patient Summary", + "Patient Summary dashboard": "Patient Summary dashboard", + "patientBreadcrumb": "Patient", "program": "Program", + "Programs dashboard": "Programs dashboard", "provider": "Provider", "quantity": "数量", "queueAddedSuccessfully": "患者已成功添加到队列中。", "queueEntryError": "将患者添加到队列时出现错误", "recommended": "Recommended", + "record": "Record", "refills": "补充处方", - "relationships": "关系", + "refreshToTryAgain": "Please refresh to try again", + "Results Viewer dashboard": "Results Viewer dashboard", + "retrospectiveEntry": "Retrospective Entry", "searchForAVisitType": "搜索就诊类型", "searchForCauseOfDeath": "搜索死亡原因", "searchThisList": "搜索此列表", + "seeAll": "See all", "selectAnOption": "选择一个选项", "selectLocation": "选择地点", "selectProgramType": "Select program type", - "selectService": "选择服务", - "selectStatus": "选择状态", "selectVisitType": "请选择就诊类型", - "service": "服务", "setAliveError": "标记患者为存活时出现错误", "setAliveSuccessfully": "患者已成功标记为存活", "setDeceased": "设置为已故", "setDeceasedError": "标记患者为已故时出现错误", "setDeceasedSuccessfully": "患者已成功标记为已故", - "showAllDetails": "展示所有细节", - "showLess": "展示更少", "start": "开始", + "startAVisit": "Start a visit", "startDate": "开始日期", "startNewVisit": "开始新的就诊", "startVisit": "开始就诊", "startVisitError": "开始当前就诊时出现错误", - "status": "状态", + "successfullyDeleted": "successfully deleted", "tests": "Tests", "time": "时间", + "timeFormat ": "Time Format", "type": "类型", + "undo": "Undo", "unknown": "未知", + "unsavedChanges": "You have unsaved changes", + "unsavedChangesInForm": "There are unsaved changes in {{formName}}. Please save them before opening another form.", + "updateError": "Error updating upcoming appointment", + "updateVisitDetails": "Update visit details", "visit": "就诊", - "visitCanceled": "成功取消活动就诊", + "visitAttributes": "Visit attributes", + "visitCancelled": "Visit cancelled", + "visitCancelSuccessMessage": "Active {{visit}} cancelled successfully", + "visitDeleted": "{{visit}} deleted", + "visitDeletedSuccessfully": "{{visit}} deleted successfully", + "visitDetailsUpdated": "Visit details updated", + "visitDetailsUpdatedSuccessfully": "{{visit}} updated successfully", "visitEnded": "就诊结束", "visitEndSuccessfully": "成功结束当前就诊", "visitLocation": "就诊地点", + "visitNotRestored": "Visit couldn't be restored", + "visitRestored": "Visit restored", + "visitRestoredSuccessfully": "{{visit}} restored successfully", "visits": "就诊", "Visits": "就诊", + "Visits dashboard": "Visits dashboard", + "visitStartDatetime": "Visit start date and time", "visitStarted": "就诊开始", "visitStartedSuccessfully": "", + "visitStopDateMustBeAfterMostRecentEncounter": "Stop date needs to be on or after {{lastEncounterDatetime}}", + "visitStopDatetime": "Visit stop date and time", "visitSummaries": "就诊总结", "visitType": "就诊类型", - "workspaceModalText": "在工作区中启动一个新表单可能会导致您丢失在 {formName} 表单上的未保存的工作。", + "visitType_title": "Visit Type", + "visitTypeRequired": "Visit type is required", + "Vitals & Biometrics dashboard": "Vitals & Biometrics dashboard", "yes": "是" } diff --git a/packages/esm-patient-chart-app/translations/zh_CN.json b/packages/esm-patient-chart-app/translations/zh_CN.json index be1202c4f0..80d172df57 100644 --- a/packages/esm-patient-chart-app/translations/zh_CN.json +++ b/packages/esm-patient-chart-app/translations/zh_CN.json @@ -1,136 +1,189 @@ { - "actions": "操作", - "activeFormWarning": "工作区中有一个正在进行中的表单", + "addAPastVisit": "Add a past visit", "addPastVisit": "添加历史就诊", "addPastVisitText": "您可以添加或更新一个历史就诊,请选择以下选项之一继续。", - "address": "地址", "all": "全部", "allEncounters": "所有问诊", + "Allergies dashboard": "Allergies dashboard", + "appointmentEdited": "Appointment edited", + "Appointments dashboard": "Appointments dashboard", + "appointmentUpdate": "Upcoming appointment updated successfully", + "Attachments dashboard": "Attachments dashboard", "cancel": "取消", - "cancelActiveVisit": "取消活动就诊", + "cancelActiveVisitConfirmation": "Are you sure you want to cancel this active visit?", + "cancellingVisit": "Cancelling visit", "cancelVisit": "取消就诊", - "cancelVisitError": "取消活动就诊时出现错误", - "cancelVisitWarningMessage": "取消此次就诊将删除所有相关的问诊记录", + "cancelVisitExplainerMessage": "Cancelling this visit will delete its associated encounters", "causeOfDeath": "死亡原因", + "causeOfDeath_title": "Cause of Death", "checkFilters": "检查上方的筛选条件", - "chooseService": "选择服务", - "chooseStatus": "选择状态", "close": "关闭", - "configurePriorities": "请配置优先级以继续。", - "configureServices": "请配置服务以继续。", - "configureStatuses": "请配置状态以继续。", + "Conditions dashboard": "Conditions dashboard", "confirm": "确认", "confirmDeceased": "确认已故", + "confirmDeletingVisitTextWithStartAndEndDate": "Are you sure you want to delete {{visit}} which started {{visitStartDate}} and ended {{visitEndDate}}?", "confirmMarkAsAlive": "您确定要将患者标记为存活吗?", - "contactDetails": "联系方式", + "confirmModifyingVisitDateToAccomodateEncounter": "The encounter date falls outside the designated visit date range. Would you like to modify the visit date to accommodate the new encounter date?", + "currentVisit": "Current Visit", "date": "日期", "dateAndTime": "日期&时间", - "dateAndTimeOfVisit": "就诊日期和时间", "dateOfDeath": "死亡日期", + "delete": "Delete", + "deleteEncounter": "Delete Encounter", + "deleteEncounterConfirmationText": "Are you sure you want to delete this encounter? This action can't be undone.", "deleteThisEncounter": "删除此次问诊", + "deleteVisit": "Delete visit", + "deleteVisitDialogHeader": "Are you sure you want to delete this visit?", + "deletingVisit": "Deleting visit", + "deletingVisitWillDeleteEncounters": "Deleting this visit will delete all associated encounters.", "diagnoses": "诊断", "discard": "放弃", "dose": "剂量", - "edit": "编辑", - "editEncounter": "编辑这次问诊", "editPastVisit": "编辑历史就诊", - "editQueueEntryStatusTooltip": "编辑", "editThisEncounter": "编辑这次问诊", + "editThisVisit": "Edit this visit", + "editVisitDetails": "Edit visit details", + "emptyStateText": "There are no {{displayText}} to display for this patient", + "encounterDeleted": "Encounter deleted", "encounters": "问诊", - "Encounters": "问诊", + "encounters_title": "Encounters", "encounterType": "问诊类型", "end": "End", - "endActiveVisit": "结束活动就诊", + "endActiveVisitConfirmation": "Are you sure you want to end this active visit?", "endDate": "End date", + "endDate_title": "End Date", "endVisit": "结束就诊", - "endVisitError": "结束当前就诊时出现错误", - "endVisitWarningMessage": "结束此次就诊后,您将无法为该患者填写另一个问诊记录表。", + "endVisit_title": "End Visit", + "endVisitExplainerMessage": "Ending this visit means that you will no longer be able to add encounters to it. If you need to add an encounter, you can create a new visit for this patient or edit a past one.", + "error": "Error", + "errorCancellingVisit": "Error cancelling active visit", + "errorCopy": "Sorry, there was a problem displaying this information. You can try to reload this page, or contact the site administrator and quote the error code above.", + "errorDeletingVisit": "Error deleting visit", + "errorEndingVisit": "Error ending visit", + "errorOccuredDeletingVisit": "An error occured when deleting visit", + "errorUpdatingVisitDetails": "Error updating visit details", + "errorWhenRestoringVisit": "Error occured when restoring {{visit}}", + "failedDeleting": "couldn't be deleted", + "failedToLoadCurrentVisit": "Failed loading current visit", "female": "女性", "fieldRequired": "此字段为必填项", "filterByEncounterType": "按问诊类型筛选", + "form": "Form name", + "Forms & Notes dashboard": "Forms & Notes dashboard", "goToThisEncounter": "前往这次问诊", "hide": "隐藏", "indication": "Indication", + "invalidTimeFormat": "Invalid time format", + "invalidVisitStartDate": "Start date needs to be on or before {{firstEncounterDatetime}}", + "invalidVisitStopDate": "Visit stop date time cannot be on or before visit start date time", "loading": "加载中", - "loadVisitInfo": "加载就诊信息", + "loadingVisit": "Loading current visit...", "location": "地点", "male": "男性", "markAlive": "标记存活", "markAsAlive": "标记为存活", "markAsDeceased": "您确定要将患者标记为已故吗?", + "markDeceased": "Mark deceased", "markingPatientDeceasedInfoText": "标记患者为已故将结束该患者的所有活动就诊", "maximize": "最大化", "medications": "药物清单", + "Medications dashboard": "Medications dashboard", "minimize": "最小化", "missingVisitType": "就诊类型缺失", + "modifyVisitDate": "Modify visit date", + "movePatient": "Move patient", + "movePatientToNextService": "Move patient to next service", "name": "Name", "no": "No", "noActiveVisit": "当前没有活动的就诊", + "noActiveVisitMessage": "active visit", + "noActiveVisitNoRDEText": "You can't add data to the patient chart without an active visit. Would you like to start a new visit?", "noActiveVisitText": "您无法在没有活动就诊的情况下向患者图表添加数据,请选择以下选项之一以继续。", "noDiagnosesFound": "未找到诊断", "noEncountersFound": "未找到问诊记录", "noEncountersToDisplay": "没有可显示的问诊记录", - "noMedicationsFound": "未找到药物清单", - "noNotesFound": "No notes found", "noObservationsFound": "未找到观察记录", - "noPrioritiesConfigured": "未配置优先级", - "noServicesConfigured": "未配置服务", - "noStatusesConfigured": "未配置状态", "notes": "Notes", + "Offline Actions dashboard": "Offline Actions dashboard", "openAnyway": "Open anyway", "optional": "可选的", "orderDurationAndUnit": "for {duration} {durationUnit}", "orderIndefiniteDuration": "无限期", "other": "其他", + "partOfFormDidntLoad": "Part of the form did not load", "pastVisitErrorText": "历史就诊错误", "pastVisits": "历史就诊", - "priority": "优先级", + "Patient Summary": "Patient Summary", + "Patient Summary dashboard": "Patient Summary dashboard", + "patientBreadcrumb": "Patient", "program": "Program", + "Programs dashboard": "Programs dashboard", "provider": "Provider", "quantity": "数量", "queueAddedSuccessfully": "患者已成功添加到队列中。", "queueEntryError": "将患者添加到队列时出现错误", "recommended": "Recommended", + "record": "Record", "refills": "补充处方", - "relationships": "关系", + "refreshToTryAgain": "Please refresh to try again", + "Results Viewer dashboard": "Results Viewer dashboard", + "retrospectiveEntry": "Retrospective Entry", "searchForAVisitType": "搜索就诊类型", "searchForCauseOfDeath": "搜索死亡原因", "searchThisList": "搜索此列表", + "seeAll": "See all", "selectAnOption": "选择一个选项", "selectLocation": "选择地点", "selectProgramType": "Select program type", - "selectService": "选择服务", - "selectStatus": "选择状态", "selectVisitType": "请选择就诊类型", - "service": "服务", "setAliveError": "标记患者为存活时出现错误", "setAliveSuccessfully": "患者已成功标记为存活", "setDeceased": "设置为已故", "setDeceasedError": "标记患者为已故时出现错误", "setDeceasedSuccessfully": "患者已成功标记为已故", - "showAllDetails": "展示所有细节", - "showLess": "展示更少", "start": "开始", + "startAVisit": "Start a visit", "startDate": "开始日期", "startNewVisit": "开始新的就诊", "startVisit": "开始就诊", "startVisitError": "开始当前就诊时出现错误", - "status": "状态", + "successfullyDeleted": "successfully deleted", "tests": "Tests", "time": "时间", + "timeFormat ": "Time Format", "type": "类型", + "undo": "Undo", "unknown": "未知", + "unsavedChanges": "You have unsaved changes", + "unsavedChangesInForm": "There are unsaved changes in {{formName}}. Please save them before opening another form.", + "updateError": "Error updating upcoming appointment", + "updateVisitDetails": "Update visit details", "visit": "就诊", - "visitCanceled": "成功取消活动就诊", + "visitAttributes": "Visit attributes", + "visitCancelled": "Visit cancelled", + "visitCancelSuccessMessage": "Active {{visit}} cancelled successfully", + "visitDeleted": "{{visit}} deleted", + "visitDeletedSuccessfully": "{{visit}} deleted successfully", + "visitDetailsUpdated": "Visit details updated", + "visitDetailsUpdatedSuccessfully": "{{visit}} updated successfully", "visitEnded": "就诊结束", "visitEndSuccessfully": "成功结束当前就诊", "visitLocation": "就诊地点", + "visitNotRestored": "Visit couldn't be restored", + "visitRestored": "Visit restored", + "visitRestoredSuccessfully": "{{visit}} restored successfully", "visits": "就诊", "Visits": "就诊", + "Visits dashboard": "Visits dashboard", + "visitStartDatetime": "Visit start date and time", "visitStarted": "就诊开始", "visitStartedSuccessfully": "", + "visitStopDateMustBeAfterMostRecentEncounter": "Stop date needs to be on or after {{lastEncounterDatetime}}", + "visitStopDatetime": "Visit stop date and time", "visitSummaries": "就诊总结", "visitType": "就诊类型", - "workspaceModalText": "在工作区中启动一个新表单可能会导致您丢失在 {formName} 表单上的未保存的工作。", + "visitType_title": "Visit Type", + "visitTypeRequired": "Visit type is required", + "Vitals & Biometrics dashboard": "Vitals & Biometrics dashboard", "yes": "是" } diff --git a/packages/esm-patient-common-lib/src/types/workspace.ts b/packages/esm-patient-common-lib/src/types/workspace.ts index 23eee841aa..4aed8d04f0 100644 --- a/packages/esm-patient-common-lib/src/types/workspace.ts +++ b/packages/esm-patient-common-lib/src/types/workspace.ts @@ -3,8 +3,12 @@ export type WorkspaceWindowState = 'maximized' | 'hidden' | 'normal'; /** The default parameters received by all workspaces */ export interface DefaultWorkspaceProps { - closeWorkspace(ignoreChanges: boolean): void; - closeWorkspace(): void; + /** + * Call this function to close the workspace. If ignoreChanges is true, the user will not be + * prompted to save changes before closing, even if the `testFcn` passed to `promptBeforeClosing` + * returns `true`. + */ + closeWorkspace(ignoreChanges?: boolean): void; /** * Call this with a no-args function that returns true if the user should be prompted before * this workspace is closed; e.g. if there is unsaved data. diff --git a/packages/esm-patient-common-lib/src/workspaces/workspaces.test.ts b/packages/esm-patient-common-lib/src/workspaces/workspaces.test.ts index 876ab54fab..2100104a98 100644 --- a/packages/esm-patient-common-lib/src/workspaces/workspaces.test.ts +++ b/packages/esm-patient-common-lib/src/workspaces/workspaces.test.ts @@ -361,6 +361,7 @@ describe('workspace system', () => { }); test('is compatible with workspaces registered as extensions', () => { + console.warn = jest.fn(); const store = getWorkspaceStore(); registerExtension({ name: 'lab-results', @@ -375,6 +376,7 @@ describe('workspace system', () => { expect(workspace.additionalProps['foo']).toBe(true); expect(workspace.title).toBe('Lab Results'); expect(workspace.preferredWindowSize).toBe('maximized'); + expect(console.warn).toHaveBeenCalled(); }); test('launching unregistered workspace throws an error', () => { diff --git a/packages/esm-patient-common-lib/src/workspaces/workspaces.ts b/packages/esm-patient-common-lib/src/workspaces/workspaces.ts index ee028ee265..516725394e 100644 --- a/packages/esm-patient-common-lib/src/workspaces/workspaces.ts +++ b/packages/esm-patient-common-lib/src/workspaces/workspaces.ts @@ -58,6 +58,7 @@ export function registerWorkspace(workspace: WorkspaceRegistration) { }; } +const workspaceExtensionWarningsIssued = new Set(); /** * This exists for compatibility with the old way of registering * workspaces (as extensions). @@ -70,6 +71,12 @@ function getWorkspaceRegistration(name: string): WorkspaceRegistration { } else { const workspaceExtension = getExtensionRegistration(name); if (workspaceExtension) { + if (!workspaceExtensionWarningsIssued.has(name)) { + console.warn( + `The workspace '${name}' is registered as an extension. This is deprecated. Please use the 'registerWorkspace' function instead.`, + ); + workspaceExtensionWarningsIssued.add(name); + } return { name: workspaceExtension.name, title: getTitleFromExtension(workspaceExtension), diff --git a/packages/esm-patient-conditions-app/translations/zh.json b/packages/esm-patient-conditions-app/translations/zh.json index b4d6c32fe4..a48d39a8a4 100644 --- a/packages/esm-patient-conditions-app/translations/zh.json +++ b/packages/esm-patient-conditions-app/translations/zh.json @@ -1,23 +1,32 @@ { - "active": "Active", "add": "添加", - "all": "全部", "cancel": "取消", "checkFilters": "检查上方的筛选条件", "condition": "病情", + "conditionDeleted": "Condition deleted", "conditionNowVisible": "现在在病情页面上可见", "conditions": "病情", + "Conditions": "Conditions", "conditionSaved": "病情保存成功", - "conditionSaveError": "保存病情时出现错误", + "conditionUpdated": "Condition updated", "currentStatus": "当前状态", "dateOfOnset": "发病日期", + "delete": "Delete", + "deleteCondition": "Delete condition", + "deleteModalConfirmationText": "Are you sure you want to delete this condition?", + "deleting": "Deleting", + "edit": "Edit", + "editCondition": "Edit a Condition", "endDate": "End date", "enterCondition": "输入病情", - "inactive": "Inactive", + "errorCreatingCondition": "Error creating condition", + "errorDeletingCondition": "Error deleting condition", + "errorUpdatingCondition": "Error updating condition", "noConditionsToDisplay": "没有可显示的病情", "noResultsFor": "No results for", "onsetDate": "Onset date", "saveAndClose": "保存并关闭", + "saving": "Saving", "searchConditions": "搜索病情", "searching": "搜索中", "seeAll": "查看全部", diff --git a/packages/esm-patient-conditions-app/translations/zh_CN.json b/packages/esm-patient-conditions-app/translations/zh_CN.json index b4d6c32fe4..a48d39a8a4 100644 --- a/packages/esm-patient-conditions-app/translations/zh_CN.json +++ b/packages/esm-patient-conditions-app/translations/zh_CN.json @@ -1,23 +1,32 @@ { - "active": "Active", "add": "添加", - "all": "全部", "cancel": "取消", "checkFilters": "检查上方的筛选条件", "condition": "病情", + "conditionDeleted": "Condition deleted", "conditionNowVisible": "现在在病情页面上可见", "conditions": "病情", + "Conditions": "Conditions", "conditionSaved": "病情保存成功", - "conditionSaveError": "保存病情时出现错误", + "conditionUpdated": "Condition updated", "currentStatus": "当前状态", "dateOfOnset": "发病日期", + "delete": "Delete", + "deleteCondition": "Delete condition", + "deleteModalConfirmationText": "Are you sure you want to delete this condition?", + "deleting": "Deleting", + "edit": "Edit", + "editCondition": "Edit a Condition", "endDate": "End date", "enterCondition": "输入病情", - "inactive": "Inactive", + "errorCreatingCondition": "Error creating condition", + "errorDeletingCondition": "Error deleting condition", + "errorUpdatingCondition": "Error updating condition", "noConditionsToDisplay": "没有可显示的病情", "noResultsFor": "No results for", "onsetDate": "Onset date", "saveAndClose": "保存并关闭", + "saving": "Saving", "searchConditions": "搜索病情", "searching": "搜索中", "seeAll": "查看全部", diff --git a/packages/esm-patient-flags-app/translations/zh.json b/packages/esm-patient-flags-app/translations/zh.json new file mode 100644 index 0000000000..adb3d22fae --- /dev/null +++ b/packages/esm-patient-flags-app/translations/zh.json @@ -0,0 +1,26 @@ +{ + "activeFirst": "Active first", + "alphabetically": "A - Z", + "clearSearch": "Clear search", + "closeFlagsBar": "Close flags bar", + "disableFlagError": "Disable flag error", + "disablingFlag": "Disabling flag...", + "discard": "Discard", + "edit": "Edit", + "editFlags": "Edit flags", + "enabledFlag": "Enabled flag", + "enablingFlag": "Enabling flag...", + "flagCount_other": "{{count}} risk flags", + "flagDisabled": "Flag disabled", + "flagDisabledSuccessfully": "Flag successfully disabled", + "flagDisableError": "Error disabling the flag", + "flagEnabled": "flag enabled", + "flagEnabledSuccessfully": "Flag successfully enabled", + "flagEnableError": "Error enabling flag", + "loading": "Loading", + "matchesForSearchTerm_other": "{{count}} flags", + "noFlagsFound": "Sorry, no flags found matching your search", + "retiredFirst": "Retired first", + "saveAndClose": "Save & close", + "searchForAFlag": "Search for a flag" +} diff --git a/packages/esm-patient-flags-app/translations/zh_CN.json b/packages/esm-patient-flags-app/translations/zh_CN.json new file mode 100644 index 0000000000..8170c34d7e --- /dev/null +++ b/packages/esm-patient-flags-app/translations/zh_CN.json @@ -0,0 +1,24 @@ +{ + "activeFirst": "Active first", + "alphabetically": "A - Z", + "clearSearch": "Clear search", + "closeFlagsBar": "Close flags bar", + "disableFlagError": "Disable flag error", + "disablingFlag": "Disabling flag...", + "discard": "Discard", + "edit": "Edit", + "editFlags": "Edit flags", + "enabledFlag": "Enabled flag", + "enablingFlag": "Enabling flag...", + "flagDisabled": "Flag disabled", + "flagDisabledSuccessfully": "Flag successfully disabled", + "flagDisableError": "Error disabling the flag", + "flagEnabled": "flag enabled", + "flagEnabledSuccessfully": "Flag successfully enabled", + "flagEnableError": "Error enabling flag", + "loading": "Loading", + "noFlagsFound": "Sorry, no flags found matching your search", + "retiredFirst": "Retired first", + "saveAndClose": "Save & close", + "searchForAFlag": "Search for a flag" +} diff --git a/packages/esm-patient-forms-app/translations/zh.json b/packages/esm-patient-forms-app/translations/zh.json index eba7b4abbe..ab1d8daac8 100644 --- a/packages/esm-patient-forms-app/translations/zh.json +++ b/packages/esm-patient-forms-app/translations/zh.json @@ -1,18 +1,17 @@ { - "all": "全部", - "clinicalForm": "临床表单", - "completed": "已完成", - "form": "表单", + "clinicalForms": "Clinical forms", + "editForm": "Edit form", "formName": "表单名称(A-Z)", "forms": "表单", "formSearchHint": "尝试使用替代名称或关键词搜索表单", - "goToSummary": "前往摘要", "homeOverviewCardView": "查看", "lastCompleted": "Last Completed", "never": "Never", - "noFormsAvailable": "该患者没有可显示的表单", + "noFormsToDisplay": "There are no forms to display.", "noMatchingFormsAvailable": "没有可显示的 {formCategory} 表单", "noMatchingFormsToDisplay": "没有匹配的表单可显示", + "offlineForms": "Offline forms", + "offlineForms__lower": "offline forms", "offlineFormsOverviewCardAvailableOffline": "离线可用", "offlineFormsTableFormAvailableOffline": "离线", "offlineFormsTableFormNameHeader": "表单名称", @@ -20,7 +19,6 @@ "offlinePatientsTableSearchLabel": "搜索此列表", "offlinePatientsTableSearchPlaceholder": "搜索此列表", "offlineToggle": "离线切换", - "recommended": "Recommended", - "searchThisList": "搜索此列表", - "seeAll": "查看全部" + "searchForAForm": "Search for a form", + "searchThisList": "搜索此列表" } diff --git a/packages/esm-patient-forms-app/translations/zh_CN.json b/packages/esm-patient-forms-app/translations/zh_CN.json index eba7b4abbe..ab1d8daac8 100644 --- a/packages/esm-patient-forms-app/translations/zh_CN.json +++ b/packages/esm-patient-forms-app/translations/zh_CN.json @@ -1,18 +1,17 @@ { - "all": "全部", - "clinicalForm": "临床表单", - "completed": "已完成", - "form": "表单", + "clinicalForms": "Clinical forms", + "editForm": "Edit form", "formName": "表单名称(A-Z)", "forms": "表单", "formSearchHint": "尝试使用替代名称或关键词搜索表单", - "goToSummary": "前往摘要", "homeOverviewCardView": "查看", "lastCompleted": "Last Completed", "never": "Never", - "noFormsAvailable": "该患者没有可显示的表单", + "noFormsToDisplay": "There are no forms to display.", "noMatchingFormsAvailable": "没有可显示的 {formCategory} 表单", "noMatchingFormsToDisplay": "没有匹配的表单可显示", + "offlineForms": "Offline forms", + "offlineForms__lower": "offline forms", "offlineFormsOverviewCardAvailableOffline": "离线可用", "offlineFormsTableFormAvailableOffline": "离线", "offlineFormsTableFormNameHeader": "表单名称", @@ -20,7 +19,6 @@ "offlinePatientsTableSearchLabel": "搜索此列表", "offlinePatientsTableSearchPlaceholder": "搜索此列表", "offlineToggle": "离线切换", - "recommended": "Recommended", - "searchThisList": "搜索此列表", - "seeAll": "查看全部" + "searchForAForm": "Search for a form", + "searchThisList": "搜索此列表" } diff --git a/packages/esm-patient-immunizations-app/translations/zh.json b/packages/esm-patient-immunizations-app/translations/zh.json index 9e26dfeeb6..a42c9cb9e8 100644 --- a/packages/esm-patient-immunizations-app/translations/zh.json +++ b/packages/esm-patient-immunizations-app/translations/zh.json @@ -1 +1,20 @@ -{} \ No newline at end of file +{ + "add": "Add", + "cancel": "Cancel", + "errorSaving": "Error saving vaccination", + "expirationDate": "Expiration Date", + "goToSummary": "Go to Summary", + "immunizations": "Immunizations", + "Immunizations": "Immunizations", + "lotNumber": "Lot Number", + "manufacturer": "Manufacturer", + "pleaseSelect": "Please select", + "recentVaccination": "Recent vaccination", + "save": "Save", + "seeAll": "See all", + "sequence": "Sequence", + "singleDoseOn": "Single Dose on", + "vaccinationDate": "Vaccination date", + "vaccinationSaved": "Vaccination saved successfully", + "vaccine": "Vaccine" +} diff --git a/packages/esm-patient-immunizations-app/translations/zh_CN.json b/packages/esm-patient-immunizations-app/translations/zh_CN.json index 9e26dfeeb6..a42c9cb9e8 100644 --- a/packages/esm-patient-immunizations-app/translations/zh_CN.json +++ b/packages/esm-patient-immunizations-app/translations/zh_CN.json @@ -1 +1,20 @@ -{} \ No newline at end of file +{ + "add": "Add", + "cancel": "Cancel", + "errorSaving": "Error saving vaccination", + "expirationDate": "Expiration Date", + "goToSummary": "Go to Summary", + "immunizations": "Immunizations", + "Immunizations": "Immunizations", + "lotNumber": "Lot Number", + "manufacturer": "Manufacturer", + "pleaseSelect": "Please select", + "recentVaccination": "Recent vaccination", + "save": "Save", + "seeAll": "See all", + "sequence": "Sequence", + "singleDoseOn": "Single Dose on", + "vaccinationDate": "Vaccination date", + "vaccinationSaved": "Vaccination saved successfully", + "vaccine": "Vaccine" +} diff --git a/packages/esm-patient-labs-app/translations/zh.json b/packages/esm-patient-labs-app/translations/zh.json new file mode 100644 index 0000000000..91ae9389ce --- /dev/null +++ b/packages/esm-patient-labs-app/translations/zh.json @@ -0,0 +1,70 @@ +{ + "add": "Add", + "additionalInstructions": "Additional instructions", + "backToOrderBasket": "Back to order basket", + "backToTimeline": "Back to timeline", + "cancel": "Cancel", + "dataLoadError": "Data Load Error", + "date": "Date", + "dateCollected": "Displaying date collected", + "discard": "Discard", + "endDate": "End date", + "error": "Error", + "errorLoadingTestTypes": "Error occured when loading test types", + "female": "Female", + "full": "Full", + "incomplete": "Incomplete", + "labOrders": "Lab orders", + "labReferenceNumber": "Lab reference number", + "loading": "Loading", + "male": "Male", + "moreResultsAvailable": "More results available", + "observationsDisplayText": "observations", + "onDate": "on", + "orderActionNew": "New", + "ordered": "Ordered", + "other": "Other", + "panel": "Panel", + "print": "Print", + "printedBy": "Printed by", + "printTestResults": "Print test results", + "priority": "Priority", + "recentResults": "Recent Results", + "recentTestResults": "recent test results", + "referenceRange": "Reference range", + "removeFromBasket": "Remove from basket", + "resetTreeText": "Reset tree", + "resulted": "Resulted", + "results": "Results", + "Results Viewer": "Results Viewer", + "resultsText": "results", + "returnToTimeline": "Return to timeline", + "saveOrder": "Save order", + "seeAllResults": "See all results", + "showTree": "Show tree", + "split": "Split", + "startDate": "Start date", + "testName": "Test name", + "testResults": "test results", + "testResults_title": "Test Results", + "testResultsData": "Test results data", + "testType": "Test type", + "testTypePlaceholder": "Select one", + "thereAreNoTestResultsFound": "There are no test results found within the specified date range", + "timeline": "Timeline", + "timeOfTest": "Time of Test", + "tree": "Tree", + "trend": "Trend", + "trendline": "Trendline", + "trendlineRangeSelector1Day": "1 day", + "trendlineRangeSelector1Month": "1 month", + "trendlineRangeSelector1Year": "1 year", + "trendlineRangeSelector5Days": "5 days", + "trendlineRangeSelector5Years": "5 years", + "trendlineRangeSelectorAll": "All", + "trendlineRangeSelectorMonths": "6 months", + "tryReopeningTheForm": "Please try launching the form again", + "unknown": "Unknown", + "value": "Value", + "view": "View" +} diff --git a/packages/esm-patient-labs-app/translations/zh_CN.json b/packages/esm-patient-labs-app/translations/zh_CN.json new file mode 100644 index 0000000000..91ae9389ce --- /dev/null +++ b/packages/esm-patient-labs-app/translations/zh_CN.json @@ -0,0 +1,70 @@ +{ + "add": "Add", + "additionalInstructions": "Additional instructions", + "backToOrderBasket": "Back to order basket", + "backToTimeline": "Back to timeline", + "cancel": "Cancel", + "dataLoadError": "Data Load Error", + "date": "Date", + "dateCollected": "Displaying date collected", + "discard": "Discard", + "endDate": "End date", + "error": "Error", + "errorLoadingTestTypes": "Error occured when loading test types", + "female": "Female", + "full": "Full", + "incomplete": "Incomplete", + "labOrders": "Lab orders", + "labReferenceNumber": "Lab reference number", + "loading": "Loading", + "male": "Male", + "moreResultsAvailable": "More results available", + "observationsDisplayText": "observations", + "onDate": "on", + "orderActionNew": "New", + "ordered": "Ordered", + "other": "Other", + "panel": "Panel", + "print": "Print", + "printedBy": "Printed by", + "printTestResults": "Print test results", + "priority": "Priority", + "recentResults": "Recent Results", + "recentTestResults": "recent test results", + "referenceRange": "Reference range", + "removeFromBasket": "Remove from basket", + "resetTreeText": "Reset tree", + "resulted": "Resulted", + "results": "Results", + "Results Viewer": "Results Viewer", + "resultsText": "results", + "returnToTimeline": "Return to timeline", + "saveOrder": "Save order", + "seeAllResults": "See all results", + "showTree": "Show tree", + "split": "Split", + "startDate": "Start date", + "testName": "Test name", + "testResults": "test results", + "testResults_title": "Test Results", + "testResultsData": "Test results data", + "testType": "Test type", + "testTypePlaceholder": "Select one", + "thereAreNoTestResultsFound": "There are no test results found within the specified date range", + "timeline": "Timeline", + "timeOfTest": "Time of Test", + "tree": "Tree", + "trend": "Trend", + "trendline": "Trendline", + "trendlineRangeSelector1Day": "1 day", + "trendlineRangeSelector1Month": "1 month", + "trendlineRangeSelector1Year": "1 year", + "trendlineRangeSelector5Days": "5 days", + "trendlineRangeSelector5Years": "5 years", + "trendlineRangeSelectorAll": "All", + "trendlineRangeSelectorMonths": "6 months", + "tryReopeningTheForm": "Please try launching the form again", + "unknown": "Unknown", + "value": "Value", + "view": "View" +} diff --git a/packages/esm-patient-lists-app/translations/zh.json b/packages/esm-patient-lists-app/translations/zh.json new file mode 100644 index 0000000000..5d0ea7cc1e --- /dev/null +++ b/packages/esm-patient-lists-app/translations/zh.json @@ -0,0 +1,19 @@ +{ + "backToPatientLists": "Back to patient lists", + "checkFilters": "Check the filters above", + "createdOn": "Created on", + "identifier": "Identifier", + "listName": "List name", + "listType": "List type", + "name": "Name", + "noMatchingListsFound": "No matching lists to display", + "noMatchingPatients": "No matching patients to display", + "noPatientListsToDisplay": "No patient lists to display", + "noPatientsInList": "There are no patients in this list", + "numberOfPatients": "No. of patients", + "patientLists": "Patient lists", + "patients": "patients", + "searchThisList": "Search this list", + "sex": "Sex", + "startDate": "Start Date" +} diff --git a/packages/esm-patient-lists-app/translations/zh_CN.json b/packages/esm-patient-lists-app/translations/zh_CN.json new file mode 100644 index 0000000000..5d0ea7cc1e --- /dev/null +++ b/packages/esm-patient-lists-app/translations/zh_CN.json @@ -0,0 +1,19 @@ +{ + "backToPatientLists": "Back to patient lists", + "checkFilters": "Check the filters above", + "createdOn": "Created on", + "identifier": "Identifier", + "listName": "List name", + "listType": "List type", + "name": "Name", + "noMatchingListsFound": "No matching lists to display", + "noMatchingPatients": "No matching patients to display", + "noPatientListsToDisplay": "No patient lists to display", + "noPatientsInList": "There are no patients in this list", + "numberOfPatients": "No. of patients", + "patientLists": "Patient lists", + "patients": "patients", + "searchThisList": "Search this list", + "sex": "Sex", + "startDate": "Start Date" +} diff --git a/packages/esm-patient-medications-app/translations/zh.json b/packages/esm-patient-medications-app/translations/zh.json index b2173da811..99de0d0ec9 100644 --- a/packages/esm-patient-medications-app/translations/zh.json +++ b/packages/esm-patient-medications-app/translations/zh.json @@ -2,21 +2,19 @@ "activeMedicationsDisplayText": "Active medications", "activeMedicationsHeaderTitle": "active medications", "activeMedicationsTableTitle": "Active Medications", - "activeVisitRequired": "An active visit is required to make orders", "add": "添加", "backToOrderBasket": "Back to order basket", - "cancel": "取消", "clearSearchResults": "清除结果", "decrement": "Decrement", "details": "Details", "directlyAddToBasket": "Immediately add to basket", "discard": "放弃", "discontinue": "Discontinue", - "discontinuedOrders_one": "{count} discontinued order(s)", - "discontinuedOrders_other": "{count} discontinued order(s)", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. 用量说明", "dose": "剂量", + "drugAlreadyPrescribed": "Already prescribed", + "drugOrders": "Drug orders", "duration": "Duration", "durationUnit": "Duration unit", "durationUnitPlaceholder": "Duration Unit", @@ -27,35 +25,32 @@ "editDoseComboBoxTitle": "剂量", "editFrequencyComboBoxTitle": "Frequency", "editRouteComboBoxTitle": "Route", - "emptyOrderBasket": "Your basket is empty", "endDate": "End date", "error": "错误", - "errorCreatingAnEncounter": "创建问诊时出现错误", "errorFetchingDrugOrderTemplates": "获取药物医嘱模板时出现错误", "errorFetchingDrugResults": "Error fetching results for \"{searchTerm}\"", "errorFetchingOrderConfig": "获取医嘱配置时发生错误", + "female": "Female", "freeTextDosage": "自由文本剂量", + "goToDrugOrderForm": "Order form", "increment": "Increment", "indication": "Indication", "indicationPlaceholder": "e.g. \"Hypertension\"", + "male": "Male", "medicationDurationAndUnit": "for {duration} {durationUnit}", "medicationIndefiniteDuration": "无限期", - "medications": "Medications", + "Medications": "Medications", "modify": "修改", "none": "None", "noResultsForDrugSearch": "No results to display for \"{searchTerm}\"", + "onDate": "on", "orderActionDiscontinue": "Discontinue", + "orderActionIncomplete": "Incomplete", "orderActionNew": "New", - "orderActionRenewed": "Renew", - "orderActionRevised": "修改", - "orderBasket": "Order Basket", - "orderBasketWithCount_one": "Order Basket ({count})", - "orderBasketWithCount_other": "Order Basket ({count})", - "orderCompleted": "Order placed", - "orderCompletedSuccessText": "Your order is complete. The items will now appear on the Orders page.", + "orderActionRenew": "Renew", + "orderActionRevise": "Modify", "orderForm": "Order Form", - "ordersAlreadyInBasketWithCount_one": "{count} item(s) already in your basket", - "ordersAlreadyInBasketWithCount_other": "{count} item(s) already in your basket", + "other": "Other", "pastMedicationsDisplayText": "Past medications", "pastMedicationsHeaderTitle": "past medications", "pastMedicationsTableTitle": "Past Medications", @@ -63,6 +58,8 @@ "patientInstructionsPlaceholder": "Additional dosing instructions (e.g. \"Take after eating\")", "prescriptionDuration": "2. Prescription duration", "prescriptionRefills": "Prescription refills", + "print": "Print", + "printedBy": "Printed by", "prn": "P.R.N.", "prnReason": "P.R.N. reason", "prnReasonPlaceholder": "Reason to take medicine", @@ -70,25 +67,17 @@ "quantityToDispense": "Quantity to dispense", "refills": "Refills", "removeFromBasket": "Remove from basket", - "renewedOrders_one": "{count} order(s) being renewed (continued)", - "renewedOrders_other": "{count} order(s) being renewed (continued)", "reorder": "Reorder", - "revisedOrders_one": "{count} order(s) being modified (revised)", - "revisedOrders_other": "{count} order(s) being modified (revised)", "saveOrder": "Save order", "searchAgain": "重新搜索", "searchFieldPlaceholder": "Search for a drug or orderset (e.g. \"Aspirin\")", - "searchForAnOrder": "Search for an order above", "searchResultsMatchesForTerm_one": "{count} result{plural} for \"{searchTerm}\"", "searchResultsMatchesForTerm_other": "{count} result{plural} for \"{searchTerm}\"", - "signAndClose": "Sign and close", - "startAVisitToRecordOrders": "Start a visit to order", "startDate": "Start date", - "startVisit": "开始就诊", "takeAsNeeded": "Take as needed", "tryReopeningTheForm": "请尝试重新启动表单", - "tryReopeningTheWorkspaceAgain": "请尝试重新启动工作区", "trySearchingAgain": "请尝试重新搜索", "tryTo": "Try to", + "unknown": "Unknown", "usingADifferentTerm": "using a different term" } diff --git a/packages/esm-patient-medications-app/translations/zh_CN.json b/packages/esm-patient-medications-app/translations/zh_CN.json index b2173da811..9457035c60 100644 --- a/packages/esm-patient-medications-app/translations/zh_CN.json +++ b/packages/esm-patient-medications-app/translations/zh_CN.json @@ -2,21 +2,19 @@ "activeMedicationsDisplayText": "Active medications", "activeMedicationsHeaderTitle": "active medications", "activeMedicationsTableTitle": "Active Medications", - "activeVisitRequired": "An active visit is required to make orders", "add": "添加", "backToOrderBasket": "Back to order basket", - "cancel": "取消", "clearSearchResults": "清除结果", "decrement": "Decrement", "details": "Details", "directlyAddToBasket": "Immediately add to basket", "discard": "放弃", "discontinue": "Discontinue", - "discontinuedOrders_one": "{count} discontinued order(s)", - "discontinuedOrders_other": "{count} discontinued order(s)", "dispensingInformation": "3. Dispensing instructions", "dosageInstructions": "1. 用量说明", "dose": "剂量", + "drugAlreadyPrescribed": "Already prescribed", + "drugOrders": "Drug orders", "duration": "Duration", "durationUnit": "Duration unit", "durationUnitPlaceholder": "Duration Unit", @@ -27,35 +25,32 @@ "editDoseComboBoxTitle": "剂量", "editFrequencyComboBoxTitle": "Frequency", "editRouteComboBoxTitle": "Route", - "emptyOrderBasket": "Your basket is empty", "endDate": "End date", "error": "错误", - "errorCreatingAnEncounter": "创建问诊时出现错误", "errorFetchingDrugOrderTemplates": "获取药物医嘱模板时出现错误", "errorFetchingDrugResults": "Error fetching results for \"{searchTerm}\"", "errorFetchingOrderConfig": "获取医嘱配置时发生错误", + "female": "Female", "freeTextDosage": "自由文本剂量", + "goToDrugOrderForm": "Order form", "increment": "Increment", "indication": "Indication", "indicationPlaceholder": "e.g. \"Hypertension\"", + "male": "Male", "medicationDurationAndUnit": "for {duration} {durationUnit}", "medicationIndefiniteDuration": "无限期", - "medications": "Medications", + "Medications": "Medications", "modify": "修改", "none": "None", "noResultsForDrugSearch": "No results to display for \"{searchTerm}\"", + "onDate": "on", "orderActionDiscontinue": "Discontinue", + "orderActionIncomplete": "Incomplete", "orderActionNew": "New", - "orderActionRenewed": "Renew", - "orderActionRevised": "修改", - "orderBasket": "Order Basket", - "orderBasketWithCount_one": "Order Basket ({count})", - "orderBasketWithCount_other": "Order Basket ({count})", - "orderCompleted": "Order placed", - "orderCompletedSuccessText": "Your order is complete. The items will now appear on the Orders page.", + "orderActionRenew": "Renew", + "orderActionRevise": "Modify", "orderForm": "Order Form", - "ordersAlreadyInBasketWithCount_one": "{count} item(s) already in your basket", - "ordersAlreadyInBasketWithCount_other": "{count} item(s) already in your basket", + "other": "Other", "pastMedicationsDisplayText": "Past medications", "pastMedicationsHeaderTitle": "past medications", "pastMedicationsTableTitle": "Past Medications", @@ -63,6 +58,8 @@ "patientInstructionsPlaceholder": "Additional dosing instructions (e.g. \"Take after eating\")", "prescriptionDuration": "2. Prescription duration", "prescriptionRefills": "Prescription refills", + "print": "Print", + "printedBy": "Printed by", "prn": "P.R.N.", "prnReason": "P.R.N. reason", "prnReasonPlaceholder": "Reason to take medicine", @@ -70,25 +67,15 @@ "quantityToDispense": "Quantity to dispense", "refills": "Refills", "removeFromBasket": "Remove from basket", - "renewedOrders_one": "{count} order(s) being renewed (continued)", - "renewedOrders_other": "{count} order(s) being renewed (continued)", "reorder": "Reorder", - "revisedOrders_one": "{count} order(s) being modified (revised)", - "revisedOrders_other": "{count} order(s) being modified (revised)", "saveOrder": "Save order", "searchAgain": "重新搜索", "searchFieldPlaceholder": "Search for a drug or orderset (e.g. \"Aspirin\")", - "searchForAnOrder": "Search for an order above", - "searchResultsMatchesForTerm_one": "{count} result{plural} for \"{searchTerm}\"", - "searchResultsMatchesForTerm_other": "{count} result{plural} for \"{searchTerm}\"", - "signAndClose": "Sign and close", - "startAVisitToRecordOrders": "Start a visit to order", "startDate": "Start date", - "startVisit": "开始就诊", "takeAsNeeded": "Take as needed", "tryReopeningTheForm": "请尝试重新启动表单", - "tryReopeningTheWorkspaceAgain": "请尝试重新启动工作区", "trySearchingAgain": "请尝试重新搜索", "tryTo": "Try to", + "unknown": "Unknown", "usingADifferentTerm": "using a different term" } diff --git a/packages/esm-patient-notes-app/translations/zh.json b/packages/esm-patient-notes-app/translations/zh.json index b68a943c52..a16d2ea664 100644 --- a/packages/esm-patient-notes-app/translations/zh.json +++ b/packages/esm-patient-notes-app/translations/zh.json @@ -7,21 +7,21 @@ "clinicalNotePlaceholder": "Write any additional points here", "date": "日期", "diagnoses": "诊断", - "diagnosis": "Diagnosis", "discard": "放弃", "emptyDiagnosisText": "No diagnosis selected — Enter a diagnosis below", "enterPrimaryDiagnoses": "Enter Primary diagnoses", "enterSecondaryDiagnoses": "Enter Secondary diagnoses", - "goToSummary": "前往摘要", "image": "Image", "imageUploadHelperText": "Upload an image or use this device's camera to capture an image", "noMatchingDiagnoses": "No diagnoses found matching", "note": "Note", "noVisitNoteToDisplay": "No visit note to display", + "primaryDiagnosis": "Primary diagnosis", "primaryDiagnosisInputPlaceholder": "Choose a primary diagnosis", "saveAndClose": "保存并关闭", "searchForPrimaryDiagnosis": "Search for a Primary diagnosis", "searchForSecondaryDiagnosis": "Search for a Secondary diagnosis", + "secondaryDiagnosis": "Secondary diagnosis", "secondaryDiagnosisInputPlaceholder": "Choose a secondary diagnosis", "seeAll": "查看全部", "visitDate": "就诊日期", diff --git a/packages/esm-patient-notes-app/translations/zh_CN.json b/packages/esm-patient-notes-app/translations/zh_CN.json index b68a943c52..a16d2ea664 100644 --- a/packages/esm-patient-notes-app/translations/zh_CN.json +++ b/packages/esm-patient-notes-app/translations/zh_CN.json @@ -7,21 +7,21 @@ "clinicalNotePlaceholder": "Write any additional points here", "date": "日期", "diagnoses": "诊断", - "diagnosis": "Diagnosis", "discard": "放弃", "emptyDiagnosisText": "No diagnosis selected — Enter a diagnosis below", "enterPrimaryDiagnoses": "Enter Primary diagnoses", "enterSecondaryDiagnoses": "Enter Secondary diagnoses", - "goToSummary": "前往摘要", "image": "Image", "imageUploadHelperText": "Upload an image or use this device's camera to capture an image", "noMatchingDiagnoses": "No diagnoses found matching", "note": "Note", "noVisitNoteToDisplay": "No visit note to display", + "primaryDiagnosis": "Primary diagnosis", "primaryDiagnosisInputPlaceholder": "Choose a primary diagnosis", "saveAndClose": "保存并关闭", "searchForPrimaryDiagnosis": "Search for a Primary diagnosis", "searchForSecondaryDiagnosis": "Search for a Secondary diagnosis", + "secondaryDiagnosis": "Secondary diagnosis", "secondaryDiagnosisInputPlaceholder": "Choose a secondary diagnosis", "seeAll": "查看全部", "visitDate": "就诊日期", diff --git a/packages/esm-patient-orders-app/translations/zh.json b/packages/esm-patient-orders-app/translations/zh.json new file mode 100644 index 0000000000..c841d2072f --- /dev/null +++ b/packages/esm-patient-orders-app/translations/zh.json @@ -0,0 +1,22 @@ +{ + "add": "Add", + "addResults": "Add Results", + "cancelOrder": "Cancel Order", + "dateOfOrder": "Date of order", + "female": "Female", + "male": "Male", + "onDate": "on", + "order": "Order", + "orderedBy": "Ordered by", + "orderId": "Order ID", + "orders": "Orders", + "Orders": "Orders", + "orderType": "Order type", + "other": "Other", + "print": "Print", + "printedBy": "Printed by", + "priority": "Priority", + "status": "Status", + "unknown": "Unknown", + "viewEdit": "View/Edit Order" +} diff --git a/packages/esm-patient-orders-app/translations/zh_CN.json b/packages/esm-patient-orders-app/translations/zh_CN.json new file mode 100644 index 0000000000..c841d2072f --- /dev/null +++ b/packages/esm-patient-orders-app/translations/zh_CN.json @@ -0,0 +1,22 @@ +{ + "add": "Add", + "addResults": "Add Results", + "cancelOrder": "Cancel Order", + "dateOfOrder": "Date of order", + "female": "Female", + "male": "Male", + "onDate": "on", + "order": "Order", + "orderedBy": "Ordered by", + "orderId": "Order ID", + "orders": "Orders", + "Orders": "Orders", + "orderType": "Order type", + "other": "Other", + "print": "Print", + "printedBy": "Printed by", + "priority": "Priority", + "status": "Status", + "unknown": "Unknown", + "viewEdit": "View/Edit Order" +} diff --git a/packages/esm-patient-programs-app/translations/zh.json b/packages/esm-patient-programs-app/translations/zh.json index d601bf2ba1..7e84f1b7f1 100644 --- a/packages/esm-patient-programs-app/translations/zh.json +++ b/packages/esm-patient-programs-app/translations/zh.json @@ -5,15 +5,12 @@ "add": "Add", "cancel": "Cancel", "carePrograms": "Care Programs", - "chooseLocation": "Choose a location", "chooseProgram": "Choose a program", "completedOn": "Completed on", "configurePrograms": "Please configure programs to continue.", "dateCompleted": "Date completed", "dateEnrolled": "Date enrolled", - "discontinue": "Discontinue", - "enroll": "Enroll", - "enrollment": "Enrollment", + "editProgram": "Edit Program", "enrollmentLocation": "Enrollment location", "enrollmentNowVisible": "It is now visible in the Programs table", "enrollmentSaved": "Program enrollment saved", @@ -27,6 +24,7 @@ "programEnrollmentSaveError": "Error saving program enrollment", "programName": "Program name", "programs": "programs", + "Programs": "Programs", "required": "Required", "saveAndClose": "Save and close", "seeAll": "See all", diff --git a/packages/esm-patient-programs-app/translations/zh_CN.json b/packages/esm-patient-programs-app/translations/zh_CN.json index d601bf2ba1..7e84f1b7f1 100644 --- a/packages/esm-patient-programs-app/translations/zh_CN.json +++ b/packages/esm-patient-programs-app/translations/zh_CN.json @@ -5,15 +5,12 @@ "add": "Add", "cancel": "Cancel", "carePrograms": "Care Programs", - "chooseLocation": "Choose a location", "chooseProgram": "Choose a program", "completedOn": "Completed on", "configurePrograms": "Please configure programs to continue.", "dateCompleted": "Date completed", "dateEnrolled": "Date enrolled", - "discontinue": "Discontinue", - "enroll": "Enroll", - "enrollment": "Enrollment", + "editProgram": "Edit Program", "enrollmentLocation": "Enrollment location", "enrollmentNowVisible": "It is now visible in the Programs table", "enrollmentSaved": "Program enrollment saved", @@ -27,6 +24,7 @@ "programEnrollmentSaveError": "Error saving program enrollment", "programName": "Program name", "programs": "programs", + "Programs": "Programs", "required": "Required", "saveAndClose": "Save and close", "seeAll": "See all", diff --git a/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-form.component.tsx b/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-form.component.tsx index 043ee5a2b1..0213a463a7 100644 --- a/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-form.component.tsx +++ b/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-form.component.tsx @@ -335,6 +335,7 @@ const VitalsAndBiometricsForm: React.FC = ({ patientUuid, diastolicBloodPressure, ) } + showErrorMessage={showErrorMessage} label={t('bloodPressure', 'Blood pressure')} unitSymbol={conceptUnits.get(config.concepts.systolicBloodPressureUuid) ?? ''} /> @@ -358,6 +359,7 @@ const VitalsAndBiometricsForm: React.FC = ({ patientUuid, pulse && isValueWithinReferenceRange(conceptMetadata, config.concepts['pulseUuid'], pulse) } label={t('heartRate', 'Heart rate')} + showErrorMessage={showErrorMessage} unitSymbol={conceptUnits.get(config.concepts.pulseUuid) ?? ''} /> @@ -557,6 +559,7 @@ const VitalsAndBiometricsForm: React.FC = ({ patientUuid, setHasInvalidVitals(false)} title={t('vitalsAndBiometricsSaveError', 'Error saving vitals and biometrics')} subtitle={t('checkForValidity', 'Some of the values entered are invalid')} /> diff --git a/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-form.test.tsx b/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-form.test.tsx index 3472f6e6ab..d73bc9eac8 100644 --- a/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-form.test.tsx +++ b/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-form.test.tsx @@ -238,6 +238,33 @@ describe('VitalsBiometricsForm', () => { title: 'Error saving vitals and biometrics', }); }); + + it('Display an inline error notification on submit if value of vitals entered is invalid', async () => { + const user = userEvent.setup(); + + renderForm(); + const systolic = screen.getByRole('spinbutton', { name: /systolic/i }); + const pulse = screen.getByRole('spinbutton', { name: /pulse/i }); + const oxygenSaturation = screen.getByRole('spinbutton', { name: /oxygen saturation/i }); + const temperature = screen.getByRole('spinbutton', { name: /temperature/i }); + + await user.type(systolic, '1000'); + await user.type(pulse, pulseValue.toString()); + await user.type(oxygenSaturation, '200'); + await user.type(temperature, temperatureValue.toString()); + + const saveButton = screen.getByRole('button', { name: /save and close/i }); + await user.click(saveButton); + + expect(screen.getByText(/Some of the values entered are invalid/i)).toBeInTheDocument(); + + // close the inline notification --> resubmit --> check for presence of inline notification + const closeInlineNotificationButton = screen.getByTitle(/close notification/i); + await user.click(closeInlineNotificationButton); + expect(screen.queryByText(/some of the values entered are invalid/i)).not.toBeInTheDocument(); + await user.click(saveButton); + expect(screen.getByText(/Some of the values entered are invalid/i)).toBeInTheDocument(); + }); }); function renderForm() { diff --git a/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-input.test.tsx b/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-input.test.tsx index ed60cae2c3..2c47b97071 100644 --- a/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-input.test.tsx +++ b/packages/esm-patient-vitals-app/src/vitals-biometrics-form/vitals-biometrics-input.test.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import { screen, render } from '@testing-library/react'; +import { screen, render, cleanup } from '@testing-library/react'; import { useConfig } from '@openmrs/esm-framework'; import { assessValue, getReferenceRangesForConcept } from '../common'; import VitalsAndBiometricsInput from './vitals-biometrics-input.component'; - +import { isValueWithinReferenceRange } from './vitals-biometrics-form.utils'; +import { useVitalsConceptMetadata } from '@openmrs/esm-patient-common-lib'; +const { conceptRanges, conceptMetadata: mockConceptMetadata } = useVitalsConceptMetadata(); jest.mock('react-hook-form', () => ({ ...jest.requireActual('react-hook-form'), useFormContext: jest.fn().mockImplementation(() => ({ @@ -56,122 +58,120 @@ jest.mock('react-hook-form', () => ({ }), })); -const mockConceptMetadata = [ - { - uuid: '5085AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Systolic blood pressure', - hiNormal: 140, - hiAbsolute: 250, - hiCritical: 180, - lowNormal: 100, - lowAbsolute: 0, - lowCritical: 85, - units: 'mmHg', - }, - { - uuid: '5086AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Diastolic blood pressure', - hiNormal: 90, - hiAbsolute: 150, - hiCritical: 120, - lowNormal: 55, - lowAbsolute: 0, - lowCritical: 40, - units: 'mmHg', - }, - { - uuid: '5088AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Temperature (c)', - hiNormal: null, - hiAbsolute: 43, - hiCritical: null, - lowNormal: null, - lowAbsolute: 25, - lowCritical: null, - units: 'DEG C', - }, - { - uuid: '5090AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Height (cm)', - hiNormal: null, - hiAbsolute: 272, - hiCritical: null, - lowNormal: null, - lowAbsolute: 10, - lowCritical: null, - units: 'cm', - }, - { - uuid: '5089AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Weight (kg)', - hiNormal: null, - hiAbsolute: 250, - hiCritical: null, - lowNormal: null, - lowAbsolute: 0, - lowCritical: null, - units: 'kg', - }, - { - uuid: '5087AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Pulse', - hiNormal: 100, - hiAbsolute: 230, - hiCritical: 130, - lowNormal: 55, - lowAbsolute: 0, - lowCritical: 49, - units: 'beats/min', - }, - { - uuid: '5092AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Arterial blood oxygen saturation (pulse oximeter)', - hiNormal: null, - hiAbsolute: 100, - hiCritical: null, - lowNormal: 95, - lowAbsolute: 0, - lowCritical: 90, - units: '%', - }, - { - uuid: '1343AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Mid-upper arm circumference', - hiNormal: null, - hiAbsolute: null, - hiCritical: null, - lowNormal: null, - lowAbsolute: null, - lowCritical: null, - units: 'cm', - }, - { - uuid: '5242AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Respiratory rate', - hiNormal: 18, - hiAbsolute: 999, - hiCritical: 26, - lowNormal: 12, - lowAbsolute: 0, - lowCritical: 8, - units: 'breaths/min', - }, - { - uuid: '5283AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Karnofsky performance score', - hiNormal: null, - hiAbsolute: null, - hiCritical: null, - lowNormal: null, - lowAbsolute: null, - lowCritical: null, - units: '%', - }, -]; - jest.mock('@openmrs/esm-patient-common-lib', () => { const originalModule = jest.requireActual('@openmrs/esm-patient-common-lib'); - + const mockConceptMetadata = [ + { + uuid: '5085AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Systolic blood pressure', + hiNormal: 140, + hiAbsolute: 250, + hiCritical: 180, + lowNormal: 100, + lowAbsolute: 0, + lowCritical: 85, + units: 'mmHg', + }, + { + uuid: '5086AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Diastolic blood pressure', + hiNormal: 90, + hiAbsolute: 150, + hiCritical: 120, + lowNormal: 55, + lowAbsolute: 0, + lowCritical: 40, + units: 'mmHg', + }, + { + uuid: '5088AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Temperature (c)', + hiNormal: null, + hiAbsolute: 43, + hiCritical: null, + lowNormal: null, + lowAbsolute: 25, + lowCritical: null, + units: 'DEG C', + }, + { + uuid: '5090AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Height (cm)', + hiNormal: null, + hiAbsolute: 272, + hiCritical: null, + lowNormal: null, + lowAbsolute: 10, + lowCritical: null, + units: 'cm', + }, + { + uuid: '5089AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Weight (kg)', + hiNormal: null, + hiAbsolute: 250, + hiCritical: null, + lowNormal: null, + lowAbsolute: 0, + lowCritical: null, + units: 'kg', + }, + { + uuid: '5087AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Pulse', + hiNormal: 100, + hiAbsolute: 230, + hiCritical: 130, + lowNormal: 55, + lowAbsolute: 0, + lowCritical: 49, + units: 'beats/min', + }, + { + uuid: '5092AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Arterial blood oxygen saturation (pulse oximeter)', + hiNormal: null, + hiAbsolute: 100, + hiCritical: null, + lowNormal: 95, + lowAbsolute: 0, + lowCritical: 90, + units: '%', + }, + { + uuid: '1343AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Mid-upper arm circumference', + hiNormal: null, + hiAbsolute: null, + hiCritical: null, + lowNormal: null, + lowAbsolute: null, + lowCritical: null, + units: 'cm', + }, + { + uuid: '5242AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Respiratory rate', + hiNormal: 18, + hiAbsolute: 999, + hiCritical: 26, + lowNormal: 12, + lowAbsolute: 0, + lowCritical: 8, + units: 'breaths/min', + }, + { + uuid: '5283AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + display: 'Karnofsky performance score', + hiNormal: null, + hiAbsolute: null, + hiCritical: null, + lowNormal: null, + lowAbsolute: null, + lowCritical: null, + units: '%', + }, + ]; return { ...originalModule, useVitalsConceptMetadata: jest.fn().mockImplementation(() => ({ @@ -187,118 +187,18 @@ jest.mock('@openmrs/esm-patient-common-lib', () => { ['5242AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', 'breaths/min'], ['5283AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', '%'], ]), - conceptMetadata: [ - { - uuid: '5085AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Systolic blood pressure', - hiNormal: 140, - hiAbsolute: 250, - hiCritical: 180, - lowNormal: 100, - lowAbsolute: 0, - lowCritical: 85, - units: 'mmHg', - }, - { - uuid: '5086AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Diastolic blood pressure', - hiNormal: 90, - hiAbsolute: 150, - hiCritical: 120, - lowNormal: 55, - lowAbsolute: 0, - lowCritical: 40, - units: 'mmHg', - }, - { - uuid: '5088AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Temperature (c)', - hiNormal: null, - hiAbsolute: 43, - hiCritical: null, - lowNormal: null, - lowAbsolute: 25, - lowCritical: null, - units: 'DEG C', - }, - { - uuid: '5090AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Height (cm)', - hiNormal: null, - hiAbsolute: 272, - hiCritical: null, - lowNormal: null, - lowAbsolute: 10, - lowCritical: null, - units: 'cm', - }, - { - uuid: '5089AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Weight (kg)', - hiNormal: null, - hiAbsolute: 250, - hiCritical: null, - lowNormal: null, - lowAbsolute: 0, - lowCritical: null, - units: 'kg', - }, - { - uuid: '5087AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Pulse', - hiNormal: 100, - hiAbsolute: 230, - hiCritical: 130, - lowNormal: 55, - lowAbsolute: 0, - lowCritical: 49, - units: 'beats/min', - }, - { - uuid: '5092AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Arterial blood oxygen saturation (pulse oximeter)', - hiNormal: null, - hiAbsolute: 100, - hiCritical: null, - lowNormal: 95, - lowAbsolute: 0, - lowCritical: 90, - units: '%', - }, - { - uuid: '1343AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Mid-upper arm circumference', - hiNormal: null, - hiAbsolute: null, - hiCritical: null, - lowNormal: null, - lowAbsolute: null, - lowCritical: null, - units: 'cm', - }, - { - uuid: '5242AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Respiratory rate', - hiNormal: 18, - hiAbsolute: 999, - hiCritical: 26, - lowNormal: 12, - lowAbsolute: 0, - lowCritical: 8, - units: 'breaths/min', - }, - { - uuid: '5283AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', - display: 'Karnofsky performance score', - hiNormal: null, - hiAbsolute: null, - hiCritical: null, - lowNormal: null, - lowAbsolute: null, - lowCritical: null, - units: '%', - }, - ], + conceptMetadata: mockConceptMetadata, + conceptRanges: mockConceptMetadata?.length + ? new Map( + mockConceptMetadata.map((concept) => [ + concept.uuid, + { + lowAbsolute: concept.lowAbsolute ?? null, + highAbsolute: concept.hiAbsolute ?? null, + }, + ]), + ) + : new Map([]), })), }; }); @@ -311,6 +211,8 @@ jest.mock('@openmrs/esm-framework', () => { useConfig: jest.fn().mockReturnValue({ concepts: { pulseUuid: '5087AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + systoleUuid: '5085AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + diastoleUuid: '5086AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', }, }), }; @@ -318,12 +220,13 @@ jest.mock('@openmrs/esm-framework', () => { const testProps = { control: undefined, - isWithinNormalRange: true, + isValueWithinReferenceRange: true, fieldProperties: [], interpretation: undefined, placeholder: '', label: '', unitSymbol: '', + showErrorMessage: undefined, }; describe('VitalsAndBiometricsInput', () => { @@ -368,31 +271,62 @@ describe('VitalsAndBiometricsInput', () => { it('should validate the input based on the provided interpretation and reference range values', () => { const config = useConfig(); - - testProps.fieldProperties = [ + const fieldsToTest = [ { id: 'pulse', name: 'Heart rate', - min: 0, - max: 230, + min: conceptRanges.get(config.concepts.pulseUuid).lowAbsolute, + max: conceptRanges.get(config.concepts.pulseUuid).highAbsolute, + type: 'number', + uuid: config.concepts.pulseUuid, + value: 300, + unitSymbol: 'bpm', + abnormalValueClass: 'critically-high', + }, + + { + id: 'systole', + name: 'Systolic blood pressure', + min: conceptRanges.get(config.concepts.systoleUuid).lowAbsolute, + max: conceptRanges.get(config.concepts.systoleUuid).highAbsolute, type: 'number', + uuid: config.concepts.systoleUuid, + value: -1, + unitSymbol: 'mmHg', + abnormalValueClass: 'critically-low', }, ]; - testProps.interpretation = assessValue( - 300, - getReferenceRangesForConcept(config.concepts.pulseUuid, mockConceptMetadata), - ); - testProps.label = 'Heart rate'; - testProps.unitSymbol = 'bpm'; - renderVitalsBiometricsInput(); + fieldsToTest.forEach((field, index) => { + testProps.fieldProperties = [fieldsToTest[index]]; + testProps.isValueWithinReferenceRange = isValueWithinReferenceRange(mockConceptMetadata, field.uuid, field.value); + testProps.interpretation = assessValue( + field.value, + getReferenceRangesForConcept(field.uuid, mockConceptMetadata), + ); + testProps.label = field.name; + testProps.unitSymbol = field.unitSymbol; + testProps.showErrorMessage = true; + + renderVitalsBiometricsInput(); + + screen.findByRole('spinbutton'); - screen.findByRole('spinbutton'); + expect(screen.getByRole('spinbutton', { name: new RegExp(`${field.name}`, 'i') })).toBeInTheDocument(); + const abnormalValueFlag = screen.getByTitle(/abnormal value/i); + expect(abnormalValueFlag).toBeInTheDocument(); + expect(abnormalValueFlag).toHaveClass(field.abnormalValueClass); + expect( + screen.getByText( + new RegExp( + `Value must be between (${fieldsToTest[index].min}|{{min}}) and (${fieldsToTest[index].max}|{{max}})`, + 'i', + ), + ), + ).toBeInTheDocument(); - expect(screen.getByRole('spinbutton', { name: /heart rate/i })).toBeInTheDocument(); - const abnormalValueFlag = screen.getByTitle(/abnormal value/i); - expect(abnormalValueFlag).toBeInTheDocument(); - expect(abnormalValueFlag).toHaveClass('critically-high'); + cleanup(); + }); }); }); diff --git a/packages/esm-patient-vitals-app/translations/zh.json b/packages/esm-patient-vitals-app/translations/zh.json index ea2fd4f7c7..b2c9043d3a 100644 --- a/packages/esm-patient-vitals-app/translations/zh.json +++ b/packages/esm-patient-vitals-app/translations/zh.json @@ -1,24 +1,35 @@ { + "abnormalValue": "Abnormal value", "add": "添加", "additionalNoteText": "Type any additional notes here", + "biometricDisplayed": "Biometric displayed", + "biometrics": "Biometrics", + "biometrics_lower": "biometrics", "bloodPressure": "血压", "bmi": "BMI", - "bmiCalc": "BMI (calc.)", "bp": "血压", - "chartView": "图表视图", + "calculatedBmi": "BMI (calc.)", "checkForValidity": "输入的一些值无效", + "date": "Date", + "dateAndTime": "Date and time", "diastolic": "舒张压", "discard": "放弃", + "error": "Error", + "female": "Female", "goToSummary": "前往摘要", "heartRate": "心率", "height": "身高", - "lastRecorded": "上次记录", "loading": "加载中", + "male": "Male", "muac": "中上臂围", "noDataRecorded": "该患者尚未记录任何数据", "notes": "Notes", - "numericInputError": "必须是在可接受范围内的数字", + "other": "Other", + "overdue": "Overdue", "oxygenSaturation": "血氧饱和度", + "pleaseFillField": "Please fill at least one field", + "print": "Print", + "printedBy": "Printed by", "pulse": "脉搏", "recordBiometrics": "记录生物特征", "recordVitals": "记录生命体征", @@ -28,15 +39,18 @@ "seeAll": "查看全部", "spo2": "血氧", "systolic": "收缩压", - "tableView": "表格视图", "temp": "体温", "temperature": "体温", "temperatureAbbreviated": "体温", + "unknown": "Unknown", + "validationInputError": "Value must be between {{min}} and {{max}}", "vitals": "生命体征", + "Vitals & Biometrics": "Vitals & Biometrics", "vitalsAndBiometrics": "生命体征和生物特征", "vitalsAndBiometricsNowAvailable": "现在在生命体征和生物特征页面上可见", "vitalsAndBiometricsRecorded": "生命体征和生物特征数据已保存", "vitalsAndBiometricsSaveError": "保存生命体征和生物特征数据时出现错误", + "vitalsHistory": "Vitals history", "vitalSignDisplayed": "生命体征已显示", "vitalSigns": "生命体征", "weight": "体重" diff --git a/packages/esm-patient-vitals-app/translations/zh_CN.json b/packages/esm-patient-vitals-app/translations/zh_CN.json index ea2fd4f7c7..b2c9043d3a 100644 --- a/packages/esm-patient-vitals-app/translations/zh_CN.json +++ b/packages/esm-patient-vitals-app/translations/zh_CN.json @@ -1,24 +1,35 @@ { + "abnormalValue": "Abnormal value", "add": "添加", "additionalNoteText": "Type any additional notes here", + "biometricDisplayed": "Biometric displayed", + "biometrics": "Biometrics", + "biometrics_lower": "biometrics", "bloodPressure": "血压", "bmi": "BMI", - "bmiCalc": "BMI (calc.)", "bp": "血压", - "chartView": "图表视图", + "calculatedBmi": "BMI (calc.)", "checkForValidity": "输入的一些值无效", + "date": "Date", + "dateAndTime": "Date and time", "diastolic": "舒张压", "discard": "放弃", + "error": "Error", + "female": "Female", "goToSummary": "前往摘要", "heartRate": "心率", "height": "身高", - "lastRecorded": "上次记录", "loading": "加载中", + "male": "Male", "muac": "中上臂围", "noDataRecorded": "该患者尚未记录任何数据", "notes": "Notes", - "numericInputError": "必须是在可接受范围内的数字", + "other": "Other", + "overdue": "Overdue", "oxygenSaturation": "血氧饱和度", + "pleaseFillField": "Please fill at least one field", + "print": "Print", + "printedBy": "Printed by", "pulse": "脉搏", "recordBiometrics": "记录生物特征", "recordVitals": "记录生命体征", @@ -28,15 +39,18 @@ "seeAll": "查看全部", "spo2": "血氧", "systolic": "收缩压", - "tableView": "表格视图", "temp": "体温", "temperature": "体温", "temperatureAbbreviated": "体温", + "unknown": "Unknown", + "validationInputError": "Value must be between {{min}} and {{max}}", "vitals": "生命体征", + "Vitals & Biometrics": "Vitals & Biometrics", "vitalsAndBiometrics": "生命体征和生物特征", "vitalsAndBiometricsNowAvailable": "现在在生命体征和生物特征页面上可见", "vitalsAndBiometricsRecorded": "生命体征和生物特征数据已保存", "vitalsAndBiometricsSaveError": "保存生命体征和生物特征数据时出现错误", + "vitalsHistory": "Vitals history", "vitalSignDisplayed": "生命体征已显示", "vitalSigns": "生命体征", "weight": "体重" diff --git a/tools/test-utils.tsx b/tools/test-utils.tsx index 770fd42982..43e4fdaf6d 100644 --- a/tools/test-utils.tsx +++ b/tools/test-utils.tsx @@ -23,9 +23,11 @@ export const renderWithSwr = (ui, options?) => render(ui, { wrapper: swrWrapper, // Helper function that waits for a loading state to disappear from the screen export function waitForLoadingToFinish() { - return waitForElementToBeRemoved(() => [...screen.queryAllByRole('progressbar')], { - timeout: 4000, - }); + if (screen.queryAllByRole('progressbar').length) { + return waitForElementToBeRemoved(() => [...screen.queryAllByRole('progressbar')], { + timeout: 4000, + }); + } } // Custom matcher that queries elements split up by multiple HTML elements by text @@ -59,14 +61,14 @@ export const mockPatient = { id: '1f0ad7a1-430f-4397-b571-59ea654a52db', use: 'secondary', system: 'Old Identification Number', - type: { text: 'Old Identification Number' }, + type: { text: 'Old Identification Number', coding: [{ code: 'Old Identification Number' }] }, value: '100732HE', }, { id: '1f0ad7a1-430f-4397-b571-59ea654a52db', use: 'usual', system: 'OpenMRS ID', - type: { text: 'OpenMRS ID' }, + type: { text: 'OpenMRS ID', coding: [{ code: 'OpenMRS ID' }] }, value: '100GEJ', }, ], diff --git a/yarn.lock b/yarn.lock index 8703d34761..29f3fc9550 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2044,6 +2044,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.14.8": + version: 7.23.8 + resolution: "@babel/runtime@npm:7.23.8" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 0bd5543c26811153822a9f382fd39886f66825ff2a397a19008011376533747cd05c33a91f6248c0b8b0edf0448d7c167ebfba34786088f1b7eb11c65be7dfc3 + languageName: node + linkType: hard + "@babel/template@npm:7.22.5": version: 7.22.5 resolution: "@babel/template@npm:7.22.5" @@ -2184,7 +2193,7 @@ __metadata: languageName: node linkType: hard -"@carbon/colors@npm:^11.20.1": +"@carbon/colors@npm:^11.20.0, @carbon/colors@npm:^11.20.1": version: 11.20.1 resolution: "@carbon/colors@npm:11.20.1" checksum: eb9d983c1ec4852f8542ea21f8bb31d383c417d55fe60a3d1ab8a0e85b617f41699b91657240f07f789b852abe48828f1546da92b1c46de9cfe21c81bb612fd7 @@ -2214,6 +2223,15 @@ __metadata: languageName: node linkType: hard +"@carbon/grid@npm:^11.21.0, @carbon/grid@npm:^11.21.1": + version: 11.21.1 + resolution: "@carbon/grid@npm:11.21.1" + dependencies: + "@carbon/layout": ^11.20.1 + checksum: e9bcb0940f6714f428864c8ec356c41c556e802694ede484259235cfc806a021fc498cc6e4f6e2014303ecfdf459ad4b0134820d0d92722f2ceafc9287321a0c + languageName: node + linkType: hard + "@carbon/icon-helpers@npm:^10.44.0": version: 10.44.0 resolution: "@carbon/icon-helpers@npm:10.44.0" @@ -2228,20 +2246,20 @@ __metadata: languageName: node linkType: hard -"@carbon/icons-react@npm:^11.28.0": - version: 11.28.0 - resolution: "@carbon/icons-react@npm:11.28.0" +"@carbon/icons-react@npm:11.26.0": + version: 11.26.0 + resolution: "@carbon/icons-react@npm:11.26.0" dependencies: "@carbon/icon-helpers": ^10.44.0 "@carbon/telemetry": 0.1.0 prop-types: ^15.7.2 peerDependencies: react: ">=16" - checksum: c52c63835b43feb3177c4a90161dfb5191a542be0dfe6a3196af96a675f58b75e6c82718413653a313829c04c06d68072a21be66f7d36e39566e61609debaabd + checksum: dabc6e7896d2a089aaabac78af9161720995f9e5b0f28694ac664459c5fae164a3d0c16b9cb22f6ab37f01b736cd2613cf232a6b6577b396afd8c083171cae67 languageName: node linkType: hard -"@carbon/icons-react@npm:^11.33.0": +"@carbon/icons-react@npm:^11.26.0, @carbon/icons-react@npm:^11.33.0": version: 11.33.0 resolution: "@carbon/icons-react@npm:11.33.0" dependencies: @@ -2254,6 +2272,19 @@ __metadata: languageName: node linkType: hard +"@carbon/icons-react@npm:^11.28.0": + version: 11.28.0 + resolution: "@carbon/icons-react@npm:11.28.0" + dependencies: + "@carbon/icon-helpers": ^10.44.0 + "@carbon/telemetry": 0.1.0 + prop-types: ^15.7.2 + peerDependencies: + react: ">=16" + checksum: c52c63835b43feb3177c4a90161dfb5191a542be0dfe6a3196af96a675f58b75e6c82718413653a313829c04c06d68072a21be66f7d36e39566e61609debaabd + languageName: node + linkType: hard + "@carbon/layout@npm:^11.19.0, @carbon/layout@npm:^11.7.0": version: 11.19.0 resolution: "@carbon/layout@npm:11.19.0" @@ -2261,6 +2292,13 @@ __metadata: languageName: node linkType: hard +"@carbon/layout@npm:^11.20.0, @carbon/layout@npm:^11.20.1": + version: 11.20.1 + resolution: "@carbon/layout@npm:11.20.1" + checksum: 8db3a31c08ab1fc62bd06404a72ca1e724c938d1ac73c708a63b06103fe054a5ab4294b1fba3471e3f55140ebe0e91e32872a2828dda73a32801fccb670acd35 + languageName: node + linkType: hard + "@carbon/motion@npm:^11.15.0, @carbon/motion@npm:^11.5.0": version: 11.15.0 resolution: "@carbon/motion@npm:11.15.0" @@ -2268,7 +2306,14 @@ __metadata: languageName: node linkType: hard -"@carbon/react@npm:^1.12.0, @carbon/react@npm:^1.33.1, @carbon/react@npm:^1.37.0": +"@carbon/motion@npm:^11.16.0": + version: 11.16.1 + resolution: "@carbon/motion@npm:11.16.1" + checksum: 1b7644fb19a9154a7d690128ed2fe831232576308dfeb30c694d533e5f8d357dbaf1b3bed7d4c274acb407d84d1ade087583d4f9aec4a8ac1aa9dfffb6922098 + languageName: node + linkType: hard + +"@carbon/react@npm:^1.12.0, @carbon/react@npm:^1.33.1": version: 1.40.0 resolution: "@carbon/react@npm:1.40.0" dependencies: @@ -2301,6 +2346,60 @@ __metadata: languageName: node linkType: hard +"@carbon/react@npm:~1.37.0": + version: 1.37.0 + resolution: "@carbon/react@npm:1.37.0" + dependencies: + "@babel/runtime": ^7.18.3 + "@carbon/feature-flags": ^0.16.0 + "@carbon/icons-react": ^11.26.0 + "@carbon/layout": ^11.19.0 + "@carbon/styles": ^1.37.0 + "@carbon/telemetry": 0.1.0 + classnames: 2.3.2 + copy-to-clipboard: ^3.3.1 + downshift: 8.1.0 + flatpickr: 4.6.9 + invariant: ^2.2.3 + lodash.debounce: ^4.0.8 + lodash.findlast: ^4.5.0 + lodash.isequal: ^4.5.0 + lodash.omit: ^4.5.0 + lodash.throttle: ^4.1.1 + prop-types: ^15.7.2 + react-is: ^18.2.0 + use-resize-observer: ^6.0.0 + wicg-inert: ^3.1.1 + window-or-global: ^1.0.1 + peerDependencies: + react: ^16.8.6 || ^17.0.1 || ^18.2.0 + react-dom: ^16.8.6 || ^17.0.1 || ^18.2.0 + sass: ^1.33.0 + checksum: 40ba04d687462d178227080582a074ca6a7b7515f7f08f602fef9fd96bb90918e0051d5ce7adc9c9a5140bd9f724634a14fd06701afa23aa2bd023c6d14efd44 + languageName: node + linkType: hard + +"@carbon/styles@npm:^1.37.0": + version: 1.47.0 + resolution: "@carbon/styles@npm:1.47.0" + dependencies: + "@carbon/colors": ^11.20.0 + "@carbon/feature-flags": ^0.16.0 + "@carbon/grid": ^11.21.0 + "@carbon/layout": ^11.20.0 + "@carbon/motion": ^11.16.0 + "@carbon/themes": ^11.28.0 + "@carbon/type": ^11.25.0 + "@ibm/plex": 6.0.0-next.6 + peerDependencies: + sass: ^1.33.0 + peerDependenciesMeta: + sass: + optional: true + checksum: 29dd2d1728bcff844632e242d4743706a74268c1b33e0b54b1f12f2811b86b5317a2a7022fa69c08a1eb494140d7d20e5c432db1b18bde6754a445d7bf857083 + languageName: node + linkType: hard + "@carbon/styles@npm:^1.40.0": version: 1.40.0 resolution: "@carbon/styles@npm:1.40.0" @@ -2361,6 +2460,18 @@ __metadata: languageName: node linkType: hard +"@carbon/themes@npm:^11.28.0": + version: 11.28.0 + resolution: "@carbon/themes@npm:11.28.0" + dependencies: + "@carbon/colors": ^11.20.0 + "@carbon/layout": ^11.20.0 + "@carbon/type": ^11.25.0 + color: ^4.0.0 + checksum: 52bc43b1b5ee846afc870c1898fadd3efe258fa66cb0e66672a1e20179c3833d6e517be433b339f6538887593342aba27f3130c0c3a61646c505eb16b24e06c2 + languageName: node + linkType: hard + "@carbon/type@npm:^11.10.0, @carbon/type@npm:^11.24.0": version: 11.24.0 resolution: "@carbon/type@npm:11.24.0" @@ -2371,6 +2482,16 @@ __metadata: languageName: node linkType: hard +"@carbon/type@npm:^11.25.0": + version: 11.25.1 + resolution: "@carbon/type@npm:11.25.1" + dependencies: + "@carbon/grid": ^11.21.1 + "@carbon/layout": ^11.20.1 + checksum: 5184b9cddf050d06dbc3a369400c149e594cd281e090eb0fea972ef964b741ca94c20b828cb6c138be0812861d335d0abbabfe78b368483a5a97bf2ad7e1fc68 + languageName: node + linkType: hard + "@carbon/utils-position@npm:^1.1.4": version: 1.1.4 resolution: "@carbon/utils-position@npm:1.1.4" @@ -4267,27 +4388,28 @@ __metadata: languageName: node linkType: hard -"@openmrs/esm-api@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-api@npm:5.2.1-pre.1168" +"@openmrs/esm-api@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-api@npm:5.3.3-pre.1404" dependencies: "@types/fhir": 0.0.31 lodash-es: ^4.17.21 peerDependencies: "@openmrs/esm-config": 5.x "@openmrs/esm-error-handling": 5.x + "@openmrs/esm-navigation": 5.x "@openmrs/esm-offline": 5.x - checksum: 7d80245995dd6541c7cab36fbe1b28335e42fd955d8daf62a1f86fc5c2d748640f0c117fb232aabe26ffec5fb5a1959502657357f60ffab981e9a5d7d705522d + checksum: 875b3b199565cc44474190be1a10563956cd6e855594f9615ab1ba5b72ca0ab451129d87b1994ef293705cd3619d5264cdece57dc18a7363b4694305d5aaa3e6 languageName: node linkType: hard -"@openmrs/esm-app-shell@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-app-shell@npm:5.2.1-pre.1168" +"@openmrs/esm-app-shell@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-app-shell@npm:5.3.3-pre.1404" dependencies: - "@carbon/react": ^1.37.0 - "@openmrs/esm-framework": 5.2.1-pre.1168 - "@openmrs/esm-styleguide": 5.2.1-pre.1168 + "@carbon/react": ~1.37.0 + "@openmrs/esm-framework": 5.3.3-pre.1404 + "@openmrs/esm-styleguide": 5.3.3-pre.1404 dayjs: ^1.10.4 dexie: ^3.0.3 html-webpack-plugin: ^5.5.0 @@ -4301,7 +4423,7 @@ __metadata: react-router-dom: ^6.3.0 rxjs: ^6.5.3 semver: ^7.3.4 - single-spa: ^5.9.2 + single-spa: ^6.0.0 swc-loader: ^0.2.3 swr: ^2.2.2 systemjs: ^6.8.3 @@ -4312,55 +4434,44 @@ __metadata: workbox-strategies: ^6.1.5 workbox-webpack-plugin: ^6.1.5 workbox-window: ^6.1.5 - checksum: 8cc7e727b002f4126ee6dfb4773aa4fa320c2fda54258f280bfa967fe717b0d5e5c6cb3d0f9df9064f54fa7f4d5ca3d8b9795730405c5c15ff92dd89ef4ce35f + checksum: 03669949fab620a034e9835764e44afb395dbc3feb310cad336a11743a64b91676d8d40816edbbddab85aaee3689796a6d55c3620f14b2e9b852774712e0d44f languageName: node linkType: hard -"@openmrs/esm-breadcrumbs@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-breadcrumbs@npm:5.2.1-pre.1168" - dependencies: - path-to-regexp: 6.1.0 - peerDependencies: - "@openmrs/esm-state": 5.x - checksum: a86e86e69e491a27a749c5b949e334b90ee3ff63b2a3583a208ed95da043f94108711f1b1ae21acb0222e53ca42bbbe06e2ba11d3beeece75889b8dc2504d601 - languageName: node - linkType: hard - -"@openmrs/esm-config@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-config@npm:5.2.1-pre.1168" +"@openmrs/esm-config@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-config@npm:5.3.3-pre.1404" dependencies: ramda: ^0.26.1 peerDependencies: "@openmrs/esm-globals": 5.x "@openmrs/esm-state": 5.x single-spa: 5.x - checksum: 883d5b52c7997f63f86898b0e43f034edf9332c7fdc9eb4c125a8440d9f2a32516d0c4272e565e320889d1ec9cb683062545984d3a2cb912f83220c79dd7050d + checksum: 93a61dc50091f19f8a92dd2575950364b0d58dca7c4d88dabaf11e39bee6bd0d008173cdf1cd60d9e622b639717b99791b8fa8a47395cc924b784c5b8d03ca75 languageName: node linkType: hard -"@openmrs/esm-dynamic-loading@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-dynamic-loading@npm:5.2.1-pre.1168" +"@openmrs/esm-dynamic-loading@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-dynamic-loading@npm:5.3.3-pre.1404" peerDependencies: "@openmrs/esm-globals": 5.x - checksum: a1b1e0042b48d4d28bbc58c6287f997dfffcdb259ab749e8638f5f4aabcc714d36b0af0698245d114ab13cb432fc7bf0d9a828de0896eec78034e664ef396d67 + checksum: 932af656d8c6d70a1731ef23f08446e2747b89d41e82ebfa1f2d88e227b083e578dd7eb096ecbad0cfb5b877e087287589f060c5a7794f71ae048614d6145e37 languageName: node linkType: hard -"@openmrs/esm-error-handling@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-error-handling@npm:5.2.1-pre.1168" +"@openmrs/esm-error-handling@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-error-handling@npm:5.3.3-pre.1404" peerDependencies: "@openmrs/esm-globals": 5.x - checksum: 2c7d90d03aad3fae75b8b19b9cc3a4a8ea048d459ceac74f92819cc7afd36aefb164a27e0e4381487cb95ea84f1cd040df8b685a35764d54ee149be4aa1d1578 + checksum: 7045047385a3486c89579f5fcb747df86f7185b30cedddd7eeb73fd110ad3d3e330dac11ba2af0dfff45e26f4392d679e1e1f335c72d09c7b0f6ff16a4e23d7d languageName: node linkType: hard -"@openmrs/esm-extensions@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-extensions@npm:5.2.1-pre.1168" +"@openmrs/esm-extensions@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-extensions@npm:5.3.3-pre.1404" dependencies: lodash-es: ^4.17.21 peerDependencies: @@ -4369,20 +4480,20 @@ __metadata: "@openmrs/esm-feature-flags": 5.x "@openmrs/esm-state": 5.x single-spa: 5.x - checksum: 73255c4cd7013a5f8642919c6c83ec851a7308e629d6853d8df1dc7c0740c0aa6c4940830f62e1cd991747f1a242055580fe10efd265b5c1d4b7a15afda4fb5f + checksum: a1a6264a70aa18ee1603005d295cb773e3cd2d8488721018ab5e859231fb2e668a2ea7b240bb10e8d759411431dea080dca5602948361aca8685ef554c059759 languageName: node linkType: hard -"@openmrs/esm-feature-flags@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-feature-flags@npm:5.2.1-pre.1168" +"@openmrs/esm-feature-flags@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-feature-flags@npm:5.3.3-pre.1404" dependencies: ramda: ^0.26.1 peerDependencies: "@openmrs/esm-globals": 5.x "@openmrs/esm-state": 5.x single-spa: 5.x - checksum: e8bfa9c5c12e1e4dd73ecb1da98064c6ab2150add5f542da574207c963932b6a9cccd086373dbadcfec8298ffaba0efea6862f1e298b68821be9bcdc56ef7d26 + checksum: 011792fefea3cb069f63492501ee55353708398dfcb523916110198d7417a898993f7e12d8c84f17ab3b90c210433356a342fcd58481a3040d4d70d8af311184 languageName: node linkType: hard @@ -4477,23 +4588,24 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-framework@npm:5.2.1-pre.1168, @openmrs/esm-framework@npm:next": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-framework@npm:5.2.1-pre.1168" - dependencies: - "@openmrs/esm-api": 5.2.1-pre.1168 - "@openmrs/esm-breadcrumbs": 5.2.1-pre.1168 - "@openmrs/esm-config": 5.2.1-pre.1168 - "@openmrs/esm-dynamic-loading": 5.2.1-pre.1168 - "@openmrs/esm-error-handling": 5.2.1-pre.1168 - "@openmrs/esm-extensions": 5.2.1-pre.1168 - "@openmrs/esm-feature-flags": 5.2.1-pre.1168 - "@openmrs/esm-globals": 5.2.1-pre.1168 - "@openmrs/esm-offline": 5.2.1-pre.1168 - "@openmrs/esm-react-utils": 5.2.1-pre.1168 - "@openmrs/esm-state": 5.2.1-pre.1168 - "@openmrs/esm-styleguide": 5.2.1-pre.1168 - "@openmrs/esm-utils": 5.2.1-pre.1168 +"@openmrs/esm-framework@npm:5.3.3-pre.1404, @openmrs/esm-framework@npm:next": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-framework@npm:5.3.3-pre.1404" + dependencies: + "@openmrs/esm-api": 5.3.3-pre.1404 + "@openmrs/esm-config": 5.3.3-pre.1404 + "@openmrs/esm-dynamic-loading": 5.3.3-pre.1404 + "@openmrs/esm-error-handling": 5.3.3-pre.1404 + "@openmrs/esm-extensions": 5.3.3-pre.1404 + "@openmrs/esm-feature-flags": 5.3.3-pre.1404 + "@openmrs/esm-globals": 5.3.3-pre.1404 + "@openmrs/esm-navigation": 5.3.3-pre.1404 + "@openmrs/esm-offline": 5.3.3-pre.1404 + "@openmrs/esm-react-utils": 5.3.3-pre.1404 + "@openmrs/esm-routes": 5.3.3-pre.1404 + "@openmrs/esm-state": 5.3.3-pre.1404 + "@openmrs/esm-styleguide": 5.3.3-pre.1404 + "@openmrs/esm-utils": 5.3.3-pre.1404 dayjs: ^1.10.7 peerDependencies: dayjs: 1.x @@ -4504,7 +4616,7 @@ __metadata: rxjs: 6.x single-spa: 5.x swr: 2.x - checksum: 035c0e92d54bcd0e003394946cfb4fff6f71283da880544a14bd6ef3eea1cbc2793b6ff8d390834bdc6ca4f07d1bddb0dfb6f1a8f15dff94a06910ddaad41f14 + checksum: 3e90fbf513e134bfd3ca7784a7518831d4b4aaf339690ce27856d3d13a05c7c2a574085930bec42d305dccf4857b7385e253cc9264f1d783245605e76c4ea93a languageName: node linkType: hard @@ -4530,18 +4642,29 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-globals@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-globals@npm:5.2.1-pre.1168" +"@openmrs/esm-globals@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-globals@npm:5.3.3-pre.1404" peerDependencies: single-spa: 5.x - checksum: 8ee32c7fc5b4b5484a8be4d109bfbc27d991376e50d1a5bd4983920d79e7558d6dece9e3ce9cbb6319e737b285126a808d2555e510f1ed4f96c86a2730675ba5 + checksum: 1a378c4246a2aff8e8e1eaf2ac576c03af2aa642f5a3c33f8543eb348a94987f87999a17f6c743e4b2b5ae35110d9cba402f3701f3185a338fe40246f8b127b0 + languageName: node + linkType: hard + +"@openmrs/esm-navigation@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-navigation@npm:5.3.3-pre.1404" + dependencies: + path-to-regexp: 6.1.0 + peerDependencies: + "@openmrs/esm-state": 5.x + checksum: e510862e5d29657319c1869eb724ac708f5fbe57870a9ddf5a39d9e9b546426e717406255267354b75bbd22fc0300e2b50fac7d2fc78914d677a559f5b94718f languageName: node linkType: hard -"@openmrs/esm-offline@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-offline@npm:5.2.1-pre.1168" +"@openmrs/esm-offline@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-offline@npm:5.3.3-pre.1404" dependencies: dexie: ^3.0.3 lodash-es: ^4.17.21 @@ -4553,7 +4676,7 @@ __metadata: "@openmrs/esm-state": 5.x "@openmrs/esm-styleguide": 5.x rxjs: 6.x - checksum: b9605c88deabbcdbb18b03b15daa335a10f970611a7c2e9b9af26420a7dc4ac713d514617de73067512892365dc9bdacf7e9aca299493782e1a0b27cfb44a6a4 + checksum: b492415acece28e1ae177ea9b2c5e0bf2d243dd009d33fbe69d93a0954fe9924e20986aadc7ffd373137390022d0839ba3a33e86398f47a4d22a2fed37c51621 languageName: node linkType: hard @@ -4963,18 +5086,19 @@ __metadata: languageName: unknown linkType: soft -"@openmrs/esm-react-utils@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-react-utils@npm:5.2.1-pre.1168" +"@openmrs/esm-react-utils@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-react-utils@npm:5.3.3-pre.1404" dependencies: lodash-es: ^4.17.21 - single-spa-react: ~5.0.0 + single-spa-react: ^6.0.0 peerDependencies: "@openmrs/esm-api": 5.x "@openmrs/esm-config": 5.x "@openmrs/esm-error-handling": 5.x "@openmrs/esm-extensions": 5.x "@openmrs/esm-globals": 5.x + "@openmrs/esm-navigation": 5.x dayjs: 1.x i18next: 19.x react: 18.x @@ -4982,27 +5106,37 @@ __metadata: react-i18next: 11.x rxjs: 6.x swr: 2.x - checksum: bdbc8dc4b65bc5eb36f25dda684c1ac29a1dee2bd904852f7cbbc8d5af539c0e3155401d570e678029a6539918bad4cdddc3db75048757054e393aaae3c54da7 + checksum: 5b1e7f1359e58d83bd05480fa33fc19a3b94d7415f8fdcc2e6ec0943f4a423e523ea64586110f7d0c5ebc910f68ee5716eb1f69ce3f2dbc5394f7ce2746e657b languageName: node linkType: hard -"@openmrs/esm-state@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-state@npm:5.2.1-pre.1168" +"@openmrs/esm-routes@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-routes@npm:5.3.3-pre.1404" + peerDependencies: + "@openmrs/esm-globals": 5.x + "@openmrs/esm-utils": 5.x + checksum: 7ddf83879362fd9680bae4c43598abac9433f98d608de869e6ad4476050758acc63868752520e7cf11c2392e9892e489fb0277e3c819afe78d081f73c1d74904 + languageName: node + linkType: hard + +"@openmrs/esm-state@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-state@npm:5.3.3-pre.1404" dependencies: zustand: ^4.3.6 peerDependencies: "@openmrs/esm-globals": 5.x - checksum: a091c43f49feb1cf8e60fa9d5daf85696e0c7a22b0813fcefd54cb772ed34f9b28bacb9075d3e15dc9ceaa07542ac6041d0a093e6a750ffe1c6b1d6217ad2358 + checksum: 989795e206c0f2ccb375a9ae9c2304803e22af4113f51ae974a61f5be31dab7b2edaf063fe653276573bf37bde980fd9b51abce7861df313308d9b5124831a8f languageName: node linkType: hard -"@openmrs/esm-styleguide@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-styleguide@npm:5.2.1-pre.1168" +"@openmrs/esm-styleguide@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-styleguide@npm:5.3.3-pre.1404" dependencies: "@carbon/charts": ^1.12.0 - "@carbon/react": ^1.37.0 + "@carbon/react": ~1.37.0 "@internationalized/date": ^3.5.0 "@react-spectrum/datepicker": ^3.8.0 "@react-spectrum/provider": ^3.9.0 @@ -5018,20 +5152,20 @@ __metadata: react: 18.x react-dom: 18.x rxjs: 6.x - checksum: 2afa4a88b6dbf99d3298ceb4af54b21d1b04cc7384f60e9049964e1987946e3b50f40e5925b7b30d2cd5481d6f337978c7b1868e786c713f577f01249a367362 + checksum: 93540fa2029ea30d7bc0df2d52fb69972831de5d442bcc02c238329e3a132affc496291aea2dbd143c6e30223da3175c0aaa2aaec736d2eec319360946e1c863 languageName: node linkType: hard -"@openmrs/esm-utils@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/esm-utils@npm:5.2.1-pre.1168" +"@openmrs/esm-utils@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/esm-utils@npm:5.3.3-pre.1404" dependencies: semver: 7.3.2 peerDependencies: dayjs: 1.x i18next: 19.x rxjs: 6.x - checksum: a7062351221814e061dd0304692b36fc5e6c0512531d28e9342c31ce84c229bbe0d66099bef0d5f582bc1e0c4c4bad08404d09388cbc7cb29f6f14468a194651 + checksum: 5ad86c28113da2a03178ee5a77fce02b42b98f5b73b5a0c439875430d03fee8a1d6a5338a6daa6132c9bd95230d654a663003b19f8e201eba18782d8c59d45b6 languageName: node linkType: hard @@ -5111,9 +5245,9 @@ __metadata: languageName: node linkType: hard -"@openmrs/webpack-config@npm:5.2.1-pre.1168": - version: 5.2.1-pre.1168 - resolution: "@openmrs/webpack-config@npm:5.2.1-pre.1168" +"@openmrs/webpack-config@npm:5.3.3-pre.1404": + version: 5.3.3-pre.1404 + resolution: "@openmrs/webpack-config@npm:5.3.3-pre.1404" dependencies: "@swc/core": ^1.3.58 clean-webpack-plugin: ^4.0.0 @@ -5130,7 +5264,7 @@ __metadata: webpack-stats-plugin: ^1.0.3 peerDependencies: webpack: 5.x - checksum: a8893c01c706f91af391ed8a605ccb082c066b542984184c1381b587a198cd5452ae55856dd19ba9465e481f7bcc86647bb3224eb4ef038662d7d2b8b1cf1799 + checksum: fcfdce97969513037dab7ab3ddd0cd1beb973d68b8e3dc79c9c35658898557f3a21f2e29266659ed203a5b934801569e71a98e78068ebe819fc8ad5812fb88d2 languageName: node linkType: hard @@ -10078,6 +10212,13 @@ __metadata: languageName: node linkType: hard +"compute-scroll-into-view@npm:^2.0.4": + version: 2.0.4 + resolution: "compute-scroll-into-view@npm:2.0.4" + checksum: f3d1db9276c16af42155b572750514939cd0ab0a0f46498906f6811c5b654c5ff2b3f9bfd65958e57439e000a5e1ae092eb96b9e153d194a73e52ffd2380550c + languageName: node + linkType: hard + "compute-scroll-into-view@npm:^3.0.3": version: 3.1.0 resolution: "compute-scroll-into-view@npm:3.1.0" @@ -11817,6 +11958,21 @@ __metadata: languageName: node linkType: hard +"downshift@npm:8.1.0": + version: 8.1.0 + resolution: "downshift@npm:8.1.0" + dependencies: + "@babel/runtime": ^7.14.8 + compute-scroll-into-view: ^2.0.4 + prop-types: ^15.7.2 + react-is: ^17.0.2 + tslib: ^2.3.0 + peerDependencies: + react: ">=16.12.0" + checksum: 5ede6190dc85ad295f623b30d3ad035a83b9ef5753084096e71e6fad5276a9abd3b1c1a26583958368e4e7fe14a40ef8b5a246f9f6eec058c4eba30a5104539d + languageName: node + linkType: hard + "downshift@npm:8.2.1": version: 8.2.1 resolution: "downshift@npm:8.2.1" @@ -18636,6 +18792,13 @@ __metadata: languageName: node linkType: hard +"node-watch@npm:^0.7.4": + version: 0.7.4 + resolution: "node-watch@npm:0.7.4" + checksum: effca2aa3575afdc8caae2a422d5738ecf8322962f051574c5dd3c1a399b4bf188c3ad3cb32890fc5e530604f0f037bc0160ec94b37f8d3ae4b76006a98f9df3 + languageName: node + linkType: hard + "nopt@npm:^6.0.0": version: 6.0.0 resolution: "nopt@npm:6.0.0" @@ -19248,16 +19411,18 @@ __metadata: linkType: hard "openmrs@npm:next": - version: 5.2.1-pre.1168 - resolution: "openmrs@npm:5.2.1-pre.1168" + version: 5.3.3-pre.1404 + resolution: "openmrs@npm:5.3.3-pre.1404" dependencies: - "@openmrs/esm-app-shell": 5.2.1-pre.1168 - "@openmrs/webpack-config": 5.2.1-pre.1168 + "@carbon/icons-react": 11.26.0 + "@openmrs/esm-app-shell": 5.3.3-pre.1404 + "@openmrs/webpack-config": 5.3.3-pre.1404 "@pnpm/npm-conf": ^2.1.0 "@swc/core": ^1.3.58 autoprefixer: ^10.4.2 axios: ^0.21.1 browserslist-config-openmrs: ^1.0.1 + chalk: ^4.1.2 copy-webpack-plugin: ^11.0.0 cssnano: ^5.0.16 ejs: ^3.1.8 @@ -19265,6 +19430,7 @@ __metadata: html-webpack-plugin: ^5.5.0 inquirer: ^7.3.3 mini-css-extract-plugin: ^2.4.5 + node-watch: ^0.7.4 npm-registry-fetch: ^14.0.3 pacote: ^15.0.0 postcss: ^8.4.6 @@ -19281,7 +19447,7 @@ __metadata: yargs: ^17.6.2 bin: openmrs: ./dist/cli.js - checksum: 9c4823e604215ab00ccfdc4cbe93baf92f905a07b1a15015ef044903280125a60ba4b9e7bc80d245e9f7d2d961e99761e9472e356d911cb06a5c94a4ee591b73 + checksum: e369415883977c3cc8aea88dd2ef29f614f4a18bf7e751d414731b1428ab97343da4eb44e815242863c4d53807e7916f1bed4d71b18e62506be3645758349bd9 languageName: node linkType: hard @@ -20976,7 +21142,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^17.0.0, react-is@npm:^17.0.1": +"react-is@npm:^17.0.0, react-is@npm:^17.0.1, react-is@npm:^17.0.2": version: 17.0.2 resolution: "react-is@npm:17.0.2" checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8 @@ -22403,9 +22569,9 @@ __metadata: languageName: node linkType: hard -"single-spa-react@npm:~5.0.0": - version: 5.0.2 - resolution: "single-spa-react@npm:5.0.2" +"single-spa-react@npm:^6.0.0": + version: 6.0.1 + resolution: "single-spa-react@npm:6.0.1" dependencies: browserslist-config-single-spa: ^1.0.1 peerDependencies: @@ -22417,14 +22583,14 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 3c2503384ab27aed7e4f9f5c6a40cf5aae120cae1749244aba12647159354c143ac03669bfc41a43533077c874866b7042dad9463abe253da198da3f200d8fe1 + checksum: aefe69502735a5a4062a0539d61e2b1e84c50146e333838d688ee3f511f101cc07f94daa27ab399e5286a2c3399278e5da8c87fdc5ca36648504de2b338e45b6 languageName: node linkType: hard -"single-spa@npm:^5.9.2": - version: 5.9.4 - resolution: "single-spa@npm:5.9.4" - checksum: 8547b5db3d1c6788f44833b1bf7a89697a72a4ca4b801c3f9ddbf4e2949a40bc1d9e9a24650460c7a16f5a668d4e332fc237acacb84f329031815c19578a5907 +"single-spa@npm:^6.0.0": + version: 6.0.0 + resolution: "single-spa@npm:6.0.0" + checksum: 4efc6248e5ba3b2c02090869a1d85c8fdb77994465d760233ff58462d35614503fefcb2330999b15ef7e43508181939a41628410912f9a1cc01860b192580d11 languageName: node linkType: hard