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 feae49317a379efff2a69bd7d528351e09a3cee0..1024d202c3dc1a87049b026891c3c27d6572d4e6 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx @@ -30,6 +30,7 @@ export const BioEntitiesAccordion = (): JSX.Element => { <BioEntitiesSubmapItem key={model.modelName} mapName={model.modelName} + mapId={model.modelId} numberOfEntities={model.numberOfEntities} bioEntities={model.bioEntities} /> 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 5fca44d875fb5454cc2d2c524cbf688bb5722850..aa753d71355ef22c7b6870a35a9356b19a598453 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,3 +1,4 @@ +/* eslint-disable no-magic-numbers */ import { act, render, screen } from '@testing-library/react'; import { StoreType } from '@/redux/store'; import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; @@ -5,9 +6,17 @@ import { InitialStoreState, getReduxWrapperWithStore, } from '@/utils/testing/getReduxWrapperWithStore'; +import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; import { drawerSearchStepOneFixture } from '@/redux/drawer/drawerFixture'; +import { + initialMapDataFixture, + openedMapsInitialValueFixture, + openedMapsThreeSubmapsFixture, +} from '@/redux/map/map.fixtures'; import { BioEntitiesSubmapItem } from './BioEntitiesSubmapItem.component'; +const CORE_MAP_ID = 5053; + const SECOND_STEP = 2; const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { @@ -17,7 +26,8 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St render( <Wrapper> <BioEntitiesSubmapItem - mapName="main map" + mapName={MODELS_MOCK_SHORT[0].name} + mapId={MODELS_MOCK_SHORT[0].idObject} numberOfEntities={21} bioEntities={bioEntitiesContentFixture} /> @@ -33,7 +43,7 @@ describe('BioEntitiesSubmapItem - component', () => { it('should display map name, number of elements, icon', () => { renderComponent(); - expect(screen.getByText('main map (21)')).toBeInTheDocument(); + expect(screen.getByText('Core PD map (21)')).toBeInTheDocument(); expect(screen.getByTestId('arrow-icon')).toBeInTheDocument(); }); it('should navigate user to bio enitites results list after clicking button', async () => { @@ -69,4 +79,103 @@ describe('BioEntitiesSubmapItem - component', () => { expect(currentStep).toBe(SECOND_STEP); expect(listOfBioEnitites).toBe(bioEntitiesContentFixture); }); + it("should open submap and set it to active if it's not already opened", async () => { + const { store } = renderComponent({ + bioEntity: { + data: [ + { + searchQueryElement: '', + loading: 'succeeded', + error: { name: '', message: '' }, + data: bioEntitiesContentFixture, + }, + ], + loading: 'succeeded', + error: { name: '', message: '' }, + }, + drawer: drawerSearchStepOneFixture, + models: { data: MODELS_MOCK_SHORT, loading: 'succeeded', error: { name: '', message: '' } }, + map: { + data: initialMapDataFixture, + loading: 'succeeded', + error: { name: '', message: '' }, + openedMaps: openedMapsInitialValueFixture, + }, + }); + + const { + data: { modelId }, + openedMaps, + } = store.getState().map; + + expect(modelId).toBe(0); + expect(openedMaps).not.toContainEqual({ + modelId: CORE_MAP_ID, + modelName: 'Core PD map', + lastPosition: { x: 0, y: 0, z: 0 }, + }); + + const navigationButton = screen.getByTestId('bio-entites-submap-button'); + await act(() => { + navigationButton.click(); + }); + + const { + data: { modelId: newModelId }, + openedMaps: newOpenedMaps, + } = store.getState().map; + + expect(newOpenedMaps).toContainEqual({ + modelId: CORE_MAP_ID, + modelName: 'Core PD map', + lastPosition: { x: 0, y: 0, z: 0 }, + }); + + expect(newModelId).toBe(CORE_MAP_ID); + }); + it("should set map active if it's already opened", async () => { + const { store } = renderComponent({ + bioEntity: { + data: [ + { + searchQueryElement: '', + loading: 'succeeded', + error: { name: '', message: '' }, + data: bioEntitiesContentFixture, + }, + ], + loading: 'succeeded', + error: { name: '', message: '' }, + }, + drawer: drawerSearchStepOneFixture, + models: { data: MODELS_MOCK_SHORT, loading: 'succeeded', error: { name: '', message: '' } }, + map: { + data: { + ...initialMapDataFixture, + modelId: CORE_MAP_ID, + }, + loading: 'succeeded', + error: { name: '', message: '' }, + openedMaps: openedMapsThreeSubmapsFixture, + }, + }); + + const navigationButton = screen.getByTestId('bio-entites-submap-button'); + await act(() => { + navigationButton.click(); + }); + + const { + map: { + data: { modelId }, + openedMaps, + }, + } = store.getState(); + + const histamineMap = openedMaps.filter(map => map.modelName === 'Histamine signaling'); + + // eslint-disable-next-line no-magic-numbers + expect(histamineMap.length).toBe(1); + expect(modelId).toBe(CORE_MAP_ID); + }); }); 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 6d86982d9f34958be5144ab1cdba3185e67fce53..cba96ef0a29207bd111abaf6511bc2cb10929bd2 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,22 +1,40 @@ +import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { Icon } from '@/shared/Icon'; import { displayBioEntitiesList } from '@/redux/drawer/drawer.slice'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { BioEntityContent } from '@/types/models'; +import { mapOpenedMapsSelector } from '@/redux/map/map.selectors'; +import { openMapAndSetActive, setActiveMap } from '@/redux/map/map.slice'; export interface BioEntitiesSubmapItemProps { mapName: string; + mapId: number; numberOfEntities: string | number; bioEntities: BioEntityContent[]; } export const BioEntitiesSubmapItem = ({ mapName, + mapId, numberOfEntities, bioEntities, }: BioEntitiesSubmapItemProps): JSX.Element => { const dispatch = useAppDispatch(); + const openedMaps = useAppSelector(mapOpenedMapsSelector); + + const isMapAlreadyOpened = (modelId: number): boolean => + openedMaps.some(map => map.modelId === modelId); + + const openSubmap = (): void => { + if (isMapAlreadyOpened(mapId)) { + dispatch(setActiveMap({ modelId: mapId })); + } else { + dispatch(openMapAndSetActive({ modelId: mapId, modelName: mapName })); + } + }; const onSubmapClick = (): void => { + openSubmap(); dispatch(displayBioEntitiesList(bioEntities)); }; diff --git a/src/redux/bioEntity/bioEntity.selectors.ts b/src/redux/bioEntity/bioEntity.selectors.ts index bbf46eb1fa4380fc2d6338ada7aaacaf0be8014a..ff071927eb014e2f0ac955b97a856da0f14bbc78 100644 --- a/src/redux/bioEntity/bioEntity.selectors.ts +++ b/src/redux/bioEntity/bioEntity.selectors.ts @@ -50,6 +50,7 @@ export const bioEntitiesPerModelSelector = createSelector( return { modelName: model.name, + modelId: model.idObject, numberOfEntities: bioEntitiesInGivenModel.length, bioEntities: bioEntitiesInGivenModel, };