Skip to content

Commit

Permalink
fix: cancelling on encounter and patient resources and composition wh…
Browse files Browse the repository at this point in the history
…en canceling a research Ref gestion-de-projet#1212
  • Loading branch information
Mehdi-BOUYAHIA committed Mar 17, 2023
1 parent 0674605 commit 9d1a736
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 83 deletions.
40 changes: 27 additions & 13 deletions src/components/Dashboard/Documents/Documents.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'
import React, { useState, useEffect, useRef } from 'react'

import { Checkbox, CssBaseline, Grid, Typography } from '@material-ui/core'
import Alert from '@material-ui/lab/Alert'
Expand All @@ -25,6 +25,8 @@ import { buildDocumentFiltersChips } from 'utils/chips'

import { docTypes } from 'assets/docTypes.json'

import { useDebounce } from 'utils/debounce'

type DocumentsProps = {
groupId?: string
deidentifiedBoolean: boolean | null
Expand Down Expand Up @@ -59,16 +61,28 @@ const Documents: React.FC<DocumentsProps> = ({ groupId, deidentifiedBoolean }) =
})

const [searchInputError, setSearchInputError] = useState<searchInputError | undefined>(undefined)
const controllerRef = useRef<AbortController | null>()
const debouncedSearchInput = useDebounce(200, searchInput)

const checkDocumentSearch = async (controller: any) => {
const checkDocumentSearch = await services.cohorts.checkDocumentSearchInput(searchInput, controller.signal)
const _cancelPendingRequest = () => {
if (controllerRef.current) {
controllerRef.current.abort()
}
controllerRef.current = new AbortController()
}

const checkDocumentSearch = async () => {
const checkDocumentSearch = await services.cohorts.checkDocumentSearchInput(
searchInput,
controllerRef.current?.signal
)

setSearchInputError(checkDocumentSearch)

return checkDocumentSearch
}

const onSearchDocument = async (newPage: number, controller: any) => {
const onSearchDocument = async (newPage: number) => {
try {
if (searchInput) {
setSearchMode(true)
Expand All @@ -77,7 +91,7 @@ const Documents: React.FC<DocumentsProps> = ({ groupId, deidentifiedBoolean }) =
}
setLoadingStatus(true)

const searchInputError = await checkDocumentSearch(controller)
const searchInputError = await checkDocumentSearch()
if (searchInputError && searchInputError.isError) {
setDocuments([])
setLoadingStatus(false)
Expand All @@ -99,7 +113,7 @@ const Documents: React.FC<DocumentsProps> = ({ groupId, deidentifiedBoolean }) =
filters.nda,
filters.ipp ?? '',
filters.onlyPdfAvailable,
controller.signal,
controllerRef?.current?.signal,
filters.startDate,
filters.endDate,
groupId
Expand Down Expand Up @@ -129,19 +143,19 @@ const Documents: React.FC<DocumentsProps> = ({ groupId, deidentifiedBoolean }) =
}
}

const handleChangePage = (newPage = 1, controller?: any) => {
const handleChangePage = (newPage = 1) => {
setPage(newPage)

onSearchDocument(newPage, controller)
onSearchDocument(newPage)
}

useEffect(() => {
const controller = new AbortController()

handleChangePage(1, controller)
// const controller = new AbortController()
_cancelPendingRequest()
handleChangePage(1)

return () => controller.abort()
}, [!!deidentifiedBoolean, filters, order, searchInput, searchBy]) // eslint-disable-line
return () => _cancelPendingRequest()
}, [!!deidentifiedBoolean, filters, order,debouncedSearchInput, searchBy]) // eslint-disable-line

const handleOpenDialog = () => {
setOpenFilter(true)
Expand Down
12 changes: 4 additions & 8 deletions src/components/DataTable/DataTableTopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ import {
} from 'types'

import displayDigit from 'utils/displayDigit'
import { useDebounce } from 'utils/debounce'

import useStyles from './styles'
import { CircularProgress } from '@material-ui/core'

Expand All @@ -48,8 +46,6 @@ const DataTableTopBar: React.FC<DataTableTopBarProps> = ({ loading, tabs, result
const [search, setSearch] = useState(searchBar?.value ?? '')
const [searchBy, setSearchBy] = useState<SearchByTypes>(SearchByTypes.text)

const debouncedSearchItem = useDebounce(0, search)

const onSearch = (newInput = search) => {
if (searchBar && searchBar.onSearch && typeof searchBar.onSearch === 'function') {
searchBar.onSearch(newInput, searchBy)
Expand Down Expand Up @@ -77,12 +73,12 @@ const DataTableTopBar: React.FC<DataTableTopBarProps> = ({ loading, tabs, result
}, [searchBar, searchBar && searchBar?.value])

useEffect(() => {
onSearch(debouncedSearchItem)
}, [debouncedSearchItem])
onSearch(search)
}, [search])

useEffect(() => {
if (debouncedSearchItem !== '') {
onSearch(debouncedSearchItem)
if (search !== '') {
onSearch(search)
}
}, [searchBy])

Expand Down
90 changes: 37 additions & 53 deletions src/services/aphp/callApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
IProcedure,
IOrganization
} from '@ahryman40k/ts-fhir-types/lib/R4'
import axios, { AxiosResponse } from 'axios'
import { AxiosResponse } from 'axios'
import apiBackend from '../apiBackend'

const reducer = (accumulator: any, currentValue: any) =>
Expand Down Expand Up @@ -118,6 +118,7 @@ type fetchPatientProps = {
pivotFacet?: ('age_gender' | 'deceased_gender')[]
_elements?: ('id' | 'gender' | 'name' | 'birthDate' | 'deceased' | 'identifier' | 'extension')[]
deidentified?: boolean
signal?: AbortSignal
}
export const fetchPatient = async (args: fetchPatientProps) => {
const {
Expand All @@ -135,7 +136,8 @@ export const fetchPatient = async (args: fetchPatientProps) => {
deceased,
minBirthdate,
maxBirthdate,
deidentified
deidentified,
signal
} = args
const _sortDirection = sortDirection === 'desc' ? '-' : ''
let { _list, pivotFacet, _elements } = args
Expand All @@ -162,7 +164,9 @@ export const fetchPatient = async (args: fetchPatientProps) => {
if (pivotFacet && pivotFacet.length > 0) options = [...options, `pivotFacet=${pivotFacet.reduce(reducer)}`] // eslint-disable-line
if (_elements && _elements.length > 0) options = [...options, `_elements=${_elements.reduce(reducer)}`] // eslint-disable-line

const response = await apiFhir.get<FHIR_API_Response<IPatient>>(`/Patient?${options.reduce(optionsReducer)}`)
const response = await apiFhir.get<FHIR_API_Response<IPatient>>(`/Patient?${options.reduce(optionsReducer)}`, {
signal: signal
})

return response
}
Expand All @@ -185,9 +189,10 @@ type fetchEncounterProps = {
status?: string[]
facet?: ('class' | 'visit-year-month-gender-facet')[]
_elements?: ('status' | 'serviceProvider' | 'identifier')[]
signal?: AbortSignal
}
export const fetchEncounter = async (args: fetchEncounterProps) => {
const { _id, size, offset, _sort, sortDirection, patient, type } = args
const { _id, size, offset, _sort, sortDirection, patient, type, signal } = args
const _sortDirection = sortDirection === 'desc' ? '-' : ''
let { _list, _elements, status, facet } = args
const typeNot = args['type:not']
Expand All @@ -211,7 +216,9 @@ export const fetchEncounter = async (args: fetchEncounterProps) => {
if (_elements && _elements.length > 0) options = [...options, `_elements=${_elements.reduce(reducer)}`] // eslint-disable-line
if (facet && facet.length > 0) options = [...options, `facet=${facet.reduce(reducer)}`] // eslint-disable-line

const response = await apiFhir.get<FHIR_API_Response<IEncounter>>(`/Encounter?${options.reduce(optionsReducer)}`)
const response = await apiFhir.get<FHIR_API_Response<IEncounter>>(`/Encounter?${options.reduce(optionsReducer)}`, {
signal: signal
})

return response
}
Expand All @@ -222,7 +229,7 @@ export const fetchEncounter = async (args: fetchEncounterProps) => {
*/

type fetchCompositionProps = {
signal?: any
signal?: AbortSignal
_id?: string
_list?: string[]
size?: number
Expand Down Expand Up @@ -262,7 +269,6 @@ export const fetchComposition = async (args: fetchCompositionProps) => {
minDate,
maxDate
} = args
console.log('args', args)
const _sortDirection = sortDirection === 'desc' ? '-' : ''
let { _list, facet, uniqueFacet, _elements } = args
const encounterIdentifier = args['encounter.identifier']
Expand Down Expand Up @@ -296,42 +302,20 @@ export const fetchComposition = async (args: fetchCompositionProps) => {
if (uniqueFacet && uniqueFacet.length > 0) options = [...options, `uniqueFacet=${uniqueFacet.reduce(reducer)}`] // eslint-disable-line
if (_elements && _elements.length > 0) options = [...options, `_elements=${_elements.reduce(reducer)}`] // eslint-disable-line

let config = undefined
if (signal) config = { signal: signal }
console.log('configlooooo', config)

try {
const response = await apiFhir.get<FHIR_API_Response<IComposition>>(
`/Composition?${options.reduce(optionsReducer)}`,
config
)

return response
} catch (error) {
if (axios.isCancel(error)) {
console.error('axios cancelled de composition frerot', error)
}
console.error('Erreur lors de la récupération des documents', error)
return {} as AxiosResponse<FHIR_API_Response<IComposition>>
}
const response = await apiFhir.get<FHIR_API_Response<IComposition>>(
`/Composition?${options.reduce(optionsReducer)}`,
{ signal: signal }
)

return response
}

export const fetchCheckDocumentSearchInput = async (searchInput: string, signal?: any) => {
const config = signal ? { signal: signal } : undefined
try {
console.log('config', config)
const checkDocumentSearchInput = await apiFhir.get<CohortComposition>(
`/Composition/$text?_text=${encodeURIComponent(searchInput)}`,
config
)
return checkDocumentSearchInput.data.parameter ?? null
} catch (error) {
console.error('Erreur lors de la vérification du champ de recherche', error)
if (axios.isCancel(error)) {
console.error('axios cancelled du check frerot', error)
}
return null
}
export const fetchCheckDocumentSearchInput = async (searchInput: string, signal?: AbortSignal) => {
const checkDocumentSearchInput = await apiFhir.get<CohortComposition>(
`/Composition/$text?_text=${encodeURIComponent(searchInput)}`,
{ signal: signal }
)
return checkDocumentSearchInput.data.parameter ?? null
}

export const fetchCompositionContent = async (compositionId: string) => {
Expand Down Expand Up @@ -417,17 +401,17 @@ export const fetchProcedure = async (args: fetchProcedureProps) => {
_list = _list ? _list.filter(uniq) : []

let options: string[] = []
if (size !== undefined) options = [...options, `size=${size}`] // eslint-disable-line
if (offset) options = [...options, `offset=${offset}`] // eslint-disable-line
if (_sort) options = [...options, `_sort=${_sortDirection}${_sort},id`] // eslint-disable-line
if (subject) options = [...options, `subject=${subject}`] // eslint-disable-line
if (patient) options = [...options, `patient=${patient}`] // eslint-disable-line
if (code) options = [...options, `code=${code}`] // eslint-disable-line
if (_text) options = [...options, `_text=${encodeURIComponent(_text)}`] // eslint-disable-line
if (status) options = [...options, `status=${status}`] // eslint-disable-line
if (encounterIdentifier) options = [...options, `encounter.identifier=${encounterIdentifier}`] // eslint-disable-line
if (minDate) options = [...options, `date=ge${minDate}`] // eslint-disable-line
if (maxDate) options = [...options, `date=le${maxDate}`] // eslint-disable-line
if (size !== undefined) options = [...options, `size=${size}`] // eslint-disable-line
if (offset) options = [...options, `offset=${offset}`] // eslint-disable-line
if (_sort) options = [...options, `_sort=${_sortDirection}${_sort},id`] // eslint-disable-line
if (subject) options = [...options, `subject=${subject}`] // eslint-disable-line
if (patient) options = [...options, `patient=${patient}`] // eslint-disable-line
if (code) options = [...options, `code=${code}`] // eslint-disable-line
if (_text) options = [...options, `_text=${encodeURIComponent(_text)}`] // eslint-disable-line
if (status) options = [...options, `status=${status}`] // eslint-disable-line
if (encounterIdentifier) options = [...options, `encounter.identifier=${encounterIdentifier}`] // eslint-disable-line
if (minDate) options = [...options, `date=ge${minDate}`] // eslint-disable-line
if (maxDate) options = [...options, `date=le${maxDate}`] // eslint-disable-line

if (_list && _list.length > 0) options = [...options, `_list=${_list.reduce(reducer)}`] // eslint-disable-line

Expand Down Expand Up @@ -575,7 +559,7 @@ export const fetchObservation = async (args: fetchObservationProps) => {
if (minDate) options = [...options, `effectiveDatetime=ge${minDate}`] // eslint-disable-line
if (maxDate) options = [...options, `effectiveDatetime=le${maxDate}`] // eslint-disable-line

if (_list && _list.length > 0) options = [...options, `_list=${_list.reduce(reducer)}`] // eslint-disable-line
if (_list && _list.length > 0) options = [...options, `_list=${_list.reduce(reducer)}`] // eslint-disable-line

const response = await apiFhir.get<FHIR_API_Response<IObservation>>(`/Observation?${options.reduce(optionsReducer)}`)

Expand Down
25 changes: 17 additions & 8 deletions src/services/aphp/serviceCohorts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export interface IServiceCohorts {
nda: string,
ipp: string,
onlyPdfAvailable: boolean,
signal?: any,
signal?: AbortSignal,
startDate?: string | null,
endDate?: string | null,
groupId?: string
Expand All @@ -157,7 +157,7 @@ export interface IServiceCohorts {
* Retourne:
* - searchInputError: objet décrivant la ou les erreurs du champ de recherche s'il y en a
*/
checkDocumentSearchInput: (searchInput: string, signal?: any) => Promise<searchInputError>
checkDocumentSearchInput: (searchInput: string, signal?: AbortSignal) => Promise<searchInputError>

/**
* Permet de récupérer le contenu d'un document
Expand Down Expand Up @@ -454,7 +454,12 @@ const servicesCohorts: IServiceCohorts = {
).valueDecimal
: totalPatientDocs

const documentsList = await getDocumentInfos(deidentifiedBoolean, getApiResponseResources(docsList), groupId)
const documentsList = await getDocumentInfos(
deidentifiedBoolean,
getApiResponseResources(docsList),
groupId,
signal
)

return {
totalDocs: totalDocs ?? 0,
Expand Down Expand Up @@ -767,8 +772,9 @@ export default servicesCohorts
const getDocumentInfos: (
deidentifiedBoolean: boolean,
documents?: IComposition[],
groupId?: string
) => Promise<CohortComposition[]> = async (deidentifiedBoolean: boolean, documents, groupId) => {
groupId?: string,
signal?: AbortSignal
) => Promise<CohortComposition[]> = async (deidentifiedBoolean: boolean, documents, groupId, signal) => {
const cohortDocuments = (documents as CohortComposition[]) ?? []

const listePatientsIds = cohortDocuments
Expand All @@ -784,14 +790,17 @@ const getDocumentInfos: (
fetchPatient({
_id: listePatientsIds,
_list: groupId ? [groupId] : [],
_elements: ['extension', 'id', 'identifier']
_elements: ['extension', 'id', 'identifier'],
signal: signal
}),
fetchEncounter({
_id: listeEncounterIds,
_list: groupId ? [groupId] : [],
type: 'VISIT',
_elements: ['status', 'serviceProvider', 'identifier']
})
_elements: ['status', 'serviceProvider', 'identifier'],
signal: signal
}),
signal
])

if (encounters.data.resourceType !== 'Bundle' || !encounters.data.entry) {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/debounce.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'

export const useDebounce = (delay: number, value?: string) => {
export const useDebounce = (delay: number, value: string) => {
const [debouncedValue, setDebouncedValue] = useState(value)

useEffect(() => {
Expand Down

0 comments on commit 9d1a736

Please sign in to comment.