From cb867685ed2c5b86200ebb5c6b41e07c3cee6722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Thu, 23 Jan 2025 14:06:04 +0100 Subject: [PATCH] feat(cleanup): access to element via store --- .../MapNavigation.component.test.tsx | 40 ++- .../AssociatedSubmap.component.test.tsx | 40 +++ .../BioEntityDrawer.component.test.tsx | 274 ++++++------------ .../BioEntityDrawer.component.tsx | 37 +-- .../Map/Drawer/Drawer.component.test.tsx | 7 + .../Elements/Elements.component.test.tsx | 49 ++-- ...udedCompartmentPathways.component.test.tsx | 95 +++--- .../ExcludedCompartmentPathways.component.tsx | 13 +- ...udedCompartmentPathways.component.test.tsx | 97 ++++--- .../IncludedCompartmentPathways.component.tsx | 13 +- ...ompartmentPathwaysCheckboxElements.test.ts | 8 +- .../getCompartmentPathwaysCheckboxElements.ts | 10 +- .../ExportDrawer/ExportDrawer.component.tsx | 13 +- .../Network/Network.component.test.tsx | 49 ++-- .../ReactionDrawer.component.test.tsx | 7 + .../ReactionDrawer.component.tsx | 6 +- .../MapLoader/MapLoader.component.test.tsx | 14 +- .../Map/MapLoader/MapLoader.component.tsx | 38 +-- .../Map/MapViewer/MapViewer.constants.ts | 12 +- .../commentsLayer/useOlMapCommentsLayer.ts | 17 +- .../config/mapCardLayer/useOlMapCardLayer.ts | 21 +- .../useBioEntitiesWithSubmapLinks.test.ts | 41 +++ .../overlaysLayer/useOlMapOverlaysLayer.ts | 17 +- .../config/pinsLayer/useOlMapPinsLayer.ts | 15 +- .../processLayer/processModelElements.ts | 3 +- .../processLayer/useOlMapProcessLayer.ts | 37 ++- .../reactionsLayer/useOlMapReactionsLayer.ts | 21 +- .../mouseClick/clickHandleReaction.test.ts | 20 +- .../mouseClick/getFeatureAtCoordinate.test.ts | 4 +- .../mouseClick/getFeatureAtCoordinate.ts | 4 +- .../mouseLeftClick/handleFeaturesClick.ts | 7 +- .../leftClickHandleAlias.test.ts | 11 +- .../mouseLeftClick/leftClickHandleAlias.ts | 30 +- .../mouseLeftClick/onMapLeftClick.test.ts | 4 +- .../mouseLeftClick/onMapLeftClick.ts | 2 +- .../mouseRightClick/onMapRightClick.test.ts | 4 +- .../mouseRightClick/onMapRightClick.ts | 4 +- .../Map/MapViewer/utils/shapes/layer/Layer.ts | 2 + src/models/bioEntitySchema.ts | 2 +- src/models/compartmentPathwaySchema.ts | 51 ---- src/models/fixtures/compartmentPathways.ts | 29 -- src/redux/apiPath.ts | 8 - src/redux/bioEntity/bioEntity.reducers.ts | 57 ---- src/redux/bioEntity/bioEntity.selectors.ts | 88 +----- src/redux/bioEntity/bioEntity.slice.ts | 2 - src/redux/bioEntity/thunks/getBioEntity.ts | 38 +-- .../bioEntity/thunks/getMultiBioEntity.ts | 52 +--- .../thunks/getSubmapConnectionsBioEntity.ts | 43 --- src/redux/comment/comment.reducers.ts | 23 +- src/redux/comment/comment.selectors.ts | 5 - src/redux/comment/comment.slice.ts | 2 - src/redux/comment/thunks/getComments.ts | 20 +- .../comparmentPathways.constants.ts | 3 - .../compartmentPathways.mock.ts | 65 ----- .../compartmentPathways.reducers.test.ts | 127 -------- .../compartmentPathways.reducers.ts | 20 -- .../compartmentPathways.selectors.ts | 17 -- .../compartmentPathways.slice.ts | 20 -- .../compartmentPathways.thunks.test.ts | 127 -------- .../compartmentPathways.thunks.ts | 129 --------- .../compartmentPathways.types.ts | 4 - src/redux/drawer/drawer.selectors.ts | 5 - .../entityNumber/entityNumber.reducers.ts | 1 - .../modelElements/modelElements.constants.ts | 2 + .../modelElements.reducers.test.ts | 4 +- .../modelElements/modelElements.selector.ts | 55 +++- .../modelElements/modelElements.thunks.ts | 2 +- .../newReactions/newReactions.selectors.ts | 10 + .../overlayBioEntity.selector.ts | 4 +- src/redux/root/init.thunks.ts | 3 - src/redux/root/root.fixtures.ts | 2 - src/redux/selectors/index.ts | 33 +++ src/redux/store.ts | 2 - .../map/triggerSearch/searchByCoordinates.ts | 2 +- .../map/triggerSearch/triggerSearch.test.ts | 4 +- src/types/models.ts | 24 +- 76 files changed, 693 insertions(+), 1478 deletions(-) delete mode 100644 src/models/compartmentPathwaySchema.ts delete mode 100644 src/models/fixtures/compartmentPathways.ts delete mode 100644 src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts delete mode 100644 src/redux/compartmentPathways/comparmentPathways.constants.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.mock.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.reducers.test.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.reducers.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.selectors.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.slice.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.thunks.test.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.thunks.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.types.ts create mode 100644 src/redux/selectors/index.ts diff --git a/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx b/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx index 22c43bc9..d08b0e9b 100644 --- a/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx +++ b/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx @@ -1,5 +1,4 @@ /* eslint-disable no-magic-numbers */ -import { MODELS_MOCK } from '@/redux/compartmentPathways/compartmentPathways.mock'; import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; import { StoreType } from '@/redux/store'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; @@ -9,7 +8,7 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { act, render, screen, within } from '@testing-library/react'; import { HISTAMINE_MAP_ID, MAIN_MAP_ID } from '@/constants/mocks'; -import { Project } from '@/types/models'; +import { MapModel, Project } from '@/types/models'; import { projectFixture } from '@/models/fixtures/projectFixture'; import { ProjectState } from '@/redux/project/project.types'; import { PROJECT_STATE_INITIAL_MOCK } from '@/redux/project/project.mock'; @@ -17,6 +16,43 @@ import { ModelsState } from '@/redux/models/models.types'; import { DEFAULT_ERROR } from '@/constants/errors'; import { MapNavigation } from './MapNavigation.component'; +const MODELS_MOCK: MapModel[] = [ + { + id: MAIN_MAP_ID, + width: 26779.25, + height: 13503.0, + defaultCenterX: null, + defaultCenterY: null, + description: '', + name: 'Core PD map', + defaultZoomLevel: null, + tileSize: 256, + references: [], + authors: [], + creationDate: null, + modificationDates: [], + minZoom: 2, + maxZoom: 9, + }, + { + id: 5054, + width: 26779.25, + height: 13503.0, + defaultCenterX: null, + defaultCenterY: null, + description: '', + name: 'Core PD map', + defaultZoomLevel: null, + tileSize: 256, + references: [], + authors: [], + creationDate: null, + modificationDates: [], + minZoom: 2, + maxZoom: 9, + }, +]; + export const MODELS_DATA: ModelsState = { data: [ { diff --git a/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx b/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx index 84ff3087..73231d8d 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx @@ -4,6 +4,7 @@ import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; import { BIOENTITY_INITIAL_STATE_MOCK, BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, + BIO_ENTITY_LINKING_TO_SUBMAP, } from '@/redux/bioEntity/bioEntity.mock'; import { DRAWER_INITIAL_STATE } from '@/redux/drawer/drawer.constants'; import { @@ -19,6 +20,7 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { act, render, screen } from '@testing-library/react'; import { HISTAMINE_MAP_ID, MAIN_MAP_ID } from '@/constants/mocks'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { AssociatedSubmap } from './AssociatedSubmap.component'; const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { @@ -51,6 +53,13 @@ describe('AssociatedSubmap - component', () => { chemicals: {}, }, }, + modelElements: { + [MAIN_MAP_ID]: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, models: { ...MODELS_INITIAL_STATE_MOCK, }, @@ -58,8 +67,18 @@ describe('AssociatedSubmap - component', () => { expect(screen.queryByTestId('associated-submap')).not.toBeInTheDocument(); }); + it('should render component when associated map model is found', () => { renderComponent({ + map: { + data: { + ...initialMapDataFixture, + modelId: MAIN_MAP_ID, + }, + loading: 'succeeded', + error: { name: '', message: '' }, + openedMaps: openedMapsThreeSubmapsFixture, + }, bioEntity: { ...BIOENTITY_INITIAL_STATE_MOCK, data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, @@ -72,6 +91,13 @@ describe('AssociatedSubmap - component', () => { chemicals: {}, }, }, + modelElements: { + [MAIN_MAP_ID]: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, models: { ...MODELS_INITIAL_STATE_MOCK, data: MODELS_MOCK_SHORT, @@ -94,6 +120,13 @@ describe('AssociatedSubmap - component', () => { ...BIOENTITY_INITIAL_STATE_MOCK, data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, }, + modelElements: { + 0: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -153,6 +186,13 @@ describe('AssociatedSubmap - component', () => { ...BIOENTITY_INITIAL_STATE_MOCK, data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, }, + modelElements: { + [MAIN_MAP_ID]: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { diff --git a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx index d72d546a..7ae2a243 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx @@ -1,14 +1,6 @@ /* eslint-disable no-magic-numbers */ -import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; -import { - bioEntitiesContentFixture, - bioEntityContentFixture, -} from '@/models/fixtures/bioEntityContentsFixture'; import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; -import { - BIOENTITY_INITIAL_STATE_MOCK, - BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, -} from '@/redux/bioEntity/bioEntity.mock'; +import { BIO_ENTITY_LINKING_TO_SUBMAP } from '@/redux/bioEntity/bioEntity.mock'; import { DRAWER_INITIAL_STATE } from '@/redux/drawer/drawer.constants'; import { MODELS_INITIAL_STATE_MOCK } from '@/redux/models/models.mock'; import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; @@ -18,6 +10,8 @@ import { InitialStoreState } from '@/utils/testing/getReduxWrapperWithStore'; import { act, render, screen } from '@testing-library/react'; import { MockStoreEnhanced } from 'redux-mock-store'; import { getTypeBySBOTerm } from '@/utils/bioEntity/getTypeBySBOTerm'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { BioEntityDrawer } from './BioEntityDrawer.component'; const renderComponent = ( @@ -65,65 +59,48 @@ describe('BioEntityDrawer - component', () => { expect(screen.queryByText('Source:')).toBeNull(); }); }); + describe('when there IS a matching bioEntity', () => { - const { bioEntity } = bioEntitiesContentFixture[FIRST_ARRAY_ELEMENT]; + const bioEntityName = 'test'; + const bioEntityFullName = 'BioEntity Full Name'; it('should show drawer header', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, }, }); - const bioEntityType = getTypeBySBOTerm(bioEntity.sboTerm); - + const bioEntityType = getTypeBySBOTerm(modelElementFixture.sboTerm); expect(screen.getByText(bioEntityType, { exact: false })).toBeInTheDocument(); - expect(screen.getByText(bioEntity.name, { exact: false })).toBeInTheDocument(); + expect(screen.getByText(bioEntityName, { exact: false })).toBeInTheDocument(); }); it('should show drawer bioEntity full name', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: 'BioEntity Full Name', - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: bioEntityFullName }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -131,35 +108,22 @@ describe('BioEntityDrawer - component', () => { }); expect(screen.getByText('Full name:', { exact: false })).toBeInTheDocument(); - expect(screen.getByText('BioEntity Full Name', { exact: false })).toBeInTheDocument(); + expect(screen.getByText(bioEntityFullName, { exact: false })).toBeInTheDocument(); }); it("should not show drawer bioEntity full name if it doesn't exists", () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -171,22 +135,17 @@ describe('BioEntityDrawer - component', () => { it('should show list of annotations ', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -194,22 +153,27 @@ describe('BioEntityDrawer - component', () => { }); expect(screen.getByText('Annotations:')).toBeInTheDocument(); - expect(screen.getByText(bioEntity.references[0].type, { exact: false })).toBeInTheDocument(); expect( - screen.getByText(bioEntity.references[0].resource, { exact: false }), + screen.getByText(modelElementFixture.references[0].type, { exact: false }), + ).toBeInTheDocument(); + expect( + screen.getByText(modelElementFixture.references[0].resource, { exact: false }), ).toBeInTheDocument(); }); it('should display associated submaps if bio entity links to submap', () => { renderComponent({ - bioEntity: { - ...BIOENTITY_INITIAL_STATE_MOCK, - data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, - }, + modelElements: { + 0: { + data: [{ ...BIO_ENTITY_LINKING_TO_SUBMAP, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: BIO_ENTITY_LINKING_TO_SUBMAP.id, drugs: {}, chemicals: {}, }, @@ -225,30 +189,17 @@ describe('BioEntityDrawer - component', () => { it('should display chemicals list header', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -260,30 +211,17 @@ describe('BioEntityDrawer - component', () => { it('should display drugs list header', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -293,86 +231,60 @@ describe('BioEntityDrawer - component', () => { expect(screen.getByText('Chemicals for target', { exact: false })).toBeInTheDocument(); }); - it('should fetch drugs on drugs for target click', () => { + it('should fetch chemicals on chemicals for target click', () => { const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, }, }); - const button = screen.getByText('Drugs for target', { exact: false }); + const button = screen.getByText('Chemicals for target', { exact: false }); act(() => { button.click(); }); - expect(store.getActions()[0].type).toBe('drawer/getDrugsForBioEntityDrawerTarget/pending'); + expect(store.getActions()[0].type).toBe( + 'drawer/getChemicalsForBioEntityDrawerTarget/pending', + ); }); - it('should fetch chemicals on chemicals for target click', () => { + it('should fetch drugs on drugs for target click', () => { const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, }, }); - const button = screen.getByText('Chemicals for target', { exact: false }); + const button = screen.getByText('Drugs for target', { exact: false }); act(() => { button.click(); }); - expect(store.getActions()[0].type).toBe( - 'drawer/getChemicalsForBioEntityDrawerTarget/pending', - ); + expect(store.getActions()[0].type).toBe('drawer/getDrugsForBioEntityDrawerTarget/pending'); }); }); }); diff --git a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx index 7b3e3ba1..48ac8915 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx @@ -1,7 +1,6 @@ import { ZERO } from '@/constants/common'; import { currentDrawerBioEntityRelatedSubmapSelector, - currentDrawerBioEntitySelector, currentDrawerElementCommentsSelector, } from '@/redux/bioEntity/bioEntity.selectors'; import { @@ -17,6 +16,10 @@ import { getTypeBySBOTerm } from '@/utils/bioEntity/getTypeBySBOTerm'; import { ModificationResidueItem } from '@/components/Map/Drawer/BioEntityDrawer/ModificationResidueItem'; import React from 'react'; import { AnnotationItemList } from '@/components/Map/Drawer/BioEntityDrawer/AnnotationItem/AnnotationItemList.component'; +import { + compartmentNameByIdSelector, + currentDrawerModelElementSelector, +} from '@/redux/modelElements/modelElements.selector'; import { CollapsibleSection } from '../ExportDrawer/CollapsibleSection'; import { AssociatedSubmap } from './AssociatedSubmap'; import { ChemicalsList } from './ChemicalsList'; @@ -27,28 +30,31 @@ const TARGET_PREFIX: ElementSearchResultType = `ALIAS`; export const BioEntityDrawer = (): React.ReactNode => { const dispatch = useAppDispatch(); - const bioEntityData = useAppSelector(currentDrawerBioEntitySelector); + const modelElement = useAppSelector(currentDrawerModelElementSelector); const commentsData = useAppSelector(currentDrawerElementCommentsSelector); const relatedSubmap = useAppSelector(currentDrawerBioEntityRelatedSubmapSelector); - const currentTargetId = bioEntityData?.id ? `${TARGET_PREFIX}:${bioEntityData.id}` : ''; + const currentTargetId = modelElement?.id ? `${TARGET_PREFIX}:${modelElement.id}` : ''; const fetchChemicalsForTarget = (): void => { dispatch(getChemicalsForBioEntityDrawerTarget(currentTargetId)); }; + const compartmentName = useAppSelector(state => + compartmentNameByIdSelector(state, modelElement?.compartment), + ); + const fetchDrugsForTarget = (): void => { dispatch(getDrugsForBioEntityDrawerTarget(currentTargetId)); }; - - if (!bioEntityData) { + if (!modelElement) { return null; } const isCommentAvailable = commentsData.length > ZERO; const modificationResidues = ( - bioEntityData.modificationResidues ? bioEntityData.modificationResidues : [] + modelElement.modificationResidues ? modelElement.modificationResidues : [] ).filter(modificationResidue => modificationResidue.state && modificationResidue.state !== ''); const isModificationAvailable = modificationResidues.length > ZERO; - const type = getTypeBySBOTerm(bioEntityData.sboTerm, bioEntityData.shape); + const type = getTypeBySBOTerm(modelElement.sboTerm, modelElement.shape); return ( <div className="h-calc-drawer" data-testid="bioentity-drawer"> @@ -56,29 +62,26 @@ export const BioEntityDrawer = (): React.ReactNode => { title={ <> <span className="font-normal">{type}:</span> - {bioEntityData.name} + {modelElement.name} </> } /> <div className="flex max-h-full flex-col gap-6 overflow-y-auto p-6"> <div className="text-sm font-normal"> - Compartment:{' '} - <b className="font-semibold"> - {bioEntityData.compartmentName ? bioEntityData.compartmentName : 'default'} - </b> + Compartment: <b className="font-semibold">{compartmentName || 'default'}</b> </div> - {bioEntityData.fullName && ( + {modelElement.fullName && ( <div className="text-sm font-normal"> - Full name: <b className="font-semibold">{bioEntityData.fullName}</b> + Full name: <b className="font-semibold">{modelElement.fullName}</b> </div> )} - {bioEntityData.notes && ( + {modelElement.notes && ( <span> <hr className="border-b border-b-divide" /> <div className="text-sm font-normal" /* eslint-disable-next-line react/no-danger */ - dangerouslySetInnerHTML={{ __html: bioEntityData.notes }} + dangerouslySetInnerHTML={{ __html: modelElement.notes }} /> </span> )} @@ -92,7 +95,7 @@ export const BioEntityDrawer = (): React.ReactNode => { ))} </ul> )} - <AnnotationItemList references={bioEntityData.references} /> + <AnnotationItemList references={modelElement.references} /> <AssociatedSubmap /> {!relatedSubmap && ( <> diff --git a/src/components/Map/Drawer/Drawer.component.test.tsx b/src/components/Map/Drawer/Drawer.component.test.tsx index eb258f9d..b677519d 100644 --- a/src/components/Map/Drawer/Drawer.component.test.tsx +++ b/src/components/Map/Drawer/Drawer.component.test.tsx @@ -101,6 +101,13 @@ describe('Drawer - component', () => { loading: 'succeeded', error: { message: '', name: '' }, }, + newReactions: { + 0: { + data: [newReactionFixture], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, }); expect(screen.queryByTestId('reaction-drawer')).not.toBeInTheDocument(); diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx index e3307241..d0e0d9b6 100644 --- a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx @@ -1,5 +1,4 @@ /* eslint-disable no-magic-numbers */ -import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways'; import { configurationFixture } from '@/models/fixtures/configurationFixture'; import { modelsFixture } from '@/models/fixtures/modelsFixture'; import { statisticsFixture } from '@/models/fixtures/statisticsFixture'; @@ -14,6 +13,9 @@ import { render, screen } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; import { act } from 'react-dom/test-utils'; import { MockStoreEnhanced } from 'redux-mock-store'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; +import { COMPARTMENT_SBO_TERM } from '@/components/Map/MapViewer/MapViewer.constants'; import { ELEMENTS_COLUMNS } from '../ExportCompound/ExportCompound.constant'; import { Elements } from './Elements.component'; @@ -70,14 +72,6 @@ describe('Elements - component', () => { name: '', }, }, - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, }); const annotations = screen.getByText('Select annotations'); @@ -90,12 +84,13 @@ describe('Elements - component', () => { expect(excludedCompartmentPathways).toBeVisible(); expect(downloadButton).toBeVisible(); }); + it('should handle download button click and dispatch proper data', async () => { mockedAxiosClient.onPost(apiPath.downloadElementsCsv()).reply(HttpStatusCode.Ok, 'test'); - const FIRST_COMPARMENT_PATHWAY_NAME = compartmentPathwaysDetailsFixture[0].name; - const FIRST_COMPARMENT_PATHWAY_ID = compartmentPathwaysDetailsFixture[0].id; - const SECOND_COMPARMENT_PATHWAY_NAME = compartmentPathwaysDetailsFixture[1].name; - const SECOND_COMPARMENT_PATHWAY_ID = compartmentPathwaysDetailsFixture[1].id; + const FIRST_COMPARMENT_PATHWAY_NAME = 'test1'; + const FIRST_COMPARMENT_PATHWAY_ID = 1; + const SECOND_COMPARMENT_PATHWAY_NAME = 'test2'; + const SECOND_COMPARMENT_PATHWAY_ID = 2; const { store } = renderComponent({ ...INITIAL_STORE_STATE_MOCK, configuration: { @@ -129,14 +124,6 @@ describe('Elements - component', () => { name: '', }, }, - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, models: { data: modelsFixture, loading: 'succeeded', @@ -145,6 +132,26 @@ describe('Elements - component', () => { name: '', }, }, + modelElements: { + 0: { + data: [ + { + ...modelElementFixture, + id: FIRST_COMPARMENT_PATHWAY_ID, + name: FIRST_COMPARMENT_PATHWAY_NAME, + sboTerm: COMPARTMENT_SBO_TERM, + }, + { + ...modelElementFixture, + id: SECOND_COMPARMENT_PATHWAY_ID, + name: SECOND_COMPARMENT_PATHWAY_NAME, + sboTerm: COMPARTMENT_SBO_TERM, + }, + ], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, }); const annotations = screen.getByText('Select annotations'); diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx index ded8e680..82d39b1e 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx @@ -6,9 +6,20 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { StoreType } from '@/redux/store'; import { act } from 'react-dom/test-utils'; -import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { ModelElement } from '@/types/models'; +import { + compartmentPathwaysSelector, + modelElementsAnyModelLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; import { ExcludedCompartmentPathways } from './ExcludedCompartmentPathways.component'; +jest.mock('../../../../../../redux/hooks/useAppSelector', () => ({ + useAppSelector: jest.fn(), +})); +type SelectorFunction = (state: never) => ModelElement[] | boolean; + const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); @@ -24,20 +35,28 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St ); }; -const CHECKBOX_ELEMENT_NAME = compartmentPathwaysDetailsFixture[0].name; +const CHECKBOX_ELEMENT_NAME = modelElementFixture.name; describe('ExcludedCompartmentPathways - component', () => { + const mockUseAppSelector = useAppSelector as jest.Mock; + it('should display compartment / pathways checkboxes when fetching data is successful', async () => { - renderComponent({ - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [ + compartmentPathwaysSelector, + [ + { + ...modelElementFixture, + }, + ], + ], + [modelElementsAnyModelLoadingSelector, false], + ]); + + return selectorMap.get(selector) ?? false; }); + renderComponent({}); expect(screen.queryByTestId('checkbox-filter')).not.toBeVisible(); @@ -55,36 +74,18 @@ describe('ExcludedCompartmentPathways - component', () => { expect(screen.getByLabelText(CHECKBOX_ELEMENT_NAME)).toBeInTheDocument(); }); }); - it('should not display compartment / pathways checkboxes when fetching data fails', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'failed', - error: { - message: '', - name: '', - }, - }, - }); - expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument(); - const navigationButton = screen.getByTestId('accordion-item-button'); - act(() => { - navigationButton.click(); - }); - expect(screen.queryByTestId('checkbox-filter')).not.toBeInTheDocument(); - }); it('should not display compartment / pathways checkboxes when fetched data is empty', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [compartmentPathwaysSelector, []], + [modelElementsAnyModelLoadingSelector, false], + ]); + + return selectorMap.get(selector) ?? false; }); + + renderComponent({}); expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { @@ -95,16 +96,16 @@ describe('ExcludedCompartmentPathways - component', () => { }); it('should display loading message when fetching data is pending', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'pending', - error: { - message: '', - name: '', - }, - }, + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [compartmentPathwaysSelector, []], + [modelElementsAnyModelLoadingSelector, true], + ]); + + return selectorMap.get(selector) ?? false; }); + + renderComponent({}); expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx index 89007fae..131819ac 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx @@ -1,10 +1,10 @@ import { ZERO } from '@/constants/common'; -import { - compartmentPathwaysDataSelector, - loadingCompartmentPathwaysSelector, -} from '@/redux/compartmentPathways/compartmentPathways.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { useContext } from 'react'; +import { + compartmentPathwaysSelector, + modelElementsAnyModelLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; import { CheckboxFilter } from '../../CheckboxFilter'; import { CollapsibleSection } from '../../CollapsibleSection'; import { ExportContext } from '../ExportCompound.context'; @@ -13,9 +13,8 @@ import { getCompartmentPathwaysCheckboxElements } from '../utils/getCompartmentP export const ExcludedCompartmentPathways = (): React.ReactNode => { const { setExcludedCompartmentPathways, data } = useContext(ExportContext); const currentExcludedCompartmentPathways = data.excludedCompartmentPathways; - const loadingCompartmentPathways = useAppSelector(loadingCompartmentPathwaysSelector); - const isPending = loadingCompartmentPathways === 'pending'; - const compartmentPathways = useAppSelector(compartmentPathwaysDataSelector); + const compartmentPathways = useAppSelector(compartmentPathwaysSelector); + const isPending = useAppSelector(modelElementsAnyModelLoadingSelector); const checkboxElements = getCompartmentPathwaysCheckboxElements('excluded', compartmentPathways); const isCheckboxFilterVisible = !isPending && checkboxElements && checkboxElements.length > ZERO; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx index 59a59c99..29ce2f87 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx @@ -6,9 +6,20 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { StoreType } from '@/redux/store'; import { act } from 'react-dom/test-utils'; -import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { + compartmentPathwaysSelector, + modelElementsAnyModelLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; +import { ModelElement } from '@/types/models'; import { IncludedCompartmentPathways } from './IncludedCompartmentPathways.component'; +jest.mock('../../../../../../redux/hooks/useAppSelector', () => ({ + useAppSelector: jest.fn(), +})); +type SelectorFunction = (state: never) => ModelElement[] | boolean; + const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); @@ -24,21 +35,29 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St ); }; -const CHECKBOX_ELEMENT_NAME = compartmentPathwaysDetailsFixture[0].name; +const CHECKBOX_ELEMENT_NAME = modelElementFixture.name; describe('IncludedCompartmentPathways - component', () => { it('should display compartment / pathways checkboxes when fetching data is successful', async () => { - renderComponent({ - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, + const mockUseAppSelector = useAppSelector as jest.Mock; + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [ + compartmentPathwaysSelector, + [ + { + ...modelElementFixture, + }, + ], + ], + [modelElementsAnyModelLoadingSelector, false], + ]); + + return selectorMap.get(selector) ?? false; }); + renderComponent({}); + expect(screen.queryByTestId('checkbox-filter')).not.toBeVisible(); const navigationButton = screen.getByTestId('accordion-item-button'); @@ -55,36 +74,19 @@ describe('IncludedCompartmentPathways - component', () => { expect(screen.getByLabelText(CHECKBOX_ELEMENT_NAME)).toBeInTheDocument(); }); }); - it('should not display compartment / pathways checkboxes when fetching data fails', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'failed', - error: { - message: '', - name: '', - }, - }, - }); - expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument(); - const navigationButton = screen.getByTestId('accordion-item-button'); - act(() => { - navigationButton.click(); - }); - expect(screen.queryByTestId('checkbox-filter')).not.toBeInTheDocument(); - }); it('should not display compartment / pathways checkboxes when fetched data is empty', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, + const mockUseAppSelector = useAppSelector as jest.Mock; + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [compartmentPathwaysSelector, []], + [modelElementsAnyModelLoadingSelector, false], + ]); + + return selectorMap.get(selector) ?? false; }); + + renderComponent({}); expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { @@ -95,16 +97,17 @@ describe('IncludedCompartmentPathways - component', () => { }); it('should display loading message when fetching data is pending', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'pending', - error: { - message: '', - name: '', - }, - }, + const mockUseAppSelector = useAppSelector as jest.Mock; + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [compartmentPathwaysSelector, []], + [modelElementsAnyModelLoadingSelector, true], + ]); + + return selectorMap.get(selector) ?? false; }); + + renderComponent({}); expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx index 4ef2cee4..509a8636 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx @@ -1,10 +1,10 @@ import { ZERO } from '@/constants/common'; -import { - compartmentPathwaysDataSelector, - loadingCompartmentPathwaysSelector, -} from '@/redux/compartmentPathways/compartmentPathways.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { useContext } from 'react'; +import { + compartmentPathwaysSelector, + modelElementsAnyModelLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; import { CheckboxFilter } from '../../CheckboxFilter'; import { CollapsibleSection } from '../../CollapsibleSection'; import { ExportContext } from '../ExportCompound.context'; @@ -13,9 +13,8 @@ import { getCompartmentPathwaysCheckboxElements } from '../utils/getCompartmentP export const IncludedCompartmentPathways = (): React.ReactNode => { const { setIncludedCompartmentPathways, data } = useContext(ExportContext); const currentIncludedCompartmentPathways = data.includedCompartmentPathways; - const loadingCompartmentPathways = useAppSelector(loadingCompartmentPathwaysSelector); - const isPending = loadingCompartmentPathways === 'pending'; - const compartmentPathways = useAppSelector(compartmentPathwaysDataSelector); + const compartmentPathways = useAppSelector(compartmentPathwaysSelector); + const isPending = useAppSelector(modelElementsAnyModelLoadingSelector); const checkboxElements = getCompartmentPathwaysCheckboxElements('included', compartmentPathways); return ( diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.test.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.test.ts index 6254cd6b..893b0367 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.test.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.test.ts @@ -1,10 +1,10 @@ /* eslint-disable no-magic-numbers */ -import { CompartmentPathwayDetails } from '@/types/models'; +import { ModelElement } from '@/types/models'; import { getCompartmentPathwaysCheckboxElements } from './getCompartmentPathwaysCheckboxElements'; describe('getCompartmentPathwaysCheckboxElements', () => { it('should return an empty array when given an empty items array', () => { - const items: CompartmentPathwayDetails[] = []; + const items: ModelElement[] = []; const result = getCompartmentPathwaysCheckboxElements('include', items); expect(result).toEqual([]); }); @@ -15,7 +15,7 @@ describe('getCompartmentPathwaysCheckboxElements', () => { { id: 2, name: 'Compartment B' }, { id: 3, name: 'Compartment A' }, { id: 4, name: 'Compartment C' }, - ] as CompartmentPathwayDetails[]; + ] as ModelElement[]; const result = getCompartmentPathwaysCheckboxElements('test', items); @@ -32,7 +32,7 @@ describe('getCompartmentPathwaysCheckboxElements', () => { { id: 3, name: 'Compartment B' }, { id: 4, name: 'Compartment A' }, { id: 5, name: 'Compartment D' }, - ] as CompartmentPathwayDetails[]; + ] as ModelElement[]; const result = getCompartmentPathwaysCheckboxElements('prefix', items); diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.ts index 9a807f04..86147944 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import { CompartmentPathwayDetails } from '@/types/models'; +import { ModelElement } from '@/types/models'; type AddedNames = { [key: string]: number }; @@ -9,11 +9,11 @@ type CheckboxElements = CheckboxElement[]; export const getCompartmentPathwaysCheckboxElements = ( prefix: string, - items: CompartmentPathwayDetails[], + items: ModelElement[], ): CheckboxElements => { const addedNames: AddedNames = {}; - const setNameToIdIfUndefined = (item: CompartmentPathwayDetails): void => { + const setNameToIdIfUndefined = (item: ModelElement): void => { if (addedNames[item.name] === undefined) { addedNames[item.name] = item.id; } @@ -31,7 +31,5 @@ export const getCompartmentPathwaysCheckboxElements = ( return -1; }; - const elements = Object.entries(addedNames).map(parseIdAndLabel).sort(sortByLabel); - - return elements; + return Object.entries(addedNames).map(parseIdAndLabel).sort(sortByLabel); }; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportDrawer.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportDrawer.component.tsx index 64d3ddfd..6847bd99 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportDrawer.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportDrawer.component.tsx @@ -1,9 +1,5 @@ -import { getCompartmentPathways } from '@/redux/compartmentPathways/compartmentPathways.thunks'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { modelsIdsSelector } from '@/redux/models/models.selectors'; import { DrawerHeading } from '@/shared/DrawerHeading'; -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { CurrentView } from './CurrentView'; import { Elements } from './Elements'; import { Graphics } from './Graphics'; @@ -13,18 +9,11 @@ import { TAB_NAMES } from './TabNavigator/TabNavigator.constants'; import { TabNames } from './TabNavigator/TabNavigator.types'; export const ExportDrawer = (): React.ReactNode => { - const modelsIds = useAppSelector(modelsIdsSelector); - const dispatch = useAppDispatch(); const [activeTab, setActiveTab] = useState<TabNames>(TAB_NAMES.ELEMENTS); const handleTabChange = (tabName: TabNames): void => { setActiveTab(tabName); }; - - useEffect(() => { - dispatch(getCompartmentPathways(modelsIds)); - }, [dispatch, modelsIds]); - return ( <div data-testid="export-drawer" className="h-full max-h-full"> <DrawerHeading title="Export" /> diff --git a/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx index 2fddcfed..88243df1 100644 --- a/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx @@ -1,5 +1,4 @@ /* eslint-disable no-magic-numbers */ -import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways'; import { configurationFixture } from '@/models/fixtures/configurationFixture'; import { modelsFixture } from '@/models/fixtures/modelsFixture'; import { statisticsFixture } from '@/models/fixtures/statisticsFixture'; @@ -14,6 +13,9 @@ import { render, screen } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; import { act } from 'react-dom/test-utils'; import { MockStoreEnhanced } from 'redux-mock-store'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { COMPARTMENT_SBO_TERM } from '@/components/Map/MapViewer/MapViewer.constants'; import { NETWORK_COLUMNS } from '../ExportCompound/ExportCompound.constant'; import { Network } from './Network.component'; @@ -70,14 +72,6 @@ describe('Network - component', () => { name: '', }, }, - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, }); const annotations = screen.getByText('Select annotations'); const includedCompartmentPathways = screen.getByText('Select included compartment / pathways'); @@ -89,12 +83,13 @@ describe('Network - component', () => { expect(excludedCompartmentPathways).toBeVisible(); expect(downloadButton).toBeVisible(); }); + it('should handle download button click and dispatch proper data', async () => { + const FIRST_COMPARMENT_PATHWAY_NAME = 'test1'; + const FIRST_COMPARMENT_PATHWAY_ID = 1; + const SECOND_COMPARMENT_PATHWAY_NAME = 'test2'; + const SECOND_COMPARMENT_PATHWAY_ID = 2; mockedAxiosClient.onPost(apiPath.downloadNetworkCsv()).reply(HttpStatusCode.Ok, 'test'); - const FIRST_COMPARMENT_PATHWAY_NAME = compartmentPathwaysDetailsFixture[0].name; - const FIRST_COMPARMENT_PATHWAY_ID = compartmentPathwaysDetailsFixture[0].id; - const SECOND_COMPARMENT_PATHWAY_NAME = compartmentPathwaysDetailsFixture[1].name; - const SECOND_COMPARMENT_PATHWAY_ID = compartmentPathwaysDetailsFixture[1].id; const { store } = renderComponent({ ...INITIAL_STORE_STATE_MOCK, configuration: { @@ -132,14 +127,6 @@ describe('Network - component', () => { name: '', }, }, - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, models: { data: modelsFixture, loading: 'succeeded', @@ -148,6 +135,26 @@ describe('Network - component', () => { name: '', }, }, + modelElements: { + 0: { + data: [ + { + ...modelElementFixture, + id: FIRST_COMPARMENT_PATHWAY_ID, + name: FIRST_COMPARMENT_PATHWAY_NAME, + sboTerm: COMPARTMENT_SBO_TERM, + }, + { + ...modelElementFixture, + id: SECOND_COMPARMENT_PATHWAY_ID, + name: SECOND_COMPARMENT_PATHWAY_NAME, + sboTerm: COMPARTMENT_SBO_TERM, + }, + ], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, }); const annotations = screen.getByText('Select annotations'); diff --git a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx index 1a76eeea..283dd29f 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx @@ -71,6 +71,13 @@ describe('ReactionDrawer - component', () => { loading: 'succeeded', error: { message: '', name: '' }, }, + newReactions: { + 0: { + data: [reaction], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, drawer: { ...DRAWER_INITIAL_STATE, reactionDrawerState: { diff --git a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx index 00d2128e..633c55a8 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx @@ -1,6 +1,4 @@ -import { currentDrawerReactionSelector } from '@/redux/reactions/reactions.selector'; import { DrawerHeading } from '@/shared/DrawerHeading'; -import { useSelector } from 'react-redux'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { currentDrawerReactionCommentsSelector } from '@/redux/bioEntity/bioEntity.selectors'; import { CommentItem } from '@/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component'; @@ -8,11 +6,11 @@ import { ZERO } from '@/constants/common'; import ReactionTypeEnum from '@/utils/reaction/ReactionTypeEnum'; import React from 'react'; import { AnnotationItemList } from '@/components/Map/Drawer/BioEntityDrawer/AnnotationItem/AnnotationItemList.component'; +import { currentDrawerNewReactionSelector } from '@/redux/newReactions/newReactions.selectors'; import { ConnectedBioEntitiesList } from './ConnectedBioEntitiesList'; export const ReactionDrawer = (): React.ReactNode => { - const reaction = useSelector(currentDrawerReactionSelector); - + const reaction = useAppSelector(currentDrawerNewReactionSelector); const commentsData = useAppSelector(currentDrawerReactionCommentsSelector); if (!reaction) { diff --git a/src/components/Map/MapLoader/MapLoader.component.test.tsx b/src/components/Map/MapLoader/MapLoader.component.test.tsx index 7f8fb00b..ec4c2e1b 100644 --- a/src/components/Map/MapLoader/MapLoader.component.test.tsx +++ b/src/components/Map/MapLoader/MapLoader.component.test.tsx @@ -7,7 +7,7 @@ import { import { StoreType } from '@/redux/store'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { newReactionsLoadingSelector } from '@/redux/newReactions/newReactions.selectors'; -import { modelElementsLoadingSelector } from '@/redux/modelElements/modelElements.selector'; +import { modelElementsCurrentModelLoadingSelector } from '@/redux/modelElements/modelElements.selector'; import { isDrawerOpenSelector } from '@/redux/drawer/drawer.selectors'; import { arrowTypesLoadingSelector, @@ -15,6 +15,7 @@ import { lineTypesLoadingSelector, } from '@/redux/shapes/shapes.selectors'; import { layersLoadingSelector } from '@/redux/layers/layers.selectors'; +import { modelLoadingSelector } from '@/redux/selectors'; import { MapLoader } from './MapLoader.component'; jest.mock('../../../redux/hooks/useAppSelector', () => ({ @@ -48,7 +49,7 @@ describe('MapLoader', () => { mockUseAppSelector.mockImplementation(selector => { const selectorMap = new Map<SelectorFunction, string | boolean>([ [newReactionsLoadingSelector, 'succeeded'], - [modelElementsLoadingSelector, 'succeeded'], + [modelElementsCurrentModelLoadingSelector, 'succeeded'], [bioShapesLoadingSelector, 'succeeded'], [lineTypesLoadingSelector, 'succeeded'], [arrowTypesLoadingSelector, 'succeeded'], @@ -65,13 +66,8 @@ describe('MapLoader', () => { it('should render the LoadingIndicator when data is loading', () => { mockUseAppSelector.mockImplementation(selector => { - const selectorMap = new Map<SelectorFunction, string | boolean>([ - [newReactionsLoadingSelector, 'pending'], - [modelElementsLoadingSelector, 'succeeded'], - [bioShapesLoadingSelector, 'succeeded'], - [lineTypesLoadingSelector, 'succeeded'], - [arrowTypesLoadingSelector, 'succeeded'], - [layersLoadingSelector, 'succeeded'], + const selectorMap = new Map<SelectorFunction, boolean>([ + [modelLoadingSelector, true], [isDrawerOpenSelector, false], ]); diff --git a/src/components/Map/MapLoader/MapLoader.component.tsx b/src/components/Map/MapLoader/MapLoader.component.tsx index a521a7f5..1e3b4e05 100644 --- a/src/components/Map/MapLoader/MapLoader.component.tsx +++ b/src/components/Map/MapLoader/MapLoader.component.tsx @@ -1,48 +1,16 @@ import { LoadingIndicator } from '@/shared/LoadingIndicator'; -import { useMemo } from 'react'; -import { newReactionsLoadingSelector } from '@/redux/newReactions/newReactions.selectors'; -import { modelElementsLoadingSelector } from '@/redux/modelElements/modelElements.selector'; -import { - arrowTypesLoadingSelector, - bioShapesLoadingSelector, - lineTypesLoadingSelector, -} from '@/redux/shapes/shapes.selectors'; -import { layersLoadingSelector } from '@/redux/layers/layers.selectors'; import './MapLoader.styles.css'; import { isDrawerOpenSelector } from '@/redux/drawer/drawer.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { modelLoadingSelector } from '@/redux/selectors'; export const MapLoader = (): JSX.Element => { - const reactionsFetching = useAppSelector(newReactionsLoadingSelector); - const modelElementsFetching = useAppSelector(modelElementsLoadingSelector); - const bioShapesFetching = useAppSelector(bioShapesLoadingSelector); - const lineTypesFetching = useAppSelector(lineTypesLoadingSelector); - const arrowTypesFetching = useAppSelector(arrowTypesLoadingSelector); - const layersLoading = useAppSelector(layersLoadingSelector); - + const isModelLoading = useAppSelector(modelLoadingSelector); const isDrawerOpen = useAppSelector(isDrawerOpenSelector); - const showLoader = useMemo(() => { - return [ - reactionsFetching, - modelElementsFetching, - bioShapesFetching, - lineTypesFetching, - arrowTypesFetching, - layersLoading, - ].includes('pending'); - }, [ - reactionsFetching, - modelElementsFetching, - bioShapesFetching, - lineTypesFetching, - arrowTypesFetching, - layersLoading, - ]); - return ( <div className={`map-loader transition-all duration-500 ${isDrawerOpen ? 'move-right' : ''}`}> - {showLoader && <LoadingIndicator width={48} height={48} />} + {isModelLoading && <LoadingIndicator width={48} height={48} />} </div> ); }; diff --git a/src/components/Map/MapViewer/MapViewer.constants.ts b/src/components/Map/MapViewer/MapViewer.constants.ts index 2d047265..e8492ee3 100644 --- a/src/components/Map/MapViewer/MapViewer.constants.ts +++ b/src/components/Map/MapViewer/MapViewer.constants.ts @@ -2,10 +2,20 @@ import { Color, ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models'; export const MAP_VIEWER_ROLE = 'map-viewer'; -export const VECTOR_MAP_LAYER_TYPE = 'vectorMapLayer'; +export const LAYER_TYPE = { + PROCESS_LAYER: 'PROCESS_LAYER', + COMMENTS_LAYER: 'COMMENTS_LAYER', + ADDITIONAL_LAYER: 'ADDITIONAL_LAYER', + MAP_CARD_LAYER: 'MAP_CARD_LAYER', + OVERLAYS_LAYER: 'OVERLAYS_LAYER', + PINS_LAYER: 'PINS_LAYER', + REACTIONS_LAYER: 'REACTIONS_LAYER', +} as const; export const COMPLEX_SBO_TERMS = ['SBO:0000253', 'SBO:0000297', 'SBO:0000289']; +export const COMPARTMENT_SBO_TERM = 'SBO:0000290'; + export const TEXT_CUTOFF_SCALE = 0.34; export const OUTLINE_CUTOFF_SCALE = 0.18; export const COMPLEX_CONTENTS_CUTOFF_SCALE = 0.215; diff --git a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts index 6eb9e2cb..7ac3b73b 100644 --- a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts @@ -11,6 +11,7 @@ import { } from '@/redux/comment/comment.selectors'; import { getCommentsFeatures } from '@/components/Map/MapViewer/utils/config/commentsLayer/getCommentsFeatures'; import { useMemo } from 'react'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; export const useOlMapCommentsLayer = (): VectorLayer<VectorSource<Feature<Geometry>>> => { const pointToProjection = usePointToProjection(); @@ -33,13 +34,11 @@ export const useOlMapCommentsLayer = (): VectorLayer<VectorSource<Feature<Geomet }); }, [elementsFeatures]); - const pinsLayer = useMemo( - () => - new VectorLayer({ - source: vectorSource, - }), - [vectorSource], - ); - - return pinsLayer; + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + }); + vectorLayer.set('type', LAYER_TYPE.COMMENTS_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts index e1fb741b..69cec807 100644 --- a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts +++ b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts @@ -8,6 +8,7 @@ import { mapDataSizeSelector } from '@/redux/map/map.selectors'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; import Style from 'ol/style/Style'; import { Fill } from 'ol/style'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; export const useOlMapCardLayer = (): VectorLayer<VectorSource<Feature<Polygon>>> => { const mapSize = useSelector(mapDataSizeSelector); @@ -35,16 +36,16 @@ export const useOlMapCardLayer = (): VectorLayer<VectorSource<Feature<Polygon>>> }); }, [rectangleFeature]); - return useMemo( - () => - new VectorLayer({ - source: vectorSource, - style: new Style({ - fill: new Fill({ - color: '#fff', - }), + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + style: new Style({ + fill: new Fill({ + color: '#fff', }), }), - [vectorSource], - ); + }); + vectorLayer.set('type', LAYER_TYPE.MAP_CARD_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts index 788b89f2..7a0643c5 100644 --- a/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts @@ -10,6 +10,9 @@ import { OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK, } from '@/redux/overlayBioEntity/overlayBioEntity.mock'; import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock'; +import { MAIN_MAP_ID } from '@/constants/mocks'; +import { BIO_ENTITY_LINKING_TO_SUBMAP } from '@/redux/bioEntity/bioEntity.mock'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { useBioEntitiesWithSubmapsLinks } from './useBioEntitiesWithSubmapLinks'; const RESULT_SUBMAP_LINKS_DIFFERENT_VALUES = [ @@ -180,6 +183,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { overlaysId: PUBLIC_OVERLAYS_MOCK.map(o => o.idObject), }, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, + modelElements: { + [MAIN_MAP_ID]: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, map: mapStateWithCurrentlySelectedMainMapFixture, }); @@ -203,6 +213,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, }, + modelElements: { + 52: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -233,6 +250,7 @@ describe('useBioEntitiesWithSubmapsLinks', () => { color: null, }); }); + it('should modify height, coordinates and return in sorted order to create submap link from several submap link rectangles', () => { const { Wrapper } = getReduxStoreWithActionsListener({ overlayBioEntity: { @@ -243,6 +261,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, }, + modelElements: { + 52: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -260,6 +285,7 @@ describe('useBioEntitiesWithSubmapsLinks', () => { expect(current).toStrictEqual(RESULT_SUBMAP_LINKS_DIFFERENT_VALUES); }); }); + describe('submap links with the same ID and overlayID and the same values or colors', () => { it('should create submap link with Infinity value, for displaying black border of submap link', () => { const { Wrapper } = getReduxStoreWithActionsListener({ @@ -271,6 +297,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, }, + modelElements: { + 52: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -301,6 +334,7 @@ describe('useBioEntitiesWithSubmapsLinks', () => { color: null, }); }); + it('should modify height, coordinates and return in sorted order to create submap link from several submap link rectangles', () => { const { Wrapper } = getReduxStoreWithActionsListener({ overlayBioEntity: { @@ -311,6 +345,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, }, + modelElements: { + 52: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer.ts index 9d3489b4..c24250e2 100644 --- a/src/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer.ts +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer.ts @@ -3,6 +3,7 @@ import VectorLayer from 'ol/layer/Vector'; import VectorSource from 'ol/source/Vector'; import { Feature } from 'ol'; import { useMemo } from 'react'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { useOverlayFeatures } from './useOverlayFeatures'; /** @@ -28,13 +29,11 @@ export const useOlMapOverlaysLayer = (): VectorLayer<VectorSource<Feature<Simple }); }, [overlaysFeatures]); - const overlaysLayer = useMemo( - () => - new VectorLayer({ - source: vectorSource, - }), - [vectorSource], - ); - - return overlaysLayer; + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + }); + vectorLayer.set('type', LAYER_TYPE.OVERLAYS_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts index 641b537d..c2e6d908 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts @@ -13,6 +13,7 @@ import VectorLayer from 'ol/layer/Vector'; import VectorSource from 'ol/source/Vector'; import { useCallback, useEffect, useMemo } from 'react'; import { useSelector } from 'react-redux'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { getBioEntitiesFeatures } from './getBioEntitiesFeatures'; import { getMarkersFeatures } from './getMarkersFeatures'; import { getMultipinsBioEntities } from './getMultipinsBioEntities'; @@ -74,11 +75,11 @@ export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>> vectorSource.addFeatures(elementsFeatures); }, [elementsFeatures, vectorSource]); - return useMemo( - () => - new VectorLayer({ - source: vectorSource, - }), - [vectorSource], - ); + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + }); + vectorLayer.set('type', LAYER_TYPE.PINS_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts index 87c6d666..b4c0b876 100644 --- a/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts @@ -13,6 +13,7 @@ import CompartmentPathway from '@/components/Map/MapViewer/utils/shapes/elements import CompartmentSquare from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare'; import CompartmentCircle from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle'; import MapElement from '@/components/Map/MapViewer/utils/shapes/elements/MapElement'; +import { COMPARTMENT_SBO_TERM } from '@/components/Map/MapViewer/MapViewer.constants'; export default function processModelElements( modelElements: Array<ModelElement>, @@ -49,7 +50,7 @@ export default function processModelElements( return; } - if (element.sboTerm === 'SBO:0000290') { + if (element.sboTerm === COMPARTMENT_SBO_TERM) { const compartmentProps = { id: element.id, sboTerm: element.sboTerm, diff --git a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts index 2837c80b..2811ec30 100644 --- a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts @@ -13,9 +13,9 @@ import { import { MapInstance } from '@/types/map'; import { modelElementsForCurrentModelSelector, - modelElementsLoadingSelector, + modelElementsCurrentModelLoadingSelector, } from '@/redux/modelElements/modelElements.selector'; -import { currentModelIdSelector } from '@/redux/models/models.selectors'; +import { currentModelIdSelector, modelsIdsSelector } from '@/redux/models/models.selectors'; import { getModelElementsForModel } from '@/redux/modelElements/modelElements.thunks'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { @@ -23,7 +23,6 @@ import { newReactionsLoadingSelector, } from '@/redux/newReactions/newReactions.selectors'; import { getNewReactionsForModel } from '@/redux/newReactions/newReactions.thunks'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { getOverlayOrderSelector, overlayBioEntitiesForCurrentModelSelector, @@ -48,6 +47,8 @@ import CompartmentCircle from '@/components/Map/MapViewer/utils/shapes/elements/ import CompartmentSquare from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare'; import MapElement from '@/components/Map/MapViewer/utils/shapes/elements/MapElement'; import areOverlayOrdersNotEqual from '@/components/Map/MapViewer/utils/shapes/overlay/areOverlayOrdersNotEqual'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { modelLoadedSuccessfullySelector, modelLoadingSelector } from '@/redux/selectors'; export const useOlMapProcessLayer = ({ mapInstance, @@ -57,6 +58,7 @@ export const useOlMapProcessLayer = ({ const dispatch = useAppDispatch(); const [overlaysOrderState, setOverlaysOrderState] = useState<Array<OverlayOrder>>([]); + const [allModelElementsLoaded, setAllModelElementsLoaded] = useState<boolean>(false); const currentModelId = useSelector(currentModelIdSelector); const shapes = useSelector(bioShapesSelector); const mapSize = useSelector(mapDataSizeSelector); @@ -71,13 +73,38 @@ export const useOlMapProcessLayer = ({ const bioEntities = useAppSelector(overlayBioEntitiesForCurrentModelSelector); const reactionsForCurrentModel = useAppSelector(newReactionsForCurrentModelSelector); - const modelElementsLoading = useAppSelector(modelElementsLoadingSelector); + const modelElementsLoading = useAppSelector(modelElementsCurrentModelLoadingSelector); const reactionsLoading = useAppSelector(newReactionsLoadingSelector); const modelElementsForCurrentModel = useAppSelector(modelElementsForCurrentModelSelector); const debouncedBioEntities = useDebouncedValue(bioEntities, 1000); const { getOverlayBioEntityColorByAvailableProperties } = useGetOverlayColor(); + const modelsIds = useAppSelector(modelsIdsSelector); + const isModelLoading = useAppSelector(modelLoadingSelector); + const modelLoadedSuccessfully = useAppSelector(modelLoadedSuccessfullySelector); + useEffect(() => { + const fetchModelElements = async (): Promise<void> => { + if (!isModelLoading && modelLoadedSuccessfully && !allModelElementsLoaded) { + const modelsIdsToFetch = modelsIds.filter(id => id !== currentModelId); + const modelElementsPromises = modelsIdsToFetch.map(modelId => { + return dispatch(getModelElementsForModel(modelId)); + }); + await Promise.all(modelElementsPromises); + setAllModelElementsLoaded(true); + } + }; + + fetchModelElements(); + }, [ + modelLoadedSuccessfully, + isModelLoading, + modelsIds, + currentModelId, + dispatch, + allModelElementsLoaded, + ]); + const pointToProjection = usePointToProjection(); const vectorSource = useMemo(() => new VectorSource(), []); @@ -251,7 +278,7 @@ export const useOlMapProcessLayer = ({ updateWhileAnimating: true, updateWhileInteracting: true, }); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); return vectorLayer; }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts index cf4416f3..bfb2668e 100644 --- a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts @@ -16,6 +16,7 @@ import { useSelector } from 'react-redux'; import { createOverlayLineFeature } from '@/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayLineFeature'; import { Geometry } from 'ol/geom'; import { getReactionLineSegments } from '@/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { getLineFeature } from './getLineFeature'; const getReactionsLines = (reactions: NewReaction[]): LinePoint[] => @@ -60,15 +61,15 @@ export const useOlMapReactionsLayer = (): VectorLayer<VectorSource<Feature<Geome vectorSource.addFeatures(markerLinesFeatures); }, [reactionsLinesFeatures, markerLinesFeatures, vectorSource]); - return useMemo( - () => - new VectorLayer({ - source: vectorSource, - style: new Style({ - fill: new Fill({ color: LINE_COLOR }), - stroke: new Stroke({ color: LINE_COLOR, width: LINE_WIDTH }), - }), + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + style: new Style({ + fill: new Fill({ color: LINE_COLOR }), + stroke: new Stroke({ color: LINE_COLOR, width: LINE_WIDTH }), }), - [vectorSource], - ); + }); + vectorLayer.set('type', LAYER_TYPE.REACTIONS_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts index d809149e..ef42a0aa 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts @@ -2,14 +2,9 @@ import { openReactionDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; -import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; -import { apiPath } from '@/redux/apiPath'; -import { HttpStatusCode } from 'axios'; -import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; -const mockedAxiosClient = mockNetworkNewAPIResponse(); jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); const eventBusDispatchEventSpy = jest.spyOn(PluginsEventBus, 'dispatchEvent'); @@ -24,7 +19,7 @@ describe('clickHandleReaction', () => { dispatch = jest.fn(); }); - it('dispatches getMultiBioEntityByIds, selectTab, and openBioEntityDrawerById, then triggers PluginsEventBus and searchFitBounds when hasFitBounds is true', async () => { + it('dispatches selectTab and openBioEntityDrawerById, then triggers PluginsEventBus and searchFitBounds when hasFitBounds is true', async () => { dispatch = jest.fn(() => { return { unwrap: jest.fn().mockResolvedValue([]), @@ -36,19 +31,6 @@ describe('clickHandleReaction', () => { reactionId = newReactionFixture.id; modelId = newReactionFixture.model; - mockedAxiosClient - .onGet(apiPath.getNewReaction(modelId, reactionId)) - .reply(HttpStatusCode.Ok, bioEntityFixture); - - [ - ...newReactionFixture.products, - ...newReactionFixture.reactants, - ...newReactionFixture.modifiers, - ].forEach(element => { - mockedAxiosClient - .onGet(apiPath.getElementById(element.element, modelId)) - .reply(HttpStatusCode.Ok, bioEntityFixture); - }); clickHandleReaction(dispatch, hasFitBounds)( [], [{ ...newReactionFixture, id: reactionId }], diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts index edc575be..34e57854 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts @@ -2,7 +2,7 @@ import { Feature } from 'ol'; import VectorLayer from 'ol/layer/Vector'; import Map from 'ol/Map'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { FEATURE_TYPE } from '@/constants/features'; import getFeatureAtCoordinate from '@/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate'; import SimpleGeometry from 'ol/geom/SimpleGeometry'; @@ -11,7 +11,7 @@ describe('getFeatureAtCoordinate', () => { let mapInstance: Map; const coordinate = [100, 50]; const vectorLayer = new VectorLayer({}); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); beforeEach(() => { const dummyElement = document.createElement('div'); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts index 5c1fc99e..88417316 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts @@ -1,9 +1,9 @@ /* eslint-disable no-magic-numbers */ -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { MapInstance } from '@/types/map'; import { Coordinate } from 'ol/coordinate'; import { FeatureLike } from 'ol/Feature'; import { FEATURE_TYPE } from '@/constants/features'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; function isFeatureFilledCompartment(feature: FeatureLike): boolean { return feature.get('type') === FEATURE_TYPE.COMPARTMENT && feature.get('filled'); @@ -37,7 +37,7 @@ export default function getFeatureAtCoordinate({ const featureZIndex = feature.get('zIndex'); if ( layer && - layer.get('type') === VECTOR_MAP_LAYER_TYPE && + layer.get('type') !== LAYER_TYPE.ADDITIONAL_LAYER && (isFeatureFilledCompartment(feature) || isFeatureNotCompartment(feature)) && (featureZIndex === undefined || featureZIndex >= 0) ) { diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts index f1b980a9..ad75ed8f 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts @@ -9,7 +9,6 @@ import { AppDispatch } from '@/redux/store'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { FeatureLike } from 'ol/Feature'; import { Comment } from '@/types/models'; -import { getCommentElement, getCommentReaction } from '@/redux/comment/thunks/getComments'; interface HandleFeaturesClickResult { shouldBlockCoordSearch: boolean; @@ -23,22 +22,18 @@ export const handleFeaturesClick = ( const pinFeatures = features.filter(feature => PIN_ICON_ANY.includes(feature.get('type'))); const surfaceFeatures = features.filter(feature => SURFACE_ANY.includes(feature.get('type'))); const shouldBlockCoordSearch = pinFeatures.length > SIZE_OF_EMPTY_ARRAY; - pinFeatures.forEach(pin => { const pinId = pin.get('id') as string | number; PluginsEventBus.dispatchEvent('onPinIconClick', { id: pinId }); - if (pin.get('type') === FEATURE_TYPE.PIN_ICON_BIOENTITY) { dispatch(openBioEntityDrawerById(pinId)); } else if (pin.get('type') === FEATURE_TYPE.PIN_ICON_COMMENT) { const filteredComments = comments.filter(comment => comment.id === pinId); if (filteredComments.length > ZERO) { - const { elementId, modelId, type } = filteredComments[ZERO]; + const { elementId, type } = filteredComments[ZERO]; if (type === 'ALIAS') { - dispatch(getCommentElement({ elementId: Number(elementId), modelId })); dispatch(openBioEntityDrawerById(Number(elementId))); } else if (type === 'REACTION') { - dispatch(getCommentReaction({ elementId: Number(elementId), modelId })); dispatch(openReactionDrawerById(Number(elementId))); } else if (type === 'POINT') { dispatch(openCommentDrawerById(Number(pinId))); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts index df86f0a2..17b253ef 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts @@ -5,6 +5,7 @@ import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; import { Feature } from 'ol'; import { FEATURE_TYPE } from '@/constants/features'; +import { ModelElement } from '@/types/models'; jest.mock('../../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); const eventBusDispatchEventSpy = jest.spyOn(PluginsEventBus, 'dispatchEvent'); @@ -21,13 +22,13 @@ describe('leftClickHandleAlias', () => { }); it('dispatches getMultiBioEntityByIds, selectTab, and openBioEntityDrawerById, then triggers PluginsEventBus and searchFitBounds when hasFitBounds is true', async () => { - const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }]; + const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }] as Array<ModelElement>; dispatch = jest.fn(() => ({ unwrap: jest.fn().mockResolvedValue(mockBioEntities), })); - await leftClickHandleAlias(dispatch, hasFitBounds)(feature, modelId); - expect(dispatch).toHaveBeenCalledTimes(3); + await leftClickHandleAlias(dispatch, hasFitBounds)(mockBioEntities, feature, modelId); + expect(dispatch).toHaveBeenCalledTimes(4); expect(dispatch).toHaveBeenCalledWith(selectTab('1')); expect(dispatch).toHaveBeenCalledWith(openBioEntityDrawerById(1)); @@ -47,12 +48,12 @@ describe('leftClickHandleAlias', () => { }); it('does not call searchFitBounds when hasFitBounds is false', async () => { - const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }]; + const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }] as Array<ModelElement>; dispatch.mockImplementation(() => ({ unwrap: jest.fn().mockResolvedValue(mockBioEntities), })); - await leftClickHandleAlias(dispatch, false)(feature, modelId); + await leftClickHandleAlias(dispatch, false)(mockBioEntities, feature, modelId); expect(searchFitBounds).not.toHaveBeenCalled(); }); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts index 06a4e4d1..4abbb3e1 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts @@ -1,32 +1,40 @@ import { openBioEntityDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; import { AppDispatch } from '@/redux/store'; -import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEntity'; import { FeatureLike } from 'ol/Feature'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; import { FEATURE_TYPE } from '@/constants/features'; +import { ModelElement } from '@/types/models'; +import { setMultipleBioEntityContents } from '@/redux/bioEntity/bioEntity.slice'; +import { addNumbersToEntityNumberData } from '@/redux/entityNumber/entityNumber.slice'; /* prettier-ignore */ export const leftClickHandleAlias = (dispatch: AppDispatch, hasFitBounds = false) => - async (feature: FeatureLike, modelId: number): Promise<void> => { + async (modelElements: Array<ModelElement>, feature: FeatureLike, modelId: number): Promise<void> => { const id = feature.get('id'); - const bioEntities = await dispatch( - getMultiBioEntityByIds({ - elementsToFetch: [{ elementId: id, type: FEATURE_TYPE.ALIAS, modelId, addNumbersToEntityNumber: true }], - }), - ).unwrap(); + + const modelElement = modelElements.find(element => + element.id === id + ); + if(!modelElement) { + return; + } + dispatch(selectTab(`${id}`)); dispatch(openBioEntityDrawerById(id)); + dispatch(setMultipleBioEntityContents([modelElement])); + dispatch(addNumbersToEntityNumberData([modelElement.elementId])); + const searchValue = { id, modelId, type: FEATURE_TYPE.ALIAS }; PluginsEventBus.dispatchEvent('onSearch', { type: 'bioEntity', searchValues: [searchValue], - results: [ - bioEntities.map(bioEntity => { - return { perfect: true, bioEntity }; - }), + results: [[{ + perfect: true, + bioEntity: modelElement + }] ], }); PluginsEventBus.dispatchEvent('onBioEntityClick', searchValue); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts index deb19107..6cf59664 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts @@ -11,7 +11,7 @@ import SimpleGeometry from 'ol/geom/SimpleGeometry'; import { Feature } from 'ol'; import { FEATURE_TYPE } from '@/constants/features'; import VectorLayer from 'ol/layer/Vector'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import * as leftClickHandleAlias from './leftClickHandleAlias'; import * as clickHandleReaction from '../clickHandleReaction'; @@ -35,7 +35,7 @@ describe('onMapLeftClick', () => { const comments: Array<Comment> = []; let mapInstance: Map; const vectorLayer = new VectorLayer({}); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); const event = { coordinate: [100, 50], pixel: [200, 100] }; const mapSize = { width: 90, diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts index 0c01e4a2..c62b97bf 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts @@ -59,7 +59,7 @@ export const onMapLeftClick = const type = featureAtCoordinate.get('type'); const id = featureAtCoordinate.get('id'); if ([FEATURE_TYPE.ALIAS, FEATURE_TYPE.GLYPH, FEATURE_TYPE.COMPARTMENT].includes(type)) { - await leftClickHandleAlias(dispatch)(featureAtCoordinate, modelId); + await leftClickHandleAlias(dispatch)(modelElements, featureAtCoordinate, modelId); } else if (type === FEATURE_TYPE.REACTION) { clickHandleReaction(dispatch)(modelElements, reactions, id, modelId); } diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts index fa6a3f17..de2c8849 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts @@ -11,7 +11,7 @@ import { Feature } from 'ol'; import { FEATURE_TYPE } from '@/constants/features'; import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import * as rightClickHandleAlias from './rightClickHandleAlias'; import * as clickHandleReaction from '../clickHandleReaction'; @@ -47,7 +47,7 @@ describe('onMapRightClick', () => { vectorLayer = new VectorLayer({ source: vectorSource, }); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); jest.clearAllMocks(); }); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts index 0daefedd..68658424 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts @@ -13,7 +13,7 @@ import { openContextMenu } from '@/redux/contextMenu/contextMenu.slice'; import { ModelElement, NewReaction } from '@/types/models'; import { rightClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias'; import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; /* prettier-ignore */ export const onMapRightClick = @@ -29,7 +29,7 @@ export const onMapRightClick = let foundFeature: Feature | undefined; mapInstance.getAllLayers().forEach(layer => { if(layer.isVisible() && layer instanceof VectorLayer) { - if (layer.get('type') === VECTOR_MAP_LAYER_TYPE) { + if (layer.get('type') === LAYER_TYPE.PROCESS_LAYER) { const source = layer.getSource(); if (source instanceof VectorSource) { foundFeature = source.getClosestFeatureToCoordinate(coordinate, (feature) => { diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts index ed6acbf4..b9070811 100644 --- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts @@ -13,6 +13,7 @@ import Style from 'ol/style/Style'; import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types'; import { LAYER_ELEMENT_TYPES, + LAYER_TYPE, REACTION_ELEMENT_CUTOFF_SCALE, TRANSPARENT_COLOR, } from '@/components/Map/MapViewer/MapViewer.constants'; @@ -116,6 +117,7 @@ export default class Layer { updateWhileAnimating: true, updateWhileInteracting: true, }); + this.vectorLayer.set('type', LAYER_TYPE.ADDITIONAL_LAYER); this.vectorLayer.set('id', layerId); this.vectorLayer.set('imagesFeatures', imagesFeatures); diff --git a/src/models/bioEntitySchema.ts b/src/models/bioEntitySchema.ts index db8670b8..a52c3aff 100644 --- a/src/models/bioEntitySchema.ts +++ b/src/models/bioEntitySchema.ts @@ -51,7 +51,7 @@ export const bioEntitySchema = z.object({ initialAmount: z.number().nullable().optional(), initialConcentration: z.number().nullable().optional(), charge: z.number().nullable().optional(), - substanceUnits: z.string().nullable().optional(), + substanceUnits: z.boolean().nullable().optional(), onlySubstanceUnits: z.boolean().optional().nullable(), shape: z.string().nullable().optional(), modificationResidues: z.optional(z.array(modificationResiduesSchema)), diff --git a/src/models/compartmentPathwaySchema.ts b/src/models/compartmentPathwaySchema.ts deleted file mode 100644 index 1259fa87..00000000 --- a/src/models/compartmentPathwaySchema.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { z } from 'zod'; - -export const compartmentPathwaySchema = z.object({ - id: z.number(), -}); - -export const boundsSchema = z.object({ - height: z.number(), - width: z.number(), - x: z.number(), - y: z.number(), - z: z.number(), -}); - -export const otherSchema = z.object({ - modifications: z.array(z.unknown()), - structuralState: z.null(), - structures: z.object({}), -}); - -export const compartmentPathwayDetailsSchema = z.object({ - abbreviation: z.null(), - activity: z.null(), - boundaryCondition: z.null(), - bounds: boundsSchema, - compartmentId: z.number().nullable(), - complexId: z.null(), - constant: z.null(), - elementId: z.string(), - formerSymbols: z.array(z.unknown()), - formula: z.null(), - fullName: z.string().nullable(), - glyph: z.any(), - hierarchyVisibilityLevel: z.string().nullable(), - homomultimer: z.null(), - hypothetical: z.null(), - id: z.number().gt(-1), - initialAmount: z.null(), - initialConcentration: z.null(), - linkedSubmodel: z.null(), - modelId: z.number(), - name: z.string(), - notes: z.string(), - other: otherSchema, - references: z.array(z.unknown()), - symbol: z.null(), - synonyms: z.array(z.unknown()), - transparencyLevel: z.string(), - type: z.string(), -}); diff --git a/src/models/fixtures/compartmentPathways.ts b/src/models/fixtures/compartmentPathways.ts deleted file mode 100644 index c93b4dc0..00000000 --- a/src/models/fixtures/compartmentPathways.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ZOD_SEED } from '@/constants'; -// eslint-disable-next-line import/no-extraneous-dependencies -import { createFixture } from 'zod-fixture'; -import { z } from 'zod'; -import { - compartmentPathwayDetailsSchema, - compartmentPathwaySchema, -} from '../compartmentPathwaySchema'; - -export const compartmentPathwaysFixture = createFixture(z.array(compartmentPathwaySchema), { - seed: ZOD_SEED, - array: { min: 3, max: 3 }, -}); - -export const compartmentPathwaysOverLimitFixture = createFixture( - z.array(compartmentPathwaySchema), - { - seed: ZOD_SEED, - array: { min: 101, max: 101 }, - }, -); - -export const compartmentPathwaysDetailsFixture = createFixture( - z.array(compartmentPathwayDetailsSchema), - { - seed: ZOD_SEED, - array: { min: 3, max: 3 }, - }, -); diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index 9f81dab4..93d49308 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -19,9 +19,6 @@ const getPublicationsURLSearchParams = ( }; export const apiPath = { - getElementById: (elementId: number, modelId: number): string => - `projects/${PROJECT_ID}/models/${modelId}/bioEntities/elements/${elementId}`, - getBioEntityContentsStringWithQuery: ({ searchQuery, isPerfectMatch, @@ -93,11 +90,6 @@ export const apiPath = { createOverlayFile: (): string => `files/`, uploadOverlayFileContent: (fileId: number): string => `files/${fileId}:uploadContent`, getStatisticsById: (projectId: string): string => `projects/${projectId}/statistics/`, - getCompartmentPathwaysIds: (objectId: number): string => - `projects/${PROJECT_ID}/models/${objectId}/bioEntities/elements/?columns=id&type=Compartment,Pathway`, - getCompartmentPathwayDetails: (ids: number[]): string => - `projects/${PROJECT_ID}/models/*/bioEntities/elements/?id=${ids.join(',')}`, - sendCompartmentPathwaysIds: (): string => `projects/${PROJECT_ID}/models/*/bioEntities/elements/`, downloadNetworkCsv: (): string => `projects/${PROJECT_ID}/models/*/bioEntities/reactions/:downloadCsv`, getAllUserOverlaysByCreatorQuery: ({ diff --git a/src/redux/bioEntity/bioEntity.reducers.ts b/src/redux/bioEntity/bioEntity.reducers.ts index bab876f9..b24e17c1 100644 --- a/src/redux/bioEntity/bioEntity.reducers.ts +++ b/src/redux/bioEntity/bioEntity.reducers.ts @@ -1,11 +1,8 @@ import { DEFAULT_ERROR } from '@/constants/errors'; import { ActionReducerMapBuilder, PayloadAction } from '@reduxjs/toolkit'; -import { getBioEntityById } from '@/redux/bioEntity/thunks/getBioEntity'; import { BioEntity, BioEntityContent } from '@/types/models'; -import { BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE } from './bioEntity.constants'; import { getBioEntity, getMultiBioEntity } from './bioEntity.thunks'; import { BioEntityContentsState } from './bioEntity.types'; -import { getSubmapConnectionsBioEntity } from './thunks/getSubmapConnectionsBioEntity'; export const getBioEntityContentsReducer = ( builder: ActionReducerMapBuilder<BioEntityContentsState>, @@ -18,14 +15,6 @@ export const getBioEntityContentsReducer = ( error: DEFAULT_ERROR, }); }); - builder.addCase(getBioEntityById.pending, (state, action) => { - state.data.push({ - searchQueryElement: `${action.meta.arg.elementId}`, - data: undefined, - loading: 'pending', - error: DEFAULT_ERROR, - }); - }); builder.addCase(getBioEntity.fulfilled, (state, action) => { const bioEntities = state.data.find( bioEntity => bioEntity.searchQueryElement === action.meta.arg.searchQuery, @@ -35,15 +24,6 @@ export const getBioEntityContentsReducer = ( bioEntities.loading = 'succeeded'; } }); - builder.addCase(getBioEntityById.fulfilled, (state, action) => { - const bioEntities = state.data.find( - bioEntity => bioEntity.searchQueryElement === `${action.meta.arg.elementId}`, - ); - if (bioEntities) { - bioEntities.data = action.payload ? [{ perfect: true, bioEntity: action.payload }] : []; - bioEntities.loading = 'succeeded'; - } - }); builder.addCase(getBioEntity.rejected, (state, action) => { const bioEntities = state.data.find( bioEntity => bioEntity.searchQueryElement === action.meta.arg.searchQuery, @@ -53,15 +33,6 @@ export const getBioEntityContentsReducer = ( // TODO: error management to be discussed in the team } }); - builder.addCase(getBioEntityById.rejected, (state, action) => { - const bioEntities = state.data.find( - bioEntity => bioEntity.searchQueryElement === `${action.meta.arg.elementId}`, - ); - if (bioEntities) { - bioEntities.loading = 'failed'; - // TODO: error management to be discussed in the team - } - }); }; export const getMultiBioEntityContentsReducer = ( @@ -80,34 +51,6 @@ export const getMultiBioEntityContentsReducer = ( }); }; -export const getSubmapConnectionsBioEntityReducer = ( - builder: ActionReducerMapBuilder<BioEntityContentsState>, -): void => { - builder.addCase(getSubmapConnectionsBioEntity.pending, state => { - state.submapConnections = { - ...BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE, - ...(state?.submapConnections ? state?.submapConnections : {}), - data: [], - loading: 'pending', - }; - }); - builder.addCase(getSubmapConnectionsBioEntity.fulfilled, (state, action) => { - state.submapConnections = { - ...BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE, - ...(state?.submapConnections ? state?.submapConnections : {}), - data: action.payload, - loading: 'succeeded', - }; - }); - builder.addCase(getSubmapConnectionsBioEntity.rejected, state => { - state.submapConnections = { - ...BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE, - ...(state?.submapConnections ? state?.submapConnections : {}), - loading: 'failed', - }; - }); -}; - export const clearBioEntitiesReducer = (state: BioEntityContentsState): void => { state.data = []; state.loading = 'idle'; diff --git a/src/redux/bioEntity/bioEntity.selectors.ts b/src/redux/bioEntity/bioEntity.selectors.ts index eb4e8f21..d9c63a0a 100644 --- a/src/redux/bioEntity/bioEntity.selectors.ts +++ b/src/redux/bioEntity/bioEntity.selectors.ts @@ -1,29 +1,25 @@ import { ONE, SIZE_OF_EMPTY_ARRAY, ZERO } from '@/constants/common'; -import { - allCommentsSelectorOfCurrentMap, - commentElementSelector, -} from '@/redux/comment/comment.selectors'; -import { currentDrawerReactionSelector } from '@/redux/reactions/reactions.selector'; +import { allCommentsSelectorOfCurrentMap } from '@/redux/comment/comment.selectors'; import { rootSelector } from '@/redux/root/root.selectors'; import { BioEntityWithPinType } from '@/types/bioEntity'; import { ElementIdTabObj } from '@/types/elements'; import { MultiSearchData } from '@/types/fetchDataState'; -import { BioEntity, BioEntityContent, Comment, MapModel } from '@/types/models'; +import { BioEntity, BioEntityContent, Comment, MapModel, ModelElement } from '@/types/models'; import { createSelector } from '@reduxjs/toolkit'; import { - allChemicalsBioEntitesOfAllMapsSelector, + currentDrawerModelElementSelector, + modelElementsWithSubmapConnectionForCurrentModelSelector, +} from '@/redux/modelElements/modelElements.selector'; +import { currentDrawerNewReactionSelector } from '@/redux/newReactions/newReactions.selectors'; +import { allChemicalsBioEntitesOfCurrentMapSelector, allChemicalsIdTabSelectorOfCurrentMap, chemicalsBioEntitiesForSelectedSearchElementSelector, searchedChemicalsBioEntitesOfCurrentMapSelector, } from '../chemicals/chemicals.selectors'; import { currentSelectedBioEntityIdSelector } from '../contextMenu/contextMenu.selector'; +import { currentSelectedSearchElement } from '../drawer/drawer.selectors'; import { - currentSearchedBioEntityId, - currentSelectedSearchElement, -} from '../drawer/drawer.selectors'; -import { - allDrugsBioEntitesOfAllMapsSelector, allDrugsBioEntitesOfCurrentMapSelector, allDrugsIdTabSelectorOfCurrentMap, drugsBioEntitiesForSelectedSearchElementSelector, @@ -49,15 +45,10 @@ export const bioEntityDataListSelector = createSelector(bioEntityDataSelector, b bioEntityData.map(b => b.data || []).flat(), ); -export const allSubmapConnectionsBioEntitySelector = createSelector( - bioEntitySelector, - (bioEntityData): BioEntity[] => bioEntityData?.submapConnections?.data || [], -); - export const allSubmapConnectionsBioEntityOfCurrentSubmapSelector = createSelector( - allSubmapConnectionsBioEntitySelector, + modelElementsWithSubmapConnectionForCurrentModelSelector, currentModelIdSelector, - (submapConnectionsBioEntity, currentModel): BioEntity[] => + (submapConnectionsBioEntity, currentModel): ModelElement[] => submapConnectionsBioEntity.filter(({ model }) => model === currentModel), ); @@ -70,14 +61,6 @@ export const bioEntitiesForSelectedSearchElement = createSelector( ), ); -export const searchedFromMapBioEntityElement = createSelector( - bioEntitiesForSelectedSearchElement, - currentSearchedBioEntityId, - (bioEntitiesState, currentBioEntityId): BioEntity | undefined => - bioEntitiesState && - bioEntitiesState.data?.find(({ bioEntity }) => bioEntity.id === currentBioEntityId)?.bioEntity, -); - export const searchedBioEntityElementForContextMapSelector = createSelector( bioEntitySelector, currentSelectedBioEntityIdSelector, @@ -95,13 +78,6 @@ export const searchedBioEntityElementUniProtIdSelector = createSelector( }, ); -export const searchedFromMapBioEntityElementRelatedSubmapSelector = createSelector( - searchedFromMapBioEntityElement, - modelsDataSelector, - (bioEntity, models): MapModel | undefined => - models.find(({ id }) => id === bioEntity?.submodel?.mapId), -); - export const loadingBioEntityStatusSelector = createSelector( bioEntitiesForSelectedSearchElement, state => state?.loading, @@ -226,30 +202,6 @@ export const allElementsForSearchElementNumberByModelId = createSelector( }, ); -export const allContentBioEntitesSelectorOfAllMaps = createSelector( - bioEntitySelector, - (bioEntities): BioEntity[] => { - if (!bioEntities) { - return []; - } - - return (bioEntities?.data || []) - .map(({ data }) => data || []) - .flat() - .map(({ bioEntity }) => bioEntity); - }, -); - -export const allBioEntitiesSelector = createSelector( - allContentBioEntitesSelectorOfAllMaps, - allChemicalsBioEntitesOfAllMapsSelector, - allDrugsBioEntitesOfAllMapsSelector, - allSubmapConnectionsBioEntitySelector, - (content, chemicals, drugs, submapConnections): BioEntity[] => { - return [content, chemicals, drugs, submapConnections].flat(); - }, -); - export const allBioEntitiesElementsIdsSelector = createSelector( allBioEntitesIdTabSelectorOfCurrentMap, allChemicalsIdTabSelectorOfCurrentMap, @@ -263,20 +215,8 @@ export const allBioEntitiesElementsIdsSelector = createSelector( }, ); -export const currentDrawerBioEntitySelector = createSelector( - allBioEntitiesSelector, - commentElementSelector, - currentSearchedBioEntityId, - (bioEntities, commentElement, currentBioEntityId): BioEntity | undefined => { - if (commentElement && commentElement.id === currentBioEntityId) { - return commentElement; - } - return bioEntities.find(({ id }) => id === currentBioEntityId); - }, -); - export const currentDrawerBioEntityRelatedSubmapSelector = createSelector( - currentDrawerBioEntitySelector, + currentDrawerModelElementSelector, modelsDataSelector, (bioEntity, models): MapModel | undefined => models.find(({ id }) => id === bioEntity?.submodel?.mapId), @@ -286,7 +226,7 @@ export const allSubmapConnectionsBioEntityOfCurrentSubmapWithRealConnectionsSele createSelector( allSubmapConnectionsBioEntityOfCurrentSubmapSelector, allElementsForSearchElementNumberByModelId, - (submapConnectionsBioEntity, modelElementsNumber): BioEntity[] => { + (submapConnectionsBioEntity, modelElementsNumber): ModelElement[] => { return submapConnectionsBioEntity.filter( ({ submodel }) => submodel && modelElementsNumber?.[submodel.mapId] > ZERO, ); @@ -317,7 +257,7 @@ export const allVisibleBioEntitiesIdsSelector = createSelector( ); export const currentDrawerElementCommentsSelector = createSelector( - currentDrawerBioEntitySelector, + currentDrawerModelElementSelector, allCommentsSelectorOfCurrentMap, (element, comments): Comment[] => { if (element) { @@ -333,7 +273,7 @@ export const currentDrawerElementCommentsSelector = createSelector( ); export const currentDrawerReactionCommentsSelector = createSelector( - currentDrawerReactionSelector, + currentDrawerNewReactionSelector, allCommentsSelectorOfCurrentMap, (reaction, comments): Comment[] => { if (reaction) { diff --git a/src/redux/bioEntity/bioEntity.slice.ts b/src/redux/bioEntity/bioEntity.slice.ts index 74dcffaa..8e40b023 100644 --- a/src/redux/bioEntity/bioEntity.slice.ts +++ b/src/redux/bioEntity/bioEntity.slice.ts @@ -4,7 +4,6 @@ import { clearBioEntitiesReducer, getBioEntityContentsReducer, getMultiBioEntityContentsReducer, - getSubmapConnectionsBioEntityReducer, setBioEntityContentsReducer, setMultipleBioEntityContentsReducer, toggleIsContentTabOpenedReducer, @@ -22,7 +21,6 @@ export const bioEntityContentsSlice = createSlice({ extraReducers: builder => { getBioEntityContentsReducer(builder); getMultiBioEntityContentsReducer(builder); - getSubmapConnectionsBioEntityReducer(builder); }, }); diff --git a/src/redux/bioEntity/thunks/getBioEntity.ts b/src/redux/bioEntity/thunks/getBioEntity.ts index c89cc25d..bf54870a 100644 --- a/src/redux/bioEntity/thunks/getBioEntity.ts +++ b/src/redux/bioEntity/thunks/getBioEntity.ts @@ -1,13 +1,12 @@ import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema'; import { apiPath } from '@/redux/apiPath'; import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; -import { BioEntity, BioEntityContent, BioEntityResponse } from '@/types/models'; -import { IdSearchQuery, PerfectSearchParams } from '@/types/search'; +import { BioEntityContent, BioEntityResponse } from '@/types/models'; +import { PerfectSearchParams } from '@/types/search'; import { ThunkConfig } from '@/types/store'; import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '@reduxjs/toolkit'; import { getError } from '@/utils/error-report/getError'; -import { getCommentElement } from '@/redux/comment/thunks/getComments'; import { addNumbersToEntityNumberData } from '../../entityNumber/entityNumber.slice'; import { BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants'; @@ -41,34 +40,3 @@ export const getBioEntity = createAsyncThunk< } }, ); - -type GetBioEntityByIdProps = IdSearchQuery; -type GetBioEntityByIdAction = PayloadAction<BioEntity | null>; // if error thrown, string containing error message is returned - -export const getBioEntityById = createAsyncThunk< - BioEntity | null, - GetBioEntityByIdProps, - ThunkConfig ->( - 'project/getBioEntityById', - async ({ elementId, modelId, type, addNumbersToEntityNumber }, { dispatch }) => { - try { - if (type === 'ALIAS') { - const elementAction = (await dispatch( - getCommentElement({ elementId, modelId }), - )) as GetBioEntityByIdAction; - - const element = elementAction.payload; - - if (addNumbersToEntityNumber && element) { - dispatch(addNumbersToEntityNumberData([element.elementId])); - } - - return element; - } - throw new Error('Not implemented'); - } catch (error) { - return Promise.reject(getError({ error, prefix: BIO_ENTITY_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/bioEntity/thunks/getMultiBioEntity.ts b/src/redux/bioEntity/thunks/getMultiBioEntity.ts index 2b84e65a..cddf3ff1 100644 --- a/src/redux/bioEntity/thunks/getMultiBioEntity.ts +++ b/src/redux/bioEntity/thunks/getMultiBioEntity.ts @@ -1,13 +1,13 @@ import { ZERO } from '@/constants/common'; import type { AppDispatch, store } from '@/redux/store'; -import { BioEntity, BioEntityContent } from '@/types/models'; -import { MultiSearchByIdParams, PerfectMultiSearchParams } from '@/types/search'; +import { BioEntityContent } from '@/types/models'; +import { PerfectMultiSearchParams } from '@/types/search'; import { ThunkConfig } from '@/types/store'; import { PayloadAction, createAsyncThunk } from '@reduxjs/toolkit'; import { getError } from '@/utils/error-report/getError'; import { addNumbersToEntityNumberData } from '../../entityNumber/entityNumber.slice'; import { MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants'; -import { getBioEntity, getBioEntityById } from './getBioEntity'; +import { getBioEntity } from './getBioEntity'; import { fetchReactionsAndGetBioEntitiesIds } from './utils/fetchReactionsAndGetBioEntitiesIds'; type GetMultiBioEntityProps = PerfectMultiSearchParams; @@ -57,49 +57,3 @@ export const getMultiBioEntity = createAsyncThunk< } }, ); - -type GetMultiBioEntityByIdProps = MultiSearchByIdParams; -type GetMultiBioEntityByIdActions = PayloadAction<BioEntity[] | undefined>[]; // if error thrown, string containing error message is returned - -export const getMultiBioEntityByIds = createAsyncThunk< - BioEntity[], - GetMultiBioEntityByIdProps, - ThunkConfig ->( - 'project/getMultiBioEntity', - // eslint-disable-next-line consistent-return - async ({ elementsToFetch }, { dispatch, getState }) => { - try { - const asyncGetBioEntityFunctions = elementsToFetch.map(elementToFetch => - dispatch(getBioEntityById(elementToFetch)), - ); - - const bioEntityContentsActions = (await Promise.all( - asyncGetBioEntityFunctions, - )) as GetMultiBioEntityByIdActions; - - const bioEntities = bioEntityContentsActions - .map(bioEntityContentsAction => bioEntityContentsAction?.payload || []) - .flat(); - - const bioEntityIds = bioEntities.map(b => b.elementId); - dispatch(addNumbersToEntityNumberData(bioEntityIds)); - - const bioEntitiesIds = await fetchReactionsAndGetBioEntitiesIds({ - bioEntityContents: bioEntities.map(bioEntity => { - return { perfect: true, bioEntity }; - }), - dispatch: dispatch as AppDispatch, - getState: getState as typeof store.getState, - }); - if (bioEntitiesIds.length > ZERO) { - const searchQueries = bioEntitiesIds.map(id => String(id)); - await dispatch(getMultiBioEntity({ searchQueries, isPerfectMatch: true })); - } - - return bioEntities; - } catch (error) { - return Promise.reject(getError({ error, prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts b/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts deleted file mode 100644 index 554dfde5..00000000 --- a/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { submapConnection } from '@/models/submapConnection'; -import { apiPath } from '@/redux/apiPath'; -import { axiosInstance, axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; -import { BioEntity, SubmapConnection } from '@/types/models'; -import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { createAsyncThunk } from '@reduxjs/toolkit'; -import { z } from 'zod'; -import { getError } from '@/utils/error-report/getError'; -import { bioEntitySchema } from '@/models/bioEntitySchema'; -import { MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants'; - -export const getSubmapConnectionsBioEntity = createAsyncThunk<BioEntity[]>( - 'project/getSubmapConnectionsBioEntity', - async () => { - try { - const response = await axiosInstance.get<SubmapConnection[]>(apiPath.getSubmapConnections()); - - const isDataValid = validateDataUsingZodSchema(response.data, z.array(submapConnection)); - if (!isDataValid) { - throw new Error('Submap connections validation error'); - } - - const targetElements = response.data.map(({ from }) => from); - - const asyncFetchBioEntityFunctions = targetElements.map(targetElement => - axiosInstanceNewAPI.get<BioEntity>( - apiPath.getElementById(targetElement.id, targetElement.modelId), - ), - ); - - const bioEntityContentResponse = await Promise.all(asyncFetchBioEntityFunctions); - - const bioEntityContents = bioEntityContentResponse - .map(contentResponse => contentResponse.data) - .flat() - .filter(content => bioEntitySchema.safeParse(content).success); - - return bioEntityContents; - } catch (error) { - return Promise.reject(getError({ error, prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/comment/comment.reducers.ts b/src/redux/comment/comment.reducers.ts index b113cdfd..55057923 100644 --- a/src/redux/comment/comment.reducers.ts +++ b/src/redux/comment/comment.reducers.ts @@ -1,10 +1,6 @@ import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { CommentsState } from '@/redux/comment/comment.types'; -import { - getCommentElement, - getCommentReaction, - getComments, -} from '@/redux/comment/thunks/getComments'; +import { getCommentReaction, getComments } from '@/redux/comment/thunks/getComments'; export const getCommentsReducer = (builder: ActionReducerMapBuilder<CommentsState>): void => { builder.addCase(getComments.pending, state => { @@ -21,23 +17,6 @@ export const getCommentsReducer = (builder: ActionReducerMapBuilder<CommentsStat }); }; -export const getCommentElementReducer = (builder: ActionReducerMapBuilder<CommentsState>): void => { - builder.addCase(getCommentElement.pending, state => { - state.loading = 'pending'; - state.commentElement = null; - }); - - builder.addCase(getCommentElement.fulfilled, (state, action) => { - state.loading = 'succeeded'; - state.commentElement = action.payload; - }); - - builder.addCase(getCommentElement.rejected, state => { - state.loading = 'failed'; - state.commentElement = null; - }); -}; - export const getCommentReactionReducer = ( builder: ActionReducerMapBuilder<CommentsState>, ): void => { diff --git a/src/redux/comment/comment.selectors.ts b/src/redux/comment/comment.selectors.ts index 7af687a2..587cf360 100644 --- a/src/redux/comment/comment.selectors.ts +++ b/src/redux/comment/comment.selectors.ts @@ -5,11 +5,6 @@ import { currentModelIdSelector } from '../models/models.selectors'; export const commentSelector = createSelector(rootSelector, state => state.comment); -export const commentElementSelector = createSelector( - commentSelector, - commentState => commentState.commentElement, -); - export const commentReactionSelector = createSelector( commentSelector, commentState => commentState.commentReaction, diff --git a/src/redux/comment/comment.slice.ts b/src/redux/comment/comment.slice.ts index ae4efb81..c426a46c 100644 --- a/src/redux/comment/comment.slice.ts +++ b/src/redux/comment/comment.slice.ts @@ -1,7 +1,6 @@ import { createSlice } from '@reduxjs/toolkit'; import { COMMENT_INITIAL_STATE } from '@/redux/comment/comment.constants'; import { - getCommentElementReducer, getCommentReactionReducer, getCommentsReducer, hideCommentsReducer, @@ -17,7 +16,6 @@ export const commentsSlice = createSlice({ }, extraReducers: builder => { getCommentsReducer(builder); - getCommentElementReducer(builder); getCommentReactionReducer(builder); }, }); diff --git a/src/redux/comment/thunks/getComments.ts b/src/redux/comment/thunks/getComments.ts index abf2d96e..df34a4f3 100644 --- a/src/redux/comment/thunks/getComments.ts +++ b/src/redux/comment/thunks/getComments.ts @@ -4,9 +4,8 @@ import { axiosInstance, axiosInstanceNewAPI } from '@/services/api/utils/axiosIn import { ThunkConfig } from '@/types/store'; import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; import { createAsyncThunk } from '@reduxjs/toolkit'; -import { BioEntity, Comment, NewReaction } from '@/types/models'; +import { Comment, NewReaction } from '@/types/models'; import { z } from 'zod'; -import { bioEntitySchema } from '@/models/bioEntitySchema'; import { GetElementProps } from '@/redux/comment/comment.types'; import { getError } from '@/utils/error-report/getError'; import { newReactionSchema } from '@/models/newReactionSchema'; @@ -26,23 +25,6 @@ export const getComments = createAsyncThunk<Comment[], void, ThunkConfig>( }, ); -export const getCommentElement = createAsyncThunk<BioEntity | null, GetElementProps, ThunkConfig>( - 'project/getCommentElement', - async ({ elementId, modelId }) => { - try { - const response = await axiosInstanceNewAPI.get<BioEntity>( - apiPath.getElementById(elementId, modelId), - ); - - const isDataValid = validateDataUsingZodSchema(response.data, bioEntitySchema); - - return isDataValid ? response.data : null; - } catch (error) { - return Promise.reject(getError({ error })); - } - }, -); - export const getCommentReaction = createAsyncThunk< NewReaction | null, GetElementProps, diff --git a/src/redux/compartmentPathways/comparmentPathways.constants.ts b/src/redux/compartmentPathways/comparmentPathways.constants.ts deleted file mode 100644 index cc54322a..00000000 --- a/src/redux/compartmentPathways/comparmentPathways.constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const MAX_NUMBER_OF_IDS_IN_GET_QUERY = 100; - -export const COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX = 'Failed to fetch compartment pathways'; diff --git a/src/redux/compartmentPathways/compartmentPathways.mock.ts b/src/redux/compartmentPathways/compartmentPathways.mock.ts deleted file mode 100644 index 8d088c4c..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.mock.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { MapModel } from '@/types/models'; -import { MAIN_MAP_ID } from '@/constants/mocks'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; - -export const COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK: CompartmentPathwaysState = { - loading: 'idle', - data: [], - error: { name: '', message: '' }, -}; -export const MODELS_MOCK: MapModel[] = [ - { - id: MAIN_MAP_ID, - width: 26779.25, - height: 13503.0, - defaultCenterX: null, - defaultCenterY: null, - description: '', - name: 'Core PD map', - defaultZoomLevel: null, - tileSize: 256, - references: [], - authors: [], - creationDate: null, - modificationDates: [], - minZoom: 2, - maxZoom: 9, - }, - { - id: 5054, - width: 26779.25, - height: 13503.0, - defaultCenterX: null, - defaultCenterY: null, - description: '', - name: 'Core PD map', - defaultZoomLevel: null, - tileSize: 256, - references: [], - authors: [], - creationDate: null, - modificationDates: [], - minZoom: 2, - maxZoom: 9, - }, -]; - -export const MODELS_MOCK_SHORT: MapModel[] = [ - { - id: 5050, - width: 26779.25, - height: 13503.0, - defaultCenterX: null, - defaultCenterY: null, - description: '', - name: 'Core PD map', - defaultZoomLevel: null, - tileSize: 256, - references: [], - authors: [], - creationDate: null, - modificationDates: [], - minZoom: 2, - maxZoom: 9, - }, -]; diff --git a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts b/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts deleted file mode 100644 index 8cfdf6ee..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { - ToolkitStoreWithSingleSlice, - createStoreInstanceUsingSliceReducer, -} from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { HttpStatusCode } from 'axios'; -import { - compartmentPathwaysDetailsFixture, - compartmentPathwaysFixture, - compartmentPathwaysOverLimitFixture, -} from '@/models/fixtures/compartmentPathways'; -import { getModelsIds } from '@/components/Map/Drawer/ExportDrawer/ExportDrawer.component.utils'; -import { unwrapResult } from '@reduxjs/toolkit'; -import { MAIN_MAP_ID } from '@/constants/mocks'; -import { apiPath } from '../apiPath'; -import compartmentPathwaysReducer from './compartmentPathways.slice'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; -import { getCompartmentPathways } from './compartmentPathways.thunks'; -import { MODELS_MOCK } from './compartmentPathways.mock'; - -const mockedAxiosClient = mockNetworkResponse(); -const MODELS_MOCK_IDS = getModelsIds(MODELS_MOCK); -const INITIAL_STATE: CompartmentPathwaysState = { - loading: 'idle', - error: { name: '', message: '' }, - data: [], -}; - -describe('compartmentPathways reducer', () => { - let store = {} as ToolkitStoreWithSingleSlice<CompartmentPathwaysState>; - beforeEach(() => { - store = createStoreInstanceUsingSliceReducer('compartmentPathways', compartmentPathwaysReducer); - }); - - it('should match initial state', () => { - const action = { type: 'unknown' }; - expect(compartmentPathwaysReducer(undefined, action)).toEqual(INITIAL_STATE); - }); - it('should update store on loading getCompartmentPathways query', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(52)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails([1, 2, 3])) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('idle'); - expect(data).toEqual([]); - - store.dispatch(getCompartmentPathways()); - - const { loading: loadingPending, data: dataPending } = store.getState().compartmentPathways; - - expect(loadingPending).toEqual('pending'); - expect(dataPending).toEqual([]); - }); - - it('should update store after succesful getCompartmentPathways query', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(MAIN_MAP_ID)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(5054)) - .reply(HttpStatusCode.Ok, compartmentPathwaysOverLimitFixture); - - const ids = compartmentPathwaysFixture.map(el => el.id); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails(ids)) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS)); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('pending'); - expect(data).toEqual([]); - - const { type } = await compartmentPathwaysPromise; - - expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled'); - - const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(dataFulfilled).toEqual([ - ...compartmentPathwaysDetailsFixture, - ...compartmentPathwaysDetailsFixture, - ]); - expect(promiseFulfilled).toEqual('succeeded'); - }); - - it('should update store after failed getCompartmentPathways query', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(MAIN_MAP_ID)) - .reply(HttpStatusCode.NotFound, []); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails([])) - .reply(HttpStatusCode.NotFound, []); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.NotFound, []); - - const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS)); - - const { loading, data } = store.getState().compartmentPathways; - expect(loading).toEqual('pending'); - expect(data).toEqual([]); - - const dispatchData = await compartmentPathwaysPromise; - - expect(() => unwrapResult(dispatchData)).toThrow( - "Failed to fetch compartment pathways: The page you're looking for doesn't exist. Please verify the URL and try again.", - ); - const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(promiseFulfilled).toEqual('failed'); - expect(dataFulfilled).toEqual([]); - }); -}); diff --git a/src/redux/compartmentPathways/compartmentPathways.reducers.ts b/src/redux/compartmentPathways/compartmentPathways.reducers.ts deleted file mode 100644 index 8010fbc0..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.reducers.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; -import { getCompartmentPathways } from './compartmentPathways.thunks'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; - -export const getCompartmentPathwaysReducer = ( - builder: ActionReducerMapBuilder<CompartmentPathwaysState>, -): void => { - builder - .addCase(getCompartmentPathways.pending, state => { - state.loading = 'pending'; - }) - .addCase(getCompartmentPathways.fulfilled, (state, action) => { - state.data = action.payload; - state.loading = 'succeeded'; - }) - .addCase(getCompartmentPathways.rejected, state => { - state.loading = 'failed'; - // TODO: error management to be discussed in the team - }); -}; diff --git a/src/redux/compartmentPathways/compartmentPathways.selectors.ts b/src/redux/compartmentPathways/compartmentPathways.selectors.ts deleted file mode 100644 index d6c82942..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.selectors.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { rootSelector } from '@/redux/root/root.selectors'; -import { createSelector } from '@reduxjs/toolkit'; - -export const compartmentPathwaysSelector = createSelector( - rootSelector, - state => state.compartmentPathways, -); - -export const compartmentPathwaysDataSelector = createSelector( - compartmentPathwaysSelector, - state => state.data, -); - -export const loadingCompartmentPathwaysSelector = createSelector( - compartmentPathwaysSelector, - state => state.loading, -); diff --git a/src/redux/compartmentPathways/compartmentPathways.slice.ts b/src/redux/compartmentPathways/compartmentPathways.slice.ts deleted file mode 100644 index 3cc1b375..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.slice.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createSlice } from '@reduxjs/toolkit'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; -import { getCompartmentPathwaysReducer } from './compartmentPathways.reducers'; - -export const initialState: CompartmentPathwaysState = { - loading: 'idle', - error: { name: '', message: '' }, - data: [], -}; - -export const compartmentPathwaysSlice = createSlice({ - name: 'compartmentPathways', - initialState, - reducers: {}, - extraReducers: builder => { - getCompartmentPathwaysReducer(builder); - }, -}); - -export default compartmentPathwaysSlice.reducer; diff --git a/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts b/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts deleted file mode 100644 index 891eeb38..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { - ToolkitStoreWithSingleSlice, - createStoreInstanceUsingSliceReducer, -} from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { HttpStatusCode } from 'axios'; -import { - compartmentPathwaysDetailsFixture, - compartmentPathwaysFixture, - compartmentPathwaysOverLimitFixture, -} from '@/models/fixtures/compartmentPathways'; -import { getModelsIds } from '@/components/Map/Drawer/ExportDrawer/ExportDrawer.component.utils'; -import { MAIN_MAP_ID } from '@/constants/mocks'; -import { apiPath } from '../apiPath'; -import compartmentPathwaysReducer from './compartmentPathways.slice'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; -import { getCompartmentPathways } from './compartmentPathways.thunks'; -import { MODELS_MOCK, MODELS_MOCK_SHORT } from './compartmentPathways.mock'; - -const mockedAxiosClient = mockNetworkResponse(); -const MODELS_MOCK_IDS = getModelsIds(MODELS_MOCK); - -describe('compartmentPathways thunk', () => { - let store = {} as ToolkitStoreWithSingleSlice<CompartmentPathwaysState>; - beforeEach(() => { - store = createStoreInstanceUsingSliceReducer('compartmentPathways', compartmentPathwaysReducer); - }); - - it('should handle query getCompartmentPathways properly when models are undefined', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(52)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails([1, 2, 3])) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('idle'); - expect(data).toEqual([]); - - const comparmentPathwaysPromise = store.dispatch(getCompartmentPathways()); - - const { loading: loadingPending, data: dataPending } = store.getState().compartmentPathways; - - expect(loadingPending).toEqual('pending'); - expect(dataPending).toEqual([]); - - await comparmentPathwaysPromise; - const { loading: loadingFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(loadingFulfilled).toEqual('succeeded'); - expect(dataFulfilled).toEqual([]); - }); - it('should handle sendCompartmentPathwaysIds request properly if it is more than 100 ids', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(MAIN_MAP_ID)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(5054)) - .reply(HttpStatusCode.Ok, compartmentPathwaysOverLimitFixture); - - const ids = compartmentPathwaysFixture.map(el => el.id); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails(ids)) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS)); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('pending'); - expect(data).toEqual([]); - - const { type } = await compartmentPathwaysPromise; - - expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled'); - - const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(dataFulfilled).toEqual([ - ...compartmentPathwaysDetailsFixture, - ...compartmentPathwaysDetailsFixture, - ]); - expect(promiseFulfilled).toEqual('succeeded'); - }); - - it('should not do a network request sendCompartmentPathwaysIds if it is less than 100 ids', async () => { - const ONE_MODEL = MODELS_MOCK_SHORT[0]; - const ID = ONE_MODEL.id; - - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(ID)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - - const ids = compartmentPathwaysFixture.map(el => el.id); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails(ids)) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways([ONE_MODEL.id])); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('pending'); - expect(data).toEqual([]); - - const { type } = await compartmentPathwaysPromise; - - expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled'); - - const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(dataFulfilled).toEqual(compartmentPathwaysDetailsFixture); - expect(promiseFulfilled).toEqual('succeeded'); - }); -}); diff --git a/src/redux/compartmentPathways/compartmentPathways.thunks.ts b/src/redux/compartmentPathways/compartmentPathways.thunks.ts deleted file mode 100644 index 8f1bd216..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.thunks.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* eslint-disable no-restricted-syntax */ -import { axiosInstance } from '@/services/api/utils/axiosInstance'; -import { createAsyncThunk } from '@reduxjs/toolkit'; -import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { CompartmentPathway, CompartmentPathwayDetails } from '@/types/models'; -import { - compartmentPathwayDetailsSchema, - compartmentPathwaySchema, -} from '@/models/compartmentPathwaySchema'; -import { z } from 'zod'; -import { getError } from '@/utils/error-report/getError'; -import { - COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX, - MAX_NUMBER_OF_IDS_IN_GET_QUERY, -} from './comparmentPathways.constants'; -import { apiPath } from '../apiPath'; - -/** UTILS */ - -const fetchCompartmentPathwaysIds = async ( - modelsIds: number[] | undefined, -): Promise<number[][]> => { - if (!modelsIds) return []; - - const compartmentIds = []; - - for (const modelId of modelsIds) { - /* eslint-disable no-await-in-loop */ - const response = await axiosInstance<CompartmentPathway[]>( - apiPath.getCompartmentPathwaysIds(modelId), - ); - - const isDataValid = validateDataUsingZodSchema( - response.data, - z.array(compartmentPathwaySchema), - ); - - if (isDataValid) { - const result = response.data; - const ids: number[] = []; - - result.forEach(item => { - ids.push(item.id); - }); - - compartmentIds.push(ids); - } - } - - return compartmentIds; -}; - -const fetchCompartmentPathwayDetailsByPost = async ( - compartmentPathwayIds: number[], -): Promise<CompartmentPathwayDetails[]> => { - const params = { - id: compartmentPathwayIds.join(','), - }; - const body = new URLSearchParams(params); - - const response = await axiosInstance.post<CompartmentPathwayDetails[]>( - apiPath.sendCompartmentPathwaysIds(), - body, - ); - - return response.data; -}; - -const fetchCompartmentPathwayDetailsByGet = async ( - compartmentPathwayIds: number[], -): Promise<CompartmentPathwayDetails[]> => { - const response = await axiosInstance.get<CompartmentPathwayDetails[]>( - apiPath.getCompartmentPathwayDetails(compartmentPathwayIds), - ); - - return response.data; -}; - -const fetchCompartmentPathwayDetails = async ( - compartmentPathwayIds: number[], -): Promise<CompartmentPathwayDetails[]> => { - if (compartmentPathwayIds.length) { - let compartmentPathwayDetails; - if (compartmentPathwayIds.length > MAX_NUMBER_OF_IDS_IN_GET_QUERY) { - compartmentPathwayDetails = await fetchCompartmentPathwayDetailsByPost(compartmentPathwayIds); - } else { - compartmentPathwayDetails = await fetchCompartmentPathwayDetailsByGet(compartmentPathwayIds); - } - - const isDataValid = validateDataUsingZodSchema( - compartmentPathwayDetails, - z.array(compartmentPathwayDetailsSchema), - ); - - if (isDataValid) return compartmentPathwayDetails; - } - return []; -}; - -export const fetchCompartmentPathways = async ( - compartmentPathwaysData: number[][], -): Promise<CompartmentPathwayDetails[]> => { - const compartments = []; - - /* eslint-disable no-await-in-loop */ - for (const compartmentPathwayIds of compartmentPathwaysData) { - const compartmentPathwayDetails = await fetchCompartmentPathwayDetails(compartmentPathwayIds); - - if (compartmentPathwayDetails) compartments.push(...compartmentPathwayDetails); - } - - return compartments; -}; - -/** UTILS */ - -export const getCompartmentPathways = createAsyncThunk( - 'compartmentPathways/getCompartmentPathways', - async (modelsIds: number[] | undefined) => { - try { - const compartmentIds = await fetchCompartmentPathwaysIds(modelsIds); - const comparmentPathways = await fetchCompartmentPathways(compartmentIds); - - return comparmentPathways; - } catch (error) { - return Promise.reject(getError({ error, prefix: COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/compartmentPathways/compartmentPathways.types.ts b/src/redux/compartmentPathways/compartmentPathways.types.ts deleted file mode 100644 index 76718b54..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.types.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { FetchDataState } from '@/types/fetchDataState'; -import { CompartmentPathwayDetails } from '@/types/models'; - -export type CompartmentPathwaysState = FetchDataState<CompartmentPathwayDetails[], []>; diff --git a/src/redux/drawer/drawer.selectors.ts b/src/redux/drawer/drawer.selectors.ts index 05a64d2e..a5f109ea 100644 --- a/src/redux/drawer/drawer.selectors.ts +++ b/src/redux/drawer/drawer.selectors.ts @@ -18,11 +18,6 @@ export const currentStepDrawerStateSelector = createSelector( state => state.currentStep, ); -export const selectedValueDrawerSelector = createSelector( - searchDrawerStateSelector, - state => state.selectedValue, -); - export const stepTypeDrawerSelector = createSelector( searchDrawerStateSelector, state => state.stepType, diff --git a/src/redux/entityNumber/entityNumber.reducers.ts b/src/redux/entityNumber/entityNumber.reducers.ts index 15662170..2c114e95 100644 --- a/src/redux/entityNumber/entityNumber.reducers.ts +++ b/src/redux/entityNumber/entityNumber.reducers.ts @@ -15,7 +15,6 @@ export const addNumbersToEntityNumberDataReducer = ( ): void => { const { payload: ids } = action; const uniqueIds = [...new Set(ids)]; - const lastNumber = Object.keys(state.data).length || ONE; // min num = 1 const newEntityNumber: EntityNumber = Object.fromEntries( uniqueIds.map((id, index) => [id, lastNumber + index]), diff --git a/src/redux/modelElements/modelElements.constants.ts b/src/redux/modelElements/modelElements.constants.ts index c3b221d3..42427c11 100644 --- a/src/redux/modelElements/modelElements.constants.ts +++ b/src/redux/modelElements/modelElements.constants.ts @@ -1 +1,3 @@ export const MODEL_ELEMENTS_FETCHING_ERROR_PREFIX = 'Failed to fetch model elements'; + +export const MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME = 'default'; diff --git a/src/redux/modelElements/modelElements.reducers.test.ts b/src/redux/modelElements/modelElements.reducers.test.ts index c6c51637..8c499a6d 100644 --- a/src/redux/modelElements/modelElements.reducers.test.ts +++ b/src/redux/modelElements/modelElements.reducers.test.ts @@ -34,7 +34,7 @@ describe('model elements reducer', () => { const { type } = await store.dispatch(getModelElementsForModel(0)); const { data, loading, error } = store.getState().modelElements[0]; - expect(type).toBe('vectorMap/getModelElementsForModel/fulfilled'); + expect(type).toBe('modelElements/getModelElementsForModel/fulfilled'); expect(loading).toEqual('succeeded'); expect(error).toEqual({ message: '', name: '' }); expect(data).toEqual(modelElementsFixture.content); @@ -46,7 +46,7 @@ describe('model elements reducer', () => { const action = await store.dispatch(getModelElementsForModel(0)); const { data, loading, error } = store.getState().modelElements[0]; - expect(action.type).toBe('vectorMap/getModelElementsForModel/rejected'); + expect(action.type).toBe('modelElements/getModelElementsForModel/rejected'); expect(() => unwrapResult(action)).toThrow( "Failed to fetch model elements: The page you're looking for doesn't exist. Please verify the URL and try again.", ); diff --git a/src/redux/modelElements/modelElements.selector.ts b/src/redux/modelElements/modelElements.selector.ts index b31fd45f..55c08d7a 100644 --- a/src/redux/modelElements/modelElements.selector.ts +++ b/src/redux/modelElements/modelElements.selector.ts @@ -1,6 +1,10 @@ import { createSelector } from '@reduxjs/toolkit'; import { rootSelector } from '@/redux/root/root.selectors'; import { currentModelIdSelector } from '@/redux/models/models.selectors'; +import { currentSearchedBioEntityId } from '@/redux/drawer/drawer.selectors'; +import { ModelElement } from '@/types/models'; +import { MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME } from '@/redux/modelElements/modelElements.constants'; +import { COMPARTMENT_SBO_TERM } from '@/components/Map/MapViewer/MapViewer.constants'; export const modelElementsSelector = createSelector(rootSelector, state => state.modelElements); @@ -15,12 +19,61 @@ export const modelElementsByModelIdSelector = createSelector( (state, modelId) => state[modelId]?.data || [], ); -export const modelElementsLoadingSelector = createSelector( +export const modelElementsCurrentModelLoadingSelector = createSelector( modelElementsStateForCurrentModelSelector, state => state?.loading, ); +export const modelElementsAnyModelLoadingSelector = createSelector(modelElementsSelector, state => + Object.values(state).some(modelElementState => modelElementState.loading === 'pending'), +); + export const modelElementsForCurrentModelSelector = createSelector( modelElementsStateForCurrentModelSelector, state => state?.data || [], ); + +export const modelElementsWithSubmapConnectionForCurrentModelSelector = createSelector( + modelElementsForCurrentModelSelector, + modelElements => modelElements.filter(modelElement => Boolean(modelElement.submodel)) || [], +); + +export const compartmentNameByIdSelector = createSelector( + [ + modelElementsForCurrentModelSelector, + (_state, compartmentId: number | undefined | null): number | undefined | null => compartmentId, + ], + (modelElements, compartmentId) => { + if (!compartmentId) { + return MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME; + } + return ( + modelElements.find(modelElement => { + return modelElement.sboTerm === COMPARTMENT_SBO_TERM && modelElement.id === compartmentId; + })?.name || MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME + ); + }, +); + +export const currentDrawerModelElementSelector = createSelector( + modelElementsForCurrentModelSelector, + currentSearchedBioEntityId, + (modelElements, currentBioEntityId): ModelElement | undefined => { + return modelElements.find(modelElement => modelElement.id === currentBioEntityId); + }, +); + +export const compartmentPathwaysSelector = createSelector( + modelElementsSelector, + (state): ModelElement[] => { + const pathways: ModelElement[] = []; + Object.values(state).forEach(modelState => { + pathways.push( + ...(modelState.data || []).filter( + modelElement => modelElement.sboTerm === COMPARTMENT_SBO_TERM, + ), + ); + }); + return pathways; + }, +); diff --git a/src/redux/modelElements/modelElements.thunks.ts b/src/redux/modelElements/modelElements.thunks.ts index fb1a3c2e..68f2419e 100644 --- a/src/redux/modelElements/modelElements.thunks.ts +++ b/src/redux/modelElements/modelElements.thunks.ts @@ -13,7 +13,7 @@ export const getModelElementsForModel = createAsyncThunk< Array<ModelElement> | undefined, number, ThunkConfig ->('vectorMap/getModelElementsForModel', async (modelId: number) => { +>('modelElements/getModelElementsForModel', async (modelId: number) => { try { const { data } = await axiosInstanceNewAPI.get<ModelElements>( apiPath.getModelElements(modelId), diff --git a/src/redux/newReactions/newReactions.selectors.ts b/src/redux/newReactions/newReactions.selectors.ts index a17245b4..b8ba305f 100644 --- a/src/redux/newReactions/newReactions.selectors.ts +++ b/src/redux/newReactions/newReactions.selectors.ts @@ -1,5 +1,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { currentModelIdSelector } from '@/redux/models/models.selectors'; +import { currentDrawerReactionIdSelector } from '@/redux/drawer/drawer.selectors'; +import { NewReaction } from '@/types/models'; import { rootSelector } from '../root/root.selectors'; export const newReactionsSelector = createSelector(rootSelector, state => state.newReactions); @@ -24,3 +26,11 @@ export const newReactionsByModelIdSelector = createSelector( [newReactionsSelector, (_state, modelId: number): number => modelId], (state, modelId) => state[modelId]?.data || [], ); + +export const currentDrawerNewReactionSelector = createSelector( + newReactionsForCurrentModelSelector, + currentDrawerReactionIdSelector, + (newReactions, currentDrawerReactionId): NewReaction | undefined => { + return newReactions.find(newReaction => newReaction.id === currentDrawerReactionId); + }, +); diff --git a/src/redux/overlayBioEntity/overlayBioEntity.selector.ts b/src/redux/overlayBioEntity/overlayBioEntity.selector.ts index 94616fd8..a7c7e93b 100644 --- a/src/redux/overlayBioEntity/overlayBioEntity.selector.ts +++ b/src/redux/overlayBioEntity/overlayBioEntity.selector.ts @@ -1,7 +1,7 @@ import { OverlayBioEntityRender } from '@/types/OLrendering'; import { createSelector } from '@reduxjs/toolkit'; -import { allSubmapConnectionsBioEntitySelector } from '@/redux/bioEntity/bioEntity.selectors'; import { mapModelIdSelector } from '@/redux/map/map.selectors'; +import { modelElementsWithSubmapConnectionForCurrentModelSelector } from '@/redux/modelElements/modelElements.selector'; import { currentSearchedBioEntityId } from '../drawer/drawer.selectors'; import { currentModelIdSelector } from '../models/models.selectors'; import { @@ -36,7 +36,7 @@ export const overlayBioEntitiesForCurrentModelSelector = createSelector( overlayBioEntityDataSelector, activeOverlaysIdSelector, currentModelIdSelector, - allSubmapConnectionsBioEntitySelector, + modelElementsWithSubmapConnectionForCurrentModelSelector, (data, activeOverlaysIds, currentModelId, submapConnections) => { const result: OverlayBioEntityRender[] = []; diff --git a/src/redux/root/init.thunks.ts b/src/redux/root/init.thunks.ts index 562789dc..4514bd87 100644 --- a/src/redux/root/init.thunks.ts +++ b/src/redux/root/init.thunks.ts @@ -15,7 +15,6 @@ import { } from '@/redux/autocomplete/autocomplete.thunks'; import { openSelectProjectModal } from '@/redux/modal/modal.slice'; import { getProjects } from '@/redux/projects/projects.thunks'; -import { getSubmapConnectionsBioEntity } from '@/redux/bioEntity/thunks/getSubmapConnectionsBioEntity'; import { getArrowTypes, getLineTypes, getShapes } from '@/redux/shapes/shapes.thunks'; import { MATOMO_URL } from '@/redux/configuration/configuration.constants'; import { @@ -133,8 +132,6 @@ export const fetchInitialAppData = createAsyncThunk< dispatch(getDrugAutocomplete()); dispatch(getChemicalAutocomplete()); - dispatch(getSubmapConnectionsBioEntity()); - /** Trigger search */ if (queryData.searchValue) { dispatch(setPerfectMatch(queryData.perfectMatch)); diff --git a/src/redux/root/root.fixtures.ts b/src/redux/root/root.fixtures.ts index f6d6110c..e21a9a9a 100644 --- a/src/redux/root/root.fixtures.ts +++ b/src/redux/root/root.fixtures.ts @@ -11,7 +11,6 @@ import { GLYPHS_STATE_INITIAL_MOCK } from '@/redux/glyphs/glyphs.mock'; import { MAP_EDIT_TOOLS_STATE_INITIAL_MOCK } from '@/redux/mapEditTools/mapEditTools.mock'; import { BIOENTITY_INITIAL_STATE_MOCK } from '../bioEntity/bioEntity.mock'; import { CHEMICALS_INITIAL_STATE_MOCK } from '../chemicals/chemicals.mock'; -import { COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK } from '../compartmentPathways/compartmentPathways.mock'; import { CONFIGURATION_INITIAL_STATE } from '../configuration/configuration.adapter'; import { CONTEXT_MENU_INITIAL_STATE } from '../contextMenu/contextMenu.constants'; import { COOKIE_BANNER_INITIAL_STATE_MOCK } from '../cookieBanner/cookieBanner.mock'; @@ -65,7 +64,6 @@ export const INITIAL_STORE_STATE_MOCK: RootState = { user: USER_INITIAL_STATE_MOCK, legend: LEGEND_INITIAL_STATE_MOCK, statistics: STATISTICS_STATE_INITIAL_MOCK, - compartmentPathways: COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK, publications: PUBLICATIONS_INITIAL_STATE_MOCK, export: EXPORT_INITIAL_STATE_MOCK, plugins: PLUGINS_INITIAL_STATE_MOCK, diff --git a/src/redux/selectors/index.ts b/src/redux/selectors/index.ts new file mode 100644 index 00000000..f1cbd61d --- /dev/null +++ b/src/redux/selectors/index.ts @@ -0,0 +1,33 @@ +import { createSelector } from '@reduxjs/toolkit'; +import { newReactionsLoadingSelector } from '@/redux/newReactions/newReactions.selectors'; +import { modelElementsCurrentModelLoadingSelector } from '@/redux/modelElements/modelElements.selector'; +import { + arrowTypesLoadingSelector, + bioShapesLoadingSelector, + lineTypesLoadingSelector, +} from '@/redux/shapes/shapes.selectors'; +import { layersLoadingSelector } from '@/redux/layers/layers.selectors'; + +export const modelLoadingSelector = createSelector( + [ + newReactionsLoadingSelector, + modelElementsCurrentModelLoadingSelector, + bioShapesLoadingSelector, + lineTypesLoadingSelector, + arrowTypesLoadingSelector, + layersLoadingSelector, + ], + (...loadingStates) => loadingStates.includes('pending'), +); + +export const modelLoadedSuccessfullySelector = createSelector( + [ + newReactionsLoadingSelector, + modelElementsCurrentModelLoadingSelector, + bioShapesLoadingSelector, + lineTypesLoadingSelector, + arrowTypesLoadingSelector, + layersLoadingSelector, + ], + (...loadingStates) => loadingStates.every(state => state === 'succeeded'), +); diff --git a/src/redux/store.ts b/src/redux/store.ts index a98370bc..3d2cc350 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -36,7 +36,6 @@ import { configureStore, } from '@reduxjs/toolkit'; import commentReducer from '@/redux/comment/comment.slice'; -import compartmentPathwaysReducer from './compartmentPathways/compartmentPathways.slice'; import entityNumberReducer from './entityNumber/entityNumber.slice'; import exportReducer from './export/export.slice'; import legendReducer from './legend/legend.slice'; @@ -78,7 +77,6 @@ export const reducers = { overlayBioEntity: overlayBioEntityReducer, legend: legendReducer, statistics: statisticsReducer, - compartmentPathways: compartmentPathwaysReducer, publications: publicationsReducer, export: exportReducer, plugins: pluginsReducer, diff --git a/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts b/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts index 235bf0f5..4a1bcd16 100644 --- a/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts +++ b/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts @@ -52,7 +52,7 @@ export const searchByCoordinates = async ( const type = searchResultVector.get('type'); const id = searchResultVector.get('id'); if ([FEATURE_TYPE.ALIAS, FEATURE_TYPE.GLYPH, FEATURE_TYPE.COMPARTMENT].includes(type)) { - await leftClickHandleAlias(dispatch, hasFitBounds)(searchResultVector, modelId); + await leftClickHandleAlias(dispatch, hasFitBounds)(modelElements, searchResultVector, modelId); } else if (type === FEATURE_TYPE.REACTION) { clickHandleReaction(dispatch)(modelElements, newReactions, id, modelId); } diff --git a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts index adba6dd6..0b3e97df 100644 --- a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts +++ b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts @@ -12,12 +12,12 @@ import { HttpStatusCode } from 'axios'; import { Feature, Map } from 'ol'; import SimpleGeometry from 'ol/geom/SimpleGeometry'; import VectorLayer from 'ol/layer/Vector'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { FEATURE_TYPE } from '@/constants/features'; import * as leftClickHandleAlias from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; import { MapManager } from '@/services/pluginsManager/map/mapManager'; import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { NewReactionsState } from '@/redux/newReactions/newReactions.types'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { ERROR_INVALID_MODEL_ID_TYPE } from '../../errorMessages'; import { triggerSearch } from './triggerSearch'; @@ -75,7 +75,7 @@ jest.mock( describe('triggerSearch', () => { let mapInstance: Map; const vectorLayer = new VectorLayer({}); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); beforeEach(() => { const dummyElement = document.createElement('div'); diff --git a/src/types/models.ts b/src/types/models.ts index 168c7fde..756f345a 100644 --- a/src/types/models.ts +++ b/src/types/models.ts @@ -3,35 +3,23 @@ import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema'; import { bioEntitySchema } from '@/models/bioEntitySchema'; import { chemicalSchema } from '@/models/chemicalSchema'; import { colorSchema } from '@/models/colorSchema'; -import { - compartmentPathwayDetailsSchema, - compartmentPathwaySchema, -} from '@/models/compartmentPathwaySchema'; import { configurationOptionSchema } from '@/models/configurationOptionSchema'; import { configurationSchema, formatSchema, miriamTypesSchema } from '@/models/configurationSchema'; -import { disease } from '@/models/disease'; import { drugSchema } from '@/models/drugSchema'; import { elementSearchResult, elementSearchResultType } from '@/models/elementSearchResult'; import { exportElementsSchema, exportNetworkchema } from '@/models/exportSchema'; import { geneVariant } from '@/models/geneVariant'; import { lineSchema } from '@/models/lineSchema'; import { loginSchema } from '@/models/loginSchema'; -import { - createdOverlayFileSchema, - createdOverlaySchema, - mapOverlay, - uploadedOverlayFileContentSchema, -} from '@/models/mapOverlay'; +import { createdOverlayFileSchema, createdOverlaySchema, mapOverlay } from '@/models/mapOverlay'; import { markerLineSchema, markerPinSchema, markerSchema, markerSurfaceSchema, - markerTypeSchema, markerWithPositionSchema, } from '@/models/markerSchema'; import { mapModelSchema, mapModelsSchema } from '@/models/modelSchema'; -import { organism } from '@/models/organism'; import { overlayBioEntitySchema, overlayElementWithBioEntitySchema, @@ -52,8 +40,6 @@ import { publicationSchema } from '@/models/publicationsSchema'; import { referenceSchema } from '@/models/referenceSchema'; import { sessionSchemaValid } from '@/models/sessionValidSchema'; import { statisticsSchema } from '@/models/statisticsSchema'; -import { submapConnection } from '@/models/submapConnection'; -import { targetElementSchema } from '@/models/targetElementSchema'; import { targetSchema } from '@/models/targetSchema'; import { targetSearchNameResult } from '@/models/targetSearchNameResult'; import { userPrivilegeSchema } from '@/models/userPrivilegesSchema'; @@ -115,8 +101,6 @@ export type ShapeRelAbs = z.infer<typeof shapeRelAbsSchema>; export type ShapeRelAbsBezierPoint = z.infer<typeof shapeRelAbsBezierPointSchema>; export type Modification = z.infer<typeof modelElementModificationSchema>; export type MapOverlay = z.infer<typeof mapOverlay>; -export type Organism = z.infer<typeof organism>; -export type Disease = z.infer<typeof disease>; export type Drug = z.infer<typeof drugSchema>; export type PinDetailsItem = z.infer<typeof targetSchema>; export type BioEntity = z.infer<typeof bioEntitySchema>; @@ -145,23 +129,17 @@ export type OverlayLeftBioEntity = z.infer<typeof overlayLeftBioEntitySchema>; export type OverlayLeftReaction = z.infer<typeof overlayLeftReactionSchema>; export type Line = z.infer<typeof lineSchema>; export type CreatedOverlayFile = z.infer<typeof createdOverlayFileSchema>; -export type UploadedOverlayFileContent = z.infer<typeof uploadedOverlayFileContentSchema>; export type CreatedOverlay = z.infer<typeof createdOverlaySchema>; export type Color = z.infer<typeof colorSchema>; export type Statistics = z.infer<typeof statisticsSchema>; -export type CompartmentPathway = z.infer<typeof compartmentPathwaySchema>; -export type CompartmentPathwayDetails = z.infer<typeof compartmentPathwayDetailsSchema>; export type Publication = z.infer<typeof publicationSchema>; export type ExportNetwork = z.infer<typeof exportNetworkchema>; export type ExportElements = z.infer<typeof exportElementsSchema>; export type MinervaPlugin = z.infer<typeof pluginSchema>; // Plugin type interferes with global Plugin type export type GeneVariant = z.infer<typeof geneVariant>; export type TargetSearchNameResult = z.infer<typeof targetSearchNameResult>; -export type TargetElement = z.infer<typeof targetElementSchema>; -export type SubmapConnection = z.infer<typeof submapConnection>; export type UserPrivilege = z.infer<typeof userPrivilegeSchema>; export type User = z.infer<typeof userSchema>; -export type MarkerType = z.infer<typeof markerTypeSchema>; export type MarkerPin = z.infer<typeof markerPinSchema>; export type MarkerSurface = z.infer<typeof markerSurfaceSchema>; export type MarkerLine = z.infer<typeof markerLineSchema>; -- GitLab