Skip to content

Commit

Permalink
select all
Browse files Browse the repository at this point in the history
  • Loading branch information
aetchego committed Nov 19, 2024
1 parent a64b047 commit ef2d2e6
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 112 deletions.
4 changes: 2 additions & 2 deletions src/components/SearchValueSet/ValueSetField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ const ValueSetField = ({ value, references, placeholder, disabled = false, onSel
{!value.length && <FormLabel component="legend">{placeholder}</FormLabel>}
</Grid>
<Grid item xs={2} container justifyContent="flex-end">
{isExtended && (
{isExtended && value.length > 0 && (
<IconButton size="small" sx={{ color: '#5BC5F2' }} onClick={() => setIsExtended(false)}>
<CloseIcon />
</IconButton>
)}
{!isExtended && (
{!isExtended && value.length > 0 && (
<IconButton size="small" sx={{ color: '#5BC5F2' }} onClick={() => setIsExtended(true)}>
<MoreHorizIcon />
</IconButton>
Expand Down
53 changes: 32 additions & 21 deletions src/components/SearchValueSet/ValueSetTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useState } from 'react'
import React, { useEffect, useState } from 'react'

import {
Checkbox,
Expand All @@ -13,7 +13,7 @@ import {
Typography
} from '@mui/material'
import { LoadingStatus, SelectedStatus } from 'types'
import { FhirHierarchy, FhirItem, Hierarchy, HierarchyInfo, SearchMode } from 'types/hierarchy'
import { FhirHierarchy, FhirItem, Hierarchy, HierarchyInfo, Mode, SearchMode } from 'types/hierarchy'
import { KeyboardArrowDown, KeyboardArrowRight, IndeterminateCheckBoxOutlined } from '@mui/icons-material'
import { CellWrapper, RowContainerWrapper, RowWrapper } from '../Hierarchy/styles'
import { sortArray } from 'utils/arrays'
Expand All @@ -25,18 +25,21 @@ import { getLabelFromCode, isDisplayedWithCode } from 'utils/valueSets'
type ValueSetRowProps = {
item: Hierarchy<FhirHierarchy, string>
loading: { expand: LoadingStatus; list: LoadingStatus }
selectionDisabled?: boolean
isSelectionDisabled: (node: Hierarchy<FhirItem>) => boolean
path: string[]
mode: SearchMode
isHierarchy: boolean
onExpand: (node: Hierarchy<FhirHierarchy, string>) => void
onSelect: (node: Hierarchy<FhirHierarchy, string>, toAdd: boolean) => void
onSelect: (
nodes: Hierarchy<FhirHierarchy, string>[],
mode: Mode.SELECT | Mode.UNSELECT | Mode.SELECT_ALL | Mode.UNSELECT_ALL
) => void
}

const ValueSetRow = ({
item,
loading,
selectionDisabled = false,
isSelectionDisabled,
path,
mode,
isHierarchy,
Expand Down Expand Up @@ -80,11 +83,11 @@ const ValueSetRow = ({
</CellWrapper>
<CellWrapper item xs={1} container>
<Checkbox
/*disabled={selectionDisabled}*/
disabled={isSelectionDisabled(item)}
checked={status === SelectedStatus.SELECTED}
indeterminate={status === SelectedStatus.INDETERMINATE}
indeterminateIcon={<IndeterminateCheckBoxOutlined />}
onChange={(event, checked) => onSelect(item, checked)}
onChange={(event, checked) => onSelect([item], checked ? Mode.SELECT : Mode.UNSELECT)}
color="info"
inputProps={{ 'aria-labelledby': label }}
/>
Expand All @@ -99,6 +102,7 @@ const ValueSetRow = ({
<ValueSetRow
mode={mode}
isHierarchy={isHierarchy}
isSelectionDisabled={isSelectionDisabled}
loading={loading}
path={[...path, id]}
key={subItem.id}
Expand All @@ -118,9 +122,12 @@ type ValueSetTableProps = {
loading: { expand: LoadingStatus; list: LoadingStatus }
isHierarchy?: boolean
mode: SearchMode
isSelectionDisabled?: (node: Hierarchy<FhirItem>) => boolean
onExpand: (node: Hierarchy<FhirHierarchy, string>) => void
onSelect: (node: Hierarchy<FhirHierarchy, string>, toAdd: boolean) => void
onSelectAll: (toAdd: boolean) => void
onSelect: (
nodes: Hierarchy<FhirHierarchy, string>[],
mode: Mode.SELECT | Mode.UNSELECT | Mode.SELECT_ALL | Mode.UNSELECT_ALL
) => void
onChangePage: (page: number) => void
}

Expand All @@ -130,15 +137,18 @@ const ValueSetTable = ({
loading,
mode,
isHierarchy = true,
isSelectionDisabled = () => false,
onSelect,
onSelectAll,
onExpand,
onChangePage
}: ValueSetTableProps) => {
const tree = useMemo(() => {
console.log('test exp change')
return mode === SearchMode.RESEARCH || isHierarchy ? hierarchy.tree : hierarchy.tree[0].subItems || []
}, [hierarchy])

const handleSelect = (checked: boolean) => {
if (mode === SearchMode.RESEARCH) {
const notDisabled = hierarchy.tree.filter((node) => !isSelectionDisabled(node))
onSelect(notDisabled, checked ? Mode.SELECT : Mode.UNSELECT)
} else onSelect(hierarchy.tree, checked ? Mode.SELECT_ALL : Mode.UNSELECT_ALL)
}

return (
<Grid container direction="column" justifyContent="space-between">
Expand All @@ -154,30 +164,31 @@ const ValueSetTable = ({
{hierarchy.count ? `${hierarchy.count} résultat(s)` : ` Aucun résultat à afficher`}
</Typography>
<Checkbox
disabled={
mode === SearchMode.RESEARCH &&
!hierarchy.tree.filter((node) => !isSelectionDisabled(node)).length
}
checked={selectAllStatus === SelectedStatus.SELECTED}
indeterminate={selectAllStatus === SelectedStatus.INDETERMINATE}
indeterminateIcon={<IndeterminateCheckBoxOutlined style={{ color: 'rgba(0,0,0,0.6)' }} />}
onChange={(event, checked) => {
if (mode === SearchMode.RESEARCH) onSelectAll(checked)
else onSelect(hierarchy.tree[0], checked)
}}
onChange={(event, checked) => handleSelect(checked)}
/>
</Grid>
</TableCell>
</TableRow>
)}
{loading.list === LoadingStatus.SUCCESS && (
<div style={{ maxHeight: '70vh', overflow: 'auto' }}>
{tree.map((item) =>
{hierarchy.tree.map((item) =>
item ? (
<ValueSetRow
mode={mode}
loading={loading}
selectionDisabled={mode === SearchMode.EXPLORATION && !isHierarchy}
isHierarchy={isHierarchy}
path={[item.id]}
key={item.id}
item={item}
isSelectionDisabled={isSelectionDisabled}
onExpand={onExpand}
onSelect={onSelect}
/>
Expand All @@ -201,7 +212,7 @@ const ValueSetTable = ({
<Pagination
count={Math.ceil(hierarchy.count / LIMIT_PER_PAGE)}
currentPage={hierarchy.page}
onPageChange={onChangePage}
onPageChange={(page) => onChangePage(page)}
color="#0063AF"
/>
</Paper>
Expand Down
13 changes: 8 additions & 5 deletions src/components/SearchValueSet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import SelectedCodes from 'components/Hierarchy/SelectedCodes'
import { useSearchValueSet } from 'hooks/valueSet/useSearchValueSet'
import { Displayer } from 'components/ui/Displayer/styles'
import ClearIcon from '@mui/icons-material/Clear'
import { FhirItem, Hierarchy, SearchMode, SearchModeLabel } from 'types/hierarchy'
import { FhirItem, Hierarchy, Mode, SearchMode, SearchModeLabel } from 'types/hierarchy'
import { cleanNode } from 'utils/hierarchy/hierarchy'
import { HIERARCHY_ROOT } from 'services/aphp/serviceValueSets'

type SearchValueSetProps = {
references: Reference[]
Expand All @@ -23,10 +24,12 @@ const SearchValueSet = ({ references, selectedNodes, onSelect }: SearchValueSetP
mode,
searchInput,
onChangeMode,
onDelete,
selectedCodes,
isSelectionDisabled,
loadingStatus,
parameters: { refs, onChangeReferences, onChangeSearchInput, onChangePage },
hierarchy: { exploration, research, selectAllStatus, expand, select, selectAll }
hierarchy: { exploration, research, selectAllStatus, expand, select }
} = useSearchValueSet(references, selectedNodes)

const tabs: TabType<SearchMode, SearchModeLabel>[] = [
Expand Down Expand Up @@ -98,8 +101,8 @@ const SearchValueSet = ({ references, selectedNodes, onSelect }: SearchValueSetP
loading={{ list: loadingStatus.init, expand: loadingStatus.expand }}
hierarchy={exploration}
selectAllStatus={selectAllStatus}
isSelectionDisabled={isSelectionDisabled}
onSelect={select}
onSelectAll={selectAll}
onExpand={expand}
onChangePage={onChangePage}
/>
Expand All @@ -111,8 +114,8 @@ const SearchValueSet = ({ references, selectedNodes, onSelect }: SearchValueSetP
isHierarchy={false}
loading={{ list: loadingStatus.search, expand: loadingStatus.expand }}
hierarchy={research}
isSelectionDisabled={isSelectionDisabled}
onSelect={select}
onSelectAll={selectAll}
onExpand={expand}
onChangePage={onChangePage}
/>
Expand All @@ -121,7 +124,7 @@ const SearchValueSet = ({ references, selectedNodes, onSelect }: SearchValueSetP
</Grid>
<div>
<Paper sx={{ backgroundColor: '#D1E2F4', padding: '10px 30px' }}>
<SelectedCodes values={selectedCodes} onDelete={(code) => select(code, false)} />
<SelectedCodes values={selectedCodes} onDelete={onDelete} />
</Paper>
</div>
</>
Expand Down
76 changes: 35 additions & 41 deletions src/hooks/hierarchy/useHierarchy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ import {
buildTree,
buildMultipleTrees,
getHierarchyDisplay,
getItemSelectedStatus,
getListDisplay,
getMissingCodes,
getMissingCodesWithSystems,
groupBySystem,
getHierarchyRootCodes,
mapHierarchyToMap,
getSelectedCodesFromTrees
getSelectedCodesFromTrees,
createHierarchyRoot
} from '../../utils/hierarchy/hierarchy'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import { Back_API_Response, LoadingStatus, SelectedStatus } from 'types'
import { getSelectedCodesFromTree } from 'utils/hierarchy/hierarchy'
import { Codes, Hierarchy, HierarchyInfo, HierarchyLoadingStatus, Mode, SearchMode } from '../../types/hierarchy'
import { replaceInMap } from 'utils/map'
import { HIERARCHY_ROOT } from 'services/aphp/serviceValueSets'
/**
* @param {Hierarchy<T>[]} selectedNodes - Nodes selected in the hierarchy.
* @param {Codes<Hierarchy<T>>} fetchedCodes - All the codes that have already been fetched and saved.
Expand All @@ -28,12 +28,12 @@ export const useHierarchy = <T>(
onCache: (codes: Codes<Hierarchy<T>>) => void,
fetchHandler: (ids: string, system: string) => Promise<Hierarchy<T>[]>
) => {
console.log('test loop hier')
const DEFAULT_HIERARCHY_INFO = {
tree: [],
count: 0,
page: 1,
system: ''
system: '',
selectAllStatus: SelectedStatus.INDETERMINATE
}
const [trees, setTrees] = useState<Map<string, Hierarchy<T>[]>>(new Map())
const [hierarchies, setHierarchies] = useState<Map<string, HierarchyInfo<T>>>(new Map())
Expand All @@ -50,11 +50,6 @@ export const useHierarchy = <T>(
expand: LoadingStatus.SUCCESS
})

const selectAllStatus = useMemo(() => {
const node = { id: 'parent', subItems: searchResults.tree } as Hierarchy<T, string>
return getItemSelectedStatus(node)
}, [searchResults.tree])

useEffect(() => {
latestCodes.current = codes
}, [codes])
Expand All @@ -64,15 +59,19 @@ export const useHierarchy = <T>(
}, [])

const initTrees = async (
initHandlers: { system: string; fetchBaseTree: () => Promise<Back_API_Response<Hierarchy<T>>> }[]
initHandlers: {
system: string
fetchBaseTree: () => Promise<Back_API_Response<Hierarchy<T>>>
}[]
) => {
const newTrees: Map<string, Hierarchy<T>[]> = new Map()
const newHierarchies: Map<string, HierarchyInfo<T>> = new Map()
let allCodes: Codes<Hierarchy<T>> = new Map()
for (const handler of initHandlers) {
const { results: baseTree, count } = await handler.fetchBaseTree()
const currentSelected = selectedCodes.get(handler.system) || new Map()
const toFind = [...baseTree, ...currentSelected.values()]
const toAdd = currentSelected.get(HIERARCHY_ROOT) ? new Map() : currentSelected
const toFind = [...baseTree, ...toAdd.values()]
const currentCodes = codes.get(handler.system) || new Map()
const newCodes = await getMissingCodes(baseTree, currentCodes, toFind, handler.system, Mode.INIT, fetchHandler)
const newTree = buildTree(baseTree, handler.system, toFind, newCodes, currentSelected, Mode.INIT)
Expand All @@ -89,12 +88,9 @@ export const useHierarchy = <T>(

const search = async (fetchSearch: () => Promise<Back_API_Response<Hierarchy<T>>>) => {
const { results: endCodes, count } = await fetchSearch()
console.log('test select endCodes', endCodes)
const bySystem = groupBySystem(endCodes)
const newCodes = await getMissingCodesWithSystems(trees, bySystem, codes, fetchHandler)
console.log('test select newCodes', newCodes)
const newTrees = buildMultipleTrees(trees, bySystem, newCodes, selectedCodes, Mode.SEARCH)
console.log('test select newTrees', newTrees)
setCodes(newCodes)
setTrees(newTrees)
return { display: getListDisplay(endCodes, newTrees), count }
Expand All @@ -115,32 +111,32 @@ export const useHierarchy = <T>(
setLoadingStatus({ ...loadingStatus, search: LoadingStatus.SUCCESS })
}

const select = (node: Hierarchy<T>, toAdd: boolean) => {
const hierarchyId = node.system
const bySystem = groupBySystem([node])
const currentHierarchy = hierarchies.get(hierarchyId) || DEFAULT_HIERARCHY_INFO
console.log('test select root', currentHierarchy)
const mode = toAdd ? Mode.SELECT : Mode.UNSELECT
const newTrees = buildMultipleTrees(trees, bySystem, codes, selectedCodes, mode)
const newTree = newTrees.get(node.system) || []
const displayHierarchy = getHierarchyDisplay(currentHierarchy.tree, newTree)
const select = (nodes: Hierarchy<T>[], mode: Mode.SELECT | Mode.UNSELECT | Mode.SELECT_ALL | Mode.UNSELECT_ALL) => {
console.log('test bug', nodes, mode)
const bySystem = groupBySystem(nodes)
const selectMode = mode === Mode.SELECT_ALL ? Mode.SELECT : mode === Mode.UNSELECT_ALL ? Mode.UNSELECT : mode
const newTrees = buildMultipleTrees(trees, bySystem, codes, selectedCodes, selectMode)
const displaySearch = getListDisplay(searchResults.tree, newTrees)
const newSelectedCodes = getSelectedCodesFromTree(newTree)
setTrees(newTrees)
setHierarchies(replaceInMap(hierarchyId, { ...currentHierarchy, tree: displayHierarchy }, hierarchies))
setSearchResults({ ...searchResults, tree: displaySearch })
setSelectedCodes(replaceInMap(hierarchyId, newSelectedCodes, selectedCodes))
}

const selectAll = (toAdd: boolean) => {
const mode = toAdd ? Mode.SELECT_ALL : Mode.UNSELECT_ALL
const bySystem = groupBySystem(searchResults.tree)
const newTrees = buildMultipleTrees(trees, bySystem, codes, selectedCodes, mode)
const displaySearch = getListDisplay(searchResults.tree, newTrees)
const newSelectedCodes = getSelectedCodesFromTrees(trees)
if (mode === Mode.SELECT_ALL || mode === Mode.UNSELECT_ALL) {
const system = nodes?.[0].system || ''
const root = new Map()
if (mode === Mode.SELECT_ALL) root.set(HIERARCHY_ROOT, createHierarchyRoot(system))
setSelectedCodes(replaceInMap(system, root, selectedCodes))
} else setSelectedCodes(getSelectedCodesFromTrees(newTrees, selectedCodes))
setTrees(newTrees)
let newHierarchies = new Map(hierarchies)
hierarchies.forEach((hierarchy) => {
if (bySystem.find((elem) => elem.system === hierarchy.system)) {
const newTree = newTrees.get(hierarchy.system) || []
newHierarchies = replaceInMap(
hierarchy.system,
{ ...hierarchy, tree: getHierarchyDisplay(hierarchy.tree, newTree) },
newHierarchies
)
}
})
setHierarchies(newHierarchies)
setSearchResults({ ...searchResults, tree: displaySearch })
setSelectedCodes(newSelectedCodes)
}

const expand = async (node: Hierarchy<T>) => {
Expand All @@ -164,10 +160,8 @@ export const useHierarchy = <T>(
searchResults,
selectedCodes,
loadingStatus,
selectAllStatus,
initTrees,
select,
selectAll,
expand,
fetchMore
}
Expand Down
Loading

0 comments on commit ef2d2e6

Please sign in to comment.