diff --git a/src/components/SearchValueSet/index.tsx b/src/components/SearchValueSet/index.tsx index e405b257a..c52034d21 100644 --- a/src/components/SearchValueSet/index.tsx +++ b/src/components/SearchValueSet/index.tsx @@ -75,7 +75,6 @@ const SearchValueSet = ({ references, selectedNodes, onSelect }: SearchValueSetP onChangeSearchInput(event.target.value)} endAdornment={ diff --git a/src/hooks/hierarchy/useHierarchy.ts b/src/hooks/hierarchy/useHierarchy.ts index 404a97750..830aede90 100644 --- a/src/hooks/hierarchy/useHierarchy.ts +++ b/src/hooks/hierarchy/useHierarchy.ts @@ -81,13 +81,22 @@ export const useHierarchy = ( } const search = async (fetchSearch: () => Promise>>) => { - const { results: endCodes, count } = await fetchSearch() - const bySystem = groupBySystem(endCodes) - const newCodes = await getMissingCodesWithSystems(trees, bySystem, codes, fetchHandler) - const newTrees = buildMultipleTrees(trees, bySystem, newCodes, selectedCodes, Mode.SEARCH) - setCodes(newCodes) - setTrees(newTrees) - return { display: getDisplayFromTrees(endCodes, newTrees), count } + setLoadingStatus({ ...loadingStatus, search: LoadingStatus.FETCHING }) + try { + const { results: endCodes, count } = await fetchSearch() + const bySystem = groupBySystem(endCodes) + const newCodes = await getMissingCodesWithSystems(trees, bySystem, codes, fetchHandler) + const newTrees = buildMultipleTrees(trees, bySystem, newCodes, selectedCodes, Mode.SEARCH) + setCodes(newCodes) + setTrees(newTrees) + setLoadingStatus({ ...loadingStatus, search: LoadingStatus.SUCCESS }) + return { display: getDisplayFromTrees(endCodes, newTrees), count } + } catch (e) { + return { + display: [], + count: 0 + } + } } const fetchMore = async ( @@ -96,13 +105,11 @@ export const useHierarchy = ( mode: SearchMode, id?: string ) => { - setLoadingStatus({ ...loadingStatus, search: LoadingStatus.FETCHING }) const { display, count } = await search(fetchSearch) if (mode == SearchMode.EXPLORATION && id) { const currentHierarchy = hierarchies.get(id) || DEFAULT_HIERARCHY_INFO setHierarchies(replaceInMap(id, { ...currentHierarchy, tree: display, page }, hierarchies)) } else setSearchResults({ tree: display, count, page, system: '' }) - setLoadingStatus({ ...loadingStatus, search: LoadingStatus.SUCCESS }) } const select = (nodes: Hierarchy[], toAdd: boolean, mode: SearchMode.EXPLORATION | SearchMode.RESEARCH) => { diff --git a/src/hooks/valueSet/useSearchValueSet.ts b/src/hooks/valueSet/useSearchValueSet.ts index 9d5b67f33..bd7ae880f 100644 --- a/src/hooks/valueSet/useSearchValueSet.ts +++ b/src/hooks/valueSet/useSearchValueSet.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { FhirItem, Reference } from 'types/valueSet' import { LIMIT_PER_PAGE, SearchParameters, useSearchParameters } from '../search/useSearchParameters' import { useHierarchy } from 'hooks/hierarchy/useHierarchy' @@ -13,6 +13,8 @@ import { Codes, Hierarchy, SearchMode } from 'types/hierarchy' import { saveValueSets, selectValueSetCodes } from 'state/valueSets' import { useAppDispatch, useAppSelector } from 'state' import { DEFAULT_HIERARCHY_INFO, getItemSelectedStatus, mapCodesToCache } from 'utils/hierarchy' +import { LoadingStatus } from 'types' +import { cancelPendingRequest } from 'utils/abortController' export const useSearchValueSet = (references: Reference[], selectedNodes: Hierarchy[]) => { const researchParameters = useSearchParameters() @@ -21,6 +23,7 @@ export const useSearchValueSet = (references: Reference[], selectedNodes: Hierar const [mode, setMode] = useState(SearchMode.EXPLORATION) const [initialized, setInitialized] = useState({ exploration: false, research: false }) const dispatch = useAppDispatch() + const controllerRef = useRef(null) const fetchChildren = useCallback( async (ids: string, system: string) => (await getChildrenFromCodes(system, ids.split(','))).results, @@ -73,7 +76,15 @@ export const useSearchValueSet = (references: Reference[], selectedNodes: Hierar const fetchSearch = async (searchInput: string, page: number, references: string[]) => { if (references.length) { - return await searchInValueSets(references, searchInput, page * LIMIT_PER_PAGE, LIMIT_PER_PAGE) + if (loadingStatus.search === LoadingStatus.FETCHING) + controllerRef.current = cancelPendingRequest(controllerRef.current) + return await searchInValueSets( + references, + searchInput, + page * LIMIT_PER_PAGE, + LIMIT_PER_PAGE, + controllerRef.current?.signal + ) } else return { results: [], count: 0 } } diff --git a/src/services/aphp/serviceValueSets.ts b/src/services/aphp/serviceValueSets.ts index 636759d6b..632da07a5 100644 --- a/src/services/aphp/serviceValueSets.ts +++ b/src/services/aphp/serviceValueSets.ts @@ -8,6 +8,7 @@ import { getConfig } from 'config' import { LOW_TOLERANCE_TAG } from './callApi' import { sortArray } from 'utils/arrays' import { FhirItem } from 'types/valueSet' +import axios from 'axios' export const UNKOWN_HIERARCHY_CHAPTER = 'UNKNOWN' export const HIERARCHY_ROOT = '*' @@ -180,7 +181,8 @@ export const searchInValueSets = async ( const response = formatValuesetExpansion(getApiResponseResourceOrThrow(res).expansion) response.results = mapAbandonedChildren(response.results) return response - } catch (e) { + } catch (error) { + if (axios.isCancel(error)) throw "Cancelled request." return { count: 0, results: [] @@ -238,23 +240,19 @@ export const getHierarchyRoots = async ( const chapters = codeList .filter((code) => filterRoots(code)) .map((e) => mapFhirHierarchyToHierarchyWithLabelAndSystem(e)) - const toBeAdoptedCodes = codeList - .filter((code) => !filterRoots(code)) - .map((e) => mapFhirHierarchyToHierarchyWithLabelAndSystem(e)) + const toBeAdoptedCodes = codeList.filter((code) => !filterRoots(code)) const childrenIds = chapters.map((code) => code.id) let subItems: Hierarchy[] | undefined = undefined if (toBeAdoptedCodes.length) { - const unknownChildren = toBeAdoptedCodes.map((child) => ({ - ...child, - above_levels_ids: `${HIERARCHY_ROOT},${UNKOWN_HIERARCHY_CHAPTER}` - })) + const unknownChaptersIds = toBeAdoptedCodes.map((code) => code.id) + const unknownChapters = (await getChildrenFromCodes(codeSystem, unknownChaptersIds)).results const unknownChapter: Hierarchy = { id: UNKOWN_HIERARCHY_CHAPTER, label: `${UNKOWN_HIERARCHY_CHAPTER}`, system: codeSystem, above_levels_ids: HIERARCHY_ROOT, - inferior_levels_ids: unknownChildren.map((code) => code.id).join(','), - subItems: unknownChildren + inferior_levels_ids: unknownChapters.map((code) => code.id).join(','), + subItems: unknownChapters } const chaptersEntities = (await getChildrenFromCodes(codeSystem, childrenIds)).results childrenIds.push(UNKOWN_HIERARCHY_CHAPTER) diff --git a/src/utils/hierarchy.ts b/src/utils/hierarchy.ts index d81bfcb60..47bea2551 100644 --- a/src/utils/hierarchy.ts +++ b/src/utils/hierarchy.ts @@ -238,7 +238,8 @@ export const getDisplayFromTree = (toDisplay: Hierarchy[], tree: Hierarchy let branches: Hierarchy[] = [] if (toDisplay.length && tree.length) branches = toDisplay.map((item) => { - const path = item.above_levels_ids ? [...getAboveLevelsWithRights(item, tree), ...[item.id]] : [item.id] + let path = item.above_levels_ids ? [...getAboveLevelsWithRights(item, tree), ...[item.id]] : [item.id] + path = updateUnknownChapter(tree, path) return findBranch(path, tree) }) return branches @@ -260,7 +261,10 @@ export const getDisplayFromTrees = ( } const findBranch = (path: string[], tree: Hierarchy[]): Hierarchy => { - let branch: Hierarchy = { id: `${path}-empty`, label: `${path}---------------` } as Hierarchy + let branch: Hierarchy = { id: `${path}-empty`, label: `ERROR | ${path}---------------` } as Hierarchy< + T, + string + > const key = path[0] const index = tree.findIndex((item) => item.id === key) const next = tree[index] @@ -270,10 +274,19 @@ const findBranch = (path: string[], tree: Hierarchy[]): Hierarchy< return branch } +const updateUnknownChapter = (baseTree: Hierarchy[], path: string[]) => { + const unknownChapterFound = baseTree[0]?.subItems?.find((chapter) => chapter.id === UNKOWN_HIERARCHY_CHAPTER) + const childrenIds = unknownChapterFound?.inferior_levels_ids.split(',') || [] + if (path?.[1] !== UNKOWN_HIERARCHY_CHAPTER && childrenIds.includes(path?.[1])) + path.splice(1, 0, UNKOWN_HIERARCHY_CHAPTER) + return path +} + const getPaths = (baseTree: Hierarchy[], endCodes: Hierarchy[]) => { - const paths = endCodes.map((item) => + let paths = endCodes.map((item) => item.above_levels_ids ? [...getAboveLevelsWithRights(item, baseTree), ...[item.id]] : [item.id] ) + paths = paths.map((path) => updateUnknownChapter(baseTree, path)) return paths } @@ -319,8 +332,9 @@ export const getItemSelectedStatus = (item: Hierarchy): SelectedStat export const getSelectedCodesFromTree = (tree: Hierarchy[]) => { const get = (node: Hierarchy, selectedCodes: Hierarchy[]) => { - if (node.status === SelectedStatus.INDETERMINATE) node.subItems?.forEach((subItem) => get(subItem, selectedCodes)) - if (node.status === SelectedStatus.SELECTED) selectedCodes.push(node) + if (node.status === SelectedStatus.INDETERMINATE || node.id === UNKOWN_HIERARCHY_CHAPTER) + node.subItems?.forEach((subItem) => get(subItem, selectedCodes)) + if (node.status === SelectedStatus.SELECTED && node.id !== UNKOWN_HIERARCHY_CHAPTER) selectedCodes.push(node) return selectedCodes } const selectedCodes = mapHierarchyToMap(tree.flatMap((hierarchy) => get(hierarchy, [])))