From 631bc1986113751b51d6486e9369bc1fb573c9e5 Mon Sep 17 00:00:00 2001 From: Mateusz Bolewski <mateusz.bolewski@allegro.pl> Date: Tue, 21 Nov 2023 12:24:20 +0100 Subject: [PATCH] Feature/search bioentities details --- .../BioEntitiesPinsList.component.tsx | 21 +++++++ .../BioEntitiesPinsListItem.component.tsx} | 44 ++++++------- .../BioEntitiesPinsListItem/index.ts | 1 + .../BioEntitiesPinsList/index.ts | 1 + .../BioEntitiesResultsList.component.tsx | 28 +++++++++ .../BioEntitiesResultsList/index.ts | 1 + .../BioEntitiesAccordion.component.tsx | 7 ++- .../BioEntitiesSubmapItem.component.test.tsx | 33 +++++++--- .../BioEntitiesSubmapItem.component.tsx | 33 +++++++--- .../PinsList/PinsList.component.tsx | 8 +-- .../PinsListItem/PinsListItem.component.tsx | 61 +++++++++++++++---- .../PinsList/PinsListItem/index.ts | 1 - .../ResultsList.component.test.tsx | 1 + .../SearchDrawerWrapper.component.test.tsx | 36 +---------- .../SearchDrawerWrapper.component.tsx | 13 ++-- src/redux/bioEntity/bioEntity.selectors.ts | 14 +++-- src/redux/drawer/drawer.reducers.test.ts | 1 + src/redux/drawer/drawer.reducers.ts | 10 +++ src/redux/drawer/drawer.selectors.ts | 4 ++ src/redux/drawer/drawer.slice.ts | 4 ++ src/redux/drawer/drawer.types.ts | 1 + src/redux/drawer/drawerFixture.ts | 4 ++ src/redux/drugs/drugs.selectors.ts | 8 +-- src/redux/mirnas/mirnas.selectors.ts | 8 +-- src/types/models.ts | 2 +- yarn.lock | 6 +- 26 files changed, 223 insertions(+), 128 deletions(-) create mode 100644 src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsList.component.tsx rename src/components/Map/Drawer/SearchDrawerWrapper/{ResultsList/PinsList/PinsListItem/MirnaPinsListItem.component.tsx => BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.tsx} (50%) create mode 100644 src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/index.ts create mode 100644 src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/index.ts create mode 100644 src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesResultsList.component.tsx create mode 100644 src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/index.ts diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsList.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsList.component.tsx new file mode 100644 index 00000000..b563e3f9 --- /dev/null +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsList.component.tsx @@ -0,0 +1,21 @@ +import { BioEntityContent } from '@/types/models'; +import { BioEntitiesPinsListItem } from './BioEntitiesPinsListItem'; + +interface BioEntitiesPinsListProps { + bioEnititesPins: BioEntityContent[]; +} + +export const BioEntitiesPinsList = ({ bioEnititesPins }: BioEntitiesPinsListProps): JSX.Element => { + return ( + <ul className="h-[calc(100vh-198px)] overflow-auto px-6 py-2"> + {bioEnititesPins && + bioEnititesPins.map(result => ( + <BioEntitiesPinsListItem + key={result.bioEntity.name} + name={result.bioEntity.name} + pin={result.bioEntity} + /> + ))} + </ul> + ); +}; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/MirnaPinsListItem.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.tsx similarity index 50% rename from src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/MirnaPinsListItem.component.tsx rename to src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.tsx index ebd97b20..098abeeb 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/MirnaPinsListItem.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.tsx @@ -1,40 +1,34 @@ import { twMerge } from 'tailwind-merge'; import { Icon } from '@/shared/Icon'; -import { MirnaItems } from '@/types/models'; -import { getPinColor } from './PinsListItem.component.utils'; -import { PinType } from '../PinsList.types'; +import { BioEntity } from '@/types/models'; +import { getPinColor } from '../../../ResultsList/PinsList/PinsListItem/PinsListItem.component.utils'; -interface MirnaPinsListItemProps { +interface BioEntitiesPinsListItemProps { name: string; - type: PinType; - pin: MirnaItems; + pin: BioEntity; } -export const MirnaPinsListItem = ({ name, type, pin }: MirnaPinsListItemProps): JSX.Element => { +export const BioEntitiesPinsListItem = ({ + name, + pin, +}: BioEntitiesPinsListItemProps): JSX.Element => { return ( <div className="mb-4 flex w-full flex-col gap-3 rounded-lg border-[1px] border-solid border-greyscale-500 p-4"> <div className="flex w-full flex-row items-center gap-2"> - <Icon name="pin" className={twMerge('mr-2 shrink-0', getPinColor(type))} /> + <Icon name="pin" className={twMerge('mr-2 shrink-0', getPinColor('bioEntity'))} /> <p> - Full name: <span className="w-full font-bold">{name}</span> + {pin.stringType}: <span className="w-full font-bold">{name}</span> </p> </div> - <ul className="leading-6"> - <div className="font-bold">Elements:</div> - {pin.targetParticipants.map(element => { - return ( - <li key={element.id} className="my-2 px-2"> - <a - href={element.link} - target="_blank" - className="cursor-pointer text-primary-500 underline" - > - {element.type} ({element.resource}) - </a> - </li> - ); - })} - </ul> + <p className="font-bold leading-6"> + Full name: <span className="w-full font-normal">{pin.fullName}</span> + </p> + <p className="font-bold leading-6"> + Symbol: <span className="w-full font-normal">{pin.symbol}</span> + </p> + <p className="font-bold leading-6"> + Synonyms: <span className="w-full font-normal">{pin.synonyms.join(', ')}</span> + </p> <ul className="leading-6"> <div className="font-bold">References:</div> {pin.references.map(reference => { diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/index.ts b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/index.ts new file mode 100644 index 00000000..ddb7a153 --- /dev/null +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/index.ts @@ -0,0 +1 @@ +export { BioEntitiesPinsListItem } from './BioEntitiesPinsListItem.component'; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/index.ts b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/index.ts new file mode 100644 index 00000000..fd4bb8c7 --- /dev/null +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/index.ts @@ -0,0 +1 @@ +export { BioEntitiesPinsList } from './BioEntitiesPinsList.component'; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesResultsList.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesResultsList.component.tsx new file mode 100644 index 00000000..6960843c --- /dev/null +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesResultsList.component.tsx @@ -0,0 +1,28 @@ +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { bioEnititiesResultListSelector } from '@/redux/drawer/drawer.selectors'; +import { DrawerHeadingBackwardButton } from '@/shared/DrawerHeadingBackwardButton'; +import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; +import { displayGroupedSearchResults } from '@/redux/drawer/drawer.slice'; +import { searchValueSelector } from '@/redux/search/search.selectors'; +import { BioEntitiesPinsList } from './BioEntitiesPinsList'; + +export const BioEntitiesResultsList = (): JSX.Element => { + const dispatch = useAppDispatch(); + const bioEntityData = useAppSelector(bioEnititiesResultListSelector); + const searchValue = useAppSelector(searchValueSelector); + + const navigateToGroupedSearchResults = (): void => { + dispatch(displayGroupedSearchResults()); + }; + + return ( + <div> + <DrawerHeadingBackwardButton + title="BioEntity" + value={searchValue} + backwardFunction={navigateToGroupedSearchResults} + /> + <BioEntitiesPinsList bioEnititesPins={bioEntityData} /> + </div> + ); +}; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/index.ts b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/index.ts new file mode 100644 index 00000000..4fc0f85b --- /dev/null +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/index.ts @@ -0,0 +1 @@ +export { BioEntitiesResultsList } from './BioEntitiesResultsList.component'; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx index 081247d8..6ca6a442 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx @@ -9,14 +9,14 @@ import { BioEntitiesSubmapItem } from '@/components/Map/Drawer/SearchDrawerWrapp import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { loadingBioEntityStatusSelector, - numberOfBioEntitiesPerModelSelector, + bioEntitiesPerModelSelector, numberOfBioEntitiesSelector, } from '@/redux/bioEntity/bioEntity.selectors'; export const BioEntitiesAccordion = (): JSX.Element => { const bioEntitiesNumber = useAppSelector(numberOfBioEntitiesSelector); const bioEntitiesState = useAppSelector(loadingBioEntityStatusSelector); - const numberOfBioEntitiesPerModel = useAppSelector(numberOfBioEntitiesPerModelSelector); + const bioEntitiesPerModel = useAppSelector(bioEntitiesPerModelSelector); return ( <AccordionItem> @@ -27,11 +27,12 @@ export const BioEntitiesAccordion = (): JSX.Element => { </AccordionItemButton> </AccordionItemHeading> <AccordionItemPanel> - {numberOfBioEntitiesPerModel.map(model => ( + {bioEntitiesPerModel.map(model => ( <BioEntitiesSubmapItem key={model.modelName} mapName={model.modelName} numberOfEntities={model.numberOfEntities} + bioEntities={model.bioEntities} /> ))} </AccordionItemPanel> diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx index 48c8a2eb..bd7472d6 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx @@ -1,15 +1,34 @@ -import { render, RenderResult, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; +import { StoreType } from '@/redux/store'; +import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { - BioEntitiesSubmapItem, - BioEntitiesSubmapItemProps, -} from './BioEntitiesSubmapItem.component'; + InitialStoreState, + getReduxWrapperWithStore, +} from '@/utils/testing/getReduxWrapperWithStore'; +import { BioEntitiesSubmapItem } from './BioEntitiesSubmapItem.component'; -const renderComponent = ({ mapName, numberOfEntities }: BioEntitiesSubmapItemProps): RenderResult => - render(<BioEntitiesSubmapItem mapName={mapName} numberOfEntities={numberOfEntities} />); +const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { + const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); + + return ( + render( + <Wrapper> + <BioEntitiesSubmapItem + mapName="main map" + numberOfEntities={21} + bioEntities={bioEntitiesContentFixture} + /> + </Wrapper>, + ), + { + store, + } + ); +}; describe('BioEntitiesSubmapItem - component', () => { it('should display map name,number of elements, icon', () => { - renderComponent({ mapName: 'main map', numberOfEntities: 21 }); + renderComponent(); expect(screen.getByText('main map (21)')).toBeInTheDocument(); }); diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.tsx index 8ee1caed..49d8fc3b 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.tsx @@ -1,18 +1,35 @@ import { Icon } from '@/shared/Icon'; +import { displayBioEntitiesList } from '@/redux/drawer/drawer.slice'; +import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; +import { BioEntityContent } from '@/types/models'; export interface BioEntitiesSubmapItemProps { mapName: string; numberOfEntities: string | number; + bioEntities: BioEntityContent[]; } export const BioEntitiesSubmapItem = ({ mapName, numberOfEntities, -}: BioEntitiesSubmapItemProps): JSX.Element => ( - <div className="flex flex-row flex-nowrap justify-between pl-6 [&:not(:last-of-type)]:pb-4"> - <p> - {mapName} ({numberOfEntities}) - </p> - <Icon name="arrow" className="h-6 w-6 fill-font-500" /> - </div> -); + bioEntities, +}: BioEntitiesSubmapItemProps): JSX.Element => { + const dispatch = useAppDispatch(); + + const onSubmapClick = (): void => { + dispatch(displayBioEntitiesList(bioEntities)); + }; + + return ( + <button + onClick={onSubmapClick} + type="button" + className="flex flex-row flex-nowrap items-center justify-between pl-6 [&:not(:last-of-type)]:pb-4" + > + <p className="text-sm font-normal"> + {mapName} ({numberOfEntities}) + </p> + <Icon name="arrow" className="h-6 w-6 fill-font-500" /> + </button> + ); +}; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.tsx index 95f53e4f..b3b3a7c5 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.tsx @@ -1,7 +1,7 @@ import { assertNever } from '@/utils/assertNever'; import { AccordionsDetails } from '../AccordionsDetails/AccordionsDetails.component'; import { PinItem, PinType } from './PinsList.types'; -import { MirnaPinsListItem } from './PinsListItem'; +import { PinsListItem } from './PinsListItem'; interface PinsListProps { pinsList: PinItem[]; @@ -17,7 +17,7 @@ export const PinsList = ({ pinsList, type }: PinsListProps): JSX.Element => { <ul className="px-6 py-2"> {pinsList.map(result => { return result.data.targets.map(pin => ( - <MirnaPinsListItem key={pin.name} name={pin.name} type={type} pin={pin} /> + <PinsListItem key={pin.name} name={pin.name} type={type} pin={pin} /> )); })} </ul> @@ -32,7 +32,7 @@ export const PinsList = ({ pinsList, type }: PinsListProps): JSX.Element => { <ul className="px-6 py-2"> {pinsList.map(result => { return result.data.targets.map(pin => ( - <MirnaPinsListItem key={pin.name} name={pin.name} type={type} pin={pin} /> + <PinsListItem key={pin.name} name={pin.name} type={type} pin={pin} /> )); })} </ul> @@ -43,7 +43,7 @@ export const PinsList = ({ pinsList, type }: PinsListProps): JSX.Element => { <ul className="h-[calc(100vh-198px)] overflow-auto px-6 py-2"> {pinsList.map(result => { return result.data.targets.map(pin => ( - <MirnaPinsListItem key={pin.name} name={pin.name} type={type} pin={pin} /> + <PinsListItem key={pin.name} name={pin.name} type={type} pin={pin} /> )); })} </ul> diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.tsx index ae58c0ea..6225c84d 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.tsx @@ -1,22 +1,57 @@ import { twMerge } from 'tailwind-merge'; import { Icon } from '@/shared/Icon'; +import { PinDetailsItem } from '@/types/models'; import { getPinColor } from './PinsListItem.component.utils'; import { PinType } from '../PinsList.types'; -interface PinsListItemProps { +interface MirnaPinsListItemProps { name: string; type: PinType; - onClick: () => void; + pin: PinDetailsItem; } -export const PinsListItem = ({ name, type, onClick }: PinsListItemProps): JSX.Element => ( - <button - className="flex w-full flex-row items-center justify-between pt-4" - onClick={onClick} - type="button" - > - <Icon name="pin" className={twMerge('mr-2 shrink-0', getPinColor(type))} /> - <p className="w-full text-left">{name}</p> - <Icon name="chevron-right" className="h-6 w-6 shrink-0" /> - </button> -); +export const PinsListItem = ({ name, type, pin }: MirnaPinsListItemProps): JSX.Element => { + return ( + <div className="mb-4 flex w-full flex-col gap-3 rounded-lg border-[1px] border-solid border-greyscale-500 p-4"> + <div className="flex w-full flex-row items-center gap-2"> + <Icon name="pin" className={twMerge('mr-2 shrink-0', getPinColor(type))} /> + <p> + Full name: <span className="w-full font-bold">{name}</span> + </p> + </div> + <ul className="leading-6"> + <div className="font-bold">Elements:</div> + {'targetParticipants' in pin && + pin.targetParticipants.map(element => { + return ( + <li key={element.id} className="my-2 px-2"> + <a + href={element.link} + target="_blank" + className="cursor-pointer text-primary-500 underline" + > + {element.type} ({element.resource}) + </a> + </li> + ); + })} + </ul> + <ul className="leading-6"> + <div className="font-bold">References:</div> + {pin.references.map(reference => { + return ( + <li key={reference.id} className="my-2 px-2"> + <a + href={reference.article?.link} + target="_blank" + className="cursor-pointer text-primary-500 underline" + > + {reference.type} ({reference.resource}) + </a> + </li> + ); + })} + </ul> + </div> + ); +}; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/index.ts b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/index.ts index bae1522b..89b9aebc 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/index.ts +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/index.ts @@ -1,2 +1 @@ export { PinsListItem } from './PinsListItem.component'; -export { MirnaPinsListItem } from './MirnaPinsListItem.component'; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/ResultsList.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/ResultsList.component.test.tsx index c6c94821..b11dfdeb 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/ResultsList.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/ResultsList.component.test.tsx @@ -20,6 +20,7 @@ const INITIAL_STATE: InitialStoreState = { currentStep: 2, stepType: 'drugs', selectedValue: undefined, + listOfBioEnitites: [], }, }, drugs: { diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.test.tsx index 63229511..5938b15b 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.test.tsx @@ -1,6 +1,4 @@ import { SearchDrawerWrapper } from '@/components/Map/Drawer/SearchDrawerWrapper'; -import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { drugFixture } from '@/models/fixtures/drugFixtures'; import { drawerSearchStepOneFixture } from '@/redux/drawer/drawerFixture'; import { StoreType } from '@/redux/store'; import { @@ -42,6 +40,7 @@ describe('SearchDrawerWrapper - component', () => { currentStep: 2, stepType: 'bioEntity', selectedValue: undefined, + listOfBioEnitites: [], }, }, }); @@ -58,42 +57,11 @@ describe('SearchDrawerWrapper - component', () => { currentStep: 2, stepType: 'drugs', selectedValue: undefined, + listOfBioEnitites: [], }, }, }); expect(screen.getByTestId('search-second-step')).toBeInTheDocument(); }); - - it('should display the third step for value type bioEntity', () => { - renderComponent({ - drawer: { - isOpen: true, - drawerName: 'search', - searchDrawerState: { - currentStep: 3, - stepType: 'bioEntity', - selectedValue: bioEntityContentFixture, - }, - }, - }); - - expect(screen.getByTestId('search-third-step')).toBeInTheDocument(); - }); - - it('should display the third step for value type drugs', () => { - renderComponent({ - drawer: { - isOpen: true, - drawerName: 'search', - searchDrawerState: { - currentStep: 3, - stepType: 'drugs', - selectedValue: drugFixture, - }, - }, - }); - - expect(screen.getByTestId('search-third-step')).toBeInTheDocument(); - }); }); diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.tsx index 23aa9763..280330ea 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.tsx @@ -7,6 +7,7 @@ import { import { useSelector } from 'react-redux'; import { ResultsList } from '@/components/Map/Drawer/SearchDrawerWrapper/ResultsList'; import { GroupedSearchResults } from '@/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults'; +import { BioEntitiesResultsList } from './BioEntitiesResultsList'; export const SearchDrawerWrapper = (): JSX.Element => { const currentStep = useSelector(currentStepDrawerStateSelector); @@ -21,7 +22,9 @@ export const SearchDrawerWrapper = (): JSX.Element => { {currentStep === STEP.FIRST && <GroupedSearchResults />} {/* 2nd step for bioEntities aka content */} {currentStep === STEP.SECOND && isBioEntityType && ( - <div data-testid="search-second-step">The second step</div> + <div data-testid="search-second-step"> + <BioEntitiesResultsList /> + </div> )} {/* 2nd step for drugs,chemicals,mirna */} {currentStep === STEP.SECOND && isChemicalsDrugsOrMirnaType && ( @@ -29,14 +32,6 @@ export const SearchDrawerWrapper = (): JSX.Element => { <ResultsList /> </div> )} - {/* last step for bioentity */} - {currentStep === STEP.THIRD && isBioEntityType && ( - <div data-testid="search-third-step">The third step</div> - )} - {/* last step for drugs,chemicals,mirna */} - {currentStep === STEP.THIRD && isChemicalsDrugsOrMirnaType && ( - <div data-testid="search-third-step">The third step</div> - )} </div> ); }; diff --git a/src/redux/bioEntity/bioEntity.selectors.ts b/src/redux/bioEntity/bioEntity.selectors.ts index dac3b8c7..941dfb6e 100644 --- a/src/redux/bioEntity/bioEntity.selectors.ts +++ b/src/redux/bioEntity/bioEntity.selectors.ts @@ -22,21 +22,23 @@ export const numberOfBioEntitiesSelector = createSelector(bioEntitySelector, sta state.data ? state.data.length : SIZE_OF_EMPTY_ARRAY, ); -export const numberOfBioEntitiesPerModelSelector = createSelector(rootSelector, state => { +export const bioEntitiesPerModelSelector = createSelector(rootSelector, state => { const { models, bioEntity: { data: bioEntities }, } = state; - const numberOfBioEntitiesPerModel = (models.data || []).map(model => { + const bioEntitiesPerModel = (models.data || []).map(model => { const bioEntitiesInGivenModel = (bioEntities || []).filter( entity => model.idObject === entity.bioEntity.model, ); - return { modelName: model.name, numberOfEntities: bioEntitiesInGivenModel.length }; + return { + modelName: model.name, + numberOfEntities: bioEntitiesInGivenModel.length, + bioEntities: bioEntitiesInGivenModel, + }; }); - return numberOfBioEntitiesPerModel.filter( - model => model.numberOfEntities !== SIZE_OF_EMPTY_ARRAY, - ); + return bioEntitiesPerModel.filter(model => model.numberOfEntities !== SIZE_OF_EMPTY_ARRAY); }); diff --git a/src/redux/drawer/drawer.reducers.test.ts b/src/redux/drawer/drawer.reducers.test.ts index a4a172f2..c275ef7a 100644 --- a/src/redux/drawer/drawer.reducers.test.ts +++ b/src/redux/drawer/drawer.reducers.test.ts @@ -21,6 +21,7 @@ const INITIAL_STATE: DrawerState = { currentStep: 0, stepType: 'none', selectedValue: undefined, + listOfBioEnitites: [], }, }; diff --git a/src/redux/drawer/drawer.reducers.ts b/src/redux/drawer/drawer.reducers.ts index 8efdb780..87675251 100644 --- a/src/redux/drawer/drawer.reducers.ts +++ b/src/redux/drawer/drawer.reducers.ts @@ -45,6 +45,16 @@ export const displayMirnaListReducer = (state: DrawerState): void => { state.searchDrawerState.stepType = 'mirna'; }; +export const displayBioEntitiesListReducer = ( + state: DrawerState, + action: PayloadAction<DrawerState['searchDrawerState']['listOfBioEnitites']>, +): void => { + state.drawerName = 'search'; + state.searchDrawerState.currentStep = STEP.SECOND; + state.searchDrawerState.listOfBioEnitites = action.payload; + state.searchDrawerState.stepType = 'bioEntity'; +}; + export const displayGroupedSearchResultsReducer = (state: DrawerState): void => { state.searchDrawerState.currentStep = STEP.FIRST; state.searchDrawerState.stepType = 'none'; diff --git a/src/redux/drawer/drawer.selectors.ts b/src/redux/drawer/drawer.selectors.ts index 6c8a5e3a..c140fbd7 100644 --- a/src/redux/drawer/drawer.selectors.ts +++ b/src/redux/drawer/drawer.selectors.ts @@ -56,3 +56,7 @@ export const resultListSelector = createSelector(rootSelector, state => { return assertNever(selectedType); } }); + +export const bioEnititiesResultListSelector = createSelector(rootSelector, state => { + return state.drawer.searchDrawerState.listOfBioEnitites; +}); diff --git a/src/redux/drawer/drawer.slice.ts b/src/redux/drawer/drawer.slice.ts index 612009e1..de472f28 100644 --- a/src/redux/drawer/drawer.slice.ts +++ b/src/redux/drawer/drawer.slice.ts @@ -2,6 +2,7 @@ import { DrawerState } from '@/redux/drawer/drawer.types'; import { createSlice } from '@reduxjs/toolkit'; import { closeDrawerReducer, + displayBioEntitiesListReducer, displayChemicalsListReducer, displayDrugsListReducer, displayEntityDetailsReducer, @@ -19,6 +20,7 @@ const initialState: DrawerState = { currentStep: 0, stepType: 'none', selectedValue: undefined, + listOfBioEnitites: [], }, }; @@ -33,6 +35,7 @@ const drawerSlice = createSlice({ displayDrugsList: displayDrugsListReducer, displayChemicalsList: displayChemicalsListReducer, displayMirnaList: displayMirnaListReducer, + displayBioEntitiesList: displayBioEntitiesListReducer, displayGroupedSearchResults: displayGroupedSearchResultsReducer, displayEntityDetails: displayEntityDetailsReducer, }, @@ -46,6 +49,7 @@ export const { displayDrugsList, displayChemicalsList, displayMirnaList, + displayBioEntitiesList, displayGroupedSearchResults, displayEntityDetails, } = drawerSlice.actions; diff --git a/src/redux/drawer/drawer.types.ts b/src/redux/drawer/drawer.types.ts index e39ff163..7e4a14b1 100644 --- a/src/redux/drawer/drawer.types.ts +++ b/src/redux/drawer/drawer.types.ts @@ -5,6 +5,7 @@ export type SearchDrawerState = { currentStep: number; stepType: 'bioEntity' | 'drugs' | 'mirna' | 'chemicals' | 'none'; selectedValue: BioEntityContent | Drug | Mirna | Chemical | undefined; + listOfBioEnitites: BioEntityContent[]; }; export type DrawerState = { diff --git a/src/redux/drawer/drawerFixture.ts b/src/redux/drawer/drawerFixture.ts index 987c01d3..6d1306b1 100644 --- a/src/redux/drawer/drawerFixture.ts +++ b/src/redux/drawer/drawerFixture.ts @@ -7,6 +7,7 @@ export const initialStateFixture: DrawerState = { currentStep: 0, stepType: 'none', selectedValue: undefined, + listOfBioEnitites: [], }, }; @@ -17,6 +18,7 @@ export const openedDrawerSubmapsFixture: DrawerState = { currentStep: 0, stepType: 'none', selectedValue: undefined, + listOfBioEnitites: [], }, }; @@ -27,6 +29,7 @@ export const drawerSearchStepOneFixture: DrawerState = { currentStep: 1, stepType: 'none', selectedValue: undefined, + listOfBioEnitites: [], }, }; @@ -37,5 +40,6 @@ export const drawerSearchDrugsStepTwoFixture: DrawerState = { currentStep: 2, stepType: 'drugs', selectedValue: undefined, + listOfBioEnitites: [], }, }; diff --git a/src/redux/drugs/drugs.selectors.ts b/src/redux/drugs/drugs.selectors.ts index af9a8d7f..e999bf83 100644 --- a/src/redux/drugs/drugs.selectors.ts +++ b/src/redux/drugs/drugs.selectors.ts @@ -10,11 +10,5 @@ export const numberOfDrugsSelector = createSelector(drugsSelector, state => { return SIZE_OF_EMPTY_ARRAY; } - let numberOfDrugs = 0; - - state.data.forEach(element => { - numberOfDrugs += element.targets.length; - }); - - return numberOfDrugs; + return state.data.length && state.data.map(e => e.targets.length)?.reduce((a, b) => a + b); }); diff --git a/src/redux/mirnas/mirnas.selectors.ts b/src/redux/mirnas/mirnas.selectors.ts index 6460f8b8..29020f54 100644 --- a/src/redux/mirnas/mirnas.selectors.ts +++ b/src/redux/mirnas/mirnas.selectors.ts @@ -10,11 +10,5 @@ export const numberOfMirnasSelector = createSelector(mirnasSelector, state => { return SIZE_OF_EMPTY_ARRAY; } - let numberOfMirnas = 0; - - state.data.forEach(element => { - numberOfMirnas += element.targets.length; - }); - - return numberOfMirnas; + return state.data.length && state.data.map(e => e.targets.length)?.reduce((a, b) => a + b); }); diff --git a/src/types/models.ts b/src/types/models.ts index 38b9e6b3..2033c775 100644 --- a/src/types/models.ts +++ b/src/types/models.ts @@ -25,7 +25,7 @@ export type Organism = z.infer<typeof organism>; export type Disease = z.infer<typeof disease>; export type Drug = z.infer<typeof drugSchema>; export type Mirna = z.infer<typeof mirnaSchema>; -export type MirnaItems = z.infer<typeof targetSchema>; +export type PinDetailsItem = z.infer<typeof targetSchema>; export type BioEntity = z.infer<typeof bioEntitySchema>; export type BioEntityContent = z.infer<typeof bioEntityContentSchema>; export type BioEntityResponse = z.infer<typeof bioEntityResponseSchema>; diff --git a/yarn.lock b/yarn.lock index 3ba2ee3e..d403655e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -847,9 +847,9 @@ "resolved" "https://registry.npmjs.org/@next/font/-/font-13.5.4.tgz" "version" "13.5.4" -"@next/swc-darwin-arm64@13.4.19": - "integrity" "sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ==" - "resolved" "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz" +"@next/swc-darwin-x64@13.4.19": + "integrity" "sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw==" + "resolved" "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz" "version" "13.4.19" "@nodelib/fs.scandir@2.1.5": -- GitLab