diff --git a/src/__tests__/patients/list/ViewPatients.test.tsx b/src/__tests__/patients/list/ViewPatients.test.tsx index 4d44f7dcb3..dfe413dc29 100644 --- a/src/__tests__/patients/list/ViewPatients.test.tsx +++ b/src/__tests__/patients/list/ViewPatients.test.tsx @@ -64,7 +64,31 @@ describe('Patients', () => { beforeEach(() => { jest.resetAllMocks() jest.spyOn(PatientRepository, 'findAll') + jest.spyOn(PatientRepository, 'searchPaged') + jest.spyOn(PatientRepository, 'findAllPaged') + mockedPatientRepository.findAll.mockResolvedValue([]) + mockedPatientRepository.findAllPaged.mockResolvedValue( + new Promise>((resolve) => { + const pagedResult: Page = { + content: [], + hasPrevious: false, + hasNext: false, + } + resolve(pagedResult) + }), + ) + + mockedPatientRepository.searchPaged.mockResolvedValue( + new Promise>((resolve) => { + const pagedResult: Page = { + content: [], + hasPrevious: false, + hasNext: false, + } + resolve(pagedResult) + }), + ) }) describe('layout', () => { @@ -147,9 +171,12 @@ describe('Patients', () => { expect(searchPatientsSpy).toHaveBeenLastCalledWith( expectedSearchText, { - sorts: [{ field: 'code', direction: 'desc' }], + sorts: [ + { field: 'fullName', direction: 'asc' }, + { field: 'code', direction: 'asc' }, + ], }, - { limit: 1, skip: 0 }, + { number: 1, size: 1 }, ) }) }) diff --git a/src/__tests__/patients/patients-slice.test.ts b/src/__tests__/patients/patients-slice.test.ts index e658a0dabe..7a561289ac 100644 --- a/src/__tests__/patients/patients-slice.test.ts +++ b/src/__tests__/patients/patients-slice.test.ts @@ -2,6 +2,8 @@ import '../../__mocks__/matchMediaMock' import { AnyAction } from 'redux' import { mocked } from 'ts-jest/utils' import { UnpagedRequest } from 'clients/db/PageRequest' +import Page from 'clients/Page' +import Patient from 'model/Patient' import patients, { fetchPatientsStart, fetchPatientsSuccess, @@ -54,6 +56,34 @@ describe('patients slice', () => { }) describe('searchPatients', () => { + beforeEach(() => { + const mockedPatientRepository = mocked(PatientRepository, true) + jest.spyOn(PatientRepository, 'findAllPaged') + jest.spyOn(PatientRepository, 'searchPaged') + + mockedPatientRepository.findAllPaged.mockResolvedValue( + new Promise>((resolve) => { + const pagedResult: Page = { + content: [], + hasPrevious: false, + hasNext: false, + } + resolve(pagedResult) + }), + ) + + mockedPatientRepository.searchPaged.mockResolvedValue( + new Promise>((resolve) => { + const pagedResult: Page = { + content: [], + hasPrevious: false, + hasNext: false, + } + resolve(pagedResult) + }), + ) + }) + it('should dispatch the FETCH_PATIENTS_START action', async () => { const dispatch = jest.fn() const getState = jest.fn() @@ -91,36 +121,15 @@ describe('patients slice', () => { const dispatch = jest.fn() const getState = jest.fn() - const expectedPatients = { - content: [ - { - id: '123', - fullName: 'test test', - isApproximateDateOfBirth: false, - givenName: 'test', - familyName: 'test', - code: 'P12345', - sex: 'male', - dateOfBirth: new Date().toISOString(), - phoneNumber: '99999999', - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - rev: '', - }, - ], - hasNext: false, - hasPrevious: false, - pageRequest: UnpagedRequest, - } - - const mockedPatientRepository = mocked(PatientRepository, true) - mockedPatientRepository.searchPaged.mockResolvedValue(expectedPatients) - await searchPatients('search string')(dispatch, getState, null) expect(dispatch).toHaveBeenLastCalledWith({ type: fetchPatientsSuccess.type, - payload: expectedPatients, + payload: { + content: [], + hasPrevious: false, + hasNext: false, + }, }) }) }) diff --git a/src/clients/Page.ts b/src/clients/Page.ts index d9a4ce9e41..ec830a1f14 100644 --- a/src/clients/Page.ts +++ b/src/clients/Page.ts @@ -3,7 +3,7 @@ import PageRequest from './db/PageRequest' export default interface Page { content: T[] - hasNext?: boolean - hasPrevious?: boolean + hasNext: boolean + hasPrevious: boolean pageRequest?: PageRequest } diff --git a/src/clients/db/PageRequest.ts b/src/clients/db/PageRequest.ts index d63098d262..447205bc39 100644 --- a/src/clients/db/PageRequest.ts +++ b/src/clients/db/PageRequest.ts @@ -1,5 +1,8 @@ export default interface PageRequest { - limit: number | undefined - skip: number + number: number | undefined + size: number | undefined +} +export const UnpagedRequest: PageRequest = { + number: undefined, + size: undefined, } -export const UnpagedRequest: PageRequest = { limit: undefined, skip: 0 } diff --git a/src/clients/db/PatientRepository.ts b/src/clients/db/PatientRepository.ts index 7ef4cad02b..a6d206ea04 100644 --- a/src/clients/db/PatientRepository.ts +++ b/src/clients/db/PatientRepository.ts @@ -4,6 +4,7 @@ import Patient from '../../model/Patient' import Repository from './Repository' import { patients } from '../../config/pouchdb' import PageRequest, { UnpagedRequest } from './PageRequest' +import SortRequest, { Unsorted } from './SortRequest' const formatPatientCode = (prefix: string, sequenceNumber: string) => `${prefix}${sequenceNumber}` @@ -13,7 +14,7 @@ export class PatientRepository extends Repository { constructor() { super(patients) patients.createIndex({ - index: { fields: ['code', 'fullName'] }, + index: { fields: ['fullName', 'code'] }, }) } @@ -37,40 +38,47 @@ export class PatientRepository extends Repository { async searchPaged( text: string, pageRequest: PageRequest = UnpagedRequest, + sortRequest: SortRequest = Unsorted, ): Promise> { - return super - .search({ - selector: { - $or: [ - { - fullName: { - $regex: RegExp(text, 'i'), - }, - }, - { - code: text, - }, - ], + const selector: any = { + $or: [ + { + fullName: { + $regex: RegExp(text, 'i'), + }, + }, + { + code: text, }, - skip: pageRequest.skip, - limit: pageRequest.limit, + ], + } + sortRequest.sorts.forEach((s) => { + selector[s.field] = { $gt: null } + }) + + const result = await super + .search({ + selector, + limit: pageRequest.size, + skip: + pageRequest.number && pageRequest.size ? (pageRequest.number - 1) * pageRequest.size : 0, + sort: + sortRequest.sorts.length > 0 + ? sortRequest.sorts.map((s) => ({ [s.field]: s.direction })) + : undefined, }) - .then( - (searchedData) => - new Promise>((resolve) => { - const pagedResult: Page = { - content: searchedData, - pageRequest, - hasNext: pageRequest.limit !== undefined && searchedData.length === pageRequest.limit, - hasPrevious: pageRequest.skip > 0, - } - resolve(pagedResult) - }), - ) .catch((err) => { console.log(err) return err }) + + const pagedResult: Page = { + content: result, + pageRequest, + hasNext: pageRequest.size !== undefined && result.length === pageRequest.size, + hasPrevious: pageRequest.number !== undefined && pageRequest.number > 1, + } + return pagedResult } async save(entity: Patient): Promise { diff --git a/src/clients/db/Repository.ts b/src/clients/db/Repository.ts index 67266172ad..cde7100407 100644 --- a/src/clients/db/Repository.ts +++ b/src/clients/db/Repository.ts @@ -55,18 +55,19 @@ export default class Repository { const result = await this.db.find({ selector, sort: sort.sorts.length > 0 ? sort.sorts.map((s) => ({ [s.field]: s.direction })) : undefined, - limit: pageRequest.limit, - skip: pageRequest.skip, + limit: pageRequest.size, + skip: + pageRequest.number && pageRequest.size ? (pageRequest.number - 1) * pageRequest.size : 0, }) const mappedResult = result.docs.map(mapDocument) const pagedResult: Page = { content: mappedResult, - hasNext: pageRequest.limit !== undefined && mappedResult.length === pageRequest.limit, - hasPrevious: pageRequest.skip > 0, + hasNext: pageRequest.size !== undefined && mappedResult.length === pageRequest.size, + hasPrevious: pageRequest.number !== undefined && pageRequest.number > 1, pageRequest: { - skip: pageRequest.skip, - limit: pageRequest.limit, + size: pageRequest.size, + number: pageRequest.number, }, } return pagedResult diff --git a/src/patients/list/ViewPatients.tsx b/src/patients/list/ViewPatients.tsx index acbd809dce..9e34fb79f9 100644 --- a/src/patients/list/ViewPatients.tsx +++ b/src/patients/list/ViewPatients.tsx @@ -26,16 +26,16 @@ const ViewPatients = () => { const setButtonToolBar = useButtonToolbarSetter() const [userPageRequest, setUserPageRequest] = useState({ - skip: 0, - limit: 1, + size: 1, + number: 1, }) const setNextPageRequest = () => { setUserPageRequest((p) => { - if (p.limit) { + if (p && p.number && p.number >= 0 && p.size) { const newPageRequest: PageRequest = { - limit: p.limit, - skip: p.skip + p.limit, + number: p.number + 1, + size: p.size, } return newPageRequest } @@ -45,10 +45,10 @@ const ViewPatients = () => { const setPreviousPageRequest = () => { setUserPageRequest((p) => { - if (p.limit) { + if (p.number && p.size) { return { - limit: p.limit, - skip: p.skip - p.limit, + number: p.number - 1, + size: p.size, } } return p @@ -60,14 +60,20 @@ const ViewPatients = () => { useEffect(() => { const sortRequest: SortRequest = { - sorts: [{ field: 'code', direction: 'desc' }], + sorts: [ + { field: 'fullName', direction: 'asc' }, + { field: 'code', direction: 'asc' }, + ], } dispatch(searchPatients(debouncedSearchText, sortRequest, userPageRequest)) }, [dispatch, debouncedSearchText, userPageRequest]) useEffect(() => { const sortRequest: SortRequest = { - sorts: [{ field: 'code', direction: 'desc' }], + sorts: [ + { field: 'fullName', direction: 'asc' }, + { field: 'code', direction: 'asc' }, + ], } dispatch(fetchPatients(sortRequest, userPageRequest)) @@ -136,7 +142,7 @@ const ViewPatients = () => { diff --git a/src/patients/patients-slice.ts b/src/patients/patients-slice.ts index 284a033d33..161dcaa3bc 100644 --- a/src/patients/patients-slice.ts +++ b/src/patients/patients-slice.ts @@ -17,10 +17,6 @@ const initialState: PatientsState = { content: [], hasNext: false, hasPrevious: false, - pageRequest: { - skip: 0, - limit: 1, - }, }, } @@ -42,8 +38,8 @@ const patientsSlice = createSlice({ export const { fetchPatientsStart, fetchPatientsSuccess } = patientsSlice.actions export const fetchPatients = ( - sortRequest: SortRequest, - pageRequest: PageRequest, + sortRequest: SortRequest = Unsorted, + pageRequest: PageRequest = UnpagedRequest, ): AppThunk => async (dispatch) => { dispatch(fetchPatientsStart()) const patients = await PatientRepository.findAllPaged(sortRequest, pageRequest)