diff --git a/e2e/pages/patient-lists-page.ts b/e2e/pages/patient-lists-page.ts index f54651b7ce..b5ac5f7e4a 100644 --- a/e2e/pages/patient-lists-page.ts +++ b/e2e/pages/patient-lists-page.ts @@ -21,7 +21,7 @@ export class PatientListsPage { async editPatientList(listName: string, description: string) { await this.page.getByRole('button', { name: 'Actions' }).click(); - await this.page.getByRole('menuitem', { name: 'Edit Name or Description' }).click(); + await this.page.getByRole('menuitem', { name: 'Edit name or description' }).click(); await this.page.getByLabel('List name').fill(listName); await this.page.getByLabel('Describe the purpose of this list in a few words').fill(description); await this.page.getByRole('button', { name: 'Edit list' }).click(); diff --git a/packages/esm-appointments-app/translations/es.json b/packages/esm-appointments-app/translations/es.json index 91a57c81b9..68195b47bf 100644 --- a/packages/esm-appointments-app/translations/es.json +++ b/packages/esm-appointments-app/translations/es.json @@ -36,6 +36,7 @@ "cancel": "Cancelar", "cancelAppointment": "Cancelar cita", "cancelled": "Cancelada", + "cancelledSuccessfully": "It has been cancelled successfully", "checkedIn": "Checked in", "checkedOut": "Completada", "checkFilters": "Compruebe los filtros anteriores", diff --git a/packages/esm-patient-list-app/src/add-patient/add-patient.component.tsx b/packages/esm-patient-list-app/src/add-patient/add-patient.component.tsx index 585d7fbc1c..751d15cbda 100644 --- a/packages/esm-patient-list-app/src/add-patient/add-patient.component.tsx +++ b/packages/esm-patient-list-app/src/add-patient/add-patient.component.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useMemo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { TFunction } from 'i18next'; import useSWR from 'swr'; import { getDynamicOfflineDataEntries, @@ -11,11 +12,10 @@ import { navigate, useConfig, } from '@openmrs/esm-framework'; -import { Button, Checkbox, Pagination, Search, SkeletonText, CheckboxSkeleton } from '@carbon/react'; +import { Button, Checkbox, Pagination, Search, CheckboxSkeleton } from '@carbon/react'; import { addPatientToList, getAllPatientLists, getPatientListIdsForPatient } from '../api/api-remote'; -import { TFunction } from 'i18next'; -import styles from './add-patient.scss'; import { ConfigSchema } from '../config-schema'; +import styles from './add-patient.scss'; interface AddPatientProps { closeModal: () => void; diff --git a/packages/esm-patient-list-app/src/api/hooks.ts b/packages/esm-patient-list-app/src/api/hooks.ts index 464f6a6d64..a4a136c2af 100755 --- a/packages/esm-patient-list-app/src/api/hooks.ts +++ b/packages/esm-patient-list-app/src/api/hooks.ts @@ -1,3 +1,9 @@ +import { useEffect, useState } from 'react'; +import useSWR from 'swr'; +import useSWRInfinite from 'swr/infinite'; +import { openmrsFetch, FetchResponse, useConfig } from '@openmrs/esm-framework'; +import { cohortUrl, getAllPatientLists, getPatientListIdsForPatient, getPatientListMembers } from './api-remote'; +import { ConfigSchema } from '../config-schema'; import { CohortResponse, CohortType, @@ -6,12 +12,6 @@ import { PatientListFilter, PatientListType, } from './types'; -import { openmrsFetch, FetchResponse, useConfig } from '@openmrs/esm-framework'; -import useSWR from 'swr'; -import useSWRInfinite from 'swr/infinite'; -import { cohortUrl, getAllPatientLists, getPatientListIdsForPatient, getPatientListMembers } from './api-remote'; -import { ConfigSchema } from '../config-schema'; -import { useEffect, useState } from 'react'; interface PatientListResponse { results: CohortResponse; @@ -134,11 +134,22 @@ export function usePatientListMembers( pageSize: number = 10, v: string = 'full', ) { - const swrResult = useSWR>, Error>( + const { data, error, mutate } = useSWR>, Error>( `${cohortUrl}/cohortmember?cohort=${patientListUuid}&startIndex=${startIndex}&limit=${pageSize}&v=${v}&q=${searchQuery}`, openmrsFetch, ); - return { ...swrResult, data: swrResult?.data?.data?.results }; + + // FIXME: This is a workaround for removing a patient from a list + const filterList = (listMembers: Array) => + listMembers.filter((member) => !member.endDate && !member.voided); + + const filteredListMembers = filterList(data?.data?.results ?? []); + + return { + listMembers: filteredListMembers, + error: error, + mutateListMembers: mutate, + }; } export function useCohortTypes() { diff --git a/packages/esm-patient-list-app/src/api/types.ts b/packages/esm-patient-list-app/src/api/types.ts index ec667dbb20..65cca28354 100644 --- a/packages/esm-patient-list-app/src/api/types.ts +++ b/packages/esm-patient-list-app/src/api/types.ts @@ -75,6 +75,7 @@ export interface OpenmrsCohortMember { name: string; uuid: string; patient: OpenmrsResource; + voided: boolean; } export interface CohortResponse { diff --git a/packages/esm-patient-list-app/src/overflow-menu/overflow-menu.component.tsx b/packages/esm-patient-list-app/src/overflow-menu/overflow-menu.component.tsx index 5baae37209..0e13792df6 100644 --- a/packages/esm-patient-list-app/src/overflow-menu/overflow-menu.component.tsx +++ b/packages/esm-patient-list-app/src/overflow-menu/overflow-menu.component.tsx @@ -40,6 +40,7 @@ const CustomOverflowMenuComponent: React.FC = onClick={toggleShowMenu} style={{ boxShadow: showMenu ? '0 2px 6px 0 rgb(0 0 0 / 30%)' : 'none', + height: '2.5rem', }}> {menuTitle} @@ -52,6 +53,7 @@ const CustomOverflowMenuComponent: React.FC = id="custom-actions-overflow-menu" style={{ display: showMenu ? 'block' : 'none', + marginTop: '-0.475rem', }}>
    {children}
diff --git a/packages/esm-patient-list-app/src/overlay.component.tsx b/packages/esm-patient-list-app/src/overlay.component.tsx index 02494242e0..2733420a8b 100644 --- a/packages/esm-patient-list-app/src/overlay.component.tsx +++ b/packages/esm-patient-list-app/src/overlay.component.tsx @@ -18,14 +18,15 @@ const Overlay: React.FC = ({ close, children, header, buttonsGroup
{isDesktop(layout) ? (
-
{header}
+ {header}
) : ( diff --git a/packages/esm-patient-list-app/src/overlay.scss b/packages/esm-patient-list-app/src/overlay.scss index 4bc911219f..e1e492d377 100644 --- a/packages/esm-patient-list-app/src/overlay.scss +++ b/packages/esm-patient-list-app/src/overlay.scss @@ -47,6 +47,7 @@ align-items: center; background-color: $ui-03; border-bottom: 1px solid $text-03; + height: 2.5rem; } .headerContent { @@ -56,7 +57,13 @@ } .closeButton { + border: none; + border-bottom: 1px solid $text-03; background-color: $ui-02; + padding-block-start: 0.75rem; + // FIXME: Why are carbon's default button styles not working? + height: 2.5rem; + width: 2.5rem; } .overlayContent { @@ -64,6 +71,14 @@ overflow-y: auto; } +:global(.omrs-breakpoint-lt-desktop) .overlayContent { + background-color: #ededed; +} + +:global(.omrs-breakpoint-gt-tablet) .overlayContent { + background-color: white; +} + .buttonsGroup { align-self: end; } diff --git a/packages/esm-patient-list-app/src/patient-list-detail/patient-list-detail.component.tsx b/packages/esm-patient-list-app/src/patient-list-detail/patient-list-detail.component.tsx index a717ad24c7..0c913e16c9 100644 --- a/packages/esm-patient-list-app/src/patient-list-detail/patient-list-detail.component.tsx +++ b/packages/esm-patient-list-app/src/patient-list-detail/patient-list-detail.component.tsx @@ -4,11 +4,11 @@ import { useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { OverflowMenuItem, Modal } from '@carbon/react'; import { OverflowMenuVertical } from '@carbon/react/icons'; +import { deletePatientList } from '../api/api-remote'; +import { usePatientListDetails, usePatientListMembers } from '../api/hooks'; import CustomOverflowMenuComponent from '../overflow-menu/overflow-menu.component'; import EditPatientListDetailsOverlay from '../create-edit-patient-list/create-edit-list.component'; import PatientListTable from '../patient-table/patient-table.component'; -import { deletePatientList } from '../api/api-remote'; -import { usePatientListDetails, usePatientListMembers } from '../api/hooks'; import styles from './patient-list-detail.scss'; interface PatientListMemberRow { @@ -27,20 +27,21 @@ const PatientListDetailComponent = () => { const [currentPageSize, setCurrentPageSize] = useState(10); const [searchString, setSearchString] = useState(''); const { data: patientListDetails, mutate: mutatePatientListDetails } = usePatientListDetails(patientListUuid); - const { data: patientListMembers, mutate: mutatePatientListMembers } = usePatientListMembers( + const { listMembers, mutateListMembers } = usePatientListMembers( patientListUuid, searchString, (currentPage - 1) * currentPageSize, currentPageSize, ); + const [showEditPatientListDetailOverlay, setEditPatientListDetailOverlay] = useState(false); const [showDeleteConfirmationModal, setShowDeleteConfirmationModal] = useState(false); const patients: PatientListMemberRow[] = useMemo( () => - patientListMembers - ? patientListMembers?.length - ? patientListMembers?.map((member) => ({ + listMembers + ? listMembers?.length + ? listMembers?.map((member) => ({ name: member?.patient?.person?.display, identifier: member?.patient?.identifiers[0]?.identifier ?? null, sex: member?.patient?.person?.gender, @@ -50,7 +51,7 @@ const PatientListDetailComponent = () => { })) : [] : [], - [patientListMembers], + [listMembers], ); const headers = useMemo( @@ -130,7 +131,7 @@ const PatientListDetailComponent = () => { }> setEditPatientListDetailOverlay(true)} /> { ({ const mockedPatientListDetails = { name: 'Test Patient List', description: 'This is a test patient list', - size: 5, + size: 1, startDate: '2023-08-14', }; @@ -51,7 +51,6 @@ const mockedPatientListMembers = [ describe('PatientListDetailComponent', () => { beforeEach(() => { - jest.clearAllMocks(); mockedUsePatientListDetails.mockReturnValue({ data: mockedPatientListDetails, }); @@ -63,30 +62,31 @@ describe('PatientListDetailComponent', () => { mockedDeletePatientList.mockResolvedValue({}); }); - it('renders patient list details', async () => { + it('renders patient list details page', async () => { render(); - await waitFor(() => { - expect(screen.getByText('Test Patient List')).toBeInTheDocument(); - expect(screen.getByText('This is a test patient list')).toBeInTheDocument(); - }); + expect(screen.getByRole('heading', { name: /^test patient list$/i })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: /this is a test patient list/i })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /actions/i })).toBeInTheDocument(); + expect(screen.getByRole('link', { name: /back to lists page/i })).toBeInTheDocument(); + expect(screen.getByText(/1 patient/)).toBeInTheDocument(); + expect(getByTextWithMarkup('Created on: 14-Aug-2023')).toBeInTheDocument(); + expect(screen.getByText(/edit name or description/i)).toBeInTheDocument(); + expect(screen.getByText(/delete patient list/i)).toBeInTheDocument(); }); - it('displays patient list members', async () => { + it('renders an empty state view if a list has no patients', async () => { render(); - await waitFor(() => { - expect(screen.getByText('John Doe')).toBeInTheDocument(); - expect(screen.getByText('Male')).toBeInTheDocument(); - expect(screen.getByText('100GEJ')).toBeInTheDocument(); - }); + expect(screen.getByTitle(/empty data illustration/i)).toBeInTheDocument(); + expect(screen.getByText(/there are no patients in this list/i)).toBeInTheDocument(); }); - it('opens edit overlay when "Edit Name or Description" is clicked', () => { + it('opens overlay with a form when the "Edit name or description" button is clicked', () => { render(); userEvent.click(screen.getByText('Actions')); - const editBtn = screen.getByText('Edit Name or Description'); + const editBtn = screen.getByText('Edit name or description'); userEvent.click(editBtn); }); diff --git a/packages/esm-patient-list-app/src/patient-list-list/empty-state/empty-state.component.tsx b/packages/esm-patient-list-app/src/patient-list-list/empty-state/empty-state.component.tsx index 398227655d..c2ce7b3a61 100644 --- a/packages/esm-patient-list-app/src/patient-list-list/empty-state/empty-state.component.tsx +++ b/packages/esm-patient-list-app/src/patient-list-list/empty-state/empty-state.component.tsx @@ -1,9 +1,9 @@ import React from 'react'; +import { useTranslation } from 'react-i18next'; import { Layer, Button, Tile } from '@carbon/react'; -import { Trans, useTranslation } from 'react-i18next'; +import { Add } from '@carbon/react/icons'; import { EmptyDataIllustration } from './empty-data-illustration.component'; import styles from './empty-state.scss'; -import { Add } from '@carbon/react/icons'; export interface EmptyStateProps { listType: string; diff --git a/packages/esm-patient-list-app/src/patient-table/patient-table.component.tsx b/packages/esm-patient-list-app/src/patient-table/patient-table.component.tsx index b3f9683bf5..5cdf3b087d 100644 --- a/packages/esm-patient-list-app/src/patient-table/patient-table.component.tsx +++ b/packages/esm-patient-list-app/src/patient-table/patient-table.component.tsx @@ -1,4 +1,5 @@ import React, { HTMLAttributes, useMemo, useState, useCallback, type CSSProperties } from 'react'; +import debounce from 'lodash-es/debounce'; import { useTranslation } from 'react-i18next'; import { Button, @@ -17,15 +18,17 @@ import { TableHead, TableHeader, TableRow, + Tile, } from '@carbon/react'; -import { TrashCan } from '@carbon/react/icons'; -import debounce from 'lodash-es/debounce'; -import { ConfigurableLink, useLayoutType, isDesktop, OpenmrsResource, showToast } from '@openmrs/esm-framework'; +import { ArrowLeft, TrashCan } from '@carbon/react/icons'; +import { ConfigurableLink, useLayoutType, isDesktop, showToast } from '@openmrs/esm-framework'; import { removePatientFromList } from '../api/api-remote'; +import { EmptyDataIllustration } from '../patient-list-list/empty-state/empty-data-illustration.component'; import styles from './patient-table.scss'; // FIXME Temporarily included types from Carbon type InputPropsBase = Omit, 'onChange'>; + interface SearchProps extends InputPropsBase { /** * Specify an optional value for the `autocomplete` property on the underlying @@ -118,14 +121,13 @@ interface SearchProps extends InputPropsBase { } interface PatientTableProps { - patients: Array; + patients; columns: Array; style?: CSSProperties; autoFocus?: boolean; isLoading: boolean; isFetching?: boolean; - cohortName: string; - mutatePatientListMembers: () => void; + mutateListMembers: () => void; search: { onSearch(searchTerm: string): any; placeHolder: string; @@ -159,62 +161,81 @@ const PatientTable: React.FC = ({ pagination, isLoading, isFetching, - cohortName, - mutatePatientListMembers, + mutateListMembers, }) => { const { t } = useTranslation(); const layout = useLayoutType(); + const patientListsPath = window.getOpenmrsSpaBase() + 'home/patient-lists'; + const [patientName, setPatientName] = useState(''); const [membershipUuid, setMembershipUuid] = useState(''); const [showConfirmationModal, setShowConfirmationModal] = useState(false); const [isDeleting, setIsDeleting] = useState(false); const rows: Array = useMemo( () => - patients.map((patient, index) => { - const row = { - id: patient.membershipUuid, - }; - columns.forEach((column) => { - const value = column.getValue?.(patient) || patient[column.key]; - row[column.key] = column.link ? ( - - {value} - - ) : ( - value - ); - }); - return row; - }), - [patients, columns], + patients.map((patient) => ({ + id: patient.membershipUuid, + identifier: patient.identifier, + membershipUuid: patient.membershipUuid, + name: columns.find((column) => column.key === 'name')?.link ? ( + column.key === 'name')?.link?.getUrl(patient)}> + {patient.name} + + ) : ( + patient.name + ), + sex: patient.sex, + startDate: patient.startDate, + })), + [columns, patients], ); - const handleSearch = useMemo(() => debounce((searchTerm) => search.onSearch(searchTerm), 300), []); + const handleSearch = useMemo(() => debounce((searchTerm) => search.onSearch(searchTerm), 300), [search]); const confirmRemovePatientFromList = useCallback(async () => { setIsDeleting(true); try { await removePatientFromList(membershipUuid); - mutatePatientListMembers(); + mutateListMembers(); showToast({ - title: t('removed', 'Removed'), - description: `${t('successRemovePatientFromList', 'Successfully removed patient from list')}: ${cohortName}`, + critical: true, + kind: 'success', + description: t('listUpToDate', 'The list is now up to date'), + title: t('patientRemovedFromList', 'Patient removed from list'), }); } catch (error) { showToast({ - title: t('error', 'Error'), + critical: true, kind: 'error', - description: `${t('errorRemovePatientFromList', 'Failed to remove patient from list')}: ${cohortName}`, + description: error?.message, + title: t('errorRemovingPatientFromList', 'Failed to remove patient from list'), }); } setIsDeleting(false); setShowConfirmationModal(false); - }, [membershipUuid, cohortName, mutatePatientListMembers, t]); + }, [membershipUuid, mutateListMembers, t]); const otherSearchProps = useMemo(() => search.otherSearchProps || {}, [search]); + const BackButton = () => ( +
+ + + +
+ ); + if (isLoading) { return ( = ({ ); } - return ( - <> -
-
-
{isFetching && }
-
- - handleSearch(evnt.target.value)} - defaultValue={search.currentSearchTerm} - {...otherSearchProps} - /> - + if (patients.length > 0) { + return ( + <> + +
+
+
{isFetching && }
+
+ + handleSearch(event.target.value)} + defaultValue={search.currentSearchTerm} + {...otherSearchProps} + /> + +
-
- - {({ rows, headers, getHeaderProps, getTableProps, getRowProps }) => ( - - - - - {headers.map((header) => ( - - {header.header?.content ?? header.header} - - ))} - - - - {rows.map((row) => ( - - {row.cells.map((cell) => ( - {cell.value?.content ?? cell.value} + + {({ rows, headers, getHeaderProps, getTableProps, getRowProps }) => ( + +
+ + + {headers.map((header) => ( + + {header.header?.content ?? header.header} + ))} - -
-
+ + + {rows.map((row) => ( + + {row.cells.map((cell) => { + if (typeof cell.value === 'object') { + setPatientName(cell.value.props.children); + } + + return {cell.value?.content ?? cell.value}; + })} + +
- {showConfirmationModal && ( - setShowConfirmationModal(false)} - onRequestSubmit={confirmRemovePatientFromList} - primaryButtonDisabled={isDeleting} - /> - )} +  {' '} + + ); + } + + return ( + <> + + + +
+ +
+

{t('noPatientsInList', 'There are no patients in this list')}

+
+
); }; diff --git a/packages/esm-patient-list-app/src/patient-table/patient-table.scss b/packages/esm-patient-list-app/src/patient-table/patient-table.scss index 6b141adc96..aa05330cc0 100644 --- a/packages/esm-patient-list-app/src/patient-table/patient-table.scss +++ b/packages/esm-patient-list-app/src/patient-table/patient-table.scss @@ -68,3 +68,48 @@ div#table-tool-bar { background-color: transparent; padding: 0rem; } + +.removeButton { + padding-block-start: 0.5rem; + padding-inline-end: 0; +} + +.tile { + text-align: center; + border: 1px solid $ui-03; + margin: spacing.$spacing-05 0; +} + +.illo { + margin-top: spacing.$spacing-05; +} + +.content { + @include type.type-style('heading-compact-01'); + color: $text-02; + margin-top: spacing.$spacing-05; + margin-bottom: spacing.$spacing-03; +} + +.backButton { + padding: spacing.$spacing-03 0; + max-width: fit-content; + + a { + text-decoration: none; + } + + button { + display: flex; + padding-left: 0 !important; + + svg { + order: 1; + margin: 0 spacing.$spacing-03; + } + + span { + order: 2; + } + } +} diff --git a/packages/esm-patient-list-app/src/patient-table/patient-table.test.tsx b/packages/esm-patient-list-app/src/patient-table/patient-table.test.tsx index 4835a6ea46..ca24e8b7bf 100644 --- a/packages/esm-patient-list-app/src/patient-table/patient-table.test.tsx +++ b/packages/esm-patient-list-app/src/patient-table/patient-table.test.tsx @@ -101,6 +101,7 @@ describe('PatientTable Component', () => { isLoading={false} autoFocus={false} isFetching={false} + mutateListMembers={jest.fn()} />, ); @@ -124,6 +125,7 @@ describe('PatientTable Component', () => { isLoading={false} autoFocus={false} isFetching={false} + mutateListMembers={jest.fn()} />, ); diff --git a/packages/esm-patient-list-app/translations/am.json b/packages/esm-patient-list-app/translations/am.json index 9ed92413ae..9fba637ea3 100644 --- a/packages/esm-patient-list-app/translations/am.json +++ b/packages/esm-patient-list-app/translations/am.json @@ -3,10 +3,10 @@ "addPatientToList": "Add patient to list", "addToList": "Add to list", "allLists": "All lists", + "backToListsPage": "Back to lists page", "cancel": "Cancel", "configureList": "Configure your patient list using the fields below", "confirmDeletePatientList": "Are you sure you want to delete this patient list?", - "confirmRemovePatient": "Are you sure you want to remove this patient from {cohortName}?", "createdOn": "Created on", "createList": "Create list", "createNewPatientList": "Create new patient list", @@ -15,14 +15,14 @@ "deletedPatientList": "Deleted patient list", "deletePatientList": "Delete patient list", "editList": "Edit list", - "editNameDescription": "Edit Name or Description", + "editNameDescription": "Edit name or description", "editPatientListHeader": "Edit patient list", "emptyStateText": "There are no {listType} patient lists to display", "error": "Error", "errorAddPatientToList": "Patient not added to list", "errorCreatePatientListDescription": "Couldn't create patient list", "errorDeleteList": "Couldn't delete patient list", - "errorRemovePatientFromList": "Failed to remove patient from list", + "errorRemovingPatientFromList": "Failed to remove patient from list", "errorUpdatePatientListDescription": "Couldn't update patient list", "home": "Home", "identifier": "Identifier", @@ -32,6 +32,7 @@ "listName": "List name", "listNamePlaceholder": "e.g. Potential research participants", "listType": "List type", + "listUpToDate": "The list is now up to date", "myLists": "My lists", "name": "Name", "newList": "New list", @@ -41,15 +42,16 @@ "nextPage": "Next page", "noOfPatients": "No. of patients", "noPatientListFound": "No patient list found", + "noPatientsInList": "There are no patients in this list", "offlinePatients": "Offline patients", "openPatientList": "Add to list", "pageNumber": "Page number", "patientLists": "Patient Lists", + "patientRemovedFromList": "Patient removed from list", "patients": "patients", "previousPage": "Previous page", - "removed": "Removed", "removeFromList": "Remove from list", - "removePatientFromList": "Remove patient from list", + "removePatientFromListConfirmation": "Are you sure you want to remove {patientName} from this list?", "searchForAListToAddThisPatientTo": "Search for a list to add this patient to.", "searchForList": "Search for a list", "searchThisList": "Search this list", @@ -62,7 +64,6 @@ "successCreatedPatientList": "Created patient list", "successCreatedPatientListDescription": "Successfully created patient list", "successfullyAdded": "Successfully added", - "successRemovePatientFromList": "Successfully removed patient from list", "successUpdatePatientList": "Updated patient list", "successUpdatePatientListDescription": "Successfully updated patient list", "systemDefined": "system-defined", diff --git a/packages/esm-patient-list-app/translations/ar.json b/packages/esm-patient-list-app/translations/ar.json index ba8d110b00..909af7cc76 100644 --- a/packages/esm-patient-list-app/translations/ar.json +++ b/packages/esm-patient-list-app/translations/ar.json @@ -3,6 +3,7 @@ "addPatientToList": "أضف المريض إلى القائمة", "addToList": "أضف إلى القائمة", "allLists": "جميع القوائم", + "backToListsPage": "Back to lists page", "cancel": "إلغاء", "configureList": "قم بتكوين قائمة المرضى باستخدام الحقول أدناه", "confirmDeletePatientList": "Are you sure you want to delete this patient list?", @@ -21,6 +22,7 @@ "errorAddPatientToList": "لم يتم إضافة المريض إلى القائمة", "errorCreatePatientListDescription": "تعذر إنشاء قائمة المرضى", "errorDeleteList": "تعذر حذف قائمة المرضى", + "errorRemovingPatientFromList": "Failed to remove patient from list", "errorUpdatePatientListDescription": "تعذر تحديث قائمة المرضى", "home": "الرئيسية", "identifier": "المعرف", @@ -30,6 +32,7 @@ "listName": "اسم القائمة", "listNamePlaceholder": "مثل: المشاركون المحتملون في البحث", "listType": "نوع القائمة", + "listUpToDate": "The list is now up to date", "myLists": "قوائمي", "name": "الاسم", "newList": "قائمة جديدة", @@ -39,12 +42,16 @@ "nextPage": "الصفحة التالية", "noOfPatients": "عدد المرضى", "noPatientListFound": "لم يتم العثور على قائمة المرضى", + "noPatientsInList": "There are no patients in this list", "offlinePatients": "المرضى غير المتصلين", "openPatientList": "أضف إلى القائمة", "pageNumber": "رقم الصفحة", "patientLists": "قوائم المرضى", + "patientRemovedFromList": "Patient removed from list", "patients": "المرضى", "previousPage": "الصفحة السابقة", + "removeFromList": "Remove from list", + "removePatientFromListConfirmation": "Are you sure you want to remove {patientName} from this list?", "searchForAListToAddThisPatientTo": "ابحث عن قائمة لإضافة هذا المريض إليها.", "searchForList": "ابحث عن قائمة", "searchThisList": "ابحث في هذه القائمة", diff --git a/packages/esm-patient-list-app/translations/en.json b/packages/esm-patient-list-app/translations/en.json index c46e554f1b..b09c75475c 100644 --- a/packages/esm-patient-list-app/translations/en.json +++ b/packages/esm-patient-list-app/translations/en.json @@ -3,10 +3,10 @@ "addPatientToList": "Add patient to list", "addToList": "Add to list", "allLists": "All lists", + "backToListsPage": "Back to lists page", "cancel": "Cancel", "configureList": "Configure your patient list using the fields below", "confirmDeletePatientList": "Are you sure you want to delete this patient list?", - "confirmRemovePatient": "Are you sure you want to remove this patient from {cohortName}?", "createdOn": "Created on", "createList": "Create list", "createNewPatientList": "Create new patient list", @@ -22,7 +22,7 @@ "errorAddPatientToList": "Patient not added to list", "errorCreatePatientListDescription": "Couldn't create patient list", "errorDeleteList": "Couldn't delete patient list", - "errorRemovePatientFromList": "Failed to remove patient from list", + "errorRemovingPatientFromList": "Failed to remove patient from list", "errorUpdatePatientListDescription": "Couldn't update patient list", "home": "Home", "identifier": "Identifier", @@ -32,6 +32,7 @@ "listName": "List name", "listNamePlaceholder": "e.g. Potential research participants", "listType": "List type", + "listUpToDate": "The list is now up to date", "myLists": "My lists", "name": "Name", "newList": "New list", @@ -41,15 +42,16 @@ "nextPage": "Next page", "noOfPatients": "No. of patients", "noPatientListFound": "No patient list found", + "noPatientsInList": "There are no patients in this list", "offlinePatients": "Offline patients", "openPatientList": "Add to list", "pageNumber": "Page number", "patientLists": "Patient lists", + "patientRemovedFromList": "Patient removed from list", "patients": "patients", "previousPage": "Previous page", - "removed": "Removed", "removeFromList": "Remove from list", - "removePatientFromList": "Remove patient from list", + "removePatientFromListConfirmation": "Are you sure you want to remove {patientName} from this list?", "searchForAListToAddThisPatientTo": "Search for a list to add this patient to.", "searchForList": "Search for a list", "searchThisList": "Search this list", @@ -62,7 +64,6 @@ "successCreatedPatientList": "Created patient list", "successCreatedPatientListDescription": "Successfully created patient list", "successfullyAdded": "Successfully added", - "successRemovePatientFromList": "Successfully removed patient from list", "successUpdatePatientList": "Updated patient list", "successUpdatePatientListDescription": "Successfully updated patient list", "systemDefined": "system-defined", diff --git a/packages/esm-patient-list-app/translations/es.json b/packages/esm-patient-list-app/translations/es.json index e19dcee728..d0ca08bd97 100644 --- a/packages/esm-patient-list-app/translations/es.json +++ b/packages/esm-patient-list-app/translations/es.json @@ -3,10 +3,10 @@ "addPatientToList": "Agregar paciente a la lista", "addToList": "Agregar a la lista", "allLists": "Todas las listas", + "backToListsPage": "Back to lists page", "cancel": "Cancelar", "configureList": "Configurar su lista de pacientes utilizando los campos abajo", "confirmDeletePatientList": "Are you sure you want to delete this patient list?", - "confirmRemovePatient": "Are you sure you want to remove this patient from {cohortName}?", "createdOn": "Creado el", "createList": "Crear lista", "createNewPatientList": "Crear nueva lista de pacientes", @@ -22,7 +22,7 @@ "errorAddPatientToList": "Paciente no agregado a la lista", "errorCreatePatientListDescription": "No se pudo crear la lista de pacientes", "errorDeleteList": "No se pudo eliminar la lista de pacientes", - "errorRemovePatientFromList": "Failed to remove patient from list", + "errorRemovingPatientFromList": "Failed to remove patient from list", "errorUpdatePatientListDescription": "No se pudo actualizar la lista de pacientes", "home": "Inicio", "identifier": "Identificador", @@ -32,6 +32,7 @@ "listName": "Nombre de la lista", "listNamePlaceholder": "p. ej. Participantes potenciales en la investigación", "listType": "Tipo de lista", + "listUpToDate": "The list is now up to date", "myLists": "Mis listas", "name": "Nombre", "newList": "Nueva lista", @@ -41,15 +42,16 @@ "nextPage": "Siguiente página", "noOfPatients": "N.º de pacientes", "noPatientListFound": "No se encontraron listas de pacientes", + "noPatientsInList": "There are no patients in this list", "offlinePatients": "Pacientes sin conexión", "openPatientList": "Agregar a la lista", "pageNumber": "Número de página", "patientLists": "Listas de pacientes", + "patientRemovedFromList": "Patient removed from list", "patients": "pacientes", "previousPage": "Página anterior", - "removed": "Removed", "removeFromList": "Remove from list", - "removePatientFromList": "Remove patient from list", + "removePatientFromListConfirmation": "Are you sure you want to remove {patientName} from this list?", "searchForAListToAddThisPatientTo": "Buscar una lista para agregar a este paciente.", "searchForList": "Buscar una lista", "searchThisList": "Buscar en esta lista", @@ -62,7 +64,6 @@ "successCreatedPatientList": "Lista de pacientes creada", "successCreatedPatientListDescription": "Lista de pacientes creada correctamente", "successfullyAdded": "Agregado correctamente", - "successRemovePatientFromList": "Successfully removed patient from list", "successUpdatePatientList": "Lista de pacientes actualizada", "successUpdatePatientListDescription": "Lista de pacientes actualizada correctamente", "systemDefined": "definida por el sistema", diff --git a/packages/esm-patient-list-app/translations/fr.json b/packages/esm-patient-list-app/translations/fr.json index a42e368804..6923396b33 100644 --- a/packages/esm-patient-list-app/translations/fr.json +++ b/packages/esm-patient-list-app/translations/fr.json @@ -3,10 +3,10 @@ "addPatientToList": "Ajouter le patient à la liste", "addToList": "Ajouter à la liste", "allLists": "All lists", + "backToListsPage": "Back to lists page", "cancel": "Annuller", "configureList": "Configurez votre liste de patients à l'aide des champs ci-dessous", "confirmDeletePatientList": "Are you sure you want to delete this patient list?", - "confirmRemovePatient": "Are you sure you want to remove this patient from {cohortName}?", "createdOn": "Créé le", "createList": "Créer une liste", "createNewPatientList": "Créer une nouvelle liste de patients", @@ -22,7 +22,7 @@ "errorAddPatientToList": "Patient non ajouté à la liste", "errorCreatePatientListDescription": "Impossible de créer une liste de patients", "errorDeleteList": "Impossible de supprimer la liste des patients", - "errorRemovePatientFromList": "Failed to remove patient from list", + "errorRemovingPatientFromList": "Failed to remove patient from list", "errorUpdatePatientListDescription": "Impossible de mettre à jour la liste des patients", "home": "Home", "identifier": "Identifiant", @@ -32,6 +32,7 @@ "listName": "List name", "listNamePlaceholder": "par ex. Participants potentiels de la recherche", "listType": "List type", + "listUpToDate": "The list is now up to date", "myLists": "My lists", "name": "Nom", "newList": "Nouvelle liste", @@ -41,15 +42,16 @@ "nextPage": "Next page", "noOfPatients": "No. of patients", "noPatientListFound": "Aucune liste de patients trouvée", + "noPatientsInList": "There are no patients in this list", "offlinePatients": "Patients hors ligne", "openPatientList": "Ajouter à la liste", "pageNumber": "Page number", "patientLists": "Listes de patients", + "patientRemovedFromList": "Patient removed from list", "patients": "Patients", "previousPage": "Previous page", - "removed": "Removed", "removeFromList": "Remove from list", - "removePatientFromList": "Remove patient from list", + "removePatientFromListConfirmation": "Are you sure you want to remove {patientName} from this list?", "searchForAListToAddThisPatientTo": "Rechercher une liste à laquelle ajouter ce patient.", "searchForList": "Rechercher une liste", "searchThisList": "Search this list", @@ -62,7 +64,6 @@ "successCreatedPatientList": "Liste de patients créée", "successCreatedPatientListDescription": "Liste de patients créée avec succès", "successfullyAdded": "Ajouté avec succès", - "successRemovePatientFromList": "Successfully removed patient from list", "successUpdatePatientList": "Liste de patients mise à jour", "successUpdatePatientListDescription": "Liste de patients mise à jour avec succès", "systemDefined": "system-defined", diff --git a/packages/esm-patient-list-app/translations/he.json b/packages/esm-patient-list-app/translations/he.json index 213f89680f..1d195ae158 100644 --- a/packages/esm-patient-list-app/translations/he.json +++ b/packages/esm-patient-list-app/translations/he.json @@ -3,10 +3,10 @@ "addPatientToList": "הוסף מטופל לרשימה", "addToList": "הוסף לרשימה", "allLists": "All lists", + "backToListsPage": "Back to lists page", "cancel": "ביטול", "configureList": "הגדר את רשימת המטופלים שלך באמצעות השדות למטה", "confirmDeletePatientList": "Are you sure you want to delete this patient list?", - "confirmRemovePatient": "Are you sure you want to remove this patient from {cohortName}?", "createdOn": "נוצר בתאריך", "createList": "צור רשימה", "createNewPatientList": "צור רשימת מטופלים חדשה", @@ -22,7 +22,7 @@ "errorAddPatientToList": "המטופל לא נוסף לרשימה", "errorCreatePatientListDescription": "לא ניתן ליצור רשימת מטופלים", "errorDeleteList": "לא ניתן למחוק רשימת מטופלים", - "errorRemovePatientFromList": "Failed to remove patient from list", + "errorRemovingPatientFromList": "Failed to remove patient from list", "errorUpdatePatientListDescription": "לא ניתן לעדכן רשימת מטופלים", "home": "Home", "identifier": "מזהה", @@ -32,6 +32,7 @@ "listName": "List name", "listNamePlaceholder": "לדוגמה, משתתפי מחקר פוטנציאליים", "listType": "List type", + "listUpToDate": "The list is now up to date", "myLists": "My lists", "name": "שם", "newList": "רשימה חדשה", @@ -41,15 +42,16 @@ "nextPage": "Next page", "noOfPatients": "No. of patients", "noPatientListFound": "לא נמצאה רשימת מטופלים", + "noPatientsInList": "There are no patients in this list", "offlinePatients": "מטופלים במצב לא מקוון", "openPatientList": "הוסף לרשימה", "pageNumber": "Page number", "patientLists": "רשימות מטופלים", + "patientRemovedFromList": "Patient removed from list", "patients": "מטופלים", "previousPage": "Previous page", - "removed": "Removed", "removeFromList": "Remove from list", - "removePatientFromList": "Remove patient from list", + "removePatientFromListConfirmation": "Are you sure you want to remove {patientName} from this list?", "searchForAListToAddThisPatientTo": "חפש רשימה להוספת המטופל לתוכה.", "searchForList": "חפש רשימה", "searchThisList": "Search this list", @@ -62,7 +64,6 @@ "successCreatedPatientList": "נוצרה רשימת מטופלים", "successCreatedPatientListDescription": "יצירת רשימת מטופלים בהצלחה", "successfullyAdded": "נוסף בהצלחה", - "successRemovePatientFromList": "Successfully removed patient from list", "successUpdatePatientList": "עודכנה רשימת מטופלים", "successUpdatePatientListDescription": "עדכון רשימת מטופלים בהצלחה", "systemDefined": "system-defined", diff --git a/packages/esm-patient-list-app/translations/km.json b/packages/esm-patient-list-app/translations/km.json index 10cf3b8d84..de42af8361 100644 --- a/packages/esm-patient-list-app/translations/km.json +++ b/packages/esm-patient-list-app/translations/km.json @@ -3,10 +3,10 @@ "addPatientToList": "បញ្ចូលអ្នកជំងឺទៅក្នុងបញ្ជី", "addToList": "បន្ថែមទៅក្នងុបញ្ជី", "allLists": "បញ្ជីទាំងអស់", + "backToListsPage": "Back to lists page", "cancel": "លប់ចេញ", "configureList": "រៀបចំបញ្ជីឈ្មោះអ្នកជំងឺដោយប្រើផ្នែកខាងក្រោម", "confirmDeletePatientList": "Are you sure you want to delete this patient list?", - "confirmRemovePatient": "Are you sure you want to remove this patient from {cohortName}?", "createdOn": "បានបង្កើតនៅលើ", "createList": "បង្កើតបញ្ជី", "createNewPatientList": "បង្កើតបញ្ជីអ្នកជំងឺថ្មី", @@ -22,7 +22,7 @@ "errorAddPatientToList": "អ្នកជំងឺមិនត្រូវបានបញ្ចូលទៅក្នុងបញ្ជីទេ", "errorCreatePatientListDescription": "មិនអាចបង្កើតបញ្ជីអ្នកជំងឺបានទេ", "errorDeleteList": "មិនអាចលុបបញ្ជីអ្នកជំងឺបានទេ", - "errorRemovePatientFromList": "Failed to remove patient from list", + "errorRemovingPatientFromList": "Failed to remove patient from list", "errorUpdatePatientListDescription": "មិនអាចធ្វើបច្ចុប្បន្នភាពបញ្ជីអ្នកជំងឺបានទេ", "home": "ទំព័រដើម", "identifier": "អ្នកកំណត់អត្តសញ្ញាណ", @@ -32,6 +32,7 @@ "listName": "ឈ្មោះបញ្ជី", "listNamePlaceholder": "ឧ. អ្នកចូលរួមស្រាវជ្រាវដែលបានកំណត់", "listType": "ប្រភេទបញ្ជី", + "listUpToDate": "The list is now up to date", "myLists": "បញ្ជីរបស់ខ្ញុំ", "name": "នាមខ្លួន", "newList": "បញ្ជីថ្មី", @@ -41,15 +42,16 @@ "nextPage": "ទំពរ័បន្ទាប់", "noOfPatients": "ចំនួនអ្នកជំងឺ", "noPatientListFound": "គ្មានបញ្ជីអ្នកជំងឺបានបង្ហាញ", + "noPatientsInList": "There are no patients in this list", "offlinePatients": "អ្នកជំងឺក្រៅប្រព័ន្ធ/បណ្តាញ", "openPatientList": "បន្ថែមទៅក្នុងបញ្ជី", "pageNumber": "លេខទំព័រ", "patientLists": "បញ្ជីអ្នកជំងឺ", + "patientRemovedFromList": "Patient removed from list", "patients": "អ្នកជំងឺ", - "previousPage": "ទំព័រ​មុន", - "removed": "Removed", + "previousPage": "ទំព័រមុន", "removeFromList": "Remove from list", - "removePatientFromList": "Remove patient from list", + "removePatientFromListConfirmation": "Are you sure you want to remove {patientName} from this list?", "searchForAListToAddThisPatientTo": "ស្វែងរកបញ្ជីដើម្បីបន្ថែមអ្នកជំងឺនេះទៅក្នុងបញ្ជី", "searchForList": "ស្វែងរកបញ្ជី", "searchThisList": "ស្វែងរកបញ្ជីនេះ", @@ -62,7 +64,6 @@ "successCreatedPatientList": "បានបង្កើតបញ្ជីអ្នកជំងឺ", "successCreatedPatientListDescription": "បង្កើតបញ្ជីអ្នកជំងឺដោយជោគជ័យ", "successfullyAdded": "បន្ថែមដោយជោគជ័យ", - "successRemovePatientFromList": "Successfully removed patient from list", "successUpdatePatientList": "បានធ្វើបច្ចុប្បន្នភាពបញ្ជីអ្នកជំងឺ", "successUpdatePatientListDescription": "បានធ្វើបច្ចុប្បន្នភាពបញ្ជីអ្នកជំងឺដោយពេញលេញ", "systemDefined": "កំណត់ដោយអ្នកប្រើប្រាស់", diff --git a/tools/test-helpers.tsx b/tools/test-helpers.tsx index 6be608da33..49e8cb1ddf 100644 --- a/tools/test-helpers.tsx +++ b/tools/test-helpers.tsx @@ -22,6 +22,19 @@ export function waitForLoadingToFinish() { }); } +// Custom matcher that queries elements split up by multiple HTML elements by text +export function getByTextWithMarkup(text: RegExp | string) { + try { + return screen.getByText((content, node) => { + const hasText = (node: Element) => node.textContent === text || node.textContent.match(text); + const childrenDontHaveText = Array.from(node.children).every((child) => !hasText(child as HTMLElement)); + return hasText(node) && childrenDontHaveText; + }); + } catch (error) { + throw new Error(`Text '${text}' not found. ${error}`); + } +} + export const mockPatient = { resourceType: 'Patient', id: '8673ee4f-e2ab-4077-ba55-4980f408773e',