diff --git a/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx b/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx index 22c43bc9002867b5657d1e80b72eaf83beb59afc..d08b0e9b177c1695be9814bbe92c1144968dc8a4 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 84ff3087084fe70ae7ff9ce01b422d00125f4214..73231d8d0cb131410be7d075427705b50ce7459b 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 d72d546ad3f2c54551eac6d45645dddd33d50cdb..7ae2a243928cae82231f3c7e4c0756a0d9018925 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 7b3e3ba196c2f8c4af9ea8d3b8e1f030baeb2eae..48ac8915019f191010dc9f0be3318c53ebfc1fa0 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 eb258f9d310fdc4a8ba9166bae6af051811ba314..b677519d0651aab559f7658225e9fd21f0188ea8 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 e330724197fd44992b57d51da0d3ee6b871d42d2..d0e0d9b6d40bcf3dd53303748a8779b0d6fba0db 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 ded8e6806f29182fd4ed22c6b8d8e0dc1cfa506d..82d39b1eac7f4b50705c9a2ef9513d484906126f 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 89007fae92f3b9ba261516041befe04ee004e3d9..131819acd569f81ae4d0de126fdc3b04b9ab5688 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 59a59c9957d597e9f46b4b38704f736e386cc477..29ce2f87c5d8fabee69d66a942b1e8b6fcd73520 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 4ef2cee4762cb803993095517e88c929323e056d..509a8636204af3263bf4046418d9059b877b0f94 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 6254cd6bd795c47606f394660040e720e61983ea..893b03671b197ddd4ef8f581ce30ee457d589409 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 9a807f04e97bc26296e9a4922fd312637bb7e54e..861479443d5e61112bde36b9b279c4c215838112 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 64d3ddfdec10967735ffd7234d8b1703c1f442eb..6847bd994fba879083633b7d2ab843c1bd7620cb 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 2fddcfedfc55f45e04a0c57d1612acb2005c3e82..88243df1272535cd78fa5a3a9dbd582963d58375 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 1a76eeeafeb412d06f87a75707d761c221e50289..283dd29f7d8a3bb9e7764a4981081507f8c9e13e 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 00d2128e8b4a2bab323c1dbbdc2b3cc2c46d592d..633c55a8b063830f4ae0fea575051d67ec0f8594 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 7f8fb00b2bb18a3bbcf71ba26ca4a7c0f7c6783f..ec4c2e1b3a89b33da92b953bc827805d15cc2f9f 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 a521a7f5462b8cef8050535f74bb9ed29f359b8c..1e3b4e05ba96d4921a41dc3d5ec564057ab66d71 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 2d0472651331df088b3e3a81f628c7de4b004580..e8492ee376dcc0cdcffbced16d022d405a9bf2b5 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 6eb9e2cbd4706836bcbb812e235b7a937d15d32c..7ac3b73b9a89368660ce511ba65dd64fbb36ae85 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 e1fb741ba7f9c9f103c192d133cb706b00fb0315..69cec807a1265f4436031878e8f4150393c0a4ea 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 788b89f248c1afb9a64d4d39b420c18b8a39c40a..7a0643c598657cf89b2a718680e8ef316b3bfe61 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 9d3489b4891923796a6feb660de21b887ff111d4..c24250e22adf5490353b05668ac70527d50b6026 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 641b537da8e0fd922993eadc7c3e2f0291d8dc0c..c2e6d9082c948893a49999ac38869032597c129c 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 87c6d666e2cc4e11eaf99ab6e365e2227159ff28..b4c0b8767ff7b4c6fc788e7af954dc3cdc359fe2 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 2837c80bf7199fee4e00a0d09fcc0cdac7b629cd..2811ec3067ad8b61391793561966ce6b9bd6ba31 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 cf4416f3a775263deac6fdc188050ff85088472e..bfb2668ed1ec46a20d6149ec928c9f2b367c5e19 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 d809149e1e2e92c5a92e5b34be306b6beb6716ff..ef42a0aabb55f5bdd588f80fa85cfb7beb3df505 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 edc575be6cb081a3c0f24143aace1552ca065265..34e57854b8260542bc92630d0ae7e33f460dd7e0 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 5c1fc99eab6a781cae57c82d1fbdb3c0eef65a64..88417316811ffc07e7270323427bba2b9f51867c 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 f1b980a9c9670573bfb071a903289eefb026bbc7..ad75ed8fd8a8dd55d34cc823ed0c748142e74c68 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 df86f0a2d5ca95724c7901ea7a24899c8eeea178..17b253ef568f7cb05c66bcc5f2bd0f56fa3b5652 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 5f07ab3d3948b4bb518ca183357654512d8f32ff..50d3f5b62a88953a4690469bcab8f26d245e863c 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts @@ -1,35 +1,42 @@ 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'; import { handleOpenImmediateLink } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleOpenImmediateLink'; -import { ZERO } from '@/constants/common'; /* 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(); - handleOpenImmediateLink(bioEntities[ZERO]); + + const modelElement = modelElements.find(element => + element.id === id + ); + if(!modelElement) { + return; + } + handleOpenImmediateLink(modelElement); + 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 deb191074f33989005b5ecd4c0f316bd8cc48547..6cf59664d96a7a3def32e75f5980884d824c5ede 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 0c01e4a2fa5fa13d6adcd3847a2095fe418bf970..c62b97bfd7e647b5f2b6b2ea020f5bf6f82f02b4 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 fa6a3f172e45ad54b22f8a5d9e9a6ef76b95ad01..de2c88490f571156e6db68e276e9247a96ec3d2e 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 0daefedd37203bd41a0ba65b142b8a174ef8c026..6865842446af58da03f5f89ef233927419f41865 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 ed6acbf48e7a33713a056c3a465e1e7e53914db2..b907081123bd0ca23c4066d8d68c6656c5dc857e 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 44d5ee656f4d8b685e368ef3a1af13ee70808664..06c194a5aa343af57e202d221df03df6741ea6bb 100644 --- a/src/models/bioEntitySchema.ts +++ b/src/models/bioEntitySchema.ts @@ -52,7 +52,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 1259fa8708e3d6514b69e113b52c97cd5c118a21..0000000000000000000000000000000000000000 --- 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 c93b4dc0a92f0efccbffa218eb4de56c00484921..0000000000000000000000000000000000000000 --- 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/models/modelElementSchema.ts b/src/models/modelElementSchema.ts index b95b6f6ad6963c137b46d7b8db1100dcaae9d68e..7f8cf7a5800c4f9fa66b9c79932aef7d9116ae0a 100644 --- a/src/models/modelElementSchema.ts +++ b/src/models/modelElementSchema.ts @@ -11,6 +11,7 @@ export const modelElementSchema = z.object({ glyph: glyphSchema.nullable(), submodel: submodelSchema.nullable(), compartment: z.number().nullable(), + immediateLink: z.string().nullable(), elementId: z.string(), x: z.number(), y: z.number(), diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index 9f81dab46dfc320c06bd3a7c74dbc871b2b9efdb..93d49308b2e2b21a73a603a7b51871f79f4bb696 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 bab876f96571388ac1120a99d8ccd86a0aa3e3db..b24e17c1b8889e85fa13201210cee9d78e1ab312 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 eb4e8f218b0c6a73fdd04872143f2e095dc62b4c..d9c63a0a6ab297c775a0f251498eed4926a05e29 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 74dcffaa384d92e0c2f6d20586e1e11c386d4e61..8e40b023c9c5100821ef1e1980a08143a100904a 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 c89cc25d3b430f33179b4249e778888ae8a0f7ed..bf54870a8db007d3785bb07606516fa293044a6f 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 2b84e65ab0a67b57e4e9843150a806812d0cfa88..cddf3ff17b9f335ab6f654365febfe99293e46ff 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 554dfde559edfe0b7700893b7764b26c69d9bc6c..0000000000000000000000000000000000000000 --- 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 b113cdfd76784c4724adbeb1a67fcf3a250d36de..5505792329aab58b0a17ed24b05a1e6b1f59ef3f 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 7af687a21dc94636d189bb663aba5750e9b7d20a..587cf36029a04617214ee15d71b59b1fd27c49dc 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 ae4efb8179ecf725686af6f8f93e95187d013323..c426a46c5405391b83d5a9fecc803b61a6e81842 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 abf2d96e12ed7abbc4200a121bdb84ddf68f30c6..df34a4f30a25897029349fb3bfd984659698d486 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 cc54322af2521fa94bbe3c5b201b1cd77f5fffd7..0000000000000000000000000000000000000000 --- 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 8d088c4c54077c0db8aab5c76b358989c45c8229..0000000000000000000000000000000000000000 --- 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 8cfdf6eedbab0ddce7bc5c5fa3212d7b733bc3d5..0000000000000000000000000000000000000000 --- 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 8010fbc062d475e23c04e3f072746b99b7f5e5c7..0000000000000000000000000000000000000000 --- 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 d6c8294223b341bae523684e0ad92bd3b79ee9a6..0000000000000000000000000000000000000000 --- 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 3cc1b37525aa6b0d4dcfa755d41a381dfc3b9556..0000000000000000000000000000000000000000 --- 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 891eeb38c70c9a8659d6123f3592c8e8305f27e3..0000000000000000000000000000000000000000 --- 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 8f1bd216b8ecbff5f0cd4e608a7ee8737b9e9ad8..0000000000000000000000000000000000000000 --- 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 76718b5456fa89850ddda36afbec9cd912a7cee1..0000000000000000000000000000000000000000 --- 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 05a64d2edd7ad18cb859b0b24a568ff2049604e6..a5f109ea50ed068bb49535e51bb3c9ec8a5eabed 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 156621700274d11eaff81e465172644abea4ed42..2c114e95801db2161a9c9a8eb69b2982ba3135b5 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 c3b221d39b259cc60755364bda17bb758e5d87cd..42427c11f62830690150e10913bfb1ea0c0ec2bc 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 c6c516372c6c6f027709aab7fde2993af47aa3c5..8c499a6dc5384cfa611805bf79ff1c831b24a860 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 b31fd45f63706fe311f14d8d43171bada5ea4cda..55c08d7a0b13596f074c08a319c8d13bd0dfbb73 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 fb1a3c2ee8ef716261d8cca78dc6e51c98e5ff1d..68f2419e35f2033c0f271c96805d96f1037f451e 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 a17245b4d6c5ddb21032444f417bc1aa409bbf04..b8ba305fae603e3cf75f6a6d4f4f530736ae83e6 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 94616fd892f4a19b17804b67a4a1c6844e26f1f1..a7c7e93b2deff86fd7cafd661332840f9a54bad7 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 562789dc95102028e759397bbebaf13825dd78b0..4514bd872f4dd44518cf8d19daf601db84044b98 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 f6d6110c91c93ae6dbc73c2109ac52d30180f3c1..e21a9a9a23b3a9052c9536e613f99f2226fa7b2d 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 0000000000000000000000000000000000000000..f1cbd61dbaa9f9f99cf43e1add0f320139703930 --- /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 a98370bc8f1c4f26e642fa1b2283c67fa696f381..3d2cc3500e6f7a2d8c3cd567fbb458d22d09abf3 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 235bf0f5cd7de671d6142cc99ec5c34fd824a830..4a1bcd16b2bea4b700b212551ba164d0857d5c25 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 a2d3165b4c99b7d73cc565844c9ea06065aa1b5a..0b3e97df409d58f3f7145bd49959d7939993e4f1 100644 --- a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts +++ b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts @@ -12,14 +12,14 @@ 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 { triggerSearch } from './triggerSearch'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { ERROR_INVALID_MODEL_ID_TYPE } from '../../errorMessages'; +import { triggerSearch } from './triggerSearch'; const mockedAxiosClient = mockNetworkNewAPIResponse(); const SEARCH_QUERY = 'park7'; @@ -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 168c7fde106887fcb19aae57f79bebf0538b7240..756f345a748fd49fb34ce1bf0328d4e5910409d1 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>;