diff --git a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/BiologyForm/components/Form/BiologyForm.tsx b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/BiologyForm/components/Form/BiologyForm.tsx index 80ac7484f..d40d4df6a 100644 --- a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/BiologyForm/components/Form/BiologyForm.tsx +++ b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/BiologyForm/components/Form/BiologyForm.tsx @@ -244,6 +244,7 @@ const BiologyForm: React.FC = (props) => { = (props) => { dispatch(fetchProcedure()) } - const getCCAMOptions = async (searchValue: string) => { - const ccamOptions = await services.cohortCreation.fetchCcamData(searchValue, false) + const getCCAMOptions = async (searchValue: string, signal: AbortSignal) => { + const ccamOptions = await services.cohortCreation.fetchCcamData(searchValue, false, signal) return ccamOptions && ccamOptions.length > 0 ? ccamOptions : [] } diff --git a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/Cim10Form/components/Form/Cim10Form.tsx b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/Cim10Form/components/Form/Cim10Form.tsx index 7668d82bf..60b3caf8b 100644 --- a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/Cim10Form/components/Form/Cim10Form.tsx +++ b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/Cim10Form/components/Form/Cim10Form.tsx @@ -49,8 +49,8 @@ const Cim10Form: React.FC = (props) => { onChangeSelectedCriteria(currentState) dispatch(fetchCondition()) } - const getDiagOptions = async (searchValue: string) => - await services.cohortCreation.fetchCim10Diagnostic(searchValue, false) + const getDiagOptions = async (searchValue: string, signal: AbortSignal) => + await services.cohortCreation.fetchCim10Diagnostic(searchValue, false, signal) const defaultValuesCode = currentState.code ? currentState.code.map((code) => { diff --git a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/GHM/components/Form/GhmForm.tsx b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/GHM/components/Form/GhmForm.tsx index 018983867..457735ca4 100644 --- a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/GHM/components/Form/GhmForm.tsx +++ b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/GHM/components/Form/GhmForm.tsx @@ -33,7 +33,8 @@ const GhmForm: React.FC = (props) => { const currentState = { ...selectedCriteria, ...initialState } const [multiFields, setMultiFields] = useState(localStorage.getItem('multiple_fields')) - const getGhmOptions = async (searchValue: string) => await services.cohortCreation.fetchGhmData(searchValue, false) + const getGhmOptions = async (searchValue: string, signal: AbortSignal) => + await services.cohortCreation.fetchGhmData(searchValue, false, signal) const _onSubmit = () => { onChangeSelectedCriteria(currentState) dispatch(fetchClaim()) diff --git a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/MedicationForm/components/Form/MedicationForm.tsx b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/MedicationForm/components/Form/MedicationForm.tsx index be5b62faf..9ba9049f1 100644 --- a/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/MedicationForm/components/Form/MedicationForm.tsx +++ b/src/components/CreationCohort/DiagramView/components/LogicalOperator/components/CriteriaRightPanel/MedicationForm/components/Form/MedicationForm.tsx @@ -49,8 +49,8 @@ const MedicationForm: React.FC = (props) => { const currentState = { ...selectedCriteria, ...initialState } const [multiFields, setMultiFields] = useState(localStorage.getItem('multiple_fields')) - const getMedicationOptions = async (searchValue: string) => - await services.cohortCreation.fetchMedicationData(searchValue, false) + const getMedicationOptions = async (searchValue: string, signal: AbortSignal) => + await services.cohortCreation.fetchMedicationData(searchValue, false, signal) const _onSubmit = () => { onChangeSelectedCriteria(currentState) diff --git a/src/components/Inputs/InputAutocompleteAsync/InputAutocompleteAsync.tsx b/src/components/Inputs/InputAutocompleteAsync/InputAutocompleteAsync.tsx index b0290dac7..3d3da712c 100644 --- a/src/components/Inputs/InputAutocompleteAsync/InputAutocompleteAsync.tsx +++ b/src/components/Inputs/InputAutocompleteAsync/InputAutocompleteAsync.tsx @@ -1,10 +1,11 @@ -import React, { FC, useEffect, useState, Fragment } from 'react' +import React, { FC, useEffect, useState, Fragment, useRef } from 'react' import { Autocomplete, CircularProgress, TextField } from '@mui/material' import { displaySystem } from 'utils/displayValueSetSystem' import { ValueSetSystem } from 'types' +import { cancelPendingRequest } from 'utils/abortController' interface ElementType { id: string @@ -22,7 +23,7 @@ type InputAutocompleteAsyncProps = { onChange?: (e: any, value: any) => void renderInput?: any autocompleteOptions?: ElementType[] - getAutocompleteOptions?: (searchValue: string) => Promise + getAutocompleteOptions?: (searchValue: string, signal: AbortSignal) => Promise noOptionsText?: string helperText?: string } @@ -46,6 +47,7 @@ const InputAutocompleteAsync: FC = (props) => { const [searchValue, setSearchValue] = useState('') const [options, setOptions] = useState(autocompleteOptions) const [loading, setLoading] = useState(false) + const controllerRef = useRef(null) useEffect(() => { let active = true @@ -53,7 +55,8 @@ const InputAutocompleteAsync: FC = (props) => { ;(async () => { setLoading(true) if (!getAutocompleteOptions) return - const response = (await getAutocompleteOptions(searchValue)) || [] + controllerRef.current = cancelPendingRequest(controllerRef.current) + const response = (await getAutocompleteOptions(searchValue, controllerRef.current?.signal)) || [] if (active) { setOptions(response) diff --git a/src/services/aphp/callApi.ts b/src/services/aphp/callApi.ts index bc8f446df..4c0c23283 100644 --- a/src/services/aphp/callApi.ts +++ b/src/services/aphp/callApi.ts @@ -823,13 +823,15 @@ export const fetchImaging = async (args: fetchImagingProps): FHIR_Bundle_Promise * @param code * @param search * @param noStar + * @param signal * @returns */ const getCodeList = async ( codeSystem: string, expandCode?: string, search?: string, - noStar = true + noStar = true, + signal?: AbortSignal ): Promise<{ code?: string; display?: string; extension?: Extension[]; codeSystem?: string }[] | undefined> => { if (!expandCode) { if (search !== undefined && !search.trim()) { @@ -844,7 +846,9 @@ const getCodeList = async ( : `&only-roots=false&_text=${encodeURIComponent(search.trim().replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'))}*` //eslint-disable-line } // TODO test if it returns all the codes without specifying the count - const res = await apiFhir.get>(`/ValueSet?reference=${codeSystem}${searchParam}`) + const res = await apiFhir.get>(`/ValueSet?reference=${codeSystem}${searchParam}`, { + signal: signal + }) const valueSetBundle = getApiResponseResourcesOrThrow(res) return valueSetBundle.length > 0 ? valueSetBundle @@ -890,7 +894,8 @@ export type FetchValueSetOptions = { export const fetchValueSet = async ( codeSystem: string, - options?: FetchValueSetOptions + options?: FetchValueSetOptions, + signal?: AbortSignal ): Promise> => { const { code, @@ -902,7 +907,7 @@ export const fetchValueSet = async ( filterRoots = () => true, filterOut = (value: HierarchyElement) => value.id === 'APHP generated' } = options || {} - const codeList = await getCodeList(codeSystem, code, search, noStar) + const codeList = await getCodeList(codeSystem, code, search, noStar, signal) const sortingFunc = sortingKey === 'id' ? idSort : labelSort const formattedCodeList = codeList diff --git a/src/services/aphp/serviceCohortCreation.ts b/src/services/aphp/serviceCohortCreation.ts index 944912fb1..fa77b3a01 100644 --- a/src/services/aphp/serviceCohortCreation.ts +++ b/src/services/aphp/serviceCohortCreation.ts @@ -85,14 +85,22 @@ export interface IServiceCohortCreation { fetchStatus: () => Promise> fetchStatusDiagnostic: () => Promise> fetchDiagnosticTypes: () => Promise> - fetchCim10Diagnostic: (searchValue?: string, noStar?: boolean) => Promise> + fetchCim10Diagnostic: ( + searchValue?: string, + noStar?: boolean, + signal?: AbortSignal + ) => Promise> fetchCim10Hierarchy: (cim10Parent?: string) => Promise> - fetchCcamData: (searchValue?: string, noStar?: boolean) => Promise> + fetchCcamData: (searchValue?: string, noStar?: boolean, signal?: AbortSignal) => Promise> fetchCcamHierarchy: (ccamParent: string) => Promise> - fetchGhmData: (searchValue?: string, noStar?: boolean) => Promise> + fetchGhmData: (searchValue?: string, noStar?: boolean, signal?: AbortSignal) => Promise> fetchGhmHierarchy: (ghmParent: string) => Promise> fetchDocTypes: () => Promise - fetchMedicationData: (searchValue?: string, noStar?: boolean) => Promise> + fetchMedicationData: ( + searchValue?: string, + noStar?: boolean, + signal?: AbortSignal + ) => Promise> fetchSingleCodeHierarchy: (resourceType: string, code: string) => Promise fetchAtcHierarchy: (atcParent: string) => Promise> fetchUCDList: (ucd?: string) => Promise> @@ -274,29 +282,41 @@ const servicesCohortCreation: IServiceCohortCreation = { ] }, fetchDiagnosticTypes: async () => fetchValueSet(CONDITION_STATUS), - fetchCim10Diagnostic: async (searchValue?: string, noStar?: boolean) => - fetchValueSet(CONDITION_HIERARCHY, { - valueSetTitle: 'Toute la hiérarchie', - search: searchValue || '', - noStar - }), + fetchCim10Diagnostic: async (searchValue?: string, noStar?: boolean, signal?: AbortSignal) => + fetchValueSet( + CONDITION_HIERARCHY, + { + valueSetTitle: 'Toute la hiérarchie', + search: searchValue || '', + noStar + }, + signal + ), fetchCim10Hierarchy: async (cim10Parent?: string) => fetchValueSet(CONDITION_HIERARCHY, { valueSetTitle: 'Toute la hiérarchie CIM10', code: cim10Parent }), - fetchCcamData: async (searchValue?: string, noStar?: boolean) => - fetchValueSet(PROCEDURE_HIERARCHY, { valueSetTitle: 'Toute la hiérarchie', search: searchValue || '', noStar }), + fetchCcamData: async (searchValue?: string, noStar?: boolean, signal?: AbortSignal) => + fetchValueSet( + PROCEDURE_HIERARCHY, + { valueSetTitle: 'Toute la hiérarchie', search: searchValue || '', noStar }, + signal + ), fetchCcamHierarchy: async (ccamParent?: string) => fetchValueSet(PROCEDURE_HIERARCHY, { valueSetTitle: 'Toute la hiérarchie CCAM', code: ccamParent }), - fetchGhmData: async (searchValue?: string, noStar?: boolean) => - fetchValueSet(CLAIM_HIERARCHY, { valueSetTitle: 'Toute la hiérarchie', search: searchValue || '', noStar }), + fetchGhmData: async (searchValue?: string, noStar?: boolean, signal?: AbortSignal) => + fetchValueSet(CLAIM_HIERARCHY, { valueSetTitle: 'Toute la hiérarchie', search: searchValue || '', noStar }, signal), fetchGhmHierarchy: async (ghmParent?: string) => fetchValueSet(CLAIM_HIERARCHY, { valueSetTitle: 'Toute la hiérarchie GHM', code: ghmParent }), fetchDocTypes: () => Promise.resolve(docTypes && docTypes.docTypes.length > 0 ? docTypes.docTypes : []), - fetchMedicationData: async (searchValue?: string, noStar?: boolean) => - fetchValueSet(`${MEDICATION_ATC},${MEDICATION_UCD}`, { - valueSetTitle: 'Toute la hiérarchie', - search: searchValue || '', - noStar - }), + fetchMedicationData: async (searchValue?: string, noStar?: boolean, signal?: AbortSignal) => + fetchValueSet( + `${MEDICATION_ATC},${MEDICATION_UCD}`, + { + valueSetTitle: 'Toute la hiérarchie', + search: searchValue || '', + noStar + }, + signal + ), fetchSingleCodeHierarchy: async (resourceType: string, code: string) => { const codeSystemPerResourceType: { [type: string]: string } = { Claim: CLAIM_HIERARCHY, diff --git a/src/utils/cohortCreation.ts b/src/utils/cohortCreation.ts index 9b1c8ae19..240a2bcb7 100644 --- a/src/utils/cohortCreation.ts +++ b/src/utils/cohortCreation.ts @@ -1583,24 +1583,24 @@ export async function unbuildRequest(_json: string): Promise { if (value?.search('le') === 0) { valueComparator = Comparators.LESS_OR_EQUAL - valueMin = parseInt(value?.replace('le', '')) + valueMin = parseFloat(value?.replace('le', '')) } else if (value?.search('lt') === 0) { valueComparator = Comparators.LESS - valueMin = parseInt(value?.replace('lt', '')) + valueMin = parseFloat(value?.replace('lt', '')) } else if (value?.search('ge') === 0) { if (nbValueComparators === 2) { valueComparator = Comparators.BETWEEN - valueMax = parseInt(value?.replace('ge', '')) + valueMax = parseFloat(value?.replace('ge', '')) } else { valueComparator = Comparators.GREATER_OR_EQUAL - valueMin = parseInt(value?.replace('ge', '')) + valueMin = parseFloat(value?.replace('ge', '')) } } else if (value?.search('gt') === 0) { valueComparator = Comparators.GREATER - valueMin = parseInt(value?.replace('gt', '')) + valueMin = parseFloat(value?.replace('gt', '')) } else { valueComparator = Comparators.EQUAL - valueMin = parseInt(value ?? '0') + valueMin = parseFloat(value ?? '0') } currentCriterion.valueComparator = valueComparator