From 6d99fbe79e78e7959d12b440f39e66e4eda9f203 Mon Sep 17 00:00:00 2001 From: Bhargav Kodali Date: Wed, 20 Nov 2024 13:00:17 -0700 Subject: [PATCH] useOpenmrsFetchall --- package.json | 4 +- .../src/hooks/useQueueEntries.ts | 118 +++--------------- .../clinic-metrics.component.tsx | 2 +- yarn.lock | 4 +- 4 files changed, 21 insertions(+), 107 deletions(-) diff --git a/package.json b/package.json index 13194bcc2..b4f900fb8 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "devDependencies": { "@babel/core": "^7.11.6", "@carbon/react": "~1.37.0", - "@openmrs/esm-framework": "^5.7.3-pre.2185", + "@openmrs/esm-framework": "next", "@openmrs/esm-patient-common-lib": "next", "@playwright/test": "1.45.2", "@swc/core": "^1.2.165", @@ -64,7 +64,7 @@ "jest-cli": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "lint-staged": "^15.2.1", - "openmrs": "^5.7.3-pre.2185", + "openmrs": "next", "prettier": "^3.1.1", "react": "^18.1.0", "react-dom": "^18.1.0", diff --git a/packages/esm-service-queues-app/src/hooks/useQueueEntries.ts b/packages/esm-service-queues-app/src/hooks/useQueueEntries.ts index 688e92ee9..15f34892c 100644 --- a/packages/esm-service-queues-app/src/hooks/useQueueEntries.ts +++ b/packages/esm-service-queues-app/src/hooks/useQueueEntries.ts @@ -1,4 +1,4 @@ -import { type FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework'; +import { type FetchResponse, openmrsFetch, restBaseUrl, useOpenmrsFetchAll } from '@openmrs/esm-framework'; import { type QueueEntry, type QueueEntrySearchCriteria } from '../types'; import useSWR from 'swr'; import { useCallback, useEffect, useMemo, useState } from 'react'; @@ -68,104 +68,22 @@ export function useMutateQueueEntries() { }; } -export function useQueueEntries(searchCriteria?: QueueEntrySearchCriteria, rep: string = repString) { - // This manually implements a kind of pagination using the useSWR hook. It does not use useSWRInfinite - // because useSWRInfinite does not support with `mutate`. The hook starts by fetching the first page, - // page zero, waits until data is fetched, then fetches the next page, and so on. - // - // Fine so far. Where things get complicated is in supporting mutation. When a mutation is made, the - // SWR hook first returns stale data with `isValidating` set to false. At this point we say we are - // "waiting for mutate," because we have called mutate, but the useSWR hook hasn't updated properly - // for it yet. Next it returns stale data again, this time with `isValidating` set to true. At this - // point we say we are no longer waiting for mutate. Finally, it returns fresh data with `isValidating` - // again set to false. We may then update the data array and move on to the next page. - const [data, setData] = useState>>([]); - const [totalCount, setTotalCount] = useState(); - const [currentPage, setCurrentPage] = useState(0); - const [currentSearchCriteria, setCurrentSearchCriteria] = useState(searchCriteria); - const [currentRep, setCurrentRep] = useState(rep); - const [pageUrl, setPageUrl] = useState(getInitialUrl(currentRep, currentSearchCriteria)); - const [error, setError] = useState(); - const { mutateQueueEntries } = useMutateQueueEntries(); - const [waitingForMutate, setWaitingForMutate] = useState(false); - - const refetchAllData = useCallback( - (newRep: string = currentRep, newSearchCriteria: QueueEntrySearchCriteria = currentSearchCriteria) => { - setWaitingForMutate(true); - setCurrentPage(0); - setPageUrl(getInitialUrl(newRep, newSearchCriteria)); - }, - [currentRep, currentSearchCriteria], - ); - - // This hook listens to the searchCriteria and rep values and refetches the data when they change. - useEffect(() => { - const isSearchCriteriaUpdated = !isEqual(currentSearchCriteria, searchCriteria); - const isRepUpdated = currentRep !== rep; - if (isSearchCriteriaUpdated || isRepUpdated) { - if (isSearchCriteriaUpdated) { - setCurrentSearchCriteria(searchCriteria); - } - if (isRepUpdated) { - setCurrentRep(rep); - } - refetchAllData(rep, searchCriteria); - } - }, [searchCriteria, currentSearchCriteria, setCurrentSearchCriteria, currentRep, rep]); +export function useQueueEntries(searchCriteria?: QueueEntrySearchCriteria, rep: string = repString){ - const { data: pageData, isValidating, error: pageError } = useSWR(pageUrl, openmrsFetch); + const [pageUrl, setPageUrl] = useState(getInitialUrl(rep, searchCriteria)); + const {data,mutate,...rest}=useOpenmrsFetchAll(pageUrl); useEffect(() => { - const nextUrl = getNextUrlFromResponse(pageData); - const stillWaitingForMutate = waitingForMutate && !isValidating; - if (waitingForMutate && isValidating) { - setWaitingForMutate(false); - } - if (pageData && !isValidating && !stillWaitingForMutate) { - // We've got results! Time to update the data array and move on to the next page. - if (pageData?.data?.totalCount > -1 && pageData?.data?.totalCount !== totalCount) { - setTotalCount(pageData?.data?.totalCount); - } - if (pageData?.data?.results) { - const newData = [...data]; - newData[currentPage] = pageData?.data?.results; - setData(newData); - } - setCurrentPage(currentPage + 1); - setPageUrl(nextUrl); - // If we're mutating existing data, then we again need to wait for the mutate to work, - // since useSWR will (again) first return stale data with isValidating set to false. - const inMutateMode = data.length > currentPage; - if (inMutateMode && nextUrl) { - setWaitingForMutate(true); - } - } - // It may happen that there are fewer pages in the new data than in the old data. In this - // case, we need to remove the extra pages, which are stored on the `data` array. - // Note that since we mutated the `data` state earlier in this function, it is important to - // use the functional form of `setData` so as not to use the stale `data` state. - if (!nextUrl) { - // I will not be very suprised if there is an off-by-one error here. - if (data.length > currentPage + 1) { - setData((prevData) => { - const newData = [...prevData]; - newData.splice(currentPage + 1); - return newData; - }); - } - } - }, [pageData, data, currentPage, totalCount, waitingForMutate, isValidating]); + setPageUrl(getInitialUrl(rep, searchCriteria)); + }, [searchCriteria,rep]); - useEffect(() => { - // An error to one is an error to all - if (pageError) { - setError(pageError); - } - }, [pageError]); + useEffect(()=>{ + mutate(); + },[pageUrl]) const queueUpdateListener = useCallback(() => { - refetchAllData(); - }, [refetchAllData]); + mutate(); + }, []); useEffect(() => { window.addEventListener('queue-entry-updated', queueUpdateListener); @@ -174,16 +92,12 @@ export function useQueueEntries(searchCriteria?: QueueEntrySearchCriteria, rep: }; }, [queueUpdateListener]); - const queueEntries = useMemo(() => data.flat(), [data]); - return { - queueEntries, - totalCount, - isLoading: totalCount === undefined || (totalCount && queueEntries.length < totalCount), - isValidating: isValidating || currentPage < data.length, - error, - mutate: mutateQueueEntries, - }; + queueEntries:data, + mutate, + ...rest + } + } export function useQueueEntriesMetrics(searchCriteria?: QueueEntrySearchCriteria) { diff --git a/packages/esm-service-queues-app/src/patient-queue-metrics/clinic-metrics.component.tsx b/packages/esm-service-queues-app/src/patient-queue-metrics/clinic-metrics.component.tsx index 38a7c63e2..0f2dca0a3 100644 --- a/packages/esm-service-queues-app/src/patient-queue-metrics/clinic-metrics.component.tsx +++ b/packages/esm-service-queues-app/src/patient-queue-metrics/clinic-metrics.component.tsx @@ -57,7 +57,7 @@ function ClinicMetrics() { />