From 7b79d139f3bea2e2d38c7ca43a906418f765e543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Fri, 17 Jan 2025 08:37:43 +0100 Subject: [PATCH 01/12] feat(map): remove raster rendering --- ...rImageObjectEditFactoryModal.component.tsx | 2 +- .../NavBar/NavBar.component.tsx | 14 -- src/components/Map/Map.component.tsx | 14 +- .../MapDrawEditActions.component.tsx | 4 +- .../MapLoader/MapLoader.component.test.tsx | 25 +-- .../Map/MapLoader/MapLoader.component.tsx | 4 +- .../Map/MapViewer/MapViewer.constants.ts | 202 ++++++++++++++++++ .../Map/MapViewer/MapViewer.types.ts | 15 ++ .../MapViewerVector.constants.ts | 201 ----------------- .../MapViewerVector/MapViewerVector.types.ts | 24 --- .../listeners/useOlMapVectorListeners.test.ts | 50 ----- .../listeners/useOlMapVectorListeners.ts | 100 --------- .../utils/config/useOlMapVectorLayers.test.ts | 85 -------- .../utils/config/useOlMapVectorLayers.ts | 21 -- .../useOlMapAdditionalLayers.test.ts | 2 +- .../useOlMapAdditionalLayers.ts | 24 +-- .../mapCardLayer/useOlMapCardLayer.test.ts | 0 .../config/mapCardLayer/useOlMapCardLayer.ts | 0 .../processLayer}/processModelElements.ts | 15 +- .../useOlMapProcessLayer.test.ts} | 4 +- .../processLayer/useOlMapProcessLayer.ts} | 26 +-- .../utils/config/useOlMapCommonLayers.test.ts | 93 -------- .../utils/config/useOlMapCommonLayers.ts | 16 -- .../utils/config/useOlMapLayers.test.ts | 28 ++- .../MapViewer/utils/config/useOlMapLayers.ts | 35 ++- .../mapSingleClick/handleReactionResults.ts | 2 +- .../mouseClick/clickHandleReaction.test.ts | 2 +- .../mouseClick/clickHandleReaction.ts | 2 +- .../getModelElementsIdsFromReaction.test.ts | 0 .../getModelElementsIdsFromReaction.ts | 0 .../leftClickHandleAlias.test.ts | 2 +- .../mouseLeftClick/leftClickHandleAlias.ts | 0 .../mouseLeftClick/onMapLeftClick.test.ts | 6 +- .../mouseLeftClick/onMapLeftClick.ts | 6 +- .../mouseRightClick/onMapRightClick.test.ts | 4 +- .../mouseRightClick/onMapRightClick.ts | 6 +- .../rightClickHandleAlias.test.ts | 2 +- .../mouseRightClick/rightClickHandleAlias.ts | 0 .../utils/listeners/useOlMapListeners.test.ts | 20 +- .../utils/listeners/useOlMapListeners.ts | 108 ++++------ .../shapes/coords/findLargestExtent.test.ts | 2 +- .../utils/shapes/coords/findLargestExtent.ts | 0 .../shapes/coords/getBezierCurve.test.ts | 0 .../utils/shapes/coords/getBezierCurve.ts | 0 .../coords/getBoundingBoxFromExtent.test.ts | 2 +- .../shapes/coords/getBoundingBoxFromExtent.ts | 2 +- .../utils/shapes/coords/getCenter.test.ts | 2 +- .../utils/shapes/coords/getCenter.ts | 0 .../utils/shapes/coords/getCoordsX.test.ts | 0 .../utils/shapes/coords/getCoordsX.ts | 0 .../utils/shapes/coords/getCoordsY.test.ts | 0 .../utils/shapes/coords/getCoordsY.ts | 0 .../shapes/coords/getCurveCoords.test.ts | 4 +- .../utils/shapes/coords/getCurveCoords.ts | 4 +- .../shapes/coords/getDividedExtents.test.ts | 2 +- .../utils/shapes/coords/getDividedExtents.ts | 0 .../shapes/coords/getEllipseCoords.test.ts | 4 +- .../utils/shapes/coords/getEllipseCoords.ts | 4 +- .../shapes/coords/getLineSegments.test.ts | 2 +- .../utils/shapes/coords/getLineSegments.ts | 0 .../shapes/coords/getPolygonCoords.test.ts | 8 +- .../utils/shapes/coords/getPolygonCoords.ts | 8 +- .../utils/shapes/coords/getRotation.test.ts | 2 +- .../utils/shapes/coords/getRotation.ts | 0 .../utils/shapes/elements/BaseMultiPolygon.ts | 19 +- .../utils/shapes/elements/Compartment.ts | 15 +- .../shapes/elements/CompartmentCircle.test.ts | 25 +-- .../shapes/elements/CompartmentCircle.ts | 11 +- .../elements/CompartmentPathway.test.ts | 25 +-- .../shapes/elements/CompartmentPathway.ts | 17 +- .../shapes/elements/CompartmentSquare.test.ts | 23 +- .../shapes/elements/CompartmentSquare.ts | 11 +- .../utils/shapes/elements/Glyph/Glyph.test.ts | 4 +- .../utils/shapes/elements/Glyph/Glyph.ts | 11 +- .../shapes/elements/Glyph/updateGlyph.ts | 0 .../utils/shapes/elements/MapElement.test.ts | 23 +- .../utils/shapes/elements/MapElement.ts | 23 +- .../shapes/elements/getArrowFeature.test.ts | 8 +- .../utils/shapes/elements/getArrowFeature.ts | 10 +- .../shapes/elements/getShapePolygon.test.ts | 6 +- .../utils/shapes/elements/getShapePolygon.ts | 6 +- .../elements/handleSemanticView.test.ts | 6 +- .../shapes/elements/handleSemanticView.ts | 8 +- .../elements/isFeatureInCompartment.test.ts | 0 .../shapes/elements/isFeatureInCompartment.ts | 0 .../elements/removeElementFromLayer.test.ts | 0 .../shapes/elements/removeElementFromLayer.ts | 0 .../utils/shapes/layer/Layer.test.ts | 17 +- .../utils/shapes/layer/Layer.ts | 21 +- .../layer/getDrawImageInteraction.test.ts | 2 +- .../shapes/layer/getDrawImageInteraction.ts | 2 +- .../getTransformImageInteraction.test.ts | 4 +- .../layer/getTransformImageInteraction.ts | 2 +- .../utils/shapes/overlay/LineOverlay.test.ts | 8 +- .../utils/shapes/overlay/LineOverlay.ts | 2 +- .../shapes/overlay/MarkerOverlay.test.ts | 8 +- .../utils/shapes/overlay/MarkerOverlay.ts | 2 +- .../overlay/areOverlayOrdersNotEqual.ts | 0 .../calculateOverlayDimensions.test.ts | 0 .../overlay/calculateOverlayDimensions.ts | 0 .../findMatchingSubmapLinkRectangle.test.ts | 0 .../findMatchingSubmapLinkRectangle.ts | 0 .../utils/shapes/overlay/getOverlays.test.ts | 0 .../utils/shapes/overlay/getOverlays.ts | 4 +- .../overlay/groupOverlayEntities.test.ts | 0 .../shapes/overlay/groupOverlayEntities.ts | 4 +- .../processOverlayGroupedElements.test.ts | 4 +- .../overlay/processOverlayGroupedElements.ts | 6 +- .../overlay/sortElementOverlayByColor.test.ts | 0 .../overlay/sortElementOverlayByColor.ts | 0 .../utils/shapes/reaction/Reaction.test.ts | 4 +- .../utils/shapes/reaction/Reaction.ts | 20 +- .../utils/shapes/style/getCoverStyles.test.ts | 8 +- .../utils/shapes/style/getCoverStyles.ts | 6 +- .../utils/shapes/style/getFill.test.ts | 0 .../utils/shapes/style/getFill.ts | 0 .../style/getScaledElementStyle.test.ts | 2 +- .../shapes/style/getScaledElementStyle.ts | 2 +- .../shapes/style/getScaledStrokeStyle.test.ts | 0 .../shapes/style/getScaledStrokeStyle.ts | 0 .../utils/shapes/style/getStroke.test.ts | 0 .../utils/shapes/style/getStroke.ts | 0 .../utils/shapes/style/getStyle.test.ts | 2 +- .../utils/shapes/style/getStyle.ts | 11 +- .../utils/shapes/style/rgbToHex.test.ts | 0 .../utils/shapes/style/rgbToHex.ts | 0 .../utils/shapes/text/Text.test.ts | 10 +- .../utils/shapes/text/Text.ts | 13 +- .../utils/shapes/text/getTextCoords.test.ts | 2 +- .../utils/shapes/text/getTextCoords.ts | 5 +- .../utils/shapes/text/getTextStyle.test.ts | 2 +- .../utils/shapes/text/getTextStyle.ts | 2 +- .../text/getWrappedTextWithFontSize.test.ts | 2 +- .../shapes/text/getWrappedTextWithFontSize.ts | 0 .../Map/MapViewer/utils/useOlMap.ts | 47 +--- src/models/mocks/modelsMock.ts | 1 - src/models/modelSchema.ts | 1 - .../fetchReactionsAndGetBioEntitiesIds.ts | 2 +- src/redux/layers/layers.reducers.ts | 3 + src/redux/models/models.reducers.ts | 13 +- src/redux/models/models.selectors.ts | 5 - src/redux/models/models.slice.ts | 8 +- 142 files changed, 592 insertions(+), 1126 deletions(-) delete mode 100644 src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts delete mode 100644 src/components/Map/MapViewer/MapViewerVector/MapViewerVector.types.ts delete mode 100644 src/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners.test.ts delete mode 100644 src/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners.ts delete mode 100644 src/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers.test.ts delete mode 100644 src/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers.ts rename src/components/Map/MapViewer/{MapViewerVector => }/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts (92%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/config/additionalLayers/useOlMapAdditionalLayers.ts (89%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/config/mapCardLayer/useOlMapCardLayer.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/config/mapCardLayer/useOlMapCardLayer.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector/utils/config/reactionsLayer => utils/config/processLayer}/processModelElements.ts (87%) rename src/components/Map/MapViewer/{MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.test.ts => utils/config/processLayer/useOlMapProcessLayer.test.ts} (79%) rename src/components/Map/MapViewer/{MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts => utils/config/processLayer/useOlMapProcessLayer.ts} (87%) delete mode 100644 src/components/Map/MapViewer/utils/config/useOlMapCommonLayers.test.ts delete mode 100644 src/components/Map/MapViewer/utils/config/useOlMapCommonLayers.ts rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/clickHandleReaction.test.ts (97%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/clickHandleReaction.ts (96%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/getModelElementsIdsFromReaction.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/getModelElementsIdsFromReaction.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts (96%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts (94%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts (95%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts (95%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/mouseRightClick/onMapRightClick.ts (94%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts (94%) rename src/components/Map/MapViewer/{MapViewerVector => utils}/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/findLargestExtent.test.ts (76%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/findLargestExtent.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getBezierCurve.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getBezierCurve.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getBoundingBoxFromExtent.test.ts (92%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getBoundingBoxFromExtent.ts (96%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getCenter.test.ts (81%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getCenter.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getCoordsX.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getCoordsX.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getCoordsY.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getCoordsY.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getCurveCoords.test.ts (90%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getCurveCoords.ts (85%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getDividedExtents.test.ts (94%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getDividedExtents.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getEllipseCoords.test.ts (89%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getEllipseCoords.ts (89%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getLineSegments.test.ts (97%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getLineSegments.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getPolygonCoords.test.ts (88%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getPolygonCoords.ts (76%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getRotation.test.ts (83%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/coords/getRotation.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/BaseMultiPolygon.ts (91%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/Compartment.ts (89%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/CompartmentCircle.test.ts (78%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/CompartmentCircle.ts (87%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/CompartmentPathway.test.ts (78%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/CompartmentPathway.ts (83%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/CompartmentSquare.test.ts (79%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/CompartmentSquare.ts (87%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/Glyph/Glyph.test.ts (93%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/Glyph/Glyph.ts (95%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/Glyph/updateGlyph.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/MapElement.test.ts (80%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/MapElement.ts (91%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/getArrowFeature.test.ts (89%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/getArrowFeature.ts (80%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/getShapePolygon.test.ts (94%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/getShapePolygon.ts (78%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/handleSemanticView.test.ts (89%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/handleSemanticView.ts (86%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/isFeatureInCompartment.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/isFeatureInCompartment.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/removeElementFromLayer.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/elements/removeElementFromLayer.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/layer/Layer.test.ts (84%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/layer/Layer.ts (92%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/layer/getDrawImageInteraction.test.ts (96%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/layer/getDrawImageInteraction.ts (97%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/layer/getTransformImageInteraction.test.ts (92%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/layer/getTransformImageInteraction.ts (98%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/LineOverlay.test.ts (78%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/LineOverlay.ts (96%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/MarkerOverlay.test.ts (79%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/MarkerOverlay.ts (96%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/areOverlayOrdersNotEqual.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/calculateOverlayDimensions.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/calculateOverlayDimensions.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/findMatchingSubmapLinkRectangle.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/findMatchingSubmapLinkRectangle.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/getOverlays.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/getOverlays.ts (83%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/groupOverlayEntities.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/groupOverlayEntities.ts (88%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/processOverlayGroupedElements.test.ts (92%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/processOverlayGroupedElements.ts (87%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/sortElementOverlayByColor.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/overlay/sortElementOverlayByColor.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/reaction/Reaction.test.ts (94%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/reaction/Reaction.ts (92%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getCoverStyles.test.ts (87%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getCoverStyles.ts (86%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getFill.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getFill.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getScaledElementStyle.test.ts (92%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getScaledElementStyle.ts (76%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getScaledStrokeStyle.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getScaledStrokeStyle.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getStroke.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getStroke.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getStyle.test.ts (94%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/getStyle.ts (65%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/rgbToHex.test.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/style/rgbToHex.ts (100%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/text/Text.test.ts (80%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/text/Text.ts (84%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/text/getTextCoords.test.ts (85%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/text/getTextCoords.ts (89%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/text/getTextStyle.test.ts (88%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/text/getTextStyle.ts (95%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/text/getWrappedTextWithFontSize.test.ts (95%) rename src/components/Map/MapViewer/{MapViewerVector => }/utils/shapes/text/getWrappedTextWithFontSize.ts (100%) diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx index 3e8d27b6..655bb8d9 100644 --- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx @@ -14,7 +14,7 @@ import { showToast } from '@/utils/showToast'; import { closeModal } from '@/redux/modal/modal.slice'; import { SerializedError } from '@reduxjs/toolkit'; import { useMapInstance } from '@/utils/context/mapInstanceContext'; -import updateGlyph from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/updateGlyph'; +import updateGlyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph'; import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; export const LayerImageObjectEditFactoryModal: React.FC = () => { diff --git a/src/components/FunctionalArea/NavBar/NavBar.component.tsx b/src/components/FunctionalArea/NavBar/NavBar.component.tsx index edd14170..eafb96e3 100644 --- a/src/components/FunctionalArea/NavBar/NavBar.component.tsx +++ b/src/components/FunctionalArea/NavBar/NavBar.component.tsx @@ -11,16 +11,11 @@ import { store } from '@/redux/store'; import Image from 'next/image'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { projectIdSelector } from '@/redux/project/project.selectors'; -import { Switch } from '@/shared/Switch'; -import { currentModelIdSelector, vectorRenderingSelector } from '@/redux/models/models.selectors'; -import { setModelVectorRendering } from '@/redux/models/models.slice'; export const NavBar = (): JSX.Element => { const dispatch = useAppDispatch(); const projectId = useAppSelector(projectIdSelector); - const vectorRendering = useAppSelector(vectorRenderingSelector); - const currentModelId = useAppSelector(currentModelIdSelector); const toggleDrawerInfo = (): void => { if (store.getState().drawer.isOpen && store.getState().drawer.drawerName === 'project-info') { @@ -91,15 +86,6 @@ export const NavBar = (): JSX.Element => { <IconButton icon="legend" onClick={toggleDrawerLegend} title="Legend" /> </div> </div> - <div className="flex flex-col items-center gap-[10px] text-center text-[12px]"> - <span>Vector rendering</span> - <Switch - isChecked={vectorRendering} - onToggle={value => - dispatch(setModelVectorRendering({ vectorRendering: value, mapId: currentModelId })) - } - /> - </div> <div className="flex flex-col items-center gap-[20px]" data-testid="nav-logos-and-powered-by"> <a href="https://www.uni.lu/en/" target="_blank"> <Image diff --git a/src/components/Map/Map.component.tsx b/src/components/Map/Map.component.tsx index 0a57b1fb..df0e5eac 100644 --- a/src/components/Map/Map.component.tsx +++ b/src/components/Map/Map.component.tsx @@ -6,16 +6,13 @@ import { MapLoader } from '@/components/Map/MapLoader/MapLoader.component'; import { MapVectorBackgroundSelector } from '@/components/Map/MapVectorBackgroundSelector/MapVectorBackgroundSelector.component'; import { MapActiveLayerSelector } from '@/components/Map/MapActiveLayerSelector/MapActiveLayerSelector.component'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { vectorRenderingSelector } from '@/redux/models/models.selectors'; import { MapAdditionalLogos } from '@/components/Map/MapAdditionalLogos'; import { MapDrawActions } from '@/components/Map/MapDrawActions/MapDrawActions.component'; import { layersActiveLayerSelector } from '@/redux/layers/layers.selectors'; import { MapAdditionalActions } from './MapAdditionalActions'; -import { MapAdditionalOptions } from './MapAdditionalOptions'; import { PluginsDrawer } from './PluginsDrawer'; export const Map = (): JSX.Element => { - const vectorRendering = useAppSelector(vectorRenderingSelector); const activeLayer = useAppSelector(layersActiveLayerSelector); return ( @@ -24,14 +21,9 @@ export const Map = (): JSX.Element => { data-testid="map-container" > <MapViewer /> - {!vectorRendering && <MapAdditionalOptions />} - {vectorRendering && ( - <> - <MapVectorBackgroundSelector /> - <MapActiveLayerSelector /> - {activeLayer && <MapDrawActions />} - </> - )} + <MapVectorBackgroundSelector /> + <MapActiveLayerSelector /> + {activeLayer && <MapDrawActions />} <Drawer /> <PluginsDrawer /> <Legend /> diff --git a/src/components/Map/MapDrawActions/MapDrawEditActions.component.tsx b/src/components/Map/MapDrawActions/MapDrawEditActions.component.tsx index 1782e00e..01ebfff1 100644 --- a/src/components/Map/MapDrawActions/MapDrawEditActions.component.tsx +++ b/src/components/Map/MapDrawActions/MapDrawEditActions.component.tsx @@ -10,12 +10,12 @@ import { layersActiveLayerSelector } from '@/redux/layers/layers.selectors'; import { layerDeleteImage, layerUpdateImage } from '@/redux/layers/layers.slice'; import { useMapInstance } from '@/utils/context/mapInstanceContext'; import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; -import updateGlyph from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/updateGlyph'; +import updateGlyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph'; import QuestionModal from '@/components/FunctionalArea/Modal/QuestionModal/QustionModal.component'; import { useState } from 'react'; import { showToast } from '@/utils/showToast'; import { SerializedError } from '@reduxjs/toolkit'; -import removeElementFromLayer from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/removeElementFromLayer'; +import removeElementFromLayer from '@/components/Map/MapViewer/utils/shapes/elements/removeElementFromLayer'; type MapDrawEditActionsComponentProps = { toggleMapEditAction: () => void; diff --git a/src/components/Map/MapLoader/MapLoader.component.test.tsx b/src/components/Map/MapLoader/MapLoader.component.test.tsx index eb35db6b..7f8fb00b 100644 --- a/src/components/Map/MapLoader/MapLoader.component.test.tsx +++ b/src/components/Map/MapLoader/MapLoader.component.test.tsx @@ -9,7 +9,6 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { newReactionsLoadingSelector } from '@/redux/newReactions/newReactions.selectors'; import { modelElementsLoadingSelector } from '@/redux/modelElements/modelElements.selector'; import { isDrawerOpenSelector } from '@/redux/drawer/drawer.selectors'; -import { vectorRenderingSelector } from '@/redux/models/models.selectors'; import { arrowTypesLoadingSelector, bioShapesLoadingSelector, @@ -50,7 +49,6 @@ describe('MapLoader', () => { const selectorMap = new Map<SelectorFunction, string | boolean>([ [newReactionsLoadingSelector, 'succeeded'], [modelElementsLoadingSelector, 'succeeded'], - [vectorRenderingSelector, true], [bioShapesLoadingSelector, 'succeeded'], [lineTypesLoadingSelector, 'succeeded'], [arrowTypesLoadingSelector, 'succeeded'], @@ -65,12 +63,11 @@ describe('MapLoader', () => { expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument(); }); - it('should render the LoadingIndicator when vectorRendering is true and data is loading', () => { + it('should render the LoadingIndicator when data is loading', () => { mockUseAppSelector.mockImplementation(selector => { const selectorMap = new Map<SelectorFunction, string | boolean>([ [newReactionsLoadingSelector, 'pending'], [modelElementsLoadingSelector, 'succeeded'], - [vectorRenderingSelector, true], [bioShapesLoadingSelector, 'succeeded'], [lineTypesLoadingSelector, 'succeeded'], [arrowTypesLoadingSelector, 'succeeded'], @@ -84,24 +81,4 @@ describe('MapLoader', () => { expect(screen.queryByTestId('loading-indicator')).toBeInTheDocument(); }); - - it('should not render the LoadingIndicator when vectorRendering is false even when data is loading', () => { - mockUseAppSelector.mockImplementation(selector => { - const selectorMap = new Map<SelectorFunction, string | boolean>([ - [newReactionsLoadingSelector, 'pending'], - [modelElementsLoadingSelector, 'succeeded'], - [vectorRenderingSelector, false], - [bioShapesLoadingSelector, 'succeeded'], - [lineTypesLoadingSelector, 'succeeded'], - [arrowTypesLoadingSelector, 'succeeded'], - [layersLoadingSelector, 'succeeded'], - [isDrawerOpenSelector, false], - ]); - - return selectorMap.get(selector) ?? false; - }); - renderComponent(); - - expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument(); - }); }); diff --git a/src/components/Map/MapLoader/MapLoader.component.tsx b/src/components/Map/MapLoader/MapLoader.component.tsx index fc457e0b..a521a7f5 100644 --- a/src/components/Map/MapLoader/MapLoader.component.tsx +++ b/src/components/Map/MapLoader/MapLoader.component.tsx @@ -2,7 +2,6 @@ import { LoadingIndicator } from '@/shared/LoadingIndicator'; import { useMemo } from 'react'; import { newReactionsLoadingSelector } from '@/redux/newReactions/newReactions.selectors'; import { modelElementsLoadingSelector } from '@/redux/modelElements/modelElements.selector'; -import { vectorRenderingSelector } from '@/redux/models/models.selectors'; import { arrowTypesLoadingSelector, bioShapesLoadingSelector, @@ -16,7 +15,6 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector'; export const MapLoader = (): JSX.Element => { const reactionsFetching = useAppSelector(newReactionsLoadingSelector); const modelElementsFetching = useAppSelector(modelElementsLoadingSelector); - const vectorRendering = useAppSelector(vectorRenderingSelector); const bioShapesFetching = useAppSelector(bioShapesLoadingSelector); const lineTypesFetching = useAppSelector(lineTypesLoadingSelector); const arrowTypesFetching = useAppSelector(arrowTypesLoadingSelector); @@ -44,7 +42,7 @@ export const MapLoader = (): JSX.Element => { return ( <div className={`map-loader transition-all duration-500 ${isDrawerOpen ? 'move-right' : ''}`}> - {vectorRendering && showLoader && <LoadingIndicator width={48} height={48} />} + {showLoader && <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 41924be9..2d047265 100644 --- a/src/components/Map/MapViewer/MapViewer.constants.ts +++ b/src/components/Map/MapViewer/MapViewer.constants.ts @@ -1 +1,203 @@ +import { Color, ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models'; + export const MAP_VIEWER_ROLE = 'map-viewer'; + +export const VECTOR_MAP_LAYER_TYPE = 'vectorMapLayer'; + +export const COMPLEX_SBO_TERMS = ['SBO:0000253', 'SBO:0000297', 'SBO:0000289']; + +export const TEXT_CUTOFF_SCALE = 0.34; +export const OUTLINE_CUTOFF_SCALE = 0.18; +export const COMPLEX_CONTENTS_CUTOFF_SCALE = 0.215; +export const REACTION_ELEMENT_CUTOFF_SCALE = 0.125; + +export const WHITE_COLOR: Color = { + alpha: 255, + rgb: 16777215, +}; + +export const BLACK_COLOR: Color = { + alpha: 255, + rgb: -16777216, +}; + +export const TRANSPARENT_COLOR: Color = { + alpha: 0, + rgb: 0, +}; + +export const REACTION_ELEMENT_TYPES = { + OPERATOR: 'OPERATOR', + SQUARE: 'SQUARE', + LINE: 'LINE', + ARROW: 'ARROW', +}; + +export const MAP_ELEMENT_TYPES = { + TEXT: 'TEXT', + MODIFICATION: 'MODIFICATION', + ACTIVITY_BORDER: 'ACTIVITY_BORDER', + ENTITY: 'ENTITY', + OVERLAY: 'OVERLAY', + COMPARTMENT: 'COMPARTMENT', +}; + +export const LAYER_ELEMENT_TYPES = { + TEXT: 'TEXT', + OVAL: 'OVAL', + RECT: 'RECT', + LINE: 'LINE', + ARROW: 'ARROW', +}; + +export const COMPARTMENT_SQUARE_POINTS: Array<ShapeRelAbs | ShapeRelAbsBezierPoint> = [ + { + type: 'REL_ABS_POINT', + absoluteX: 10.0, + absoluteY: 0.0, + relativeX: 0.0, + relativeY: 0.0, + relativeHeightForX: null, + relativeWidthForY: null, + }, + { + type: 'REL_ABS_POINT', + absoluteX: -10.0, + absoluteY: 0.0, + relativeX: 100.0, + relativeY: 0.0, + relativeHeightForX: null, + relativeWidthForY: null, + }, + { + type: 'REL_ABS_BEZIER_POINT', + absoluteX1: 0.0, + absoluteY1: 10.0, + relativeX1: 100.0, + relativeY1: 0.0, + relativeHeightForX1: null, + relativeWidthForY1: null, + absoluteX2: -5.0, + absoluteY2: 0.0, + relativeX2: 100.0, + relativeY2: 0.0, + relativeHeightForX2: null, + relativeWidthForY2: null, + absoluteX3: 0.0, + absoluteY3: 5.0, + relativeX3: 100.0, + relativeY3: 0.0, + relativeHeightForX3: null, + relativeWidthForY3: null, + }, + { + type: 'REL_ABS_POINT', + absoluteX: 0.0, + absoluteY: -10.0, + relativeX: 100.0, + relativeY: 100.0, + relativeHeightForX: null, + relativeWidthForY: null, + }, + { + type: 'REL_ABS_BEZIER_POINT', + absoluteX1: -10.0, + absoluteY1: 0.0, + relativeX1: 100.0, + relativeY1: 100.0, + relativeHeightForX1: null, + relativeWidthForY1: null, + absoluteX2: 0.0, + absoluteY2: -5.0, + relativeX2: 100.0, + relativeY2: 100.0, + relativeHeightForX2: null, + relativeWidthForY2: null, + absoluteX3: -5.0, + absoluteY3: 0.0, + relativeX3: 100.0, + relativeY3: 100.0, + relativeHeightForX3: null, + relativeWidthForY3: null, + }, + { + type: 'REL_ABS_POINT', + absoluteX: 10.0, + absoluteY: 0.0, + relativeX: 0.0, + relativeY: 100.0, + relativeHeightForX: null, + relativeWidthForY: null, + }, + { + type: 'REL_ABS_BEZIER_POINT', + absoluteX1: 0.0, + absoluteY1: -10.0, + relativeX1: 0.0, + relativeY1: 100.0, + relativeHeightForX1: null, + relativeWidthForY1: null, + absoluteX2: 5.0, + absoluteY2: 0.0, + relativeX2: 0.0, + relativeY2: 100.0, + relativeHeightForX2: null, + relativeWidthForY2: null, + absoluteX3: 0.0, + absoluteY3: -5.0, + relativeX3: 0.0, + relativeY3: 100.0, + relativeHeightForX3: null, + relativeWidthForY3: null, + }, + { + type: 'REL_ABS_POINT', + absoluteX: 0.0, + absoluteY: 10.0, + relativeX: 0.0, + relativeY: 0.0, + relativeHeightForX: null, + relativeWidthForY: null, + }, + { + type: 'REL_ABS_BEZIER_POINT', + absoluteX1: 10.0, + absoluteY1: 0.0, + relativeX1: 0.0, + relativeY1: 0.0, + relativeHeightForX1: null, + relativeWidthForY1: null, + absoluteX2: 0.0, + absoluteY2: 5.0, + relativeX2: 0.0, + relativeY2: 0.0, + relativeHeightForX2: null, + relativeWidthForY2: null, + absoluteX3: 5.0, + absoluteY3: 0.0, + relativeX3: 0.0, + relativeY3: 0.0, + relativeHeightForX3: null, + relativeWidthForY3: null, + }, +]; + +export const COMPARTMENT_CIRCLE_CENTER: ShapeRelAbs = { + type: 'REL_ABS_POINT', + absoluteX: 0.0, + absoluteY: 0.0, + relativeX: 50.0, + relativeY: 50.0, + relativeHeightForX: null, + relativeWidthForY: null, +}; + +export const COMPARTMENT_CIRCLE_RADIUS: ShapeRelAbs = { + type: 'REL_ABS_RADIUS', + absoluteX: 0.0, + absoluteY: 0.0, + relativeX: 50.0, + relativeY: 50.0, + relativeHeightForX: null, + relativeWidthForY: null, +}; diff --git a/src/components/Map/MapViewer/MapViewer.types.ts b/src/components/Map/MapViewer/MapViewer.types.ts index f6750e5c..f10c9070 100644 --- a/src/components/Map/MapViewer/MapViewer.types.ts +++ b/src/components/Map/MapViewer/MapViewer.types.ts @@ -1,7 +1,22 @@ import View from 'ol/View'; import BaseLayer from 'ol/layer/Base'; +import { OverlayBioEntityRender } from '@/types/OLrendering'; export type MapConfig = { view: View; layers: BaseLayer[]; }; + +export type VerticalAlign = 'TOP' | 'MIDDLE' | 'BOTTOM'; +export type HorizontalAlign = 'LEFT' | 'RIGHT' | 'CENTER' | 'END' | 'START'; + +export type OverlayBioEntityGroupedElementsType = { + [id: string]: Array<OverlayBioEntityRender & { amount: number }>; +}; + +export type BoundingBox = { + x: number; + y: number; + width: number; + height: number; +}; diff --git a/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts b/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts deleted file mode 100644 index 614d3dcf..00000000 --- a/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { Color, ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models'; - -export const VECTOR_MAP_LAYER_TYPE = 'vectorMapLayer'; - -export const COMPLEX_SBO_TERMS = ['SBO:0000253', 'SBO:0000297', 'SBO:0000289']; - -export const TEXT_CUTOFF_SCALE = 0.34; -export const OUTLINE_CUTOFF_SCALE = 0.18; -export const COMPLEX_CONTENTS_CUTOFF_SCALE = 0.215; -export const REACTION_ELEMENT_CUTOFF_SCALE = 0.125; - -export const WHITE_COLOR: Color = { - alpha: 255, - rgb: 16777215, -}; - -export const BLACK_COLOR: Color = { - alpha: 255, - rgb: -16777216, -}; - -export const TRANSPARENT_COLOR: Color = { - alpha: 0, - rgb: 0, -}; - -export const REACTION_ELEMENT_TYPES = { - OPERATOR: 'OPERATOR', - SQUARE: 'SQUARE', - LINE: 'LINE', - ARROW: 'ARROW', -}; - -export const MAP_ELEMENT_TYPES = { - TEXT: 'TEXT', - MODIFICATION: 'MODIFICATION', - ACTIVITY_BORDER: 'ACTIVITY_BORDER', - ENTITY: 'ENTITY', - OVERLAY: 'OVERLAY', - COMPARTMENT: 'COMPARTMENT', -}; - -export const LAYER_ELEMENT_TYPES = { - TEXT: 'TEXT', - OVAL: 'OVAL', - RECT: 'RECT', - LINE: 'LINE', - ARROW: 'ARROW', -}; - -export const COMPARTMENT_SQUARE_POINTS: Array<ShapeRelAbs | ShapeRelAbsBezierPoint> = [ - { - type: 'REL_ABS_POINT', - absoluteX: 10.0, - absoluteY: 0.0, - relativeX: 0.0, - relativeY: 0.0, - relativeHeightForX: null, - relativeWidthForY: null, - }, - { - type: 'REL_ABS_POINT', - absoluteX: -10.0, - absoluteY: 0.0, - relativeX: 100.0, - relativeY: 0.0, - relativeHeightForX: null, - relativeWidthForY: null, - }, - { - type: 'REL_ABS_BEZIER_POINT', - absoluteX1: 0.0, - absoluteY1: 10.0, - relativeX1: 100.0, - relativeY1: 0.0, - relativeHeightForX1: null, - relativeWidthForY1: null, - absoluteX2: -5.0, - absoluteY2: 0.0, - relativeX2: 100.0, - relativeY2: 0.0, - relativeHeightForX2: null, - relativeWidthForY2: null, - absoluteX3: 0.0, - absoluteY3: 5.0, - relativeX3: 100.0, - relativeY3: 0.0, - relativeHeightForX3: null, - relativeWidthForY3: null, - }, - { - type: 'REL_ABS_POINT', - absoluteX: 0.0, - absoluteY: -10.0, - relativeX: 100.0, - relativeY: 100.0, - relativeHeightForX: null, - relativeWidthForY: null, - }, - { - type: 'REL_ABS_BEZIER_POINT', - absoluteX1: -10.0, - absoluteY1: 0.0, - relativeX1: 100.0, - relativeY1: 100.0, - relativeHeightForX1: null, - relativeWidthForY1: null, - absoluteX2: 0.0, - absoluteY2: -5.0, - relativeX2: 100.0, - relativeY2: 100.0, - relativeHeightForX2: null, - relativeWidthForY2: null, - absoluteX3: -5.0, - absoluteY3: 0.0, - relativeX3: 100.0, - relativeY3: 100.0, - relativeHeightForX3: null, - relativeWidthForY3: null, - }, - { - type: 'REL_ABS_POINT', - absoluteX: 10.0, - absoluteY: 0.0, - relativeX: 0.0, - relativeY: 100.0, - relativeHeightForX: null, - relativeWidthForY: null, - }, - { - type: 'REL_ABS_BEZIER_POINT', - absoluteX1: 0.0, - absoluteY1: -10.0, - relativeX1: 0.0, - relativeY1: 100.0, - relativeHeightForX1: null, - relativeWidthForY1: null, - absoluteX2: 5.0, - absoluteY2: 0.0, - relativeX2: 0.0, - relativeY2: 100.0, - relativeHeightForX2: null, - relativeWidthForY2: null, - absoluteX3: 0.0, - absoluteY3: -5.0, - relativeX3: 0.0, - relativeY3: 100.0, - relativeHeightForX3: null, - relativeWidthForY3: null, - }, - { - type: 'REL_ABS_POINT', - absoluteX: 0.0, - absoluteY: 10.0, - relativeX: 0.0, - relativeY: 0.0, - relativeHeightForX: null, - relativeWidthForY: null, - }, - { - type: 'REL_ABS_BEZIER_POINT', - absoluteX1: 10.0, - absoluteY1: 0.0, - relativeX1: 0.0, - relativeY1: 0.0, - relativeHeightForX1: null, - relativeWidthForY1: null, - absoluteX2: 0.0, - absoluteY2: 5.0, - relativeX2: 0.0, - relativeY2: 0.0, - relativeHeightForX2: null, - relativeWidthForY2: null, - absoluteX3: 5.0, - absoluteY3: 0.0, - relativeX3: 0.0, - relativeY3: 0.0, - relativeHeightForX3: null, - relativeWidthForY3: null, - }, -]; - -export const COMPARTMENT_CIRCLE_CENTER: ShapeRelAbs = { - type: 'REL_ABS_POINT', - absoluteX: 0.0, - absoluteY: 0.0, - relativeX: 50.0, - relativeY: 50.0, - relativeHeightForX: null, - relativeWidthForY: null, -}; - -export const COMPARTMENT_CIRCLE_RADIUS: ShapeRelAbs = { - type: 'REL_ABS_RADIUS', - absoluteX: 0.0, - absoluteY: 0.0, - relativeX: 50.0, - relativeY: 50.0, - relativeHeightForX: null, - relativeWidthForY: null, -}; diff --git a/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.types.ts b/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.types.ts deleted file mode 100644 index 709336b1..00000000 --- a/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.types.ts +++ /dev/null @@ -1,24 +0,0 @@ -import View from 'ol/View'; -import BaseLayer from 'ol/layer/Base'; -import { OverlayBioEntityRender } from '@/types/OLrendering'; - -export type MapConfig = { - view: View; - layers: BaseLayer[]; -}; - -export type VerticalAlign = 'TOP' | 'MIDDLE' | 'BOTTOM'; -export type HorizontalAlign = 'LEFT' | 'RIGHT' | 'CENTER' | 'END' | 'START'; - -export type ScaleFunction = (resolution: number) => number; - -export type OverlayBioEntityGroupedElementsType = { - [id: string]: Array<OverlayBioEntityRender & { amount: number }>; -}; - -export type BoundingBox = { - x: number; - y: number; - width: number; - height: number; -}; diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners.test.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners.test.ts deleted file mode 100644 index 2821fe91..00000000 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-function-return-type */ -import { renderHook } from '@testing-library/react'; -import { View } from 'ol'; -import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; -import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; -import { useOlMapVectorListeners } from '@/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners'; -import { onMapLeftClick } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; - -jest.mock('./mouseClick/mouseLeftClick/onMapLeftClick', () => ({ - __esModule: true, - onMapLeftClick: jest.fn(), -})); - -jest.mock('use-debounce', () => { - return { - useDebounce: () => {}, - useDebouncedCallback: () => {}, - }; -}); - -describe('useOlMapVectorListeners - util', () => { - const { Wrapper } = getReduxWrapperWithStore({ - map: { - data: { ...initialMapDataFixture }, - loading: 'succeeded', - error: { message: '', name: '' }, - openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, - }, - }); - - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe('on left click event', () => { - it('should run onMapLeftClick event', () => { - const CALLED_ONCE = 1; - const view = new View(); - - renderHook(() => useOlMapVectorListeners({ mapInstance: undefined }), { - wrapper: Wrapper, - }); - view.dispatchEvent('singleclick'); - - expect(onMapLeftClick).toBeCalledTimes(CALLED_ONCE); - }); - }); -}); diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners.ts deleted file mode 100644 index 444cf47b..00000000 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { OPTIONS } from '@/constants/map'; -import { resultDrawerOpen } from '@/redux/drawer/drawer.selectors'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { mapDataSizeSelector } from '@/redux/map/map.selectors'; -import { currentModelIdSelector, vectorRenderingSelector } from '@/redux/models/models.selectors'; -import { MapInstance } from '@/types/map'; -import { unByKey } from 'ol/Observable'; -import { useEffect, useRef } from 'react'; -import { useSelector } from 'react-redux'; -import { useDebouncedCallback } from 'use-debounce'; -import { allCommentsSelectorOfCurrentMap } from '@/redux/comment/comment.selectors'; -import { onMapLeftClick } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { Coordinate } from 'ol/coordinate'; -import { Pixel } from 'ol/pixel'; -import { onMapRightClick } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick'; -import { modelElementsForCurrentModelSelector } from '@/redux/modelElements/modelElements.selector'; -import { newReactionsForCurrentModelSelector } from '@/redux/newReactions/newReactions.selectors'; - -interface UseOlMapVectorListenersInput { - mapInstance: MapInstance; -} - -export const useOlMapVectorListeners = ({ mapInstance }: UseOlMapVectorListenersInput): void => { - const mapSize = useSelector(mapDataSizeSelector); - const modelId = useSelector(currentModelIdSelector); - const isResultDrawerOpen = useSelector(resultDrawerOpen); - const modelElementsForCurrentModel = useSelector(modelElementsForCurrentModelSelector); - const newReactionsForCurrentModel = useSelector(newReactionsForCurrentModelSelector); - const dispatch = useAppDispatch(); - const coordinate = useRef<Coordinate>([]); - const pixel = useRef<Pixel>([]); - - const comments = useSelector(allCommentsSelectorOfCurrentMap); - const vectorRendering = useAppSelector(vectorRenderingSelector); - - const handleMapLeftClick = useDebouncedCallback( - onMapLeftClick( - mapSize, - modelId, - dispatch, - isResultDrawerOpen, - comments, - modelElementsForCurrentModel || [], - newReactionsForCurrentModel, - ), - OPTIONS.clickPersistTime, - { leading: false }, - ); - - const handleRightClick = useDebouncedCallback( - onMapRightClick( - mapSize, - modelId, - dispatch, - modelElementsForCurrentModel || [], - newReactionsForCurrentModel, - ), - OPTIONS.clickPersistTime, - { - leading: false, - }, - ); - - useEffect(() => { - if (!mapInstance || !vectorRendering) { - return; - } - - const key = mapInstance.on('singleclick', event => - handleMapLeftClick({ coordinate: event.coordinate, pixel: event.pixel }, mapInstance), - ); - - // eslint-disable-next-line consistent-return - return () => unByKey(key); - }, [mapInstance, handleMapLeftClick, vectorRendering]); - - useEffect(() => { - if (!mapInstance || !vectorRendering) { - return; - } - - const rightClickEvent = (e: MouseEvent): Promise<void> | undefined => { - e.preventDefault(); - - coordinate.current = mapInstance.getEventCoordinate(e); - pixel.current = mapInstance.getEventPixel(e); - - return handleRightClick( - { coordinate: coordinate.current, pixel: pixel.current }, - mapInstance, - ); - }; - - mapInstance.getViewport().addEventListener('contextmenu', rightClickEvent); - - // eslint-disable-next-line consistent-return - return () => mapInstance.getViewport().removeEventListener('contextmenu', rightClickEvent); - }, [mapInstance, handleRightClick, vectorRendering]); -}; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers.test.ts b/src/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers.test.ts deleted file mode 100644 index 9ec7e614..00000000 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers.test.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/map.constants'; -import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; -import { renderHook } from '@testing-library/react'; -import BaseLayer from 'ol/layer/Base'; -import VectorLayer from 'ol/layer/Vector'; -import React from 'react'; -import { useOlMap } from '@/components/Map/MapViewer/utils/useOlMap'; -import { useOlMapVectorLayers } from '@/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; - -const useRefValue = { - current: null, -}; - -Object.defineProperty(useRefValue, 'current', { - get: jest.fn(() => ({ - innerHTML: '', - appendChild: jest.fn(), - addEventListener: jest.fn(), - getRootNode: jest.fn(), - })), - set: jest.fn(() => ({ - innerHTML: '', - appendChild: jest.fn(), - addEventListener: jest.fn(), - getRootNode: jest.fn(), - })), -}); - -jest.spyOn(React, 'useRef').mockReturnValue(useRefValue); - -describe('useOlMapLayers - util', () => { - const getRenderedHookResults = (): BaseLayer[] => { - const { Wrapper } = getReduxWrapperWithStore({ - map: { - data: { - ...MAP_DATA_INITIAL_STATE, - size: { - width: 256, - height: 256, - tileSize: 256, - minZoom: 1, - maxZoom: 1, - }, - position: { - initial: { - x: 256, - y: 256, - }, - last: { - x: 256, - y: 256, - }, - }, - }, - loading: 'idle', - error: { - name: '', - message: '', - }, - openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, - }, - }); - const dummyElement = document.createElement('div'); - const { result: hohResult } = renderHook(() => useOlMap({ target: dummyElement }), { - wrapper: Wrapper, - }); - - const { result } = renderHook( - () => useOlMapVectorLayers({ mapInstance: hohResult.current.mapInstance }), - { - wrapper: Wrapper, - }, - ); - return result.current; - }; - - it('should return valid VectorLayer instance [1]', () => { - const result = getRenderedHookResults(); - expect(result[0]).toBeInstanceOf(VectorLayer); - expect(result[0].getSourceState()).toBe('ready'); - }); -}); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers.ts b/src/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers.ts deleted file mode 100644 index 253c3a38..00000000 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { MapInstance } from '@/types/map'; -import { useOlMapAdditionalLayers } from '@/components/Map/MapViewer/MapViewerVector/utils/config/additionalLayers/useOlMapAdditionalLayers'; -import { useMemo } from 'react'; -import { useOlMapCardLayer } from '@/components/Map/MapViewer/MapViewerVector/utils/config/mapCardLayer/useOlMapCardLayer'; -import { useOlMapReactionsLayer } from './reactionsLayer/useOlMapReactionsLayer'; -import { MapConfig } from '../../MapViewerVector.types'; - -interface UseOlMapLayersInput { - mapInstance: MapInstance; -} - -export const useOlMapVectorLayers = ({ mapInstance }: UseOlMapLayersInput): MapConfig['layers'] => { - const reactionsLayer = useOlMapReactionsLayer({ mapInstance }); - const additionalLayers = useOlMapAdditionalLayers(mapInstance); - const mapCardLayer = useOlMapCardLayer(); - - return useMemo(() => { - return [mapCardLayer, reactionsLayer, ...additionalLayers]; - }, [mapCardLayer, reactionsLayer, additionalLayers]); -}; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts similarity index 92% rename from src/components/Map/MapViewer/MapViewerVector/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts rename to src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts index 68151ba0..eba9fde5 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts +++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts @@ -5,7 +5,7 @@ import VectorLayer from 'ol/layer/Vector'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; import { BACKGROUND_INITIAL_STATE_MOCK } from '@/redux/backgrounds/background.mock'; import { Map } from 'ol'; -import { useOlMapAdditionalLayers } from '@/components/Map/MapViewer/MapViewerVector/utils/config/additionalLayers/useOlMapAdditionalLayers'; +import { useOlMapAdditionalLayers } from '@/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers'; describe('useOlMapAdditionalLayers - util', () => { it('should return VectorLayer', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/additionalLayers/useOlMapAdditionalLayers.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts similarity index 89% rename from src/components/Map/MapViewer/MapViewerVector/utils/config/additionalLayers/useOlMapAdditionalLayers.ts rename to src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts index 01518c93..537df192 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/additionalLayers/useOlMapAdditionalLayers.ts +++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts @@ -4,7 +4,7 @@ import VectorLayer from 'ol/layer/Vector'; import VectorSource from 'ol/source/Vector'; import { useEffect, useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; -import { currentModelIdSelector, vectorRenderingSelector } from '@/redux/models/models.selectors'; +import { currentModelIdSelector } from '@/redux/models/models.selectors'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { getLayersForModel } from '@/redux/layers/layers.thunks'; import { @@ -17,16 +17,16 @@ import { usePointToProjection } from '@/utils/map/usePointToProjection'; import { MapInstance } from '@/types/map'; import { Geometry, LineString, MultiPolygon, Point } from 'ol/geom'; import Polygon from 'ol/geom/Polygon'; -import Layer from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer'; +import Layer from '@/components/Map/MapViewer/utils/shapes/layer/Layer'; import { arrowTypesSelector, lineTypesSelector } from '@/redux/shapes/shapes.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { mapDataSizeSelector } from '@/redux/map/map.selectors'; -import getDrawImageInteraction from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getDrawImageInteraction'; +import getDrawImageInteraction from '@/components/Map/MapViewer/utils/shapes/layer/getDrawImageInteraction'; import { LayerState } from '@/redux/layers/layers.types'; import { mapEditToolsActiveActionSelector } from '@/redux/mapEditTools/mapEditTools.selectors'; import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants'; import { Extent } from 'ol/extent'; -import getTransformImageInteraction from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getTransformImageInteraction'; +import getTransformImageInteraction from '@/components/Map/MapViewer/utils/shapes/layer/getTransformImageInteraction'; import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; export const useOlMapAdditionalLayers = ( @@ -45,7 +45,6 @@ export const useOlMapAdditionalLayers = ( const layersLoading = useAppSelector(layersLoadingSelector); const layersVisibilityForCurrentModel = useAppSelector(layersVisibilityForCurrentModelSelector); const activeLayer = useAppSelector(layersActiveLayerSelector); - const vectorRendering = useAppSelector(vectorRenderingSelector); const [layersState, setLayersState] = useState<Array<LayerState>>([]); const [layersLoadingState, setLayersLoadingState] = useState(false); @@ -164,7 +163,7 @@ export const useOlMapAdditionalLayers = ( if (!transformInteraction) { return () => {}; } - if (!activeLayer || !vectorRendering || activeAction !== MAP_EDIT_ACTIONS.TRANSFORM_IMAGE) { + if (!activeLayer || activeAction !== MAP_EDIT_ACTIONS.TRANSFORM_IMAGE) { return () => {}; } mapInstance?.addInteraction(transformInteraction); @@ -172,25 +171,18 @@ export const useOlMapAdditionalLayers = ( dispatch(mapEditToolsSetLayerObject(null)); mapInstance?.removeInteraction(transformInteraction); }; - }, [activeAction, activeLayer, dispatch, mapInstance, transformInteraction, vectorRendering]); + }, [activeAction, activeLayer, dispatch, mapInstance, transformInteraction]); useEffect(() => { if (!drawImageInteraction) { return; } mapInstance?.removeInteraction(drawImageInteraction); - if (!activeLayer || !vectorRendering || activeAction !== MAP_EDIT_ACTIONS.DRAW_IMAGE) { + if (!activeLayer || activeAction !== MAP_EDIT_ACTIONS.DRAW_IMAGE) { return; } mapInstance?.addInteraction(drawImageInteraction); - }, [ - activeAction, - activeLayer, - currentModelId, - drawImageInteraction, - mapInstance, - vectorRendering, - ]); + }, [activeAction, activeLayer, currentModelId, drawImageInteraction, mapInstance]); return vectorLayers; }; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/mapCardLayer/useOlMapCardLayer.test.ts b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/config/mapCardLayer/useOlMapCardLayer.test.ts rename to src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/mapCardLayer/useOlMapCardLayer.ts b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/config/mapCardLayer/useOlMapCardLayer.ts rename to src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/processModelElements.ts b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts similarity index 87% rename from src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/processModelElements.ts rename to src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts index d832a64b..25aa2078 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/processModelElements.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts @@ -1,13 +1,5 @@ import { ModelElement } from '@/types/models'; -import MapElement from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement'; -import CompartmentCircle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle'; -import CompartmentSquare from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare'; -import CompartmentPathway from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway'; -import Glyph from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph'; -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { MapInstance } from '@/types/map'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { BioShapesDict, LineTypeDict } from '@/redux/shapes/shapes.types'; @@ -16,6 +8,11 @@ import { OverlayBioEntityRender } from '@/types/OLrendering'; import { GetOverlayBioEntityColorByAvailableProperties } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useGetOverlayColor'; import VectorSource from 'ol/source/Vector'; import { MapSize } from '@/redux/map/map.types'; +import Glyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph'; +import CompartmentPathway from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway'; +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'; export default function processModelElements( modelElements: Array<ModelElement>, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.test.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.test.ts similarity index 79% rename from src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.test.ts rename to src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.test.ts index b54a29b4..c8e961ed 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.test.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.test.ts @@ -4,7 +4,7 @@ import VectorLayer from 'ol/layer/Vector'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; import { BACKGROUND_INITIAL_STATE_MOCK } from '@/redux/backgrounds/background.mock'; import { Map } from 'ol'; -import { useOlMapReactionsLayer } from '@/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer'; +import { useOlMapProcessLayer } from '@/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer'; describe('useOlMapReactionsLayer - util', () => { it('should return VectorLayer', () => { @@ -15,7 +15,7 @@ describe('useOlMapReactionsLayer - util', () => { const dummyElement = document.createElement('div'); const mapInstance = new Map({ target: dummyElement }); - const { result } = renderHook(() => useOlMapReactionsLayer({ mapInstance }), { + const { result } = renderHook(() => useOlMapProcessLayer({ mapInstance }), { wrapper: Wrapper, }); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts similarity index 87% rename from src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts rename to src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts index fd83ac6f..09d5b04e 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts @@ -4,7 +4,6 @@ import VectorLayer from 'ol/layer/Vector'; import VectorSource from 'ol/source/Vector'; import { useEffect, useMemo, useState } from 'react'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; -import MapElement from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement'; import { useSelector } from 'react-redux'; import { arrowTypesSelector, @@ -19,17 +18,12 @@ import { import { currentModelIdSelector } from '@/redux/models/models.selectors'; import { getModelElementsForModel } from '@/redux/modelElements/modelElements.thunks'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import CompartmentSquare from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare'; -import CompartmentCircle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle'; -import Glyph from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph'; -import CompartmentPathway from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway'; -import Reaction from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction'; import { newReactionsForCurrentModelSelector, newReactionsLoadingSelector, } from '@/redux/newReactions/newReactions.selectors'; import { getNewReactionsForModel } from '@/redux/newReactions/newReactions.thunks'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { getOverlayOrderSelector, overlayBioEntitiesForCurrentModelSelector, @@ -37,21 +31,27 @@ import { import { groupBy } from '@/utils/array/groupBy'; import { useGetOverlayColor } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useGetOverlayColor'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import getOverlays from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/getOverlays'; -import LineOverlay from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/LineOverlay'; import { markersSufraceOfCurrentMapDataSelector } from '@/redux/markers/markers.selectors'; import { parseSurfaceMarkersToBioEntityRender } from '@/components/Map/MapViewer/utils/config/overlaysLayer/parseSurfaceMarkersToBioEntityRender'; -import MarkerOverlay from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/MarkerOverlay'; -import processModelElements from '@/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/processModelElements'; +import processModelElements from '@/components/Map/MapViewer/utils/config/processLayer/processModelElements'; import useDebouncedValue from '@/utils/useDebouncedValue'; import { mapBackgroundTypeSelector, mapDataSizeSelector } from '@/redux/map/map.selectors'; import MapBackgroundsEnum from '@/redux/map/map.enums'; import { setMapBackgroundType } from '@/redux/map/map.slice'; import { ZOOM_RESCALING_FACTOR } from '@/constants/map'; import { OverlayOrder } from '@/redux/overlayBioEntity/overlayBioEntity.utils'; -import areOverlayOrdersNotEqual from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/areOverlayOrdersNotEqual'; +import MarkerOverlay from '@/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay'; +import LineOverlay from '@/components/Map/MapViewer/utils/shapes/overlay/LineOverlay'; +import getOverlays from '@/components/Map/MapViewer/utils/shapes/overlay/getOverlays'; +import Reaction from '@/components/Map/MapViewer/utils/shapes/reaction/Reaction'; +import CompartmentPathway from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway'; +import Glyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph'; +import CompartmentCircle from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle'; +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'; -export const useOlMapReactionsLayer = ({ +export const useOlMapProcessLayer = ({ mapInstance, }: { mapInstance: MapInstance; diff --git a/src/components/Map/MapViewer/utils/config/useOlMapCommonLayers.test.ts b/src/components/Map/MapViewer/utils/config/useOlMapCommonLayers.test.ts deleted file mode 100644 index b3117b1f..00000000 --- a/src/components/Map/MapViewer/utils/config/useOlMapCommonLayers.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/map.constants'; -import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; -import { renderHook } from '@testing-library/react'; -import BaseLayer from 'ol/layer/Base'; -import React from 'react'; -import VectorLayer from 'ol/layer/Vector'; -import { useOlMapCommonLayers } from '@/components/Map/MapViewer/utils/config/useOlMapCommonLayers'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; - -const useRefValue = { - current: null, -}; - -Object.defineProperty(useRefValue, 'current', { - get: jest.fn(() => ({ - innerHTML: '', - appendChild: jest.fn(), - addEventListener: jest.fn(), - getRootNode: jest.fn(), - })), - set: jest.fn(() => ({ - innerHTML: '', - appendChild: jest.fn(), - addEventListener: jest.fn(), - getRootNode: jest.fn(), - })), -}); - -jest.spyOn(React, 'useRef').mockReturnValue(useRefValue); - -describe('useOlMapCommonLayers - util', () => { - const getRenderedHookResults = (): BaseLayer[] => { - const { Wrapper } = getReduxWrapperWithStore({ - map: { - data: { - ...MAP_DATA_INITIAL_STATE, - size: { - width: 256, - height: 256, - tileSize: 256, - minZoom: 1, - maxZoom: 1, - }, - position: { - initial: { - x: 256, - y: 256, - }, - last: { - x: 256, - y: 256, - }, - }, - }, - loading: 'idle', - error: { - name: '', - message: '', - }, - openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, - }, - }); - - const { result } = renderHook(() => useOlMapCommonLayers(), { - wrapper: Wrapper, - }); - - return result.current; - }; - - it('should return valid VectorLayer instance [1]', () => { - const result = getRenderedHookResults(); - - expect(result[0]).toBeInstanceOf(VectorLayer); - expect(result[0].getSourceState()).toBe('ready'); - }); - - it('should return valid VectorLayer instance [2]', () => { - const result = getRenderedHookResults(); - - expect(result[1]).toBeInstanceOf(VectorLayer); - expect(result[1].getSourceState()).toBe('ready'); - }); - - it('should return valid VectorLayer instance [3]', () => { - const result = getRenderedHookResults(); - - expect(result[2]).toBeInstanceOf(VectorLayer); - expect(result[2].getSourceState()).toBe('ready'); - }); -}); diff --git a/src/components/Map/MapViewer/utils/config/useOlMapCommonLayers.ts b/src/components/Map/MapViewer/utils/config/useOlMapCommonLayers.ts deleted file mode 100644 index ad70201b..00000000 --- a/src/components/Map/MapViewer/utils/config/useOlMapCommonLayers.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { useOlMapPinsLayer } from '@/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer'; -import { useOlMapReactionsLayer } from '@/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer'; -import { useOlMapCommentsLayer } from '@/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer'; -import { useMemo } from 'react'; -import { MapConfig } from '../../MapViewer.types'; - -export const useOlMapCommonLayers = (): MapConfig['layers'] => { - const pinsLayer = useOlMapPinsLayer(); - const reactionsLayer = useOlMapReactionsLayer(); - const commentsLayer = useOlMapCommentsLayer(); - - return useMemo(() => { - return [pinsLayer, reactionsLayer, commentsLayer]; - }, [pinsLayer, reactionsLayer, commentsLayer]); -}; diff --git a/src/components/Map/MapViewer/utils/config/useOlMapLayers.test.ts b/src/components/Map/MapViewer/utils/config/useOlMapLayers.test.ts index b4bfec60..3fe8e861 100644 --- a/src/components/Map/MapViewer/utils/config/useOlMapLayers.test.ts +++ b/src/components/Map/MapViewer/utils/config/useOlMapLayers.test.ts @@ -3,11 +3,11 @@ import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/m import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { renderHook } from '@testing-library/react'; import BaseLayer from 'ol/layer/Base'; -import TileLayer from 'ol/layer/Tile'; -import React from 'react'; import VectorLayer from 'ol/layer/Vector'; +import React from 'react'; +import { useOlMap } from '@/components/Map/MapViewer/utils/useOlMap'; +import { useOlMapLayers } from '@/components/Map/MapViewer/utils/config/useOlMapLayers'; import MapBackgroundsEnum from '@/redux/map/map.enums'; -import { useOlMapLayers } from './useOlMapLayers'; const useRefValue = { current: null, @@ -63,25 +63,23 @@ describe('useOlMapLayers - util', () => { backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); - - const { result } = renderHook(() => useOlMapLayers(), { + const dummyElement = document.createElement('div'); + const { result: hohResult } = renderHook(() => useOlMap({ target: dummyElement }), { wrapper: Wrapper, }); + const { result } = renderHook( + () => useOlMapLayers({ mapInstance: hohResult.current.mapInstance }), + { + wrapper: Wrapper, + }, + ); return result.current; }; - it('should return valid TileLayer instance [1]', () => { + it('should return valid VectorLayer instance [1]', () => { const result = getRenderedHookResults(); - - expect(result[0]).toBeInstanceOf(TileLayer); + expect(result[0]).toBeInstanceOf(VectorLayer); expect(result[0].getSourceState()).toBe('ready'); }); - - it('should return valid VectorLayer instance [2]', () => { - const result = getRenderedHookResults(); - - expect(result[1]).toBeInstanceOf(VectorLayer); - expect(result[1].getSourceState()).toBe('ready'); - }); }); diff --git a/src/components/Map/MapViewer/utils/config/useOlMapLayers.ts b/src/components/Map/MapViewer/utils/config/useOlMapLayers.ts index 10169c98..ed7dc2ff 100644 --- a/src/components/Map/MapViewer/utils/config/useOlMapLayers.ts +++ b/src/components/Map/MapViewer/utils/config/useOlMapLayers.ts @@ -1,11 +1,34 @@ /* eslint-disable no-magic-numbers */ -import { useOlMapOverlaysLayer } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer'; +import { MapInstance } from '@/types/map'; +import { useOlMapAdditionalLayers } from '@/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers'; +import { useMemo } from 'react'; +import { useOlMapCardLayer } from '@/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer'; +import { useOlMapPinsLayer } from '@/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer'; +import { useOlMapReactionsLayer } from '@/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer'; +import { useOlMapCommentsLayer } from '@/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer'; import { MapConfig } from '../../MapViewer.types'; -import { useOlMapTileLayer } from './useOlMapTileLayer'; +import { useOlMapProcessLayer } from './processLayer/useOlMapProcessLayer'; -export const useOlMapLayers = (): MapConfig['layers'] => { - const overlaysLayer = useOlMapOverlaysLayer(); - const tileLayer = useOlMapTileLayer(); +interface UseOlMapLayersInput { + mapInstance: MapInstance; +} - return [tileLayer, overlaysLayer]; +export const useOlMapLayers = ({ mapInstance }: UseOlMapLayersInput): MapConfig['layers'] => { + const processLayer = useOlMapProcessLayer({ mapInstance }); + const additionalLayers = useOlMapAdditionalLayers(mapInstance); + const mapCardLayer = useOlMapCardLayer(); + const pinsLayer = useOlMapPinsLayer(); + const reactionsLayer = useOlMapReactionsLayer(); + const commentsLayer = useOlMapCommentsLayer(); + + return useMemo(() => { + return [ + mapCardLayer, + processLayer, + pinsLayer, + reactionsLayer, + commentsLayer, + ...additionalLayers, + ]; + }, [mapCardLayer, processLayer, pinsLayer, reactionsLayer, commentsLayer, additionalLayers]); }; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts index 963fc428..5631573e 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts @@ -11,7 +11,7 @@ import { apiPath } from '@/redux/apiPath'; import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEntity'; import { newReactionSchema } from '@/models/newReactionSchema'; -import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/getModelElementsIdsFromReaction'; +import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction'; import { handleReactionSearchClickFailure } from './handleReactionSearchClickFailure'; import { findClosestReactionPoint } from './findClosestReactionPoint'; diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/clickHandleReaction.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts similarity index 97% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/clickHandleReaction.test.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts index 47b21acd..d809149e 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/clickHandleReaction.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts @@ -6,7 +6,7 @@ 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/MapViewerVector/listeners/mouseClick/clickHandleReaction'; +import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; const mockedAxiosClient = mockNetworkNewAPIResponse(); diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/clickHandleReaction.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.ts similarity index 96% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/clickHandleReaction.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.ts index f9cbc6ac..2cd86bfa 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/clickHandleReaction.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.ts @@ -8,7 +8,7 @@ import { setMultipleBioEntityContents } from '@/redux/bioEntity/bioEntity.slice' import { addNumbersToEntityNumberData } from '@/redux/entityNumber/entityNumber.slice'; import { setReactions } from '@/redux/reactions/reactions.slice'; import { mapReactionToBioEntity } from '@/utils/bioEntity/mapReactionToBioEntity'; -import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/getModelElementsIdsFromReaction'; +import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction'; import { mapModelElementToBioEntity } from '@/utils/bioEntity/mapModelElementToBioEntity'; /* prettier-ignore */ diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/getModelElementsIdsFromReaction.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/getModelElementsIdsFromReaction.test.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/getModelElementsIdsFromReaction.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/getModelElementsIdsFromReaction.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts similarity index 96% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts index 46ca1e40..df86f0a2 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import { leftClickHandleAlias } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; +import { leftClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; import { openBioEntityDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts similarity index 94% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts index 11211b8b..2ef85495 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts @@ -5,17 +5,17 @@ import { resetReactionsData } from '@/redux/reactions/reactions.slice'; import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick'; import Map from 'ol/Map'; -import { onMapLeftClick } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; +import { onMapLeftClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; import { Comment } from '@/types/models'; 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/MapViewerVector/MapViewerVector.constants'; +import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import * as leftClickHandleAlias from './leftClickHandleAlias'; import * as clickHandleReaction from '../clickHandleReaction'; -jest.mock('../../../../utils/listeners/mapSingleClick/handleFeaturesClick', () => ({ +jest.mock('../../mapSingleClick/handleFeaturesClick', () => ({ handleFeaturesClick: jest.fn(), })); jest.mock('./leftClickHandleAlias', () => ({ diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts similarity index 95% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts index d9a8031c..fdca7e96 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts @@ -9,13 +9,13 @@ import { latLngToPoint } from '@/utils/map/latLngToPoint'; import { FeatureLike } from 'ol/Feature'; import { closeDrawer } from '@/redux/drawer/drawer.slice'; import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; -import { leftClickHandleAlias } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; +import { leftClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick'; import { resetReactionsData } from '@/redux/reactions/reactions.slice'; import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset'; import { FEATURE_TYPE } from '@/constants/features'; -import { clickHandleReaction } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/clickHandleReaction'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; +import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; function isFeatureFilledCompartment(feature: FeatureLike): boolean { return feature.get('type') === FEATURE_TYPE.COMPARTMENT && feature.get('filled'); diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts similarity index 95% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts index 4f9a3ade..fa6a3f17 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts @@ -1,7 +1,7 @@ /* eslint-disable no-magic-numbers */ import { updateLastRightClick } from '@/redux/map/map.slice'; import Map from 'ol/Map'; -import { onMapRightClick } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick'; +import { onMapRightClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick'; import { Layer } from 'ol/layer'; import { openContextMenu } from '@/redux/contextMenu/contextMenu.slice'; import { Source } from 'ol/source'; @@ -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/MapViewerVector/MapViewerVector.constants'; +import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import * as rightClickHandleAlias from './rightClickHandleAlias'; import * as clickHandleReaction from '../clickHandleReaction'; diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts similarity index 94% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts index 74e10fc2..9773b48e 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts @@ -11,9 +11,9 @@ import VectorLayer from 'ol/layer/Vector'; import VectorSource from 'ol/source/Vector'; import { openContextMenu } from '@/redux/contextMenu/contextMenu.slice'; import { ModelElement, NewReaction } from '@/types/models'; -import { rightClickHandleAlias } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/rightClickHandleAlias'; -import { clickHandleReaction } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/clickHandleReaction'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +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'; /* prettier-ignore */ export const onMapRightClick = diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts similarity index 94% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts index 2b936519..ae53b95c 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import { rightClickHandleAlias } from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/rightClickHandleAlias'; +import { rightClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias'; import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { setBioEntityContents } from '@/redux/bioEntity/bioEntity.slice'; import { addNumbersToEntityNumberData } from '@/redux/entityNumber/entityNumber.slice'; diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts diff --git a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.test.ts b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.test.ts index 94a53559..328c827b 100644 --- a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.test.ts @@ -4,18 +4,18 @@ import { View } from 'ol'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; import MapBackgroundsEnum from '@/redux/map/map.enums'; -import * as singleClickListener from './mapSingleClick/onMapSingleClick'; -import * as positionListener from './onMapPositionChange'; -import { useOlMapListeners } from './useOlMapListeners'; +import * as positionListener from '@/components/Map/MapViewer/utils/listeners/onMapPositionChange'; +import { useOlMapListeners } from '@/components/Map/MapViewer/utils/listeners/useOlMapListeners'; +import { onMapLeftClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; jest.mock('./onMapPositionChange', () => ({ __esModule: true, onMapPositionChange: jest.fn(), })); -jest.mock('./mapSingleClick/onMapSingleClick', () => ({ +jest.mock('./mouseClick/mouseLeftClick/onMapLeftClick', () => ({ __esModule: true, - onMapSingleClick: jest.fn(), + onMapLeftClick: jest.fn(), })); jest.mock('use-debounce', () => { @@ -52,15 +52,17 @@ describe('useOlMapListeners - util', () => { }); }); - describe('on singleclick view event', () => { - it('should run onMapPositionChange event', () => { + describe('on left click event', () => { + it('should run onMapLeftClick event', () => { const CALLED_ONCE = 1; const view = new View(); - renderHook(() => useOlMapListeners({ view, mapInstance: undefined }), { wrapper: Wrapper }); + renderHook(() => useOlMapListeners({ view, mapInstance: undefined }), { + wrapper: Wrapper, + }); view.dispatchEvent('singleclick'); - expect(singleClickListener.onMapSingleClick).toBeCalledTimes(CALLED_ONCE); + expect(onMapLeftClick).toBeCalledTimes(CALLED_ONCE); }); }); }); diff --git a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts index e7df6b03..f2952ea6 100644 --- a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts +++ b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts @@ -1,38 +1,24 @@ -import { DEFAULT_ZOOM, OPTIONS } from '@/constants/map'; -import { searchDistanceValSelector } from '@/redux/configuration/configuration.selectors'; +import { OPTIONS } from '@/constants/map'; import { resultDrawerOpen } from '@/redux/drawer/drawer.selectors'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { - mapDataLastZoomValue, - mapDataMaxZoomValue, - mapDataSizeSelector, -} from '@/redux/map/map.selectors'; -import { - currentModelSelector, - currentModelIdSelector, - vectorRenderingSelector, -} from '@/redux/models/models.selectors'; +import { mapDataSizeSelector } from '@/redux/map/map.selectors'; +import { currentModelIdSelector } from '@/redux/models/models.selectors'; import { MapInstance } from '@/types/map'; -import { View } from 'ol'; import { unByKey } from 'ol/Observable'; -import { Coordinate } from 'ol/coordinate'; -import { Pixel } from 'ol/pixel'; import { useEffect, useRef } from 'react'; import { useSelector } from 'react-redux'; import { useDebouncedCallback } from 'use-debounce'; import { allCommentsSelectorOfCurrentMap } from '@/redux/comment/comment.selectors'; -import { currentBackgroundSelector } from '@/redux/backgrounds/background.selectors'; -import { - PATHWAYS_AND_COMPARTMENTS_BACKGROUND, - SEMANTIC_BACKGROUND, -} from '@/redux/backgrounds/backgrounds.constants'; -import { TWO } from '@/constants/common'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { onMapRightClick } from './mapRightClick/onMapRightClick'; -import { onMapSingleClick } from './mapSingleClick/onMapSingleClick'; -import { onMapPositionChange } from './onMapPositionChange'; -import { onPointerMove } from './onPointerMove'; -import { useHandlePinIconClick } from './pinIconClick/useHandlePinIconClick'; +import { onMapLeftClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; +import { Coordinate } from 'ol/coordinate'; +import { Pixel } from 'ol/pixel'; +import { onMapRightClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick'; +import { modelElementsForCurrentModelSelector } from '@/redux/modelElements/modelElements.selector'; +import { newReactionsForCurrentModelSelector } from '@/redux/newReactions/newReactions.selectors'; +import { useHandlePinIconClick } from '@/components/Map/MapViewer/utils/listeners/pinIconClick/useHandlePinIconClick'; +import { onMapPositionChange } from '@/components/Map/MapViewer/utils/listeners/onMapPositionChange'; +import { onPointerMove } from '@/components/Map/MapViewer/utils/listeners/onPointerMove'; +import { View } from 'ol'; interface UseOlMapListenersInput { view: View; @@ -41,36 +27,17 @@ interface UseOlMapListenersInput { export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput): void => { const mapSize = useSelector(mapDataSizeSelector); - const model = useSelector(currentModelSelector); const modelId = useSelector(currentModelIdSelector); - const modelMinZoom = model?.minZoom || TWO; - const lastZoom = useSelector(mapDataLastZoomValue) || TWO; - const background = useSelector(currentBackgroundSelector); - const searchDistance = useSelector(searchDistanceValSelector); - const maxZoom = useSelector(mapDataMaxZoomValue); const isResultDrawerOpen = useSelector(resultDrawerOpen); + const modelElementsForCurrentModel = useSelector(modelElementsForCurrentModelSelector); + const newReactionsForCurrentModel = useSelector(newReactionsForCurrentModelSelector); + const dispatch = useAppDispatch(); const coordinate = useRef<Coordinate>([]); const pixel = useRef<Pixel>([]); - const dispatch = useAppDispatch(); const comments = useSelector(allCommentsSelectorOfCurrentMap); - const vectorRendering = useAppSelector(vectorRenderingSelector); - useHandlePinIconClick(); - const handleRightClick = useDebouncedCallback( - onMapRightClick( - mapSize, - modelId, - dispatch, - background?.name === SEMANTIC_BACKGROUND || - background?.name === PATHWAYS_AND_COMPARTMENTS_BACKGROUND, - lastZoom - modelMinZoom, - ), - OPTIONS.clickPersistTime, - { - leading: false, - }, - ); + useHandlePinIconClick(); const handleChangeCenter = useDebouncedCallback( onMapPositionChange(mapSize, dispatch), @@ -78,24 +45,34 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) { leading: false }, ); - const handleMapSingleClick = useDebouncedCallback( - onMapSingleClick( + const handleMapLeftClick = useDebouncedCallback( + onMapLeftClick( mapSize, modelId, dispatch, - searchDistance, - maxZoom, - lastZoom || DEFAULT_ZOOM, isResultDrawerOpen, comments, - background?.name === SEMANTIC_BACKGROUND || - background?.name === PATHWAYS_AND_COMPARTMENTS_BACKGROUND, - lastZoom - modelMinZoom, + modelElementsForCurrentModel || [], + newReactionsForCurrentModel, ), OPTIONS.clickPersistTime, { leading: false }, ); + const handleRightClick = useDebouncedCallback( + onMapRightClick( + mapSize, + modelId, + dispatch, + modelElementsForCurrentModel || [], + newReactionsForCurrentModel, + ), + OPTIONS.clickPersistTime, + { + leading: false, + }, + ); + useEffect(() => { const key = view.on('change:center', handleChangeCenter); return () => unByKey(key); @@ -113,20 +90,20 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) }, [mapInstance]); useEffect(() => { - if (!mapInstance || vectorRendering) { + if (!mapInstance) { return; } const key = mapInstance.on('singleclick', event => - handleMapSingleClick({ coordinate: event.coordinate, pixel: event.pixel }, mapInstance), + handleMapLeftClick({ coordinate: event.coordinate, pixel: event.pixel }, mapInstance), ); // eslint-disable-next-line consistent-return return () => unByKey(key); - }, [mapInstance, handleMapSingleClick, vectorRendering]); + }, [mapInstance, handleMapLeftClick]); useEffect(() => { - if (!mapInstance || vectorRendering) { + if (!mapInstance) { return; } @@ -136,12 +113,15 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) coordinate.current = mapInstance.getEventCoordinate(e); pixel.current = mapInstance.getEventPixel(e); - return handleRightClick(coordinate.current, pixel.current); + return handleRightClick( + { coordinate: coordinate.current, pixel: pixel.current }, + mapInstance, + ); }; mapInstance.getViewport().addEventListener('contextmenu', rightClickEvent); // eslint-disable-next-line consistent-return return () => mapInstance.getViewport().removeEventListener('contextmenu', rightClickEvent); - }, [mapInstance, handleRightClick, vectorRendering]); + }, [mapInstance, handleRightClick]); }; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/findLargestExtent.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/findLargestExtent.test.ts similarity index 76% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/findLargestExtent.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/findLargestExtent.test.ts index 2a41ebad..2bd23b66 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/findLargestExtent.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/findLargestExtent.test.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ -import findLargestExtent from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/findLargestExtent'; +import findLargestExtent from '@/components/Map/MapViewer/utils/shapes/coords/findLargestExtent'; import { Extent } from 'ol/extent'; describe('findLargestExtent', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/findLargestExtent.ts b/src/components/Map/MapViewer/utils/shapes/coords/findLargestExtent.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/findLargestExtent.ts rename to src/components/Map/MapViewer/utils/shapes/coords/findLargestExtent.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBezierCurve.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getBezierCurve.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBezierCurve.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getBezierCurve.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBezierCurve.ts b/src/components/Map/MapViewer/utils/shapes/coords/getBezierCurve.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBezierCurve.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getBezierCurve.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent.test.ts similarity index 92% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent.test.ts index 532c485d..7c44ef3e 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent.test.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ import { Extent } from 'ol/extent'; -import getBoundingBoxFromExtent from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent'; +import getBoundingBoxFromExtent from '@/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent'; describe('getBoundingBoxFromExtent', () => { it('should return a bounding box for extent', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent.ts b/src/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent.ts similarity index 96% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent.ts index efab1e2d..7201ee00 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent.ts @@ -3,7 +3,7 @@ import { MapSize } from '@/redux/map/map.types'; import { toLonLat } from 'ol/proj'; import { latLngToPoint } from '@/utils/map/latLngToPoint'; import { Extent } from 'ol/extent'; -import { BoundingBox } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { BoundingBox } from '@/components/Map/MapViewer/MapViewer.types'; export default function getBoundingBoxFromExtent(extent: Extent, mapSize: MapSize): BoundingBox { const [startLng, startLat] = toLonLat([extent[0], extent[3]]); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCenter.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getCenter.test.ts similarity index 81% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCenter.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getCenter.test.ts index 6373f63b..83defeab 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCenter.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getCenter.test.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ import { Coordinate } from 'ol/coordinate'; -import getCenter from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCenter'; +import getCenter from '@/components/Map/MapViewer/utils/shapes/coords/getCenter'; describe('getCenter', () => { it('should return a center for coordinates', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCenter.ts b/src/components/Map/MapViewer/utils/shapes/coords/getCenter.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCenter.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getCenter.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getCoordsX.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getCoordsX.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX.ts b/src/components/Map/MapViewer/utils/shapes/coords/getCoordsX.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getCoordsX.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getCoordsY.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getCoordsY.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY.ts b/src/components/Map/MapViewer/utils/shapes/coords/getCoordsY.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getCoordsY.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getCurveCoords.test.ts similarity index 90% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getCurveCoords.test.ts index adf5685f..1c824de0 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getCurveCoords.test.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ -import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX'; -import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY'; +import getCoordsX from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsX'; +import getCoordsY from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsY'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { ShapeRelAbsBezierPoint } from '@/types/models'; import getCurveCoords from './getCurveCoords'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords.ts b/src/components/Map/MapViewer/utils/shapes/coords/getCurveCoords.ts similarity index 85% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getCurveCoords.ts index 8cd0f0ec..e75d72f2 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getCurveCoords.ts @@ -1,7 +1,7 @@ import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { Coordinate } from 'ol/coordinate'; -import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX'; -import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY'; +import getCoordsX from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsX'; +import getCoordsY from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsY'; import { ShapeRelAbsBezierPoint } from '@/types/models'; export default function getCurveCoords({ diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getDividedExtents.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getDividedExtents.test.ts similarity index 94% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getDividedExtents.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getDividedExtents.test.ts index ea4a9f89..302b8f11 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getDividedExtents.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getDividedExtents.test.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ import { Extent } from 'ol/extent'; -import getDividedExtents from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getDividedExtents'; +import getDividedExtents from '@/components/Map/MapViewer/utils/shapes/coords/getDividedExtents'; describe('getDividedExtents', () => { it('should return original extents if there is no intersection with dividingExtent', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getDividedExtents.ts b/src/components/Map/MapViewer/utils/shapes/coords/getDividedExtents.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getDividedExtents.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getDividedExtents.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords.test.ts similarity index 89% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords.test.ts index 515eabf4..8c4fd4dc 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords.test.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ -import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX'; -import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY'; +import getCoordsX from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsX'; +import getCoordsY from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsY'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { ShapeRelAbs } from '@/types/models'; import getEllipseCoords from './getEllipseCoords'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords.ts b/src/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords.ts similarity index 89% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords.ts index c617ffaf..bd72dd21 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ -import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX'; -import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY'; +import getCoordsX from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsX'; +import getCoordsY from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsY'; import { Coordinate } from 'ol/coordinate'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { ShapeRelAbs } from '@/types/models'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getLineSegments.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getLineSegments.test.ts similarity index 97% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getLineSegments.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getLineSegments.test.ts index ec6d5a70..9ce67a91 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getLineSegments.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getLineSegments.test.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ import { Line } from '@/types/models'; -import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import getLineSegments from './getLineSegments'; describe('getLineSegments', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getLineSegments.ts b/src/components/Map/MapViewer/utils/shapes/coords/getLineSegments.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getLineSegments.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getLineSegments.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords.test.ts similarity index 88% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords.test.ts index ed84c661..6060feff 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords.test.ts @@ -1,8 +1,8 @@ /* eslint-disable no-magic-numbers */ -import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX'; -import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY'; -import getCurveCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords'; -import getBezierCurve from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBezierCurve'; +import getCoordsX from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsX'; +import getCoordsY from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsY'; +import getCurveCoords from '@/components/Map/MapViewer/utils/shapes/coords/getCurveCoords'; +import getBezierCurve from '@/components/Map/MapViewer/utils/shapes/coords/getBezierCurve'; import { ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models'; import getPolygonCoords from './getPolygonCoords'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords.ts b/src/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords.ts similarity index 76% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords.ts index d00816b5..db3f1b7c 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords.ts @@ -1,10 +1,10 @@ /* eslint-disable no-magic-numbers */ import { Coordinate } from 'ol/coordinate'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; -import getBezierCurve from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBezierCurve'; -import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX'; -import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY'; -import getCurveCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords'; +import getBezierCurve from '@/components/Map/MapViewer/utils/shapes/coords/getBezierCurve'; +import getCoordsX from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsX'; +import getCoordsY from '@/components/Map/MapViewer/utils/shapes/coords/getCoordsY'; +import getCurveCoords from '@/components/Map/MapViewer/utils/shapes/coords/getCurveCoords'; import { ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models'; export default function getPolygonCoords({ diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getRotation.test.ts b/src/components/Map/MapViewer/utils/shapes/coords/getRotation.test.ts similarity index 83% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getRotation.test.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getRotation.test.ts index 363add1a..0e26ba92 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getRotation.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/coords/getRotation.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import getRotation from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getRotation'; +import getRotation from '@/components/Map/MapViewer/utils/shapes/coords/getRotation'; import { Coordinate } from 'ol/coordinate'; const testCases: Array<[Coordinate, Coordinate, number]> = [ diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getRotation.ts b/src/components/Map/MapViewer/utils/shapes/coords/getRotation.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getRotation.ts rename to src/components/Map/MapViewer/utils/shapes/coords/getRotation.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts b/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts similarity index 91% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts rename to src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts index dd541d11..23277551 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts @@ -4,14 +4,8 @@ import { Stroke, Style } from 'ol/style'; import Feature, { FeatureLike } from 'ol/Feature'; import { MultiPolygon } from 'ol/geom'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { MapInstance } from '@/types/map'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; import { Color } from '@/types/models'; import { COMPLEX_CONTENTS_CUTOFF_SCALE, @@ -19,13 +13,16 @@ import { MAP_ELEMENT_TYPES, OUTLINE_CUTOFF_SCALE, TEXT_CUTOFF_SCALE, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +} from '@/components/Map/MapViewer/MapViewer.constants'; import VectorSource from 'ol/source/Vector'; import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MapSize } from '@/redux/map/map.types'; -import getCoverStyles from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getCoverStyles'; -import handleSemanticView from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView'; -import getScaledStrokeStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledStrokeStyle'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import getCoverStyles from '@/components/Map/MapViewer/utils/shapes/style/getCoverStyles'; +import handleSemanticView from '@/components/Map/MapViewer/utils/shapes/elements/handleSemanticView'; +import getScaledStrokeStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledStrokeStyle'; export interface BaseMapElementProps { type: string; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment.ts b/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts similarity index 89% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment.ts rename to src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts index 75c519ef..10802411 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts @@ -1,24 +1,21 @@ /* eslint-disable no-magic-numbers */ import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; -import BaseMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { Coordinate } from 'ol/coordinate'; import Polygon from 'ol/geom/Polygon'; import { Stroke, Style } from 'ol/style'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; import { MapInstance } from '@/types/map'; import { Color } from '@/types/models'; import { MAP_ELEMENT_TYPES, TRANSPARENT_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +} from '@/components/Map/MapViewer/MapViewer.constants'; import VectorSource from 'ol/source/Vector'; import { MapSize } from '@/redux/map/map.types'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import BaseMultiPolygon from '@/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon'; export interface CompartmentProps { id: number; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts similarity index 78% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts index 7c5956c6..eb94b525 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts @@ -2,24 +2,21 @@ import { Feature, Map } from 'ol'; import { Fill, Stroke, Style, Text } from 'ol/style'; import { Polygon, MultiPolygon } from 'ol/geom'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; -import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import View from 'ol/View'; -import { - WHITE_COLOR, - BLACK_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import CompartmentCircle, { - CompartmentCircleProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle'; -import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; +import { WHITE_COLOR, BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import VectorSource from 'ol/source/Vector'; import MapBackgroundsEnum from '@/redux/map/map.enums'; import { DEFAULT_TILE_SIZE } from '@/constants/map'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import getShapePolygon from '@/components/Map/MapViewer/utils/shapes/elements/getShapePolygon'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import CompartmentCircle, { + CompartmentCircleProps, +} from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle'; +import getEllipseCoords from '@/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; jest.mock('../text/getTextStyle'); jest.mock('../text/getTextCoords'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts similarity index 87% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle.ts rename to src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts index 94a65df8..78915ae4 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentCircle.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts @@ -1,21 +1,18 @@ /* eslint-disable no-magic-numbers */ import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { MapInstance } from '@/types/map'; -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { BLACK_COLOR, COMPARTMENT_CIRCLE_CENTER, COMPARTMENT_CIRCLE_RADIUS, WHITE_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords'; -import Compartment from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment'; +} from '@/components/Map/MapViewer/MapViewer.constants'; import { Color } from '@/types/models'; import VectorSource from 'ol/source/Vector'; import { MapSize } from '@/redux/map/map.types'; +import Compartment from '@/components/Map/MapViewer/utils/shapes/elements/Compartment'; +import getEllipseCoords from '@/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords'; export type CompartmentCircleProps = { id: number; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts similarity index 78% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts index 00c1931b..05e1801e 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts @@ -2,24 +2,21 @@ import { Feature, Map } from 'ol'; import { Fill, Stroke, Style, Text } from 'ol/style'; import { Polygon, MultiPolygon } from 'ol/geom'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; -import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import View from 'ol/View'; -import { - WHITE_COLOR, - BLACK_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import CompartmentPathway, { - CompartmentPathwayProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway'; -import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; +import { WHITE_COLOR, BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import VectorSource from 'ol/source/Vector'; import MapBackgroundsEnum from '@/redux/map/map.enums'; import { DEFAULT_TILE_SIZE } from '@/constants/map'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import getShapePolygon from '@/components/Map/MapViewer/utils/shapes/elements/getShapePolygon'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import CompartmentPathway, { + CompartmentPathwayProps, +} from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway'; +import getEllipseCoords from '@/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; jest.mock('../text/getTextStyle'); jest.mock('../text/getTextCoords'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts similarity index 83% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.ts rename to src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts index eef5c0f7..94034677 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts @@ -1,26 +1,23 @@ /* eslint-disable no-magic-numbers */ import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { MapInstance } from '@/types/map'; -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { BLACK_COLOR, MAP_ELEMENT_TYPES, TRANSPARENT_COLOR, WHITE_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +} from '@/components/Map/MapViewer/MapViewer.constants'; import Polygon from 'ol/geom/Polygon'; -import BaseMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; import { Color } from '@/types/models'; import VectorSource from 'ol/source/Vector'; import { Style } from 'ol/style'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import { MapSize } from '@/redux/map/map.types'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; +import BaseMultiPolygon from '@/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; export type CompartmentPathwayProps = { id: number; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts similarity index 79% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts index 53fff2ff..acf2471c 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts @@ -2,23 +2,20 @@ import { Feature, Map } from 'ol'; import { Fill, Stroke, Style, Text } from 'ol/style'; import { MultiPolygon } from 'ol/geom'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import View from 'ol/View'; -import { - WHITE_COLOR, - BLACK_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import CompartmentSquare, { - CompartmentSquareProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare'; -import getPolygonCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; +import { WHITE_COLOR, BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import VectorSource from 'ol/source/Vector'; import MapBackgroundsEnum from '@/redux/map/map.enums'; import { DEFAULT_TILE_SIZE } from '@/constants/map'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import CompartmentSquare, { + CompartmentSquareProps, +} from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare'; +import getPolygonCoords from '@/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; jest.mock('../text/getTextStyle'); jest.mock('../text/getTextCoords'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts similarity index 87% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare.ts rename to src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts index 8f033df3..34f95693 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentSquare.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts @@ -1,20 +1,17 @@ /* eslint-disable no-magic-numbers */ import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { MapInstance } from '@/types/map'; -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { BLACK_COLOR, COMPARTMENT_SQUARE_POINTS, WHITE_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import getPolygonCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords'; -import Compartment from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment'; +} from '@/components/Map/MapViewer/MapViewer.constants'; import { Color } from '@/types/models'; import VectorSource from 'ol/source/Vector'; import { MapSize } from '@/redux/map/map.types'; +import Compartment from '@/components/Map/MapViewer/utils/shapes/elements/Compartment'; +import getPolygonCoords from '@/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords'; export type CompartmentSquareProps = { id: number; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.test.ts similarity index 93% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.test.ts index ff2a0ac2..2680f7ef 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.test.ts @@ -2,9 +2,7 @@ import { Feature, Map, View } from 'ol'; import { Style } from 'ol/style'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; -import Glyph, { - GlyphProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph'; +import Glyph, { GlyphProps } from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph'; import { MapInstance } from '@/types/map'; import Polygon from 'ol/geom/Polygon'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph.ts b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts similarity index 95% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph.ts rename to src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts index a0676acd..1da2b4fb 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts @@ -11,13 +11,13 @@ import Polygon from 'ol/geom/Polygon'; import { Point } from 'ol/geom'; import { Coordinate } from 'ol/coordinate'; import { FEATURE_TYPE } from '@/constants/features'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; -import { WHITE_COLOR } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import getScaledElementStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle'; -import getBoundingBoxFromExtent from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent'; +import { WHITE_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import { MapSize } from '@/redux/map/map.types'; import { LayerImage } from '@/types/models'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle'; +import getBoundingBoxFromExtent from '@/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent'; export type GlyphProps = { elementId: number; @@ -249,6 +249,7 @@ export default class Glyph { }), zIndex: this.zIndex, }); + this.feature.changed(); }; img.src = `${BASE_NEW_API_URL}${apiPath.getGlyphImage(this.glyphId)}`; } diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/updateGlyph.ts b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/updateGlyph.ts rename to src/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts similarity index 80% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts index 9dbf5336..744c6529 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts @@ -2,24 +2,21 @@ import { Feature, Map } from 'ol'; import { Fill, Stroke, Style, Text } from 'ol/style'; import { Polygon, MultiPolygon } from 'ol/geom'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; -import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; -import MapElement, { - MapElementProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement'; import View from 'ol/View'; -import { - WHITE_COLOR, - BLACK_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; +import { WHITE_COLOR, BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import { shapesFixture } from '@/models/fixtures/shapesFixture'; import VectorSource from 'ol/source/Vector'; import MapBackgroundsEnum from '@/redux/map/map.enums'; import { DEFAULT_TILE_SIZE } from '@/constants/map'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import getShapePolygon from '@/components/Map/MapViewer/utils/shapes/elements/getShapePolygon'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import MapElement, { + MapElementProps, +} from '@/components/Map/MapViewer/utils/shapes/elements/MapElement'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; jest.mock('../text/getTextStyle'); jest.mock('../text/getTextCoords'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts similarity index 91% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts rename to src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts index 38b6b16d..ead1dd13 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts @@ -1,28 +1,17 @@ /* eslint-disable no-magic-numbers */ import { Style } from 'ol/style'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; import Polygon from 'ol/geom/Polygon'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import { Color, Modification, Shape } from '@/types/models'; import { MapInstance } from '@/types/map'; -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { BLACK_COLOR, COMPLEX_SBO_TERMS, MAP_ELEMENT_TYPES, TRANSPARENT_COLOR, WHITE_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import BaseMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; -import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; +} from '@/components/Map/MapViewer/MapViewer.constants'; import { BioShapesDict, LineTypeDict } from '@/redux/shapes/shapes.types'; import { FEATURE_TYPE } from '@/constants/features'; import { OverlayBioEntityRender } from '@/types/OLrendering'; @@ -32,6 +21,14 @@ import { OverlayOrder } from '@/redux/overlayBioEntity/overlayBioEntity.utils'; import { GetOverlayBioEntityColorByAvailableProperties } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useGetOverlayColor'; import VectorSource from 'ol/source/Vector'; import { MapSize } from '@/redux/map/map.types'; +import getShapePolygon from '@/components/Map/MapViewer/utils/shapes/elements/getShapePolygon'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; +import BaseMultiPolygon from '@/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; export type MapElementProps = { id: number; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/getArrowFeature.test.ts similarity index 89% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/getArrowFeature.test.ts index 71a6ce39..970241b9 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/getArrowFeature.test.ts @@ -2,11 +2,11 @@ import { Feature } from 'ol'; import { Fill, Stroke, Style } from 'ol/style'; import { Polygon, MultiPolygon } from 'ol/geom'; -import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; -import getArrowFeature from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature'; -import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import { ArrowTypeDict } from '@/redux/shapes/shapes.types'; +import getShapePolygon from '@/components/Map/MapViewer/utils/shapes/elements/getShapePolygon'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; +import getArrowFeature from '@/components/Map/MapViewer/utils/shapes/elements/getArrowFeature'; jest.mock('../style/getStyle'); jest.mock('./getShapePolygon'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.ts b/src/components/Map/MapViewer/utils/shapes/elements/getArrowFeature.ts similarity index 80% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.ts rename to src/components/Map/MapViewer/utils/shapes/elements/getArrowFeature.ts index c8f46d9d..0ccc40a2 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/getArrowFeature.ts @@ -1,16 +1,16 @@ /* eslint-disable no-magic-numbers */ import Style from 'ol/style/Style'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; import { Feature } from 'ol'; import { MultiPolygon } from 'ol/geom'; import { Arrow, Color } from '@/types/models'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; -import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; import Polygon from 'ol/geom/Polygon'; -import { WHITE_COLOR } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +import { WHITE_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import { ArrowTypeDict } from '@/redux/shapes/shapes.types'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; +import getShapePolygon from '@/components/Map/MapViewer/utils/shapes/elements/getShapePolygon'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; export default function getArrowFeature({ arrowTypes, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/getShapePolygon.test.ts similarity index 94% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/getShapePolygon.test.ts index 0074f57b..5254b54e 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/getShapePolygon.test.ts @@ -1,9 +1,9 @@ /* eslint-disable no-magic-numbers */ -import getPolygonCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords'; -import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords'; +import getPolygonCoords from '@/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords'; +import getEllipseCoords from '@/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords'; import Polygon from 'ol/geom/Polygon'; import { Shape } from '@/types/models'; -import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; +import getShapePolygon from '@/components/Map/MapViewer/utils/shapes/elements/getShapePolygon'; jest.mock('../coords/getPolygonCoords'); jest.mock('../coords/getEllipseCoords'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon.ts b/src/components/Map/MapViewer/utils/shapes/elements/getShapePolygon.ts similarity index 78% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon.ts rename to src/components/Map/MapViewer/utils/shapes/elements/getShapePolygon.ts index 7e2f7a59..a2082fe3 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/getShapePolygon.ts @@ -1,11 +1,11 @@ /* eslint-disable no-magic-numbers */ import Polygon from 'ol/geom/Polygon'; import { Coordinate } from 'ol/coordinate'; -import getPolygonCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords'; -import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords'; +import getPolygonCoords from '@/components/Map/MapViewer/utils/shapes/coords/getPolygonCoords'; +import getEllipseCoords from '@/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords'; import { Shape } from '@/types/models'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; -import getCenter from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCenter'; +import getCenter from '@/components/Map/MapViewer/utils/shapes/coords/getCenter'; export default function getShapePolygon({ shape, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.test.ts similarity index 89% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.test.ts index f6360b51..c2d9e620 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.test.ts @@ -1,9 +1,9 @@ /* eslint-disable no-magic-numbers */ import Feature from 'ol/Feature'; import VectorSource from 'ol/source/Vector'; -import getDividedExtents from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getDividedExtents'; -import findLargestExtent from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/findLargestExtent'; -import handleSemanticView from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView'; +import getDividedExtents from '@/components/Map/MapViewer/utils/shapes/coords/getDividedExtents'; +import findLargestExtent from '@/components/Map/MapViewer/utils/shapes/coords/findLargestExtent'; +import handleSemanticView from '@/components/Map/MapViewer/utils/shapes/elements/handleSemanticView'; import Geometry from 'ol/geom/Geometry'; import { fromExtent } from 'ol/geom/Polygon'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts b/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.ts similarity index 86% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts rename to src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.ts index 71c32e6f..cd5aa1f4 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.ts @@ -1,14 +1,14 @@ /* eslint-disable no-magic-numbers */ -import getDividedExtents from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getDividedExtents'; -import findLargestExtent from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/findLargestExtent'; import Feature from 'ol/Feature'; import VectorSource from 'ol/source/Vector'; import { Extent } from 'ol/extent'; import { COMPLEX_SBO_TERMS, MAP_ELEMENT_TYPES, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import isFeatureInCompartment from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/isFeatureInCompartment'; +} from '@/components/Map/MapViewer/MapViewer.constants'; +import findLargestExtent from '@/components/Map/MapViewer/utils/shapes/coords/findLargestExtent'; +import getDividedExtents from '@/components/Map/MapViewer/utils/shapes/coords/getDividedExtents'; +import isFeatureInCompartment from '@/components/Map/MapViewer/utils/shapes/elements/isFeatureInCompartment'; export default function handleSemanticView({ vectorSource, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/isFeatureInCompartment.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/isFeatureInCompartment.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/isFeatureInCompartment.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/isFeatureInCompartment.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/isFeatureInCompartment.ts b/src/components/Map/MapViewer/utils/shapes/elements/isFeatureInCompartment.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/isFeatureInCompartment.ts rename to src/components/Map/MapViewer/utils/shapes/elements/isFeatureInCompartment.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/removeElementFromLayer.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/removeElementFromLayer.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/removeElementFromLayer.test.ts rename to src/components/Map/MapViewer/utils/shapes/elements/removeElementFromLayer.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/removeElementFromLayer.ts b/src/components/Map/MapViewer/utils/shapes/elements/removeElementFromLayer.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/removeElementFromLayer.ts rename to src/components/Map/MapViewer/utils/shapes/elements/removeElementFromLayer.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts similarity index 84% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.test.ts rename to src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts index 9da93414..d9f3c022 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts @@ -1,20 +1,15 @@ /* eslint-disable no-magic-numbers */ import { Map } from 'ol'; import { Stroke, Style, Text } from 'ol/style'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import View from 'ol/View'; -import { - WHITE_COLOR, - BLACK_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; -import Layer, { - LayerProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer'; +import { WHITE_COLOR, BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import VectorSource from 'ol/source/Vector'; import VectorLayer from 'ol/layer/Vector'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; +import Layer, { LayerProps } from '@/components/Map/MapViewer/utils/shapes/layer/Layer'; jest.mock('../text/getTextCoords'); jest.mock('../text/getTextStyle'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts similarity index 92% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts rename to src/components/Map/MapViewer/utils/shapes/layer/Layer.ts index 84c3f317..282e25e4 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts @@ -4,18 +4,10 @@ import { MapInstance } from '@/types/map'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { Feature } from 'ol'; import { LineString, MultiPolygon, Point } from 'ol/geom'; -import Text from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text'; import Polygon from 'ol/geom/Polygon'; import VectorSource from 'ol/source/Vector'; import VectorLayer from 'ol/layer/Vector'; -import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; -import getRotation from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getRotation'; -import getArrowFeature from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { FeatureLike } from 'ol/Feature'; import Style from 'ol/style/Style'; import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types'; @@ -23,11 +15,16 @@ import { LAYER_ELEMENT_TYPES, REACTION_ELEMENT_CUTOFF_SCALE, TRANSPARENT_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import getScaledElementStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle'; +} from '@/components/Map/MapViewer/MapViewer.constants'; import { Stroke } from 'ol/style'; -import Glyph from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph/Glyph'; import { MapSize } from '@/redux/map/map.types'; +import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle'; +import Glyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph'; +import getArrowFeature from '@/components/Map/MapViewer/utils/shapes/elements/getArrowFeature'; +import getRotation from '@/components/Map/MapViewer/utils/shapes/coords/getRotation'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; +import getEllipseCoords from '@/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords'; +import Text from '@/components/Map/MapViewer/utils/shapes/text/Text'; export interface LayerProps { texts: Array<LayerText>; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getDrawImageInteraction.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/getDrawImageInteraction.test.ts similarity index 96% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getDrawImageInteraction.test.ts rename to src/components/Map/MapViewer/utils/shapes/layer/getDrawImageInteraction.test.ts index e0c9fb44..2e9e3f88 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getDrawImageInteraction.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/getDrawImageInteraction.test.ts @@ -12,7 +12,7 @@ import { DEFAULT_TILE_SIZE } from '@/constants/map'; import { Map } from 'ol'; import getDrawImageInteraction from './getDrawImageInteraction'; -jest.mock('../../../../../../../utils/map/latLngToPoint', () => ({ +jest.mock('../../../../../../utils/map/latLngToPoint', () => ({ latLngToPoint: jest.fn(latLng => ({ x: latLng[0], y: latLng[1] })), })); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getDrawImageInteraction.ts b/src/components/Map/MapViewer/utils/shapes/layer/getDrawImageInteraction.ts similarity index 97% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getDrawImageInteraction.ts rename to src/components/Map/MapViewer/utils/shapes/layer/getDrawImageInteraction.ts index 35bd90a5..8c37bf36 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getDrawImageInteraction.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/getDrawImageInteraction.ts @@ -7,7 +7,7 @@ import { AppDispatch } from '@/redux/store'; import { Coordinate } from 'ol/coordinate'; import { openLayerImageObjectFactoryModal } from '@/redux/modal/modal.slice'; import { Extent } from 'ol/extent'; -import getBoundingBoxFromExtent from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent'; +import getBoundingBoxFromExtent from '@/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent'; export default function getDrawImageInteraction( mapSize: MapSize, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getTransformImageInteraction.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/getTransformImageInteraction.test.ts similarity index 92% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getTransformImageInteraction.test.ts rename to src/components/Map/MapViewer/utils/shapes/layer/getTransformImageInteraction.test.ts index 92a891c8..718037ff 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getTransformImageInteraction.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/getTransformImageInteraction.test.ts @@ -8,11 +8,11 @@ import { import { ModalState } from '@/redux/modal/modal.types'; import { DEFAULT_TILE_SIZE } from '@/constants/map'; import { Collection, Feature } from 'ol'; -import getTransformImageInteraction from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getTransformImageInteraction'; +import getTransformImageInteraction from '@/components/Map/MapViewer/utils/shapes/layer/getTransformImageInteraction'; import Transform from 'ol-ext/interaction/Transform'; import { Geometry } from 'ol/geom'; -jest.mock('../../../../../../../utils/map/latLngToPoint', () => ({ +jest.mock('../../../../../../utils/map/latLngToPoint', () => ({ latLngToPoint: jest.fn(latLng => ({ x: latLng[0], y: latLng[1] })), })); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getTransformImageInteraction.ts b/src/components/Map/MapViewer/utils/shapes/layer/getTransformImageInteraction.ts similarity index 98% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getTransformImageInteraction.ts rename to src/components/Map/MapViewer/utils/shapes/layer/getTransformImageInteraction.ts index eecc3665..596205e6 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/getTransformImageInteraction.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/getTransformImageInteraction.ts @@ -7,7 +7,7 @@ import { Collection, Feature } from 'ol'; import BaseEvent from 'ol/events/Event'; import { updateLayerImageObject } from '@/redux/layers/layers.thunks'; import { layerUpdateImage } from '@/redux/layers/layers.slice'; -import getBoundingBoxFromExtent from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBoundingBoxFromExtent'; +import getBoundingBoxFromExtent from '@/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent'; import { MapSize } from '@/redux/map/map.types'; import { Extent } from 'ol/extent'; import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/LineOverlay.test.ts b/src/components/Map/MapViewer/utils/shapes/overlay/LineOverlay.test.ts similarity index 78% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/LineOverlay.test.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/LineOverlay.test.ts index 4efbc9d6..0888de5c 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/LineOverlay.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/overlay/LineOverlay.test.ts @@ -1,13 +1,13 @@ /* eslint-disable no-magic-numbers */ import { Feature, Map } from 'ol'; import { Stroke, Style } from 'ol/style'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; import View from 'ol/View'; import LineOverlay, { LineOverlayProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/LineOverlay'; +} from '@/components/Map/MapViewer/utils/shapes/overlay/LineOverlay'; import { Coordinate } from 'ol/coordinate'; jest.mock('../style/getStroke'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/LineOverlay.ts b/src/components/Map/MapViewer/utils/shapes/overlay/LineOverlay.ts similarity index 96% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/LineOverlay.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/LineOverlay.ts index b6d8eecb..adf9beb8 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/LineOverlay.ts +++ b/src/components/Map/MapViewer/utils/shapes/overlay/LineOverlay.ts @@ -2,7 +2,7 @@ import { OverlayBioEntityRender } from '@/types/OLrendering'; import { GetOverlayBioEntityColorByAvailableProperties } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useGetOverlayColor'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { LineString } from 'ol/geom'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; import { Feature } from 'ol'; import { FeatureLike } from 'ol/Feature'; import Style from 'ol/style/Style'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/MarkerOverlay.test.ts b/src/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay.test.ts similarity index 79% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/MarkerOverlay.test.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay.test.ts index 4fe3c4aa..19bc84b6 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/MarkerOverlay.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay.test.ts @@ -1,14 +1,14 @@ /* eslint-disable no-magic-numbers */ import { Feature, Map } from 'ol'; import { Stroke, Style } from 'ol/style'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; import View from 'ol/View'; import { Coordinate } from 'ol/coordinate'; import MarkerOverlay, { MarkerOverlayProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/MarkerOverlay'; +} from '@/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay'; jest.mock('../style/getStroke'); jest.mock('../style/getFill'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/MarkerOverlay.ts b/src/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay.ts similarity index 96% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/MarkerOverlay.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay.ts index a0336335..e963d768 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/MarkerOverlay.ts +++ b/src/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay.ts @@ -1,7 +1,7 @@ import { OverlayBioEntityRender } from '@/types/OLrendering'; import { GetOverlayBioEntityColorByAvailableProperties } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useGetOverlayColor'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; import { Feature } from 'ol'; import { FeatureLike } from 'ol/Feature'; import Style from 'ol/style/Style'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/areOverlayOrdersNotEqual.ts b/src/components/Map/MapViewer/utils/shapes/overlay/areOverlayOrdersNotEqual.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/areOverlayOrdersNotEqual.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/areOverlayOrdersNotEqual.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/calculateOverlayDimensions.test.ts b/src/components/Map/MapViewer/utils/shapes/overlay/calculateOverlayDimensions.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/calculateOverlayDimensions.test.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/calculateOverlayDimensions.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/calculateOverlayDimensions.ts b/src/components/Map/MapViewer/utils/shapes/overlay/calculateOverlayDimensions.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/calculateOverlayDimensions.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/calculateOverlayDimensions.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/findMatchingSubmapLinkRectangle.test.ts b/src/components/Map/MapViewer/utils/shapes/overlay/findMatchingSubmapLinkRectangle.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/findMatchingSubmapLinkRectangle.test.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/findMatchingSubmapLinkRectangle.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/findMatchingSubmapLinkRectangle.ts b/src/components/Map/MapViewer/utils/shapes/overlay/findMatchingSubmapLinkRectangle.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/findMatchingSubmapLinkRectangle.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/findMatchingSubmapLinkRectangle.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/getOverlays.test.ts b/src/components/Map/MapViewer/utils/shapes/overlay/getOverlays.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/getOverlays.test.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/getOverlays.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/getOverlays.ts b/src/components/Map/MapViewer/utils/shapes/overlay/getOverlays.ts similarity index 83% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/getOverlays.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/getOverlays.ts index 8cc7c004..687e2e67 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/getOverlays.ts +++ b/src/components/Map/MapViewer/utils/shapes/overlay/getOverlays.ts @@ -1,7 +1,7 @@ import { OverlayBioEntityRender } from '@/types/OLrendering'; import { GetOverlayBioEntityColorByAvailableProperties } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useGetOverlayColor'; -import groupOverlayEntities from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/groupOverlayEntities'; -import processOverlayGroupedElements from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/processOverlayGroupedElements'; +import groupOverlayEntities from '@/components/Map/MapViewer/utils/shapes/overlay/groupOverlayEntities'; +import processOverlayGroupedElements from '@/components/Map/MapViewer/utils/shapes/overlay/processOverlayGroupedElements'; export default function getOverlays( groupedOverlays: Record<string, Array<OverlayBioEntityRender>>, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/groupOverlayEntities.test.ts b/src/components/Map/MapViewer/utils/shapes/overlay/groupOverlayEntities.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/groupOverlayEntities.test.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/groupOverlayEntities.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/groupOverlayEntities.ts b/src/components/Map/MapViewer/utils/shapes/overlay/groupOverlayEntities.ts similarity index 88% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/groupOverlayEntities.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/groupOverlayEntities.ts index 984574cf..f9a63e9e 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/groupOverlayEntities.ts +++ b/src/components/Map/MapViewer/utils/shapes/overlay/groupOverlayEntities.ts @@ -1,6 +1,6 @@ import { OverlayBioEntityRender } from '@/types/OLrendering'; -import findMatchingSubmapLinkRectangle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/findMatchingSubmapLinkRectangle'; -import { OverlayBioEntityGroupedElementsType } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { OverlayBioEntityGroupedElementsType } from '@/components/Map/MapViewer/MapViewer.types'; +import findMatchingSubmapLinkRectangle from '@/components/Map/MapViewer/utils/shapes/overlay/findMatchingSubmapLinkRectangle'; export default function groupOverlayEntities( overlayBioEntities: Array<OverlayBioEntityRender>, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/processOverlayGroupedElements.test.ts b/src/components/Map/MapViewer/utils/shapes/overlay/processOverlayGroupedElements.test.ts similarity index 92% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/processOverlayGroupedElements.test.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/processOverlayGroupedElements.test.ts index 680002ea..c3a094e2 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/processOverlayGroupedElements.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/overlay/processOverlayGroupedElements.test.ts @@ -1,8 +1,8 @@ /* eslint-disable no-magic-numbers */ import { OverlayBioEntityRender } from '@/types/OLrendering'; import { GetOverlayBioEntityColorByAvailableProperties } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useGetOverlayColor'; -import processOverlayGroupedElements from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/processOverlayGroupedElements'; -import { OverlayBioEntityGroupedElementsType } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { OverlayBioEntityGroupedElementsType } from '@/components/Map/MapViewer/MapViewer.types'; +import processOverlayGroupedElements from '@/components/Map/MapViewer/utils/shapes/overlay/processOverlayGroupedElements'; describe('processOverlayGroupedElements', () => { it('should correctly process overlay grouped elements and add to entityOverlays', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/processOverlayGroupedElements.ts b/src/components/Map/MapViewer/utils/shapes/overlay/processOverlayGroupedElements.ts similarity index 87% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/processOverlayGroupedElements.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/processOverlayGroupedElements.ts index 7e2a9b43..48ecc167 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/processOverlayGroupedElements.ts +++ b/src/components/Map/MapViewer/utils/shapes/overlay/processOverlayGroupedElements.ts @@ -1,9 +1,9 @@ /* eslint-disable no-magic-numbers */ import { OverlayBioEntityRender } from '@/types/OLrendering'; import { GetOverlayBioEntityColorByAvailableProperties } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useGetOverlayColor'; -import sortElementOverlayByColor from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/sortElementOverlayByColor'; -import calculateOverlayDimensions from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/calculateOverlayDimensions'; -import { OverlayBioEntityGroupedElementsType } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { OverlayBioEntityGroupedElementsType } from '@/components/Map/MapViewer/MapViewer.types'; +import sortElementOverlayByColor from '@/components/Map/MapViewer/utils/shapes/overlay/sortElementOverlayByColor'; +import calculateOverlayDimensions from '@/components/Map/MapViewer/utils/shapes/overlay/calculateOverlayDimensions'; export default function processOverlayGroupedElements( groupedElements: OverlayBioEntityGroupedElementsType, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/sortElementOverlayByColor.test.ts b/src/components/Map/MapViewer/utils/shapes/overlay/sortElementOverlayByColor.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/sortElementOverlayByColor.test.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/sortElementOverlayByColor.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/sortElementOverlayByColor.ts b/src/components/Map/MapViewer/utils/shapes/overlay/sortElementOverlayByColor.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/sortElementOverlayByColor.ts rename to src/components/Map/MapViewer/utils/shapes/overlay/sortElementOverlayByColor.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.test.ts b/src/components/Map/MapViewer/utils/shapes/reaction/Reaction.test.ts similarity index 94% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.test.ts rename to src/components/Map/MapViewer/utils/shapes/reaction/Reaction.test.ts index 0e6dce24..4125a801 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/reaction/Reaction.test.ts @@ -1,8 +1,6 @@ /* eslint-disable no-magic-numbers */ import { Feature, Map } from 'ol'; -import Reaction, { - ReactionProps, -} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction'; +import Reaction, { ReactionProps } from '@/components/Map/MapViewer/utils/shapes/reaction/Reaction'; import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; import { lineTypesFixture } from '@/models/fixtures/lineTypesFixture'; import { arrowTypesFixture } from '@/models/fixtures/arrowTypesFixture'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts b/src/components/Map/MapViewer/utils/shapes/reaction/Reaction.ts similarity index 92% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts rename to src/components/Map/MapViewer/utils/shapes/reaction/Reaction.ts index ccefcd64..a2e786fc 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts +++ b/src/components/Map/MapViewer/utils/shapes/reaction/Reaction.ts @@ -3,7 +3,6 @@ import { Line, Operator, ReactionProduct, Shape } from '@/types/models'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { Feature } from 'ol'; import { Circle, LineString, MultiLineString, MultiPolygon } from 'ol/geom'; -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; import Polygon from 'ol/geom/Polygon'; import Style from 'ol/style/Style'; import { @@ -11,21 +10,22 @@ import { REACTION_ELEMENT_TYPES, TEXT_CUTOFF_SCALE, WHITE_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +} from '@/components/Map/MapViewer/MapViewer.constants'; import { FeatureLike } from 'ol/Feature'; import { MapInstance } from '@/types/map'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types'; import { FEATURE_TYPE } from '@/constants/features'; -import getScaledElementStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle'; import VectorSource from 'ol/source/Vector'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; import { Stroke } from 'ol/style'; -import getLineSegments from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getLineSegments'; -import getRotation from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getRotation'; -import getArrowFeature from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature'; -import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; +import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; +import getLineSegments from '@/components/Map/MapViewer/utils/shapes/coords/getLineSegments'; +import getRotation from '@/components/Map/MapViewer/utils/shapes/coords/getRotation'; +import getArrowFeature from '@/components/Map/MapViewer/utils/shapes/elements/getArrowFeature'; +import getShapePolygon from '@/components/Map/MapViewer/utils/shapes/elements/getShapePolygon'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; export interface ReactionProps { id: number; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getCoverStyles.test.ts b/src/components/Map/MapViewer/utils/shapes/style/getCoverStyles.test.ts similarity index 87% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getCoverStyles.test.ts rename to src/components/Map/MapViewer/utils/shapes/style/getCoverStyles.test.ts index 8178ab4a..a8ea5c82 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getCoverStyles.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/style/getCoverStyles.test.ts @@ -1,15 +1,15 @@ /* eslint-disable no-magic-numbers */ import Style from 'ol/style/Style'; import { Extent } from 'ol/extent'; -import getWrappedTextWithFontSize from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getWrappedTextWithFontSize'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; +import getWrappedTextWithFontSize from '@/components/Map/MapViewer/utils/shapes/text/getWrappedTextWithFontSize'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; import { latLngToPoint } from '@/utils/map/latLngToPoint'; -import getCoverStyles from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getCoverStyles'; +import getCoverStyles from '@/components/Map/MapViewer/utils/shapes/style/getCoverStyles'; import { DEFAULT_TILE_SIZE } from '@/constants/map'; jest.mock('../text/getWrappedTextWithFontSize'); jest.mock('../text/getTextStyle'); -jest.mock('../../../../../../../utils/map/latLngToPoint'); +jest.mock('../../../../../../utils/map/latLngToPoint'); describe('getCoverStyles', () => { it('should return cover and text styles based on the provided parameters', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getCoverStyles.ts b/src/components/Map/MapViewer/utils/shapes/style/getCoverStyles.ts similarity index 86% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getCoverStyles.ts rename to src/components/Map/MapViewer/utils/shapes/style/getCoverStyles.ts index 78f2ef6b..83ad9a71 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getCoverStyles.ts +++ b/src/components/Map/MapViewer/utils/shapes/style/getCoverStyles.ts @@ -3,12 +3,12 @@ import Style from 'ol/style/Style'; import { Extent, getCenter } from 'ol/extent'; import { toLonLat } from 'ol/proj'; import { latLngToPoint } from '@/utils/map/latLngToPoint'; -import getWrappedTextWithFontSize from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getWrappedTextWithFontSize'; +import getWrappedTextWithFontSize from '@/components/Map/MapViewer/utils/shapes/text/getWrappedTextWithFontSize'; import { Point } from 'ol/geom'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; import { MapSize } from '@/redux/map/map.types'; import { Stroke } from 'ol/style'; -import getScaledStrokeStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledStrokeStyle'; +import getScaledStrokeStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledStrokeStyle'; export default function getCoverStyles({ coverStyle, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill.test.ts b/src/components/Map/MapViewer/utils/shapes/style/getFill.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill.test.ts rename to src/components/Map/MapViewer/utils/shapes/style/getFill.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill.ts b/src/components/Map/MapViewer/utils/shapes/style/getFill.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill.ts rename to src/components/Map/MapViewer/utils/shapes/style/getFill.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.test.ts b/src/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle.test.ts similarity index 92% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.test.ts rename to src/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle.test.ts index 5c22d994..bd36a7d8 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle.test.ts @@ -1,7 +1,7 @@ /* eslint-disable no-magic-numbers */ import Style from 'ol/style/Style'; import { Stroke, Text } from 'ol/style'; -import getScaledStrokeStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledStrokeStyle'; +import getScaledStrokeStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledStrokeStyle'; import getScaledElementStyle from './getScaledElementStyle'; jest.mock('./getScaledStrokeStyle'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.ts b/src/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle.ts similarity index 76% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.ts rename to src/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle.ts index a91c0309..5f2eaa40 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.ts +++ b/src/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle.ts @@ -1,7 +1,7 @@ /* eslint-disable no-magic-numbers */ import Style from 'ol/style/Style'; import { Stroke } from 'ol/style'; -import getScaledStrokeStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledStrokeStyle'; +import getScaledStrokeStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledStrokeStyle'; export default function getScaledElementStyle( style: Style, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledStrokeStyle.test.ts b/src/components/Map/MapViewer/utils/shapes/style/getScaledStrokeStyle.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledStrokeStyle.test.ts rename to src/components/Map/MapViewer/utils/shapes/style/getScaledStrokeStyle.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledStrokeStyle.ts b/src/components/Map/MapViewer/utils/shapes/style/getScaledStrokeStyle.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledStrokeStyle.ts rename to src/components/Map/MapViewer/utils/shapes/style/getScaledStrokeStyle.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke.test.ts b/src/components/Map/MapViewer/utils/shapes/style/getStroke.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke.test.ts rename to src/components/Map/MapViewer/utils/shapes/style/getStroke.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke.ts b/src/components/Map/MapViewer/utils/shapes/style/getStroke.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke.ts rename to src/components/Map/MapViewer/utils/shapes/style/getStroke.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle.test.ts b/src/components/Map/MapViewer/utils/shapes/style/getStyle.test.ts similarity index 94% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle.test.ts rename to src/components/Map/MapViewer/utils/shapes/style/getStyle.test.ts index e46f9ef0..974b9272 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/style/getStyle.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; import Style from 'ol/style/Style'; import Polygon from 'ol/geom/Polygon'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle.ts b/src/components/Map/MapViewer/utils/shapes/style/getStyle.ts similarity index 65% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle.ts rename to src/components/Map/MapViewer/utils/shapes/style/getStyle.ts index 96083434..9e121e1a 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStyle.ts +++ b/src/components/Map/MapViewer/utils/shapes/style/getStyle.ts @@ -1,14 +1,11 @@ /* eslint-disable no-magic-numbers */ import Style from 'ol/style/Style'; import { Geometry } from 'ol/geom'; -import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; -import { - BLACK_COLOR, - WHITE_COLOR, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill'; +import { BLACK_COLOR, WHITE_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; import { Color } from '@/types/models'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; export default function getStyle({ geometry, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex.test.ts b/src/components/Map/MapViewer/utils/shapes/style/rgbToHex.test.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex.test.ts rename to src/components/Map/MapViewer/utils/shapes/style/rgbToHex.test.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex.ts b/src/components/Map/MapViewer/utils/shapes/style/rgbToHex.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex.ts rename to src/components/Map/MapViewer/utils/shapes/style/rgbToHex.ts diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.test.ts b/src/components/Map/MapViewer/utils/shapes/text/Text.test.ts similarity index 80% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.test.ts rename to src/components/Map/MapViewer/utils/shapes/text/Text.test.ts index 68b8d9f8..d40cf459 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/Text.test.ts @@ -1,12 +1,12 @@ /* eslint-disable no-magic-numbers */ import { Map } from 'ol'; import { Style } from 'ol/style'; -import Text, { TextProps } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import View from 'ol/View'; -import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; +import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; +import Text, { TextProps } from '@/components/Map/MapViewer/utils/shapes/text/Text'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; jest.mock('./getTextCoords'); jest.mock('./getTextStyle'); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.ts b/src/components/Map/MapViewer/utils/shapes/text/Text.ts similarity index 84% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.ts rename to src/components/Map/MapViewer/utils/shapes/text/Text.ts index 27b8ec6f..c853b369 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/Text.ts @@ -1,19 +1,16 @@ /* eslint-disable no-magic-numbers */ -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; -import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import Style from 'ol/style/Style'; import { Point } from 'ol/geom'; import { Feature } from 'ol'; import { FeatureLike } from 'ol/Feature'; import { MapInstance } from '@/types/map'; -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; import { Color } from '@/types/models'; -import { TEXT_CUTOFF_SCALE } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; +import { TEXT_CUTOFF_SCALE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; export interface TextProps { x: number; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords.test.ts b/src/components/Map/MapViewer/utils/shapes/text/getTextCoords.test.ts similarity index 85% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords.test.ts rename to src/components/Map/MapViewer/utils/shapes/text/getTextCoords.test.ts index 6121a92d..a48c180a 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/getTextCoords.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords'; +import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; describe('getTextCoords', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords.ts b/src/components/Map/MapViewer/utils/shapes/text/getTextCoords.ts similarity index 89% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords.ts rename to src/components/Map/MapViewer/utils/shapes/text/getTextCoords.ts index 3dcbb8fa..e3224fc9 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/getTextCoords.ts @@ -1,8 +1,5 @@ /* eslint-disable no-magic-numbers */ -import { - HorizontalAlign, - VerticalAlign, -} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { Coordinate } from 'ol/coordinate'; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle.test.ts b/src/components/Map/MapViewer/utils/shapes/text/getTextStyle.test.ts similarity index 88% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle.test.ts rename to src/components/Map/MapViewer/utils/shapes/text/getTextStyle.test.ts index d16623b5..3d6fc5f4 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/getTextStyle.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; +import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; import Style from 'ol/style/Style'; describe('getTextStyle', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle.ts b/src/components/Map/MapViewer/utils/shapes/text/getTextStyle.ts similarity index 95% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle.ts rename to src/components/Map/MapViewer/utils/shapes/text/getTextStyle.ts index 4858fb21..6558ab9a 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/getTextStyle.ts @@ -1,6 +1,6 @@ import { Fill, Text } from 'ol/style'; import Style from 'ol/style/Style'; -import { HorizontalAlign } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; +import { HorizontalAlign } from '@/components/Map/MapViewer/MapViewer.types'; export default function getTextStyle({ text, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getWrappedTextWithFontSize.test.ts b/src/components/Map/MapViewer/utils/shapes/text/getWrappedTextWithFontSize.test.ts similarity index 95% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getWrappedTextWithFontSize.test.ts rename to src/components/Map/MapViewer/utils/shapes/text/getWrappedTextWithFontSize.test.ts index 2cfaa243..eba60616 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getWrappedTextWithFontSize.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/getWrappedTextWithFontSize.test.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import getWrappedTextWithFontSize from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getWrappedTextWithFontSize'; +import getWrappedTextWithFontSize from '@/components/Map/MapViewer/utils/shapes/text/getWrappedTextWithFontSize'; describe('getWrappedTextWithFontSize', () => { it('should return a wrapped text and font size for this text when maxWidth is limited and maxHeight is unlimited', () => { diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getWrappedTextWithFontSize.ts b/src/components/Map/MapViewer/utils/shapes/text/getWrappedTextWithFontSize.ts similarity index 100% rename from src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getWrappedTextWithFontSize.ts rename to src/components/Map/MapViewer/utils/shapes/text/getWrappedTextWithFontSize.ts diff --git a/src/components/Map/MapViewer/utils/useOlMap.ts b/src/components/Map/MapViewer/utils/useOlMap.ts index 68ec65bd..6e372dc3 100644 --- a/src/components/Map/MapViewer/utils/useOlMap.ts +++ b/src/components/Map/MapViewer/utils/useOlMap.ts @@ -2,15 +2,9 @@ import { MapInstance } from '@/types/map'; import { useMapInstance } from '@/utils/context/mapInstanceContext'; import Map from 'ol/Map'; import { Zoom } from 'ol/control'; -import React, { MutableRefObject, useEffect, useMemo } from 'react'; -import { useOlMapVectorLayers } from '@/components/Map/MapViewer/MapViewerVector/utils/config/useOlMapVectorLayers'; -import LayerGroup from 'ol/layer/Group'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { vectorRenderingSelector } from '@/redux/models/models.selectors'; +import React, { MutableRefObject, useEffect } from 'react'; +import { useOlMapLayers } from '@/components/Map/MapViewer/utils/config/useOlMapLayers'; import { defaults, MouseWheelZoom } from 'ol/interaction'; -import { useOlMapVectorListeners } from '@/components/Map/MapViewer/MapViewerVector/listeners/useOlMapVectorListeners'; -import { useOlMapCommonLayers } from '@/components/Map/MapViewer/utils/config/useOlMapCommonLayers'; -import { useOlMapLayers } from './config/useOlMapLayers'; import { useOlMapView } from './config/useOlMapView'; import { useOlMapListeners } from './listeners/useOlMapListeners'; @@ -25,34 +19,13 @@ interface UseOlMapOutput { type UseOlMap = (input?: UseOlMapInput) => UseOlMapOutput; export const useOlMap: UseOlMap = ({ target } = {}) => { - const vectorRendering = useAppSelector(vectorRenderingSelector); const mapRef = React.useRef<null | HTMLDivElement>(null); const { mapInstance, handleSetMapInstance } = useMapInstance(); const view = useOlMapView({ mapInstance }); - const rasterLayers = useOlMapLayers(); - const rasterLayersGroup = useMemo(() => { - return new LayerGroup({ - layers: rasterLayers, - }); - }, [rasterLayers]); - - const vectorLayers = useOlMapVectorLayers({ mapInstance }); - const vectorLayersGroup = useMemo(() => { - return new LayerGroup({ - layers: vectorLayers, - }); - }, [vectorLayers]); - - const commonLayers = useOlMapCommonLayers(); - const commonLayersGroup = useMemo(() => { - return new LayerGroup({ - layers: commonLayers, - }); - }, [commonLayers]); + const mapLayers = useOlMapLayers({ mapInstance }); useOlMapListeners({ view, mapInstance }); - useOlMapVectorListeners({ mapInstance }); useEffect(() => { // checking if innerHTML is empty due to possibility of target element cloning by OpenLayers map instance @@ -86,18 +59,8 @@ export const useOlMap: UseOlMap = ({ target } = {}) => { if (!mapInstance) { return; } - mapInstance.setLayers([vectorLayersGroup, rasterLayersGroup, commonLayersGroup]); - }, [mapInstance, rasterLayersGroup, vectorLayersGroup, commonLayersGroup]); - - useEffect(() => { - if (vectorRendering) { - rasterLayersGroup.setVisible(false); - vectorLayersGroup.setVisible(true); - } else { - vectorLayersGroup.setVisible(false); - rasterLayersGroup.setVisible(true); - } - }, [rasterLayersGroup, vectorLayersGroup, vectorRendering]); + mapInstance.setLayers(mapLayers); + }, [mapInstance, mapLayers]); return { mapRef, diff --git a/src/models/mocks/modelsMock.ts b/src/models/mocks/modelsMock.ts index 85e29299..5c14d13a 100644 --- a/src/models/mocks/modelsMock.ts +++ b/src/models/mocks/modelsMock.ts @@ -475,7 +475,6 @@ export const CORE_PD_MODEL_MOCK: MapModel = { modificationDates: [], minZoom: 2, maxZoom: 9, - vectorRendering: true, }; export const MODEL_WITH_DESCRIPTION: MapModel = { diff --git a/src/models/modelSchema.ts b/src/models/modelSchema.ts index feb8817b..392cda85 100644 --- a/src/models/modelSchema.ts +++ b/src/models/modelSchema.ts @@ -29,7 +29,6 @@ export const mapModelSchema = z.object({ references: z.array(referenceSchema), creationDate: z.string().nullable(), modificationDates: z.array(z.string()), - vectorRendering: z.boolean().optional(), }); export const mapModelsSchema = pageableSchema(mapModelSchema); diff --git a/src/redux/bioEntity/thunks/utils/fetchReactionsAndGetBioEntitiesIds.ts b/src/redux/bioEntity/thunks/utils/fetchReactionsAndGetBioEntitiesIds.ts index cae4025d..a29317ed 100644 --- a/src/redux/bioEntity/thunks/utils/fetchReactionsAndGetBioEntitiesIds.ts +++ b/src/redux/bioEntity/thunks/utils/fetchReactionsAndGetBioEntitiesIds.ts @@ -5,7 +5,7 @@ import { modelsNameMapSelector } from '@/redux/models/models.selectors'; import { getReactionsByIds } from '@/redux/reactions/reactions.thunks'; import type { AppDispatch, store } from '@/redux/store'; import type { BioEntityContent, NewReaction } from '@/types/models'; -import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/getModelElementsIdsFromReaction'; +import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction'; interface Args { bioEntityContents: BioEntityContent[]; diff --git a/src/redux/layers/layers.reducers.ts b/src/redux/layers/layers.reducers.ts index 715611f1..58aa3a23 100644 --- a/src/redux/layers/layers.reducers.ts +++ b/src/redux/layers/layers.reducers.ts @@ -57,6 +57,9 @@ export const setActiveLayerReducer = ( action: PayloadAction<{ modelId: number; layerId: number | null }>, ): void => { const { modelId, layerId } = action.payload; + if (!state[modelId]) { + return; + } const { data } = state[modelId]; if (!data) { return; diff --git a/src/redux/models/models.reducers.ts b/src/redux/models/models.reducers.ts index 054b4c0b..eb653786 100644 --- a/src/redux/models/models.reducers.ts +++ b/src/redux/models/models.reducers.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import { ActionReducerMapBuilder, PayloadAction } from '@reduxjs/toolkit'; +import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { getModels } from './models.thunks'; import { ModelsState } from './models.types'; @@ -16,14 +16,3 @@ export const getModelsReducer = (builder: ActionReducerMapBuilder<ModelsState>): // TODO to discuss manage state of failure }); }; - -export const setModelVectorRenderingReducer = ( - state: ModelsState, - action: PayloadAction<{ vectorRendering: boolean; mapId: number }>, -): void => { - const { payload } = action; - const modelIndex = state.data.findIndex(model => model.id === payload.mapId); - if (modelIndex !== -1) { - state.data[modelIndex].vectorRendering = payload.vectorRendering; - } -}; diff --git a/src/redux/models/models.selectors.ts b/src/redux/models/models.selectors.ts index 606aa70e..a26e8e94 100644 --- a/src/redux/models/models.selectors.ts +++ b/src/redux/models/models.selectors.ts @@ -63,8 +63,3 @@ export const mainMapModelDescriptionSelector = createSelector( mainMapModelSelector, model => model?.description, ); - -export const vectorRenderingSelector = createSelector( - currentModelSelector, - model => model?.vectorRendering || false, -); diff --git a/src/redux/models/models.slice.ts b/src/redux/models/models.slice.ts index 48cf8654..5c969f3e 100644 --- a/src/redux/models/models.slice.ts +++ b/src/redux/models/models.slice.ts @@ -1,6 +1,6 @@ import { ModelsState } from '@/redux/models/models.types'; import { createSlice } from '@reduxjs/toolkit'; -import { getModelsReducer, setModelVectorRenderingReducer } from './models.reducers'; +import { getModelsReducer } from './models.reducers'; const initialState: ModelsState = { data: [], @@ -11,14 +11,10 @@ const initialState: ModelsState = { export const modelsSlice = createSlice({ name: 'models', initialState, - reducers: { - setModelVectorRendering: setModelVectorRenderingReducer, - }, + reducers: {}, extraReducers: builder => { getModelsReducer(builder); }, }); -export const { setModelVectorRendering } = modelsSlice.actions; - export default modelsSlice.reducer; -- GitLab From 8d1cbb00fa002e86c0d77ef767b42b44df4bc657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Mon, 20 Jan 2025 11:09:40 +0100 Subject: [PATCH 02/12] feat(vector-map): remove communication with backend about backgrounds --- .../MapNavigation.component.test.tsx | 8 -- .../utils/useOverviewImageLinkActions.test.ts | 9 -- .../ElementLink.component.test.tsx | 2 - .../TopBar/TopBar.component.test.tsx | 7 -- .../AssociatedSubmap.component.test.tsx | 3 - .../ExportCompound.component.tsx | 12 +- .../OverlayListItem.component.test.tsx | 19 +--- .../hooks/useEmptyBackground.test.ts | 43 -------- .../hooks/useEmptyBackground.ts | 22 ---- .../Drawer/OverlaysDrawer/hooks/useOverlay.ts | 6 +- .../BioEntitiesSubmapItem.component.test.tsx | 3 - .../PinsListItem.component.test.tsx | 4 - .../DownloadSubmap.component.test.tsx | 10 -- .../utils/useGetSubmapDownloadUrl.test.ts | 10 -- .../utils/useGetSubmapDownloadUrl.ts | 9 +- .../SubmapsDrawer/SubmapsDrawer.test.tsx | 3 - .../MapAdditionalActions.component.test.tsx | 2 - .../utils/useAdditionalActions.test.ts | 2 - .../BackgroundsSelector.component.test.tsx | 104 ------------------ .../BackgroundsSelector.component.tsx | 86 --------------- .../BackgroundsSelector/index.ts | 1 - .../MapAdditionalOptions.component.test.tsx | 29 ----- .../MapAdditionalOptions.component.tsx | 10 -- .../Map/MapAdditionalOptions/index.ts | 1 - .../MapVectorBackgroundSelector.component.tsx | 12 +- .../MapViewer/MapViewer.component.test.tsx | 2 - .../useOlMapAdditionalLayers.test.ts | 2 - .../mapCardLayer/useOlMapCardLayer.test.ts | 2 - .../processLayer/processModelElements.ts | 6 +- .../processLayer/useOlMapProcessLayer.test.ts | 2 - .../processLayer/useOlMapProcessLayer.ts | 16 +-- .../utils/config/useOlMapLayers.test.ts | 2 - .../utils/config/useOlMapTileLayer.test.ts | 79 ------------- .../utils/config/useOlMapTileLayer.ts | 66 ----------- .../utils/config/useOlMapView.test.ts | 8 -- .../utils/listeners/useOlMapListeners.test.ts | 2 - .../utils/shapes/elements/BaseMultiPolygon.ts | 10 +- .../utils/shapes/elements/Compartment.ts | 6 +- .../shapes/elements/CompartmentCircle.test.ts | 2 +- .../shapes/elements/CompartmentCircle.ts | 6 +- .../elements/CompartmentPathway.test.ts | 2 +- .../shapes/elements/CompartmentPathway.ts | 6 +- .../shapes/elements/CompartmentSquare.test.ts | 2 +- .../shapes/elements/CompartmentSquare.ts | 6 +- .../utils/shapes/elements/MapElement.test.ts | 2 +- .../utils/shapes/elements/MapElement.ts | 6 +- .../Map/MapViewer/utils/useOlMap.test.ts | 2 - src/constants/backgrounds.ts | 1 - src/models/fixtures/backgroundsFixture.ts | 10 -- src/models/mapBackground.ts | 21 ---- src/redux/apiPath.ts | 2 - src/redux/backgrounds/background.mock.ts | 60 ---------- src/redux/backgrounds/background.selectors.ts | 56 ---------- .../backgrounds/backgrounds.constants.ts | 3 - .../backgrounds/backgrounds.reducers.test.ts | 86 --------------- src/redux/backgrounds/backgrounds.reducers.ts | 19 ---- src/redux/backgrounds/backgrounds.slice.ts | 20 ---- src/redux/backgrounds/backgrounds.thunks.ts | 27 ----- src/redux/backgrounds/backgrounds.types.ts | 4 - src/redux/map/map.constants.ts | 3 +- src/redux/map/map.fixtures.ts | 4 +- src/redux/map/map.reducers.ts | 10 +- src/redux/map/map.selectors.ts | 2 +- src/redux/map/map.slice.ts | 3 - src/redux/map/map.thunks.test.ts | 20 ++-- src/redux/map/map.thunks.ts | 21 +--- src/redux/map/map.types.ts | 4 +- .../checkIfIsMapUpdateActionValid.test.ts | 2 - .../map/middleware/map.middleware.test.ts | 2 - src/redux/map/middleware/map.middleware.ts | 5 +- .../overlayBioEntity.thunk.ts | 7 -- src/redux/root/init.selectors.ts | 4 - src/redux/root/init.thunks.ts | 2 - src/redux/root/root.fixtures.ts | 2 - src/redux/store.ts | 2 - .../pluginsManager/map/data/getBounds.test.ts | 2 - .../map/fitBounds/fitBounds.test.ts | 3 - .../pluginsManager/map/openMap.test.ts | 4 - .../setBackgroundtoEmptyIfAvailable.test.ts | 52 --------- .../setBackgroundtoEmptyIfAvailable.ts | 12 -- .../showDataOverlay/showDataOverlay.test.ts | 43 -------- .../showDataOverlay/showDataOverlay.ts | 5 +- .../map/position/getCenter.test.ts | 2 - .../map/triggerSearch/triggerSearch.test.ts | 2 - .../pluginsManager/map/zoom/getZoom.test.ts | 3 - .../pluginsManager/map/zoom/setZoom.test.ts | 2 - src/types/mapLayers.ts | 15 --- src/types/models.ts | 2 - .../initialize/useInitializeStore.test.ts | 18 +-- src/utils/initialize/useInitializeStore.ts | 3 +- src/utils/map/getUpdatedMapData.ts | 7 +- src/utils/map/useSetBounds.test.ts | 3 - .../useReduxBusQueryManager.test.ts | 3 - 93 files changed, 84 insertions(+), 1153 deletions(-) delete mode 100644 src/components/Map/Drawer/OverlaysDrawer/hooks/useEmptyBackground.test.ts delete mode 100644 src/components/Map/Drawer/OverlaysDrawer/hooks/useEmptyBackground.ts delete mode 100644 src/components/Map/MapAdditionalOptions/BackgroundsSelector/BackgroundsSelector.component.test.tsx delete mode 100644 src/components/Map/MapAdditionalOptions/BackgroundsSelector/BackgroundsSelector.component.tsx delete mode 100644 src/components/Map/MapAdditionalOptions/BackgroundsSelector/index.ts delete mode 100644 src/components/Map/MapAdditionalOptions/MapAdditionalOptions.component.test.tsx delete mode 100644 src/components/Map/MapAdditionalOptions/MapAdditionalOptions.component.tsx delete mode 100644 src/components/Map/MapAdditionalOptions/index.ts delete mode 100644 src/components/Map/MapViewer/utils/config/useOlMapTileLayer.test.ts delete mode 100644 src/components/Map/MapViewer/utils/config/useOlMapTileLayer.ts delete mode 100644 src/constants/backgrounds.ts delete mode 100644 src/models/fixtures/backgroundsFixture.ts delete mode 100644 src/models/mapBackground.ts delete mode 100644 src/redux/backgrounds/background.mock.ts delete mode 100644 src/redux/backgrounds/background.selectors.ts delete mode 100644 src/redux/backgrounds/backgrounds.constants.ts delete mode 100644 src/redux/backgrounds/backgrounds.reducers.test.ts delete mode 100644 src/redux/backgrounds/backgrounds.reducers.ts delete mode 100644 src/redux/backgrounds/backgrounds.slice.ts delete mode 100644 src/redux/backgrounds/backgrounds.thunks.ts delete mode 100644 src/redux/backgrounds/backgrounds.types.ts delete mode 100644 src/services/pluginsManager/map/overlays/showDataOverlay/setBackgroundtoEmptyIfAvailable.test.ts delete mode 100644 src/services/pluginsManager/map/overlays/showDataOverlay/setBackgroundtoEmptyIfAvailable.ts delete mode 100644 src/types/mapLayers.ts diff --git a/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx b/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx index e1839e66..22c43bc9 100644 --- a/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx +++ b/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx @@ -9,7 +9,6 @@ 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 MapBackgroundsEnum from '@/redux/map/map.enums'; import { Project } from '@/types/models'; import { projectFixture } from '@/models/fixtures/projectFixture'; import { ProjectState } from '@/redux/project/project.types'; @@ -75,7 +74,6 @@ describe('MapNavigation - component', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); @@ -96,7 +94,6 @@ describe('MapNavigation - component', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); @@ -123,7 +120,6 @@ describe('MapNavigation - component', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); @@ -155,7 +151,6 @@ describe('MapNavigation - component', () => { modelId: HISTAMINE_MAP_ID, }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, loading: 'succeeded', error: { message: '', name: '' }, }, @@ -203,7 +198,6 @@ describe('MapNavigation - component', () => { modelId: HISTAMINE_MAP_ID, }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, loading: 'succeeded', error: { message: '', name: '' }, }, @@ -231,7 +225,6 @@ describe('MapNavigation - component', () => { modelId: HISTAMINE_MAP_ID, }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, loading: 'succeeded', error: { message: '', name: '' }, }, @@ -257,7 +250,6 @@ describe('MapNavigation - component', () => { modelId: HISTAMINE_MAP_ID, }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, loading: 'succeeded', error: { message: '', name: '' }, }, diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.test.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.test.ts index 33e0afd0..4cf7330e 100644 --- a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.test.ts +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageLinkActions.test.ts @@ -17,7 +17,6 @@ import { OverviewImageLink } from '@/types/models'; import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { renderHook } from '@testing-library/react'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MAIN_MAP_ID } from '@/constants/mocks'; import { FIRST_ARRAY_ELEMENT, @@ -61,7 +60,6 @@ describe('useOverviewImageLinkActions - hook', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); @@ -112,7 +110,6 @@ describe('useOverviewImageLinkActions - hook', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); @@ -170,7 +167,6 @@ describe('useOverviewImageLinkActions - hook', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK_SHORT, @@ -249,7 +245,6 @@ describe('useOverviewImageLinkActions - hook', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK_SHORT, @@ -354,7 +349,6 @@ describe('useOverviewImageLinkActions - hook', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK_SHORT, @@ -412,7 +406,6 @@ describe('useOverviewImageLinkActions - hook', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK_SHORT, @@ -474,7 +467,6 @@ describe('useOverviewImageLinkActions - hook', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK_SHORT, @@ -538,7 +530,6 @@ describe('useOverviewImageLinkActions - hook', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK_SHORT, diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.test.tsx b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.test.tsx index cdd2e42f..ea4fe1f6 100644 --- a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.test.tsx +++ b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.test.tsx @@ -14,7 +14,6 @@ import { import { render, screen, waitFor } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; import { MockStoreEnhanced } from 'redux-mock-store'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { isReactionBioEntity } from '@/redux/reactions/isReactionBioentity'; import { ElementLink } from './ElementLink.component'; @@ -203,7 +202,6 @@ describe('ElementLink - component', () => { lastPosition: DEFAULT_POSITION, }, ], - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }, ); diff --git a/src/components/FunctionalArea/TopBar/TopBar.component.test.tsx b/src/components/FunctionalArea/TopBar/TopBar.component.test.tsx index f87cc56c..3f7463f3 100644 --- a/src/components/FunctionalArea/TopBar/TopBar.component.test.tsx +++ b/src/components/FunctionalArea/TopBar/TopBar.component.test.tsx @@ -10,10 +10,6 @@ import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreA import { PROJECT_STATE_INITIAL_MOCK } from '@/redux/project/project.mock'; import { projectFixture } from '@/models/fixtures/projectFixture'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { - BACKGROUNDS_MOCK, - BACKGROUND_INITIAL_STATE_MOCK, -} from '@/redux/backgrounds/background.mock'; import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; import { USER_INITIAL_STATE_MOCK } from '@/redux/user/user.mock'; import { SEARCH_STATE_INITIAL_MOCK } from '@/redux/search/search.mock'; @@ -103,7 +99,6 @@ describe('TopBar - component', () => { }, }, map: initialMapStateFixture, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, }); expect(screen.getByText('Browse overview images')).toBeInTheDocument(); }); @@ -121,7 +116,6 @@ describe('TopBar - component', () => { autocompleteSearch: AUTOCOMPLETE_INITIAL_STATE, autocompleteDrug: AUTOCOMPLETE_INITIAL_STATE, autocompleteChemical: AUTOCOMPLETE_INITIAL_STATE, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, }); const overviewImageButton = screen.getByText('Browse overview images'); @@ -149,7 +143,6 @@ describe('TopBar - component', () => { }, }, map: initialMapStateFixture, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, }); const overviewImageButton = screen.queryByText('Browse overview images'); 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 267ad439..84ff3087 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx @@ -18,7 +18,6 @@ import { getReduxWrapperWithStore, } from '@/utils/testing/getReduxWrapperWithStore'; import { act, render, screen } from '@testing-library/react'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { HISTAMINE_MAP_ID, MAIN_MAP_ID } from '@/constants/mocks'; import { AssociatedSubmap } from './AssociatedSubmap.component'; @@ -90,7 +89,6 @@ describe('AssociatedSubmap - component', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, bioEntity: { ...BIOENTITY_INITIAL_STATE_MOCK, @@ -150,7 +148,6 @@ describe('AssociatedSubmap - component', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, bioEntity: { ...BIOENTITY_INITIAL_STATE_MOCK, diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx index 906dd9ee..1a60d63d 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx @@ -1,5 +1,4 @@ import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; -import { currentBackgroundSelector } from '@/redux/backgrounds/background.selectors'; import { downloadElements, downloadNetwork } from '@/redux/export/export.thunks'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; @@ -12,6 +11,7 @@ import { ReactNode, useCallback, useMemo, useState } from 'react'; import { activeOverlaysIdSelector } from '@/redux/overlayBioEntity/overlayBioEntity.selector'; import { DownloadCurrentView } from '@/components/Map/Drawer/ExportDrawer/ExportCompound/DownloadCurrentView/DownloadCurrentView.component'; import { getZoom } from '@/services/pluginsManager/map/zoom/getZoom'; +import { mapBackgroundSelector } from '@/redux/map/map.selectors'; import { CheckboxItem } from '../CheckboxFilter/CheckboxFilter.types'; import { Annotations } from './Annotations'; import { DownloadElements } from './DownloadElements/DownloadElements'; @@ -41,7 +41,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { const selectedModelId = useAppSelector(currentModelIdSelector); const currentModels = useAppSelector(modelsDataSelector); - const currentBackground = useAppSelector(currentBackgroundSelector); + const background = useAppSelector(mapBackgroundSelector); const overlays = useAppSelector(activeOverlaysIdSelector); const [annotations, setAnnotations] = useState<CheckboxItem[]>([]); const [includedCompartmentPathways, setIncludedCompartmentPathways] = useState<CheckboxItem[]>( @@ -82,7 +82,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { const model = currentModels.find(currentModel => currentModel.id === Number(modelId)); const url = getGraphicsDownloadUrl({ - backgroundId: currentBackground?.id, + backgroundId: background, modelId: models?.[FIRST_ARRAY_ELEMENT]?.id, handler: imageFormats?.[FIRST_ARRAY_ELEMENT]?.id, zoom: getModelExportZoom(imageSize.width, model), @@ -93,11 +93,11 @@ export const Export = ({ children }: ExportProps): JSX.Element => { if (url) { window.open(url); } - }, [models, imageFormats, currentBackground, currentModels, imageSize.width, overlays]); + }, [models, imageFormats, background, currentModels, imageSize.width, overlays]); const handleDownloadCurrentView = useCallback(async () => { const url = getGraphicsDownloadUrl({ - backgroundId: currentBackground?.id, + backgroundId: background, modelId: `${selectedModelId}`, handler: imageFormats?.[FIRST_ARRAY_ELEMENT]?.id, zoom: getZoom(), @@ -108,7 +108,7 @@ export const Export = ({ children }: ExportProps): JSX.Element => { if (url) { window.open(url); } - }, [selectedModelId, imageFormats, currentBackground, overlays]); + }, [selectedModelId, imageFormats, background, overlays]); const globalContextDataValue = useMemo( () => ({ diff --git a/src/components/Map/Drawer/OverlaysDrawer/GeneralOverlays/OverlayListItem/OverlayListItem.component.test.tsx b/src/components/Map/Drawer/OverlaysDrawer/GeneralOverlays/OverlayListItem/OverlayListItem.component.test.tsx index d1080df9..83ac53a3 100644 --- a/src/components/Map/Drawer/OverlaysDrawer/GeneralOverlays/OverlayListItem/OverlayListItem.component.test.tsx +++ b/src/components/Map/Drawer/OverlaysDrawer/GeneralOverlays/OverlayListItem/OverlayListItem.component.test.tsx @@ -4,10 +4,6 @@ import { InitialStoreState, getReduxWrapperWithStore, } from '@/utils/testing/getReduxWrapperWithStore'; -import { - BACKGROUNDS_MOCK, - BACKGROUND_INITIAL_STATE_MOCK, -} from '@/redux/backgrounds/background.mock'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK } from '@/redux/overlayBioEntity/overlayBioEntity.mock'; @@ -19,11 +15,11 @@ import { MODELS_INITIAL_STATE_MOCK } from '@/redux/models/models.mock'; import { parseOverlayBioEntityToOlRenderingFormat } from '@/redux/overlayBioEntity/overlayBioEntity.utils'; import { BASE_API_URL } from '@/constants'; import { MAIN_MAP_ID } from '@/constants/mocks'; +import MapBackgroundsEnum from '@/redux/map/map.enums'; import { OverlayListItem } from './OverlayListItem.component'; const mockedAxiosNewClient = mockNetworkNewAPIResponse(); -const DEFAULT_BACKGROUND_ID = 0; -const EMPTY_BACKGROUND_ID = 15; +const DEFAULT_BACKGROUND_ID = 2; const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); @@ -50,11 +46,10 @@ describe('OverlayListItem - component', () => { }); describe('view overlays', () => { - it('should trigger view overlays on view button click and switch background to Empty if available', async () => { + it('should trigger view overlays on view button click and switch background to Network', async () => { const OVERLAY_ID = 21; const { store } = renderComponent({ map: initialMapStateFixture, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, overlayBioEntity: OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK, models: { ...MODELS_INITIAL_STATE_MOCK, data: [CORE_PD_MODEL_MOCK] }, }); @@ -69,7 +64,7 @@ describe('OverlayListItem - component', () => { ViewButton.click(); }); - expect(store.getState().map.data.backgroundId).toBe(EMPTY_BACKGROUND_ID); + expect(store.getState().map.data.backgroundId).toBe(MapBackgroundsEnum.NETWORK); expect(store.getState().overlayBioEntity.data).toEqual({ [OVERLAY_ID]: { [MAIN_MAP_ID]: parseOverlayBioEntityToOlRenderingFormat( @@ -84,9 +79,8 @@ describe('OverlayListItem - component', () => { const { store } = renderComponent({ map: { ...initialMapStateFixture, - data: { ...initialMapStateFixture.data, backgroundId: EMPTY_BACKGROUND_ID }, + data: { ...initialMapStateFixture.data, backgroundId: MapBackgroundsEnum.NETWORK }, }, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, overlayBioEntity: { ...OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK, overlaysId: [OVERLAY_ID] }, models: { ...MODELS_INITIAL_STATE_MOCK, data: [CORE_PD_MODEL_MOCK] }, }); @@ -120,9 +114,8 @@ describe('OverlayListItem - component', () => { renderComponent({ map: { ...initialMapStateFixture, - data: { ...initialMapStateFixture.data, backgroundId: EMPTY_BACKGROUND_ID }, + data: { ...initialMapStateFixture.data, backgroundId: MapBackgroundsEnum.SEMANTIC }, }, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, overlayBioEntity: { ...OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK, overlaysId: [OVERLAY_ID] }, models: { ...MODELS_INITIAL_STATE_MOCK, data: [CORE_PD_MODEL_MOCK] }, }); diff --git a/src/components/Map/Drawer/OverlaysDrawer/hooks/useEmptyBackground.test.ts b/src/components/Map/Drawer/OverlaysDrawer/hooks/useEmptyBackground.test.ts deleted file mode 100644 index 9c58dfc3..00000000 --- a/src/components/Map/Drawer/OverlaysDrawer/hooks/useEmptyBackground.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; -import { initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { - BACKGROUNDS_MOCK, - BACKGROUND_INITIAL_STATE_MOCK, -} from '@/redux/backgrounds/background.mock'; -import { renderHook } from '@testing-library/react'; -import { useEmptyBackground } from './useEmptyBackground'; - -const DEFAULT_BACKGROUND_ID = 0; -const EMPTY_BACKGROUND_ID = 15; - -describe('useEmptyBackground - hook', () => { - describe('returns setEmptyBackground function', () => { - it('should not set background to "Empty" if its not available', () => { - const { Wrapper, store } = getReduxWrapperWithStore({ - map: initialMapStateFixture, - backgrounds: BACKGROUND_INITIAL_STATE_MOCK, - }); - const { result } = renderHook(() => useEmptyBackground(), { wrapper: Wrapper }); - - expect(store.getState().map.data.backgroundId).toBe(DEFAULT_BACKGROUND_ID); - - result.current.setBackgroundtoEmptyIfAvailable(); - - expect(store.getState().map.data.backgroundId).toBe(DEFAULT_BACKGROUND_ID); - }); - - it('should set background to "Empty" if its available', () => { - const { Wrapper, store } = getReduxWrapperWithStore({ - map: initialMapStateFixture, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, - }); - const { result } = renderHook(() => useEmptyBackground(), { wrapper: Wrapper }); - - expect(store.getState().map.data.backgroundId).toBe(DEFAULT_BACKGROUND_ID); - - result.current.setBackgroundtoEmptyIfAvailable(); - - expect(store.getState().map.data.backgroundId).toBe(EMPTY_BACKGROUND_ID); - }); - }); -}); diff --git a/src/components/Map/Drawer/OverlaysDrawer/hooks/useEmptyBackground.ts b/src/components/Map/Drawer/OverlaysDrawer/hooks/useEmptyBackground.ts deleted file mode 100644 index 2536fa84..00000000 --- a/src/components/Map/Drawer/OverlaysDrawer/hooks/useEmptyBackground.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useCallback } from 'react'; -import { emptyBackgroundIdSelector } from '@/redux/backgrounds/background.selectors'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { setMapBackground } from '@/redux/map/map.slice'; - -type UseEmptyBackgroundReturn = { - setBackgroundtoEmptyIfAvailable: () => void; -}; - -export const useEmptyBackground = (): UseEmptyBackgroundReturn => { - const dispatch = useAppDispatch(); - const emptyBackgroundId = useAppSelector(emptyBackgroundIdSelector); - - const setBackgroundtoEmptyIfAvailable = useCallback(() => { - if (emptyBackgroundId) { - dispatch(setMapBackground(emptyBackgroundId)); - } - }, [dispatch, emptyBackgroundId]); - - return { setBackgroundtoEmptyIfAvailable }; -}; diff --git a/src/components/Map/Drawer/OverlaysDrawer/hooks/useOverlay.ts b/src/components/Map/Drawer/OverlaysDrawer/hooks/useOverlay.ts index 084877fd..bca5b9ad 100644 --- a/src/components/Map/Drawer/OverlaysDrawer/hooks/useOverlay.ts +++ b/src/components/Map/Drawer/OverlaysDrawer/hooks/useOverlay.ts @@ -14,7 +14,8 @@ import { addOverlayToOverlaysId, removeOverlayFromOverlaysId, } from '@/redux/overlayBioEntity/overlayBioEntity.slice'; -import { useEmptyBackground } from './useEmptyBackground'; +import { setMapBackground } from '@/redux/map/map.slice'; +import MapBackgroundsEnum from '@/redux/map/map.enums'; type UseOverlay = { toggleOverlay: () => void; @@ -27,7 +28,6 @@ export const useOverlay = (overlayId: number): UseOverlay => { const dispatch = useAppDispatch(); const isOverlayActive = useAppSelector(state => isOverlayActiveSelector(state, overlayId)); const isOverlayLoading = useAppSelector(state => isOverlayLoadingSelector(state, overlayId)); - const { setBackgroundtoEmptyIfAvailable } = useEmptyBackground(); const overlay = useAppSelector(state => overlaySelector(state, overlayId)); const areOverlayBioEntitiesLoaded = useAppSelector(state => areOverlayBioEntitiesLoadedSelector(state, overlayId), @@ -55,7 +55,7 @@ export const useOverlay = (overlayId: number): UseOverlay => { } else { await dispatch(getOverlayBioEntityForAllModels({ overlayId })); } - setBackgroundtoEmptyIfAvailable(); + dispatch(setMapBackground(MapBackgroundsEnum.NETWORK)); } dispatchPluginEvents(); diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx index 62654f69..a93282db 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx @@ -13,7 +13,6 @@ import { openedMapsInitialValueFixture, openedMapsThreeSubmapsFixture, } from '@/redux/map/map.fixtures'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MAIN_MAP_ID } from '@/constants/mocks'; import { BioEntitiesSubmapItem } from './BioEntitiesSubmapItem.component'; @@ -100,7 +99,6 @@ describe('BioEntitiesSubmapItem - component', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); @@ -158,7 +156,6 @@ describe('BioEntitiesSubmapItem - component', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.test.tsx index 23c0490f..0b9a5de5 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.test.tsx @@ -11,7 +11,6 @@ import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/ma import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock'; import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; import { MockStoreEnhanced } from 'redux-mock-store'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MAIN_MAP_ID } from '@/constants/mocks'; import { PinTypeWithNone } from '../PinsList.types'; import { PinsListItem } from './PinsListItem.component'; @@ -39,7 +38,6 @@ const INITIAL_STORE_STATE: InitialStoreState = { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }; @@ -172,7 +170,6 @@ describe('PinsListItem - component ', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }, ); @@ -206,7 +203,6 @@ describe('PinsListItem - component ', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }, ); diff --git a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.test.tsx b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.test.tsx index 4789c9c5..b753634e 100644 --- a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.test.tsx +++ b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/DownloadSubmap.component.test.tsx @@ -1,5 +1,4 @@ import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; -import { backgroundsFixture } from '@/models/fixtures/backgroundsFixture'; import { configurationFixture } from '@/models/fixtures/configurationFixture'; import { modelsFixture } from '@/models/fixtures/modelsFixture'; import { @@ -44,15 +43,6 @@ const getState = (): RootState => ({ }, ], }, - backgrounds: { - ...INITIAL_STORE_STATE_MOCK.backgrounds, - data: [ - { - ...backgroundsFixture[FIRST_ARRAY_ELEMENT], - id: VALID_BACKGROUND_ID, - }, - ], - }, configuration: { ...INITIAL_STORE_STATE_MOCK.configuration, main: { diff --git a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.test.ts b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.test.ts index 8bb6e92d..8c078809 100644 --- a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.test.ts +++ b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.test.ts @@ -1,6 +1,5 @@ import { BASE_API_URL, PROJECT_ID } from '@/constants'; import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; -import { backgroundsFixture } from '@/models/fixtures/backgroundsFixture'; import { modelsFixture } from '@/models/fixtures/modelsFixture'; import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; import { RootState } from '@/redux/store'; @@ -45,15 +44,6 @@ const getState = ({ }, ], }, - backgrounds: { - ...INITIAL_STORE_STATE_MOCK.backgrounds, - data: [ - { - ...backgroundsFixture[FIRST_ARRAY_ELEMENT], - id: VALID_BACKGROUND_ID, - }, - ], - }, }); describe('useGetSubmapDownloadUrl - hook', () => { diff --git a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.ts b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.ts index 397f7aad..5d05f263 100644 --- a/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.ts +++ b/src/components/Map/Drawer/SubmapsDrawer/SubmapItem/DownloadSubmap/utils/useGetSubmapDownloadUrl.ts @@ -1,6 +1,5 @@ import { BASE_API_URL, PROJECT_ID } from '@/constants'; -import { currentBackgroundSelector } from '@/redux/backgrounds/background.selectors'; -import { mapDataSizeSelector } from '@/redux/map/map.selectors'; +import { mapBackgroundSelector, mapDataSizeSelector } from '@/redux/map/map.selectors'; import { currentModelSelector } from '@/redux/models/models.selectors'; import { useSelector } from 'react-redux'; @@ -8,11 +7,11 @@ export type GetSubmapDownloadUrl = ({ handler }: { handler: string }) => string; export const useGetSubmapDownloadUrl = (): GetSubmapDownloadUrl => { const model = useSelector(currentModelSelector); - const background = useSelector(currentBackgroundSelector); + const background = useSelector(mapBackgroundSelector); const mapSize = useSelector(mapDataSizeSelector); const getSubmapDownloadUrl: GetSubmapDownloadUrl = ({ handler }) => { - const allParamsValid = [model?.id, background?.id, mapSize.maxZoom, handler].reduce( + const allParamsValid = [model?.id, background, mapSize.maxZoom, handler].reduce( (a, b) => Boolean(a) && Boolean(b), true, ); @@ -20,7 +19,7 @@ export const useGetSubmapDownloadUrl = (): GetSubmapDownloadUrl => { return ''; } - return `${BASE_API_URL}/projects/${PROJECT_ID}/models/${model?.id}:downloadModel?backgroundOverlayId=${background?.id}&handlerClass=${handler}&zoomLevel=${mapSize.maxZoom}`; + return `${BASE_API_URL}/projects/${PROJECT_ID}/models/${model?.id}:downloadModel?backgroundOverlayId=${background}&handlerClass=${handler}&zoomLevel=${mapSize.maxZoom}`; }; return getSubmapDownloadUrl; diff --git a/src/components/Map/Drawer/SubmapsDrawer/SubmapsDrawer.test.tsx b/src/components/Map/Drawer/SubmapsDrawer/SubmapsDrawer.test.tsx index 492be6cb..d4a6e092 100644 --- a/src/components/Map/Drawer/SubmapsDrawer/SubmapsDrawer.test.tsx +++ b/src/components/Map/Drawer/SubmapsDrawer/SubmapsDrawer.test.tsx @@ -11,7 +11,6 @@ import { openedMapsInitialValueFixture, openedMapsThreeSubmapsFixture, } from '@/redux/map/map.fixtures'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { HISTAMINE_MAP_ID, MAIN_MAP_ID } from '@/constants/mocks'; import { SubmapsDrawer } from './SubmapsDrawer'; @@ -63,7 +62,6 @@ describe('SubmapsDrawer - component', () => { loading: 'succeeded', error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); @@ -109,7 +107,6 @@ describe('SubmapsDrawer - component', () => { openedMaps: openedMapsThreeSubmapsFixture, loading: 'succeeded', error: { name: '', message: '' }, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); diff --git a/src/components/Map/MapAdditionalActions/MapAdditionalActions.component.test.tsx b/src/components/Map/MapAdditionalActions/MapAdditionalActions.component.test.tsx index 5fe7353f..06bd09fe 100644 --- a/src/components/Map/MapAdditionalActions/MapAdditionalActions.component.test.tsx +++ b/src/components/Map/MapAdditionalActions/MapAdditionalActions.component.test.tsx @@ -11,7 +11,6 @@ import { import { act, render, screen } from '@testing-library/react'; import Map from 'ol/Map'; import { MockStoreEnhanced } from 'redux-mock-store'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MapAdditionalActions } from './MapAdditionalActions.component'; import { useVisibleBioEntitiesPolygonCoordinates } from './utils/useVisibleBioEntitiesPolygonCoordinates'; @@ -146,7 +145,6 @@ describe('MapAdditionalActions - component', () => { message: '', }, openedMaps: [], - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); diff --git a/src/components/Map/MapAdditionalActions/utils/useAdditionalActions.test.ts b/src/components/Map/MapAdditionalActions/utils/useAdditionalActions.test.ts index a65473f7..de9d56f1 100644 --- a/src/components/Map/MapAdditionalActions/utils/useAdditionalActions.test.ts +++ b/src/components/Map/MapAdditionalActions/utils/useAdditionalActions.test.ts @@ -8,7 +8,6 @@ import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreA import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { renderHook } from '@testing-library/react'; import Map from 'ol/Map'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { useAddtionalActions } from './useAdditionalActions'; import { useVisibleBioEntitiesPolygonCoordinates } from './useVisibleBioEntitiesPolygonCoordinates'; @@ -95,7 +94,6 @@ describe('useAddtionalActions - hook', () => { message: '', }, openedMaps: [], - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }, { diff --git a/src/components/Map/MapAdditionalOptions/BackgroundsSelector/BackgroundsSelector.component.test.tsx b/src/components/Map/MapAdditionalOptions/BackgroundsSelector/BackgroundsSelector.component.test.tsx deleted file mode 100644 index 8aaf2bd1..00000000 --- a/src/components/Map/MapAdditionalOptions/BackgroundsSelector/BackgroundsSelector.component.test.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { StoreType } from '@/redux/store'; -import { render, screen } from '@testing-library/react'; -import { act } from 'react-dom/test-utils'; -import { initialMapDataFixture, initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { - InitialStoreState, - getReduxWrapperWithStore, -} from '@/utils/testing/getReduxWrapperWithStore'; -import { - BACKGROUNDS_MOCK, - BACKGROUND_INITIAL_STATE_MOCK, -} from '@/redux/backgrounds/background.mock'; -import { BackgroundSelector } from './BackgroundsSelector.component'; - -const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { - const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); - - return ( - render( - <Wrapper> - <BackgroundSelector /> - </Wrapper>, - ), - { - store, - } - ); -}; - -describe('BackgroundSelector - component', () => { - it('should initialy display default value', () => { - renderComponent(); - - const buttonName = screen.getByTestId('background-dropdown-button-name'); - - expect(buttonName.textContent).toBe('Background'); - }); - - it("should display selected value name when it's not main background", async () => { - renderComponent({ - map: initialMapStateFixture, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, - }); - - const buttonName = screen.getByTestId('background-dropdown-button-name'); - await act(() => { - buttonName.click(); - }); - expect(buttonName.textContent).toBe('Background'); - - const backgroundButton = screen.getByText('Network'); - await act(() => { - backgroundButton.click(); - }); - - expect(buttonName.textContent).toBe('Network'); - }); - - it('should change redux map state on selecting background', async () => { - const { store } = renderComponent({ - map: initialMapStateFixture, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, - }); - expect(store.getState().map.data.modelId).toBe(0); - - const buttonName = screen.getByTestId('background-dropdown-button-name'); - await act(() => { - buttonName.click(); - }); - - const backgroundButton = screen.getByText('Network'); - await act(() => { - backgroundButton.click(); - }); - - expect(store.getState().map.data.backgroundId).toBe(14); - }); - - describe('query params', () => { - it('should display default value when main background id is in query params', async () => { - await renderComponent({ - map: { ...initialMapStateFixture, data: { ...initialMapDataFixture, backgroundId: 13 } }, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, - }); - - const buttonName = screen.getByTestId('background-dropdown-button-name'); - expect(buttonName.textContent).toBe('Background'); - }); - it('should display correct background when background id is in query params', async () => { - await renderComponent({ - map: { ...initialMapStateFixture, data: { ...initialMapDataFixture, backgroundId: 15 } }, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, - }); - - const buttonName = screen.getByTestId('background-dropdown-button-name'); - expect(buttonName.textContent).toBe('Empty'); - }); - it.skip('should set backgroundid in query on selecting background', () => { - // TODO e2e - expect(true).toBe(false); - }); - }); -}); diff --git a/src/components/Map/MapAdditionalOptions/BackgroundsSelector/BackgroundsSelector.component.tsx b/src/components/Map/MapAdditionalOptions/BackgroundsSelector/BackgroundsSelector.component.tsx deleted file mode 100644 index 610cb371..00000000 --- a/src/components/Map/MapAdditionalOptions/BackgroundsSelector/BackgroundsSelector.component.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useSelect } from 'downshift'; -import { - backgroundsDataSelector, - currentBackgroundSelector, - mainBackgroundIdSelector, -} from '@/redux/backgrounds/background.selectors'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { twMerge } from 'tailwind-merge'; -import { Icon } from '@/shared/Icon'; -import { MapBackground } from '@/types/models'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { setMapBackground } from '@/redux/map/map.slice'; - -const DEFAULT_TOGGLE_BUTTON_TEXT = 'Background'; - -export const BackgroundSelector = (): JSX.Element => { - const selectedBackground = useAppSelector(currentBackgroundSelector); - const dispatch = useAppDispatch(); - const backgrounds = useAppSelector(backgroundsDataSelector); - const mainBackgroundId = useAppSelector(mainBackgroundIdSelector); - - const onItemSelect = (background: MapBackground | undefined | null): void => { - if (background) { - dispatch(setMapBackground(background.id)); - } - }; - - const { isOpen, getToggleButtonProps, getMenuProps, highlightedIndex, getItemProps } = useSelect({ - items: backgrounds || [], - selectedItem: selectedBackground, - onSelectedItemChange: ({ selectedItem: newSelectedItem }) => onItemSelect(newSelectedItem), - }); - - const getToggleButtonName = (): string => { - const isSelectedBackgroundMainBackground = selectedBackground?.id === mainBackgroundId; - if (!selectedBackground || isSelectedBackgroundMainBackground) { - return DEFAULT_TOGGLE_BUTTON_TEXT; - } - return selectedBackground.name; - }; - - return ( - <div - data-testid="background-selector" - className={twMerge('rounded-t bg-white text-xs shadow-primary', !isOpen && 'rounded-b')} - > - <div className={twMerge('flex w-[135px] flex-col rounded-t py-2 pl-4 pr-3')}> - <div - className="flex cursor-pointer flex-row items-center justify-between bg-white" - {...getToggleButtonProps()} - > - <span data-testid="background-dropdown-button-name" className="font-medium"> - {getToggleButtonName()} - </span> - <Icon - name="chevron-down" - className={twMerge('arrow-button h-6 w-6 fill-primary-500', isOpen && 'rotate-180')} - /> - </div> - </div> - <ul - className={`absolute z-10 max-h-80 w-[135px] overflow-scroll rounded-b bg-white p-0 ${ - !isOpen && 'hidden' - }`} - {...getMenuProps()} - > - {isOpen && - backgrounds && - backgrounds.map((item, index) => ( - <li - className={twMerge( - 'border-t', - highlightedIndex === index && 'text-primary-500', - selectedBackground === item && 'font-bold', - 'flex flex-col px-4 py-2 shadow-sm', - )} - key={item.id} - {...getItemProps({ item, index })} - > - <span>{item.name}</span> - </li> - ))} - </ul> - </div> - ); -}; diff --git a/src/components/Map/MapAdditionalOptions/BackgroundsSelector/index.ts b/src/components/Map/MapAdditionalOptions/BackgroundsSelector/index.ts deleted file mode 100644 index 0b379515..00000000 --- a/src/components/Map/MapAdditionalOptions/BackgroundsSelector/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { BackgroundSelector } from './BackgroundsSelector.component'; diff --git a/src/components/Map/MapAdditionalOptions/MapAdditionalOptions.component.test.tsx b/src/components/Map/MapAdditionalOptions/MapAdditionalOptions.component.test.tsx deleted file mode 100644 index 5b877e38..00000000 --- a/src/components/Map/MapAdditionalOptions/MapAdditionalOptions.component.test.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { StoreType } from '@/redux/store'; -import { - InitialStoreState, - getReduxWrapperWithStore, -} from '@/utils/testing/getReduxWrapperWithStore'; -import { render, screen } from '@testing-library/react'; -import { MapAdditionalOptions } from './MapAdditionalOptions.component'; - -const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { - const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); - - return ( - render( - <Wrapper> - <MapAdditionalOptions /> - </Wrapper>, - ), - { - store, - } - ); -}; - -describe('MapAdditionalOptions - component', () => { - it('should display background selector', () => { - renderComponent(); - expect(screen.getByTestId('background-selector')).toBeInTheDocument(); - }); -}); diff --git a/src/components/Map/MapAdditionalOptions/MapAdditionalOptions.component.tsx b/src/components/Map/MapAdditionalOptions/MapAdditionalOptions.component.tsx deleted file mode 100644 index ce96a907..00000000 --- a/src/components/Map/MapAdditionalOptions/MapAdditionalOptions.component.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { twMerge } from 'tailwind-merge'; -import { BackgroundSelector } from './BackgroundsSelector'; - -// top-[calc(64px+40px+24px)] -> TOP_BAR_HEIGHT+MAP_NAVIGATION_HEIGHT+DISTANCE_FROM_MAP_NAVIGATION - -export const MapAdditionalOptions = (): JSX.Element => ( - <div className={twMerge('absolute right-6 top-[calc(64px+40px+24px)] z-10 flex')}> - <BackgroundSelector /> - </div> -); diff --git a/src/components/Map/MapAdditionalOptions/index.ts b/src/components/Map/MapAdditionalOptions/index.ts deleted file mode 100644 index ff61a27a..00000000 --- a/src/components/Map/MapAdditionalOptions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { MapAdditionalOptions } from './MapAdditionalOptions.component'; diff --git a/src/components/Map/MapVectorBackgroundSelector/MapVectorBackgroundSelector.component.tsx b/src/components/Map/MapVectorBackgroundSelector/MapVectorBackgroundSelector.component.tsx index 97463f27..caea44b9 100644 --- a/src/components/Map/MapVectorBackgroundSelector/MapVectorBackgroundSelector.component.tsx +++ b/src/components/Map/MapVectorBackgroundSelector/MapVectorBackgroundSelector.component.tsx @@ -1,24 +1,24 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { mapBackgroundTypeSelector } from '@/redux/map/map.selectors'; +import { mapBackgroundSelector } from '@/redux/map/map.selectors'; import { twMerge } from 'tailwind-merge'; import { MAP_BACKGROUND_TYPES } from '@/redux/map/map.constants'; -import { setMapBackgroundType } from '@/redux/map/map.slice'; +import { setMapBackground } from '@/redux/map/map.slice'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { Select } from '@/shared/Select'; export const MapVectorBackgroundSelector = (): JSX.Element => { const dispatch = useAppDispatch(); - const backgroundType = useAppSelector(mapBackgroundTypeSelector); + const backgroundId = useAppSelector(mapBackgroundSelector); - const handleChange = (selectedBackgroundType: string | number): void => { - dispatch(setMapBackgroundType(+selectedBackgroundType)); + const handleChange = (selectedBackgroundId: string | number): void => { + dispatch(setMapBackground(+selectedBackgroundId)); }; return ( <div className={twMerge('absolute right-6 top-[calc(64px+40px+24px)] z-10 flex')}> <Select options={MAP_BACKGROUND_TYPES} - selectedId={backgroundType} + selectedId={backgroundId} onChange={handleChange} width={140} /> diff --git a/src/components/Map/MapViewer/MapViewer.component.test.tsx b/src/components/Map/MapViewer/MapViewer.component.test.tsx index 23485420..ea37b540 100644 --- a/src/components/Map/MapViewer/MapViewer.component.test.tsx +++ b/src/components/Map/MapViewer/MapViewer.component.test.tsx @@ -1,7 +1,6 @@ import { render, screen } from '@testing-library/react'; import { StoreType } from '@/redux/store'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { BACKGROUND_INITIAL_STATE_MOCK } from '@/redux/backgrounds/background.mock'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { MapViewer } from './MapViewer.component'; import { MAP_VIEWER_ROLE } from './MapViewer.constants'; @@ -9,7 +8,6 @@ import { MAP_VIEWER_ROLE } from './MapViewer.constants'; const renderComponent = (): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore({ map: initialMapStateFixture, - backgrounds: BACKGROUND_INITIAL_STATE_MOCK, }); return ( diff --git a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts index eba9fde5..a23de57b 100644 --- a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts +++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.test.ts @@ -3,7 +3,6 @@ import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithSto import { renderHook } from '@testing-library/react'; import VectorLayer from 'ol/layer/Vector'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { BACKGROUND_INITIAL_STATE_MOCK } from '@/redux/backgrounds/background.mock'; import { Map } from 'ol'; import { useOlMapAdditionalLayers } from '@/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers'; @@ -11,7 +10,6 @@ describe('useOlMapAdditionalLayers - util', () => { it('should return VectorLayer', () => { const { Wrapper } = getReduxWrapperWithStore({ map: initialMapStateFixture, - backgrounds: BACKGROUND_INITIAL_STATE_MOCK, }); const dummyElement = document.createElement('div'); diff --git a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.test.ts b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.test.ts index dd9a5220..bec6905d 100644 --- a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.test.ts +++ b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.test.ts @@ -5,7 +5,6 @@ import { renderHook } from '@testing-library/react'; import BaseLayer from 'ol/layer/Base'; import VectorLayer from 'ol/layer/Vector'; import React from 'react'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { useOlMapCardLayer } from './useOlMapCardLayer'; const useRefValue = { @@ -59,7 +58,6 @@ describe('useOlMapCardLayer - util', () => { message: '', }, openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); diff --git a/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts index 25aa2078..87c6d666 100644 --- a/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts @@ -24,7 +24,7 @@ export default function processModelElements( vectorSource: VectorSource, mapInstance: MapInstance, pointToProjection: UsePointToProjectionResult, - mapBackgroundType: number, + backgroundId: number, mapSize: MapSize, ): Array<MapElement | CompartmentCircle | CompartmentSquare | CompartmentPathway | Glyph> { const overlaysVisible = Boolean(overlaysOrder.length); @@ -78,7 +78,7 @@ export default function processModelElements( pointToProjection, mapInstance, vectorSource, - mapBackgroundType, + backgroundId, mapSize, }; if (element.shape === 'OVAL_COMPARTMENT') { @@ -129,7 +129,7 @@ export default function processModelElements( overlaysOrder, overlaysVisible, getOverlayColor, - mapBackgroundType, + backgroundId, mapSize, }), ); diff --git a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.test.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.test.ts index c8e961ed..c03a9e9f 100644 --- a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.test.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.test.ts @@ -2,7 +2,6 @@ import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithSto import { renderHook } from '@testing-library/react'; import VectorLayer from 'ol/layer/Vector'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { BACKGROUND_INITIAL_STATE_MOCK } from '@/redux/backgrounds/background.mock'; import { Map } from 'ol'; import { useOlMapProcessLayer } from '@/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer'; @@ -10,7 +9,6 @@ describe('useOlMapReactionsLayer - util', () => { it('should return VectorLayer', () => { const { Wrapper } = getReduxWrapperWithStore({ map: initialMapStateFixture, - backgrounds: BACKGROUND_INITIAL_STATE_MOCK, }); const dummyElement = document.createElement('div'); diff --git a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts index 09d5b04e..2837c80b 100644 --- a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts @@ -35,9 +35,7 @@ import { markersSufraceOfCurrentMapDataSelector } from '@/redux/markers/markers. import { parseSurfaceMarkersToBioEntityRender } from '@/components/Map/MapViewer/utils/config/overlaysLayer/parseSurfaceMarkersToBioEntityRender'; import processModelElements from '@/components/Map/MapViewer/utils/config/processLayer/processModelElements'; import useDebouncedValue from '@/utils/useDebouncedValue'; -import { mapBackgroundTypeSelector, mapDataSizeSelector } from '@/redux/map/map.selectors'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; -import { setMapBackgroundType } from '@/redux/map/map.slice'; +import { mapBackgroundSelector, mapDataSizeSelector } from '@/redux/map/map.selectors'; import { ZOOM_RESCALING_FACTOR } from '@/constants/map'; import { OverlayOrder } from '@/redux/overlayBioEntity/overlayBioEntity.utils'; import MarkerOverlay from '@/components/Map/MapViewer/utils/shapes/overlay/MarkerOverlay'; @@ -65,7 +63,7 @@ export const useOlMapProcessLayer = ({ const lineTypes = useSelector(lineTypesSelector); const arrowTypes = useSelector(arrowTypesSelector); const overlaysOrder = useSelector(getOverlayOrderSelector); - const mapBackgroundType = useSelector(mapBackgroundTypeSelector); + const backgroundId = useSelector(mapBackgroundSelector); const currentMarkers = useAppSelector(markersSufraceOfCurrentMapDataSelector); const markersRender = useMemo(() => { return parseSurfaceMarkersToBioEntityRender(currentMarkers); @@ -108,12 +106,6 @@ export const useOlMapProcessLayer = ({ } }, [currentModelId, dispatch, reactionsLoading, modelElementsLoading]); - useEffect(() => { - if (overlaysOrderState.length) { - dispatch(setMapBackgroundType(MapBackgroundsEnum.NETWORK)); - } - }, [dispatch, overlaysOrderState]); - const groupedElementsOverlays = useMemo(() => { const elementsBioEntitesOverlay = debouncedBioEntities.filter( bioEntity => bioEntity.type !== 'line', @@ -219,7 +211,7 @@ export const useOlMapProcessLayer = ({ vectorSource, mapInstance, pointToProjection, - mapBackgroundType, + backgroundId, mapSize, ); }, [ @@ -233,7 +225,7 @@ export const useOlMapProcessLayer = ({ vectorSource, mapInstance, pointToProjection, - mapBackgroundType, + backgroundId, mapSize, ]); diff --git a/src/components/Map/MapViewer/utils/config/useOlMapLayers.test.ts b/src/components/Map/MapViewer/utils/config/useOlMapLayers.test.ts index 3fe8e861..4b52f2cd 100644 --- a/src/components/Map/MapViewer/utils/config/useOlMapLayers.test.ts +++ b/src/components/Map/MapViewer/utils/config/useOlMapLayers.test.ts @@ -7,7 +7,6 @@ import VectorLayer from 'ol/layer/Vector'; import React from 'react'; import { useOlMap } from '@/components/Map/MapViewer/utils/useOlMap'; import { useOlMapLayers } from '@/components/Map/MapViewer/utils/config/useOlMapLayers'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; const useRefValue = { current: null, @@ -60,7 +59,6 @@ describe('useOlMapLayers - util', () => { message: '', }, openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); const dummyElement = document.createElement('div'); diff --git a/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.test.ts b/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.test.ts deleted file mode 100644 index 58e4aaa5..00000000 --- a/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/map.constants'; -import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; -import { renderHook } from '@testing-library/react'; -import BaseLayer from 'ol/layer/Base'; -import TileLayer from 'ol/layer/Tile'; -import React from 'react'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; -import { useOlMapTileLayer } from './useOlMapTileLayer'; - -const useRefValue = { - current: null, -}; - -Object.defineProperty(useRefValue, 'current', { - get: jest.fn(() => ({ - innerHTML: '', - appendChild: jest.fn(), - addEventListener: jest.fn(), - getRootNode: jest.fn(), - })), - set: jest.fn(() => ({ - innerHTML: '', - appendChild: jest.fn(), - addEventListener: jest.fn(), - getRootNode: jest.fn(), - })), -}); - -jest.spyOn(React, 'useRef').mockReturnValue(useRefValue); - -describe('useOlMapTileLayer - util', () => { - const getRenderedHookResults = (): BaseLayer => { - const { Wrapper } = getReduxWrapperWithStore({ - map: { - data: { - ...MAP_DATA_INITIAL_STATE, - size: { - width: 256, - height: 256, - tileSize: 256, - minZoom: 1, - maxZoom: 1, - }, - position: { - initial: { - x: 256, - y: 256, - }, - last: { - x: 256, - y: 256, - }, - }, - }, - loading: 'idle', - error: { - name: '', - message: '', - }, - openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, - }, - }); - - const { result } = renderHook(() => useOlMapTileLayer(), { - wrapper: Wrapper, - }); - - return result.current; - }; - - it('should return valid TileLayer instance', () => { - const result = getRenderedHookResults(); - - expect(result).toBeInstanceOf(TileLayer); - expect(result.getSourceState()).toBe('ready'); - }); -}); diff --git a/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.ts b/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.ts deleted file mode 100644 index d98b480f..00000000 --- a/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { OPTIONS } from '@/constants/map'; -import { currentBackgroundImagePathSelector } from '@/redux/backgrounds/background.selectors'; -import { mapDataSizeSelector } from '@/redux/map/map.selectors'; -import { projectDataSelector } from '@/redux/project/project.selectors'; -import { Point } from '@/types/map'; -import { usePointToProjection } from '@/utils/map/usePointToProjection'; -import { Extent, boundingExtent } from 'ol/extent'; -import BaseLayer from 'ol/layer/Base'; -import TileLayer from 'ol/layer/Tile'; -import { XYZ } from 'ol/source'; -import { useMemo } from 'react'; -import { useSelector } from 'react-redux'; -import { getMapTileUrl } from './getMapTileUrl'; - -// useOlMapTileLayer returns visual tile layer of the map -// it makes it possible to view the map, scroll, zoom etc. -export const useOlMapTileLayer = (): BaseLayer => { - const mapSize = useSelector(mapDataSizeSelector); - const currentBackgroundImagePath = useSelector(currentBackgroundImagePathSelector); - const project = useSelector(projectDataSelector); - const pointToProjection = usePointToProjection(); - - const tileExtent = useMemo((): Extent => { - const topLeftPoint: Point = { - x: mapSize.width, - y: mapSize.height, - }; - - const bottomRightPoint: Point = { - x: 0, - y: 0, - }; - - return boundingExtent([topLeftPoint, bottomRightPoint].map(pointToProjection)); - }, [pointToProjection, mapSize]); - - const sourceUrl = useMemo( - () => getMapTileUrl({ projectDirectory: project?.directory, currentBackgroundImagePath }), - [project?.directory, currentBackgroundImagePath], - ); - - const source = useMemo( - () => - new XYZ({ - url: sourceUrl, - maxZoom: mapSize.maxZoom, - minZoom: mapSize.minZoom, - tileSize: Math.max(mapSize.tileSize, 1), - wrapX: OPTIONS.wrapXInTileLayer, - }), - [sourceUrl, mapSize.maxZoom, mapSize.minZoom, mapSize.tileSize], - ); - - const tileLayer = useMemo( - (): TileLayer<XYZ> => - new TileLayer({ - visible: true, - source, - extent: tileExtent, - }), - [source, tileExtent], - ); - - return tileLayer; -}; diff --git a/src/components/Map/MapViewer/utils/config/useOlMapView.test.ts b/src/components/Map/MapViewer/utils/config/useOlMapView.test.ts index d630b12b..0a786468 100644 --- a/src/components/Map/MapViewer/utils/config/useOlMapView.test.ts +++ b/src/components/Map/MapViewer/utils/config/useOlMapView.test.ts @@ -1,8 +1,4 @@ /* eslint-disable no-magic-numbers */ -import { - BACKGROUNDS_MOCK, - BACKGROUND_INITIAL_STATE_MOCK, -} from '@/redux/backgrounds/background.mock'; import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/map.constants'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; import { setMapPosition } from '@/redux/map/map.slice'; @@ -11,7 +7,6 @@ import { act, renderHook, waitFor } from '@testing-library/react'; import { View } from 'ol'; import Map from 'ol/Map'; import React from 'react'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { useOlMap } from '../useOlMap'; import { useOlMapView } from './useOlMapView'; @@ -40,7 +35,6 @@ describe('useOlMapView - util', () => { it('should modify view of the map instance on INITIAL position config change', async () => { const { Wrapper, store } = getReduxWrapperWithStore({ map: initialMapStateFixture, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, }); const dummyElement = document.createElement('div'); @@ -96,9 +90,7 @@ describe('useOlMapView - util', () => { message: '', }, openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, - backgrounds: BACKGROUND_INITIAL_STATE_MOCK, }); const dummyElement = document.createElement('div'); const { result: hohResult } = renderHook(() => useOlMap({ target: dummyElement }), { diff --git a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.test.ts b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.test.ts index 328c827b..2b2fabe1 100644 --- a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.test.ts @@ -3,7 +3,6 @@ import { renderHook } from '@testing-library/react'; import { View } from 'ol'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import * as positionListener from '@/components/Map/MapViewer/utils/listeners/onMapPositionChange'; import { useOlMapListeners } from '@/components/Map/MapViewer/utils/listeners/useOlMapListeners'; import { onMapLeftClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; @@ -32,7 +31,6 @@ describe('useOlMapListeners - util', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }); diff --git a/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts b/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts index 23277551..59af80b8 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts @@ -49,7 +49,7 @@ export interface BaseMapElementProps { pointToProjection: UsePointToProjectionResult; overlaysVisible: boolean; vectorSource: VectorSource; - mapBackgroundType: number; + backgroundId: number; mapSize: MapSize; mapInstance: MapInstance; } @@ -117,7 +117,7 @@ export default abstract class BaseMultiPolygon { vectorSource: VectorSource; - mapBackgroundType: number; + backgroundId: number; mapSize: MapSize; @@ -153,7 +153,7 @@ export default abstract class BaseMultiPolygon { pointToProjection, overlaysVisible, vectorSource, - mapBackgroundType, + backgroundId, mapSize, mapInstance, }: BaseMapElementProps) { @@ -181,7 +181,7 @@ export default abstract class BaseMultiPolygon { this.overlaysVisible = overlaysVisible; this.pointToProjection = pointToProjection; this.vectorSource = vectorSource; - this.mapBackgroundType = mapBackgroundType; + this.backgroundId = backgroundId; this.mapSize = mapSize; const maxZoom = mapInstance?.getView().get('originalMaxZoom'); @@ -371,7 +371,7 @@ export default abstract class BaseMultiPolygon { const styles: Array<Style> = []; const scale = this.minResolution / resolution; - if (this.mapBackgroundType === MapBackgroundsEnum.SEMANTIC && scale < TEXT_CUTOFF_SCALE) { + if (this.backgroundId === MapBackgroundsEnum.SEMANTIC && scale < TEXT_CUTOFF_SCALE) { const { hide, coverStyle } = this.processSemanticView(feature, resolution, scale); if (hide) { return undefined; diff --git a/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts b/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts index 10802411..76770a4b 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts @@ -45,7 +45,7 @@ export interface CompartmentProps { pointToProjection: UsePointToProjectionResult; mapInstance: MapInstance; vectorSource: VectorSource; - mapBackgroundType: number; + backgroundId: number; mapSize: MapSize; } @@ -90,7 +90,7 @@ export default abstract class Compartment extends BaseMultiPolygon { pointToProjection, mapInstance, vectorSource, - mapBackgroundType, + backgroundId, mapSize, }: CompartmentProps) { super({ @@ -118,7 +118,7 @@ export default abstract class Compartment extends BaseMultiPolygon { pointToProjection, overlaysVisible, vectorSource, - mapBackgroundType, + backgroundId, mapSize, mapInstance, }); diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts index eb94b525..1d5f41d6 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts @@ -67,7 +67,7 @@ describe('CompartmentCircle', () => { pointToProjection: jest.fn(), mapInstance, vectorSource: new VectorSource(), - mapBackgroundType: MapBackgroundsEnum.SEMANTIC, + backgroundId: MapBackgroundsEnum.SEMANTIC, mapSize: { minZoom: 1, maxZoom: 9, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts index 78915ae4..0de0037b 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts @@ -42,7 +42,7 @@ export type CompartmentCircleProps = { pointToProjection: UsePointToProjectionResult; mapInstance: MapInstance; vectorSource: VectorSource; - mapBackgroundType: number; + backgroundId: number; mapSize: MapSize; }; @@ -75,7 +75,7 @@ export default class CompartmentCircle extends Compartment { pointToProjection, mapInstance, vectorSource, - mapBackgroundType, + backgroundId, mapSize, }: CompartmentCircleProps) { super({ @@ -106,7 +106,7 @@ export default class CompartmentCircle extends Compartment { pointToProjection, mapInstance, vectorSource, - mapBackgroundType, + backgroundId, mapSize, }); } diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts index 05e1801e..0b0da3b4 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts @@ -65,7 +65,7 @@ describe('CompartmentPathway', () => { pointToProjection: jest.fn(() => [10, 10]), mapInstance, vectorSource: new VectorSource(), - mapBackgroundType: MapBackgroundsEnum.SEMANTIC, + backgroundId: MapBackgroundsEnum.SEMANTIC, mapSize: { minZoom: 1, maxZoom: 9, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts index 94034677..bf6b269e 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts @@ -45,7 +45,7 @@ export type CompartmentPathwayProps = { pointToProjection: UsePointToProjectionResult; mapInstance: MapInstance; vectorSource: VectorSource; - mapBackgroundType: number; + backgroundId: number; mapSize: MapSize; }; @@ -80,7 +80,7 @@ export default class CompartmentPathway extends BaseMultiPolygon { pointToProjection, mapInstance, vectorSource, - mapBackgroundType, + backgroundId, mapSize, }: CompartmentPathwayProps) { super({ @@ -108,7 +108,7 @@ export default class CompartmentPathway extends BaseMultiPolygon { pointToProjection, overlaysVisible, vectorSource, - mapBackgroundType, + backgroundId, mapSize, mapInstance, }); diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts index acf2471c..ebfdcd7a 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts @@ -65,7 +65,7 @@ describe('CompartmentSquare', () => { pointToProjection: jest.fn(), mapInstance, vectorSource: new VectorSource(), - mapBackgroundType: MapBackgroundsEnum.SEMANTIC, + backgroundId: MapBackgroundsEnum.SEMANTIC, mapSize: { minZoom: 1, maxZoom: 9, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts index 34f95693..32bb5a24 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts @@ -41,7 +41,7 @@ export type CompartmentSquareProps = { pointToProjection: UsePointToProjectionResult; mapInstance: MapInstance; vectorSource: VectorSource; - mapBackgroundType: number; + backgroundId: number; mapSize: MapSize; }; @@ -74,7 +74,7 @@ export default class CompartmentSquare extends Compartment { pointToProjection, mapInstance, vectorSource, - mapBackgroundType, + backgroundId, mapSize, }: CompartmentSquareProps) { super({ @@ -105,7 +105,7 @@ export default class CompartmentSquare extends Compartment { pointToProjection, mapInstance, vectorSource, - mapBackgroundType, + backgroundId, mapSize, }); } diff --git a/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts index 744c6529..2137147c 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts @@ -66,7 +66,7 @@ describe('MapElement', () => { overlaysVisible: false, vectorSource: new VectorSource(), getOverlayColor: (): string => '#ffffff', - mapBackgroundType: MapBackgroundsEnum.SEMANTIC, + backgroundId: MapBackgroundsEnum.SEMANTIC, mapSize: { minZoom: 1, maxZoom: 9, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts index ead1dd13..8f5f66d3 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts @@ -66,7 +66,7 @@ export type MapElementProps = { overlaysOrder?: Array<OverlayOrder>; overlaysVisible: boolean; getOverlayColor: GetOverlayBioEntityColorByAvailableProperties; - mapBackgroundType: number; + backgroundId: number; mapSize: MapSize; }; @@ -131,7 +131,7 @@ export default class MapElement extends BaseMultiPolygon { overlaysOrder = [], overlaysVisible, getOverlayColor, - mapBackgroundType, + backgroundId, mapSize, }: MapElementProps) { super({ @@ -159,7 +159,7 @@ export default class MapElement extends BaseMultiPolygon { pointToProjection, vectorSource, overlaysVisible, - mapBackgroundType, + backgroundId, mapSize, mapInstance, }); diff --git a/src/components/Map/MapViewer/utils/useOlMap.test.ts b/src/components/Map/MapViewer/utils/useOlMap.test.ts index 79bc1ed1..5b5fa97b 100644 --- a/src/components/Map/MapViewer/utils/useOlMap.test.ts +++ b/src/components/Map/MapViewer/utils/useOlMap.test.ts @@ -3,7 +3,6 @@ import { Map } from 'ol'; import React from 'react'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { BACKGROUND_INITIAL_STATE_MOCK } from '@/redux/backgrounds/background.mock'; import { useOlMap } from './useOlMap'; const useRefValue = { @@ -30,7 +29,6 @@ jest.spyOn(React, 'useRef').mockReturnValue(useRefValue); describe('useOlMap - util', () => { const { Wrapper } = getReduxWrapperWithStore({ map: initialMapStateFixture, - backgrounds: BACKGROUND_INITIAL_STATE_MOCK, }); describe('when initializing', () => { diff --git a/src/constants/backgrounds.ts b/src/constants/backgrounds.ts deleted file mode 100644 index 1bfb4619..00000000 --- a/src/constants/backgrounds.ts +++ /dev/null @@ -1 +0,0 @@ -export const EMPTY_BACKGROUND_NAME = 'Empty'; diff --git a/src/models/fixtures/backgroundsFixture.ts b/src/models/fixtures/backgroundsFixture.ts deleted file mode 100644 index e06e5c15..00000000 --- a/src/models/fixtures/backgroundsFixture.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ZOD_SEED } from '@/constants'; -import { z } from 'zod'; -// eslint-disable-next-line import/no-extraneous-dependencies -import { createFixture } from 'zod-fixture'; -import { mapBackground } from '../mapBackground'; - -export const backgroundsFixture = createFixture(z.array(mapBackground), { - seed: ZOD_SEED, - array: { min: 2, max: 2 }, -}); diff --git a/src/models/mapBackground.ts b/src/models/mapBackground.ts deleted file mode 100644 index fe6c6e9e..00000000 --- a/src/models/mapBackground.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { z } from 'zod'; - -export const mapBackground = z.object({ - id: z.number(), - name: z.string(), - defaultOverlay: z.boolean(), - project: z.object({ projectId: z.string() }), - creator: z.object({ login: z.string() }), - status: z.string(), - progress: z.number(), - description: z.string().nullable(), - order: z.number(), - images: z.array( - z.object({ - id: z.number(), - model: z.object({ id: z.number() }), - projectBackground: z.object({ id: z.number() }), - path: z.string(), - }), - ), -}); diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index d20f1a79..1e0c81b8 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -89,8 +89,6 @@ export const apiPath = { projectId: string, { publicOverlay }: { publicOverlay: boolean }, ): string => `projects/${projectId}/overlays/?isPublic=${String(publicOverlay)}`, - getAllBackgroundsByProjectIdQuery: (projectId: string): string => - `projects/${projectId}/backgrounds/`, getProjectById: (projectId: string): string => `projects/${projectId}`, getProjects: (): string => `projects/`, getSessionValid: (): string => `users/isSessionValid`, diff --git a/src/redux/backgrounds/background.mock.ts b/src/redux/backgrounds/background.mock.ts deleted file mode 100644 index 515bb724..00000000 --- a/src/redux/backgrounds/background.mock.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { DEFAULT_ERROR } from '@/constants/errors'; -import { MapBackground } from '@/types/models'; -import { BackgroundsState } from './backgrounds.types'; - -export const BACKGROUND_INITIAL_STATE_MOCK: BackgroundsState = { - data: undefined, - loading: 'idle', - error: DEFAULT_ERROR, -}; - -export const BACKGROUNDS_MOCK: MapBackground[] = [ - { - id: 13, - name: 'Pathways and compartments', - defaultOverlay: false, - project: { - projectId: 'pdmap_appu_test', - }, - creator: { - login: 'admin', - }, - status: 'NA', - progress: 0, - description: null, - order: 0, - images: [], - }, - { - id: 14, - name: 'Network', - defaultOverlay: false, - project: { - projectId: 'pdmap_appu_test', - }, - creator: { - login: 'admin', - }, - status: 'NA', - progress: 0, - description: null, - order: 1, - images: [], - }, - { - id: 15, - name: 'Empty', - defaultOverlay: false, - project: { - projectId: 'pdmap_appu_test', - }, - creator: { - login: 'admin', - }, - status: 'NA', - progress: 0, - description: null, - order: 2, - images: [], - }, -]; diff --git a/src/redux/backgrounds/background.selectors.ts b/src/redux/backgrounds/background.selectors.ts deleted file mode 100644 index eda37034..00000000 --- a/src/redux/backgrounds/background.selectors.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { EMPTY_BACKGROUND_NAME } from '@/constants/backgrounds'; -import { createSelector } from '@reduxjs/toolkit'; -import { mapDataSelector } from '../map/map.selectors'; -import { rootSelector } from '../root/root.selectors'; -import { PATHWAYS_AND_COMPARTMENTS_BACKGROUND, SEMANTIC_BACKGROUND } from './backgrounds.constants'; - -export const backgroundsSelector = createSelector(rootSelector, state => state.backgrounds); - -export const backgroundsDataSelector = createSelector(backgroundsSelector, backgrounds => { - return (backgrounds?.data || []).map(background => { - if (background.name === PATHWAYS_AND_COMPARTMENTS_BACKGROUND) { - return { - ...background, - name: SEMANTIC_BACKGROUND, - }; - } - - return background; - }); -}); - -const MAIN_BACKGROUND = 0; -export const mainBackgroundsDataSelector = createSelector( - backgroundsDataSelector, - backgrounds => backgrounds && backgrounds[MAIN_BACKGROUND], -); -export const mainBackgroundIdSelector = createSelector( - backgroundsDataSelector, - backgrounds => backgrounds && backgrounds[MAIN_BACKGROUND]?.id, -); - -export const currentBackgroundSelector = createSelector( - backgroundsDataSelector, - mapDataSelector, - (backgrounds, mapData) => - backgrounds && backgrounds.find(background => background.id === mapData.backgroundId), -); - -export const currentBackgroundImageSelector = createSelector( - mapDataSelector, - currentBackgroundSelector, - (mapData, background) => - background && background.images.find(image => image.model.id === mapData.modelId), -); - -export const currentBackgroundImagePathSelector = createSelector( - currentBackgroundImageSelector, - image => (image ? image.path : ''), -); - -export const emptyBackgroundIdSelector = createSelector(backgroundsDataSelector, backgrounds => { - const emptyBackground = backgrounds?.find( - background => background.name === EMPTY_BACKGROUND_NAME, - ); - return emptyBackground?.id; -}); diff --git a/src/redux/backgrounds/backgrounds.constants.ts b/src/redux/backgrounds/backgrounds.constants.ts deleted file mode 100644 index 49499431..00000000 --- a/src/redux/backgrounds/backgrounds.constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const BACKGROUNDS_FETCHING_ERROR_PREFIX = 'Failed to fetch backgrounds'; -export const PATHWAYS_AND_COMPARTMENTS_BACKGROUND = 'Pathways and compartments'; -export const SEMANTIC_BACKGROUND = 'Semantic'; diff --git a/src/redux/backgrounds/backgrounds.reducers.test.ts b/src/redux/backgrounds/backgrounds.reducers.test.ts deleted file mode 100644 index dd13a771..00000000 --- a/src/redux/backgrounds/backgrounds.reducers.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { PROJECT_ID } from '@/constants'; -import { backgroundsFixture } from '@/models/fixtures/backgroundsFixture'; -import { - ToolkitStoreWithSingleSlice, - createStoreInstanceUsingSliceReducer, -} from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { HttpStatusCode } from 'axios'; -import { unwrapResult } from '@reduxjs/toolkit'; -import { apiPath } from '../apiPath'; -import backgroundsReducer from './backgrounds.slice'; -import { getAllBackgroundsByProjectId } from './backgrounds.thunks'; -import { BackgroundsState } from './backgrounds.types'; - -jest.mock('../../utils/showToast'); - -const mockedAxiosClient = mockNetworkResponse(); - -const INITIAL_STATE: BackgroundsState = { - data: [], - loading: 'idle', - error: { name: '', message: '' }, -}; - -describe('backgrounds reducer', () => { - let store = {} as ToolkitStoreWithSingleSlice<BackgroundsState>; - beforeEach(() => { - store = createStoreInstanceUsingSliceReducer('backgrounds', backgroundsReducer); - }); - - it('should match initial state', () => { - const action = { type: 'unknown' }; - - expect(backgroundsReducer(undefined, action)).toEqual(INITIAL_STATE); - }); - it('should update store after succesfull getAllBackgroundsByProjectId query', async () => { - mockedAxiosClient - .onGet(apiPath.getAllBackgroundsByProjectIdQuery(PROJECT_ID)) - .reply(HttpStatusCode.Ok, backgroundsFixture); - - const { type } = await store.dispatch(getAllBackgroundsByProjectId(PROJECT_ID)); - const { data, loading, error } = store.getState().backgrounds; - - expect(type).toBe('backgrounds/getAllBackgroundsByProjectId/fulfilled'); - expect(loading).toEqual('succeeded'); - expect(error).toEqual({ message: '', name: '' }); - expect(data).toEqual(backgroundsFixture); - }); - - it('should update store after failed getAllBackgroundsByProjectId query', async () => { - mockedAxiosClient - .onGet(apiPath.getAllBackgroundsByProjectIdQuery(PROJECT_ID)) - .reply(HttpStatusCode.NotFound, []); - - const action = await store.dispatch(getAllBackgroundsByProjectId(PROJECT_ID)); - const { data, loading, error } = store.getState().backgrounds; - - expect(action.type).toBe('backgrounds/getAllBackgroundsByProjectId/rejected'); - expect(loading).toEqual('failed'); - expect(error).toEqual({ message: '', name: '' }); - expect(data).toEqual([]); - expect(() => unwrapResult(action)).toThrow( - "Failed to fetch backgrounds: The page you're looking for doesn't exist. Please verify the URL and try again.", - ); - }); - - it('should update store on loading getAllBackgroundsByProjectId query', async () => { - mockedAxiosClient - .onGet(apiPath.getAllBackgroundsByProjectIdQuery(PROJECT_ID)) - .reply(HttpStatusCode.Ok, backgroundsFixture); - - const actionPromise = store.dispatch(getAllBackgroundsByProjectId(PROJECT_ID)); - - const { data, loading } = store.getState().backgrounds; - expect(data).toEqual([]); - expect(loading).toEqual('pending'); - - actionPromise.then(() => { - const { data: dataPromiseFulfilled, loading: promiseFulfilled } = - store.getState().backgrounds; - - expect(dataPromiseFulfilled).toEqual(backgroundsFixture); - expect(promiseFulfilled).toEqual('succeeded'); - }); - }); -}); diff --git a/src/redux/backgrounds/backgrounds.reducers.ts b/src/redux/backgrounds/backgrounds.reducers.ts deleted file mode 100644 index 2f0868b4..00000000 --- a/src/redux/backgrounds/backgrounds.reducers.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; -import { getAllBackgroundsByProjectId } from './backgrounds.thunks'; -import { BackgroundsState } from './backgrounds.types'; - -export const getAllBackgroundsByProjectIdReducer = ( - builder: ActionReducerMapBuilder<BackgroundsState>, -): void => { - builder.addCase(getAllBackgroundsByProjectId.pending, state => { - state.loading = 'pending'; - }); - builder.addCase(getAllBackgroundsByProjectId.fulfilled, (state, action) => { - state.data = action.payload || []; - state.loading = 'succeeded'; - }); - builder.addCase(getAllBackgroundsByProjectId.rejected, state => { - state.loading = 'failed'; - // TODO to discuss manage state of failure - }); -}; diff --git a/src/redux/backgrounds/backgrounds.slice.ts b/src/redux/backgrounds/backgrounds.slice.ts deleted file mode 100644 index 491e981d..00000000 --- a/src/redux/backgrounds/backgrounds.slice.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createSlice } from '@reduxjs/toolkit'; -import { getAllBackgroundsByProjectIdReducer } from './backgrounds.reducers'; -import { BackgroundsState } from './backgrounds.types'; - -const initialState: BackgroundsState = { - data: [], - loading: 'idle', - error: { name: '', message: '' }, -}; - -const backgroundsState = createSlice({ - name: 'backgrounds', - initialState, - reducers: {}, - extraReducers: builder => { - getAllBackgroundsByProjectIdReducer(builder); - }, -}); - -export default backgroundsState.reducer; diff --git a/src/redux/backgrounds/backgrounds.thunks.ts b/src/redux/backgrounds/backgrounds.thunks.ts deleted file mode 100644 index d2ce1949..00000000 --- a/src/redux/backgrounds/backgrounds.thunks.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { mapBackground } from '@/models/mapBackground'; -import { axiosInstance } from '@/services/api/utils/axiosInstance'; -import { MapBackground } from '@/types/models'; -import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { createAsyncThunk } from '@reduxjs/toolkit'; -import { z } from 'zod'; -import { ThunkConfig } from '@/types/store'; -import { getError } from '@/utils/error-report/getError'; -import { apiPath } from '../apiPath'; -import { BACKGROUNDS_FETCHING_ERROR_PREFIX } from './backgrounds.constants'; - -export const getAllBackgroundsByProjectId = createAsyncThunk<MapBackground[], string, ThunkConfig>( - 'backgrounds/getAllBackgroundsByProjectId', - async (projectId: string) => { - try { - const response = await axiosInstance.get<MapBackground[]>( - apiPath.getAllBackgroundsByProjectIdQuery(projectId), - ); - - const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapBackground)); - - return isDataValid ? response.data : []; - } catch (error) { - return Promise.reject(getError({ error, prefix: BACKGROUNDS_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/backgrounds/backgrounds.types.ts b/src/redux/backgrounds/backgrounds.types.ts deleted file mode 100644 index 7ce8fcfc..00000000 --- a/src/redux/backgrounds/backgrounds.types.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { FetchDataState } from '@/types/fetchDataState'; -import { MapBackground } from '@/types/models'; - -export type BackgroundsState = FetchDataState<MapBackground[]>; diff --git a/src/redux/map/map.constants.ts b/src/redux/map/map.constants.ts index 55b67d50..92de423d 100644 --- a/src/redux/map/map.constants.ts +++ b/src/redux/map/map.constants.ts @@ -18,7 +18,7 @@ export const MAP_BACKGROUND_TYPES = [ export const MODEL_ID_DEFAULT: number = 0; -export const BACKGROUND_ID_DEFAULT: number = 0; +export const BACKGROUND_ID_DEFAULT: number = MapBackgroundsEnum.SEMANTIC; export const OVERVIEW_IMAGE_ID_DEFAULT: number = 0; @@ -73,7 +73,6 @@ export const MAP_INITIAL_STATE: MapState = { loading: 'idle', error: { name: '', message: '' }, openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, }; export const INIT_MAP_SIZE_MODEL_ID_ERROR_PREFIX = 'Failed to initialize map size and model ID'; diff --git a/src/redux/map/map.fixtures.ts b/src/redux/map/map.fixtures.ts index 21674c65..77d17df6 100644 --- a/src/redux/map/map.fixtures.ts +++ b/src/redux/map/map.fixtures.ts @@ -22,7 +22,7 @@ export const initialMapDataFixture: MapData = { projectId: 'pdmap', meshId: '', modelId: 0, - backgroundId: 0, + backgroundId: MapBackgroundsEnum.SEMANTIC, overlaysIds: [], position: { initial: { x: 0, y: 0, z: 5 }, @@ -60,7 +60,6 @@ export const initialMapStateFixture: MapState = { loading: 'idle', error: DEFAULT_ERROR, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }; export const mapStateWithCurrentlySelectedMainMapFixture: MapState = { @@ -78,5 +77,4 @@ export const mapStateWithCurrentlySelectedMainMapFixture: MapState = { loading: 'idle', error: DEFAULT_ERROR, openedMaps: openedMapsInitialValueFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }; diff --git a/src/redux/map/map.reducers.ts b/src/redux/map/map.reducers.ts index 5ae6707d..553ad617 100644 --- a/src/redux/map/map.reducers.ts +++ b/src/redux/map/map.reducers.ts @@ -1,6 +1,6 @@ import { DEFAULT_ZOOM } from '@/constants/map'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; -import { ActionReducerMapBuilder, PayloadAction } from '@reduxjs/toolkit'; +import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { getPointMerged } from '@/utils/object/getPointMerged'; import { initMapBackground, @@ -221,11 +221,3 @@ export const initOpenedMapsReducer = (builder: ActionReducerMapBuilder<MapState> state.openedMaps = action.payload; }); }; - -export const setMapBackgroundTypeReducer = ( - state: MapState, - action: PayloadAction<number>, -): void => { - const { payload } = action; - state.backgroundType = payload; -}; diff --git a/src/redux/map/map.selectors.ts b/src/redux/map/map.selectors.ts index 8cb88035..92737498 100644 --- a/src/redux/map/map.selectors.ts +++ b/src/redux/map/map.selectors.ts @@ -35,4 +35,4 @@ export const mapDataLastZoomValue = createSelector( export const mapDataMaxZoomValue = createSelector(mapDataSizeSelector, model => model.maxZoom); -export const mapBackgroundTypeSelector = createSelector(mapSelector, map => map.backgroundType); +export const mapBackgroundSelector = createSelector(mapSelector, map => map.data.backgroundId); diff --git a/src/redux/map/map.slice.ts b/src/redux/map/map.slice.ts index dbfd8bbe..3106a118 100644 --- a/src/redux/map/map.slice.ts +++ b/src/redux/map/map.slice.ts @@ -12,7 +12,6 @@ import { setActiveMapReducer, setLastPositionZoomReducer, setMapBackgroundReducer, - setMapBackgroundTypeReducer, setMapDataReducer, setMapPositionReducer, updateLastClickReducer, @@ -36,7 +35,6 @@ const mapSlice = createSlice({ setLastPositionZoom: setLastPositionZoomReducer, updateLastClick: updateLastClickReducer, updateLastRightClick: updateLastRightClickReducer, - setMapBackgroundType: setMapBackgroundTypeReducer, }, extraReducers: builder => { initMapPositionReducers(builder); @@ -59,7 +57,6 @@ export const { setLastPositionZoom, updateLastClick, updateLastRightClick, - setMapBackgroundType, } = mapSlice.actions; export default mapSlice.reducer; diff --git a/src/redux/map/map.thunks.test.ts b/src/redux/map/map.thunks.test.ts index b44d0fd8..81feb7da 100644 --- a/src/redux/map/map.thunks.test.ts +++ b/src/redux/map/map.thunks.test.ts @@ -6,7 +6,7 @@ import { Project } from '@/types/models'; import { PROJECT_STATE_INITIAL_MOCK } from '@/redux/project/project.mock'; import { ProjectState } from '@/redux/project/project.types'; import { MAIN_MAP_ID } from '@/constants/mocks'; -import { BACKGROUNDS_MOCK, BACKGROUND_INITIAL_STATE_MOCK } from '../backgrounds/background.mock'; +import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MODELS_INITIAL_STATE_MOCK } from '../models/models.mock'; import { INITIAL_STORE_STATE_MOCK } from '../root/root.fixtures'; import { RootState } from '../store'; @@ -68,33 +68,27 @@ const STATE_WITH_MODELS: RootState = { describe('map thunks - utils', () => { describe('getBackgroundId', () => { - it('should return backgroundId value from queryData', () => { - const backgroundId = getBackgroundId(INITIAL_STORE_STATE_MOCK, QUERY_DATA_WITH_BG); - expect(backgroundId).toBe(21); - }); - it('should return main map background id if query param does not include background id', () => { + it('should return main map background id (2 - semantic) if query param does not include background id', () => { const store: RootState = { ...INITIAL_STORE_STATE_MOCK, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, }; const backgroundId = getBackgroundId(store, EMPTY_QUERY_DATA); - expect(backgroundId).toBe(13); + expect(backgroundId).toBe(MapBackgroundsEnum.SEMANTIC); }); - it('should return default value (0) if query data does not include backgroundId and could not find main background in the store', () => { + it('should return default value (2 - semantic) if query data does not include backgroundId and could not find main background in the store', () => { const backgroundId = getBackgroundId(INITIAL_STORE_STATE_MOCK, EMPTY_QUERY_DATA); - expect(backgroundId).toBe(0); + expect(backgroundId).toBe(MapBackgroundsEnum.SEMANTIC); }); - it('should return main map background id if query param background id is invalid', () => { + it('should return semantic map background id if query param background id is invalid', () => { const store: RootState = { ...INITIAL_STORE_STATE_MOCK, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, }; const backgroundId = getBackgroundId(store, QUERY_DATA_WITH_BG); - expect(backgroundId).toBe(13); + expect(backgroundId).toBe(MapBackgroundsEnum.SEMANTIC); }); }); diff --git a/src/redux/map/map.thunks.ts b/src/redux/map/map.thunks.ts index 363b1d9c..bb1a81d3 100644 --- a/src/redux/map/map.thunks.ts +++ b/src/redux/map/map.thunks.ts @@ -7,6 +7,7 @@ import { getPointMerged } from '@/utils/object/getPointMerged'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { ThunkConfig } from '@/types/store'; import { getError } from '@/utils/error-report/getError'; +import MapBackgroundsEnum from '@/redux/map/map.enums'; import type { AppDispatch, RootState } from '../store'; import { InitMapBackgroundActionPayload, @@ -21,10 +22,6 @@ import { OppenedMap, Position, } from './map.types'; -import { - backgroundsDataSelector, - mainBackgroundsDataSelector, -} from '../backgrounds/background.selectors'; import { currentModelSelector, mainMapModelSelector, @@ -43,21 +40,13 @@ import { /** UTILS - in the same file because of dependency cycle */ export const getBackgroundId = (state: RootState, queryData: QueryData): number => { - const mainMapBackground = mainBackgroundsDataSelector(state); - const backgrounds = backgroundsDataSelector(state); - let backgroundId = queryData?.backgroundId || mainMapBackground?.id || ZERO; + let backgroundId = queryData?.backgroundId; - if (backgrounds.length > 0) { - if ( - backgrounds.filter(background => { - return background.id === backgroundId; - }).length === 0 - ) { - backgroundId = backgrounds[ZERO].id; - } + if (!backgroundId || !Object.values(MapBackgroundsEnum).includes(backgroundId)) { + backgroundId = MapBackgroundsEnum.SEMANTIC; } - if (backgroundId !== mainMapBackground?.id) { + if (backgroundId !== MapBackgroundsEnum.SEMANTIC) { PluginsEventBus.dispatchEvent('onBackgroundOverlayChange', backgroundId); } diff --git a/src/redux/map/map.types.ts b/src/redux/map/map.types.ts index dc838aaa..72b600dc 100644 --- a/src/redux/map/map.types.ts +++ b/src/redux/map/map.types.ts @@ -44,9 +44,7 @@ export type MapData = { }; }; -export type MapState = FetchDataState<MapData, MapData> & { openedMaps: OppenedMap[] } & { - backgroundType: number; -}; +export type MapState = FetchDataState<MapData, MapData> & { openedMaps: OppenedMap[] }; export type SetMapDataActionPayload = | (Omit<Partial<MapData>, 'position' | 'projectId'> & { diff --git a/src/redux/map/middleware/checkIfIsMapUpdateActionValid.test.ts b/src/redux/map/middleware/checkIfIsMapUpdateActionValid.test.ts index 1509a089..5580c024 100644 --- a/src/redux/map/middleware/checkIfIsMapUpdateActionValid.test.ts +++ b/src/redux/map/middleware/checkIfIsMapUpdateActionValid.test.ts @@ -1,6 +1,5 @@ import { RootState } from '@/redux/store'; import { Loading } from '@/types/loadingState'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MAP_DATA_INITIAL_STATE, MIDDLEWARE_ALLOWED_ACTIONS, @@ -18,7 +17,6 @@ const state: Pick<RootState, 'map'> = { loading: 'idle' as Loading, error: { name: '', message: '' }, openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }; diff --git a/src/redux/map/middleware/map.middleware.test.ts b/src/redux/map/middleware/map.middleware.test.ts index cb928afd..b783347e 100644 --- a/src/redux/map/middleware/map.middleware.test.ts +++ b/src/redux/map/middleware/map.middleware.test.ts @@ -3,7 +3,6 @@ import { modelsFixture } from '@/models/fixtures/modelsFixture'; import { Loading } from '@/types/loadingState'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { Action } from '@reduxjs/toolkit'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MAP_DATA_INITIAL_STATE, MIDDLEWARE_ALLOWED_ACTIONS, @@ -64,7 +63,6 @@ const { store } = getReduxWrapperWithStore({ modelId: modelsFixture[0].id, }, openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { ...defaultSliceState, diff --git a/src/redux/map/middleware/map.middleware.ts b/src/redux/map/middleware/map.middleware.ts index bacbb729..d4eef340 100644 --- a/src/redux/map/middleware/map.middleware.ts +++ b/src/redux/map/middleware/map.middleware.ts @@ -1,8 +1,7 @@ -import { currentBackgroundSelector } from '@/redux/backgrounds/background.selectors'; import type { AppListenerEffectAPI, AppStartListening } from '@/redux/store'; import { getUpdatedMapData } from '@/utils/map/getUpdatedMapData'; import { Action, createListenerMiddleware, isAnyOf } from '@reduxjs/toolkit'; -import { mapOpenedMapPositionByIdSelector } from '../map.selectors'; +import { mapBackgroundSelector, mapOpenedMapPositionByIdSelector } from '../map.selectors'; import { closeMapAndSetMainMapActive, openMapAndOrSetActiveIfSelected, @@ -31,7 +30,7 @@ export const mapDataMiddlewareListener = async ( return; } - const background = currentBackgroundSelector(state); + const background = mapBackgroundSelector(state); const modelId = updatedModel.id; const lastPosition = mapOpenedMapPositionByIdSelector(state, modelId); const updatedMapData = getUpdatedMapData({ diff --git a/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts b/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts index f726bd8f..c0d3daed 100644 --- a/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts +++ b/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts @@ -12,8 +12,6 @@ import { import { apiPath } from '../apiPath'; import { modelsIdsSelector } from '../models/models.selectors'; import type { RootState } from '../store'; -import { setMapBackground } from '../map/map.slice'; -import { emptyBackgroundIdSelector } from '../backgrounds/background.selectors'; import { overlaySelector, userOverlaySelector } from '../overlays/overlays.selectors'; import { INIT_OVERLAYS_ERROR_PREFIX, @@ -89,11 +87,6 @@ export const getInitOverlays = createAsyncThunk< try { const state = getState(); - const emptyBackgroundId = emptyBackgroundIdSelector(state); - if (emptyBackgroundId) { - dispatch(setMapBackground(emptyBackgroundId)); - } - overlaysId.forEach(id => { const userOverlay = userOverlaySelector(state, id); const overlay = overlaySelector(state, id); diff --git a/src/redux/root/init.selectors.ts b/src/redux/root/init.selectors.ts index 67cdfa08..5ddcf77a 100644 --- a/src/redux/root/init.selectors.ts +++ b/src/redux/root/init.selectors.ts @@ -1,5 +1,4 @@ import { createSelector } from '@reduxjs/toolkit'; -import { backgroundsSelector } from '../backgrounds/background.selectors'; import { mapSelector } from '../map/map.selectors'; import { modelsSelector } from '../models/models.selectors'; import { overlaysSelector } from '../overlays/overlays.selectors'; @@ -7,7 +6,6 @@ import { projectSelector } from '../project/project.selectors'; export const initDataLoadingInitialized = createSelector( projectSelector, - backgroundsSelector, modelsSelector, overlaysSelector, (...selectors) => selectors.every(selector => selector.loading !== 'idle'), @@ -15,7 +13,6 @@ export const initDataLoadingInitialized = createSelector( export const initDataLoadingFinishedSelector = createSelector( projectSelector, - backgroundsSelector, modelsSelector, overlaysSelector, (...selectors) => selectors.every(selector => selector.loading === 'succeeded'), @@ -23,7 +20,6 @@ export const initDataLoadingFinishedSelector = createSelector( export const initDataAndMapLoadingFinished = createSelector( projectSelector, - backgroundsSelector, modelsSelector, overlaysSelector, mapSelector, diff --git a/src/redux/root/init.thunks.ts b/src/redux/root/init.thunks.ts index ba7f3059..562789dc 100644 --- a/src/redux/root/init.thunks.ts +++ b/src/redux/root/init.thunks.ts @@ -24,7 +24,6 @@ import { } from '@/components/FunctionalArea/CookieBanner/CookieBanner.constants'; import { injectMatomoTracking } from '@/utils/injectMatomoTracking'; import { getGlyphs } from '@/redux/glyphs/glyphs.thunks'; -import { getAllBackgroundsByProjectId } from '../backgrounds/backgrounds.thunks'; import { getConfiguration, getConfigurationOptions } from '../configuration/configuration.thunks'; import { initMapBackground, @@ -64,7 +63,6 @@ export const fetchInitialAppData = createAsyncThunk< dispatch(getConfiguration()), dispatch(getConfigurationOptions()), dispatch(getProjectById(PROJECT_ID)), - dispatch(getAllBackgroundsByProjectId(PROJECT_ID)), dispatch(getAllPublicOverlaysByProjectId(PROJECT_ID)), dispatch(getModels()), dispatch(getShapes()), diff --git a/src/redux/root/root.fixtures.ts b/src/redux/root/root.fixtures.ts index c90d96c3..f6d6110c 100644 --- a/src/redux/root/root.fixtures.ts +++ b/src/redux/root/root.fixtures.ts @@ -9,7 +9,6 @@ import { LAYERS_STATE_INITIAL_MOCK } from '@/redux/layers/layers.mock'; import { NEW_REACTIONS_INITIAL_STATE_MOCK } from '@/redux/newReactions/newReactions.mock'; import { GLYPHS_STATE_INITIAL_MOCK } from '@/redux/glyphs/glyphs.mock'; import { MAP_EDIT_TOOLS_STATE_INITIAL_MOCK } from '@/redux/mapEditTools/mapEditTools.mock'; -import { BACKGROUND_INITIAL_STATE_MOCK } from '../backgrounds/background.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'; @@ -51,7 +50,6 @@ export const INITIAL_STORE_STATE_MOCK: RootState = { modelElements: MODEL_ELEMENTS_INITIAL_STATE_MOCK, layers: LAYERS_STATE_INITIAL_MOCK, bioEntity: BIOENTITY_INITIAL_STATE_MOCK, - backgrounds: BACKGROUND_INITIAL_STATE_MOCK, drawer: drawerInitialStateMock, map: initialMapStateFixture, oauth: OAUTH_INITIAL_STATE_MOCK, diff --git a/src/redux/store.ts b/src/redux/store.ts index 0e3a85b9..a98370bc 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -1,4 +1,3 @@ -import backgroundsReducer from '@/redux/backgrounds/backgrounds.slice'; import bioEntityReducer from '@/redux/bioEntity/bioEntity.slice'; import chemicalsReducer from '@/redux/chemicals/chemicals.slice'; import configurationReducer from '@/redux/configuration/configuration.slice'; @@ -62,7 +61,6 @@ export const reducers = { drawer: drawerReducer, modal: modalReducer, map: mapReducer, - backgrounds: backgroundsReducer, overlays: overlaysReducer, models: modelsReducer, shapes: shapesReducer, diff --git a/src/services/pluginsManager/map/data/getBounds.test.ts b/src/services/pluginsManager/map/data/getBounds.test.ts index b824df10..99f587da 100644 --- a/src/services/pluginsManager/map/data/getBounds.test.ts +++ b/src/services/pluginsManager/map/data/getBounds.test.ts @@ -2,7 +2,6 @@ import { MAP_DATA_INITIAL_STATE } from '@/redux/map/map.constants'; import { store } from '@/redux/store'; import { Map } from 'ol'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { MapManager } from '../mapManager'; import { getBounds } from './getBounds'; @@ -46,7 +45,6 @@ describe('getBounds', () => { message: '', }, openedMaps: [], - backgroundType: MapBackgroundsEnum.SEMANTIC, }, // eslint-disable-next-line @typescript-eslint/no-explicit-any }) as any, diff --git a/src/services/pluginsManager/map/fitBounds/fitBounds.test.ts b/src/services/pluginsManager/map/fitBounds/fitBounds.test.ts index de852078..1fd5ec32 100644 --- a/src/services/pluginsManager/map/fitBounds/fitBounds.test.ts +++ b/src/services/pluginsManager/map/fitBounds/fitBounds.test.ts @@ -2,7 +2,6 @@ import { MAP_DATA_INITIAL_STATE } from '@/redux/map/map.constants'; import { Map } from 'ol'; import { store } from '@/redux/store'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { fitBounds } from './fitBounds'; import { MapManager } from '../mapManager'; @@ -52,7 +51,6 @@ describe('fitBounds', () => { message: '', }, openedMaps: [], - backgroundType: MapBackgroundsEnum.SEMANTIC, }, // eslint-disable-next-line @typescript-eslint/no-explicit-any }) as any, @@ -103,7 +101,6 @@ describe('fitBounds', () => { message: '', }, openedMaps: [], - backgroundType: MapBackgroundsEnum.SEMANTIC, }, // eslint-disable-next-line @typescript-eslint/no-explicit-any }) as any, diff --git a/src/services/pluginsManager/map/openMap.test.ts b/src/services/pluginsManager/map/openMap.test.ts index 69aca9db..ddebdab0 100644 --- a/src/services/pluginsManager/map/openMap.test.ts +++ b/src/services/pluginsManager/map/openMap.test.ts @@ -3,7 +3,6 @@ import { openMapAndSetActive, setActiveMap } from '@/redux/map/map.slice'; import { RootState, store } from '@/redux/store'; import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; import { MODELS_MOCK, MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { HISTAMINE_MAP_ID, MAIN_MAP_ID } from '@/constants/mocks'; import { PluginsEventBus } from '../pluginsEventBus'; import { openMap } from './openMap'; @@ -27,7 +26,6 @@ describe('openMap', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK_SHORT, @@ -53,7 +51,6 @@ describe('openMap', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK, @@ -81,7 +78,6 @@ describe('openMap', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, models: { data: MODELS_MOCK, diff --git a/src/services/pluginsManager/map/overlays/showDataOverlay/setBackgroundtoEmptyIfAvailable.test.ts b/src/services/pluginsManager/map/overlays/showDataOverlay/setBackgroundtoEmptyIfAvailable.test.ts deleted file mode 100644 index 15b32c94..00000000 --- a/src/services/pluginsManager/map/overlays/showDataOverlay/setBackgroundtoEmptyIfAvailable.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { - BACKGROUNDS_MOCK, - BACKGROUND_INITIAL_STATE_MOCK, -} from '@/redux/backgrounds/background.mock'; -import { initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { RootState, store } from '@/redux/store'; -import { setBackgroundtoEmptyIfAvailable } from './setBackgroundtoEmptyIfAvailable'; - -const DEFAULT_BACKGROUND_ID = 0; -const EMPTY_BACKGROUND_ID = 15; - -describe('setEmptyBackground', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - const getStateSpy = jest.spyOn(store, 'getState'); - const dispatchSpy = jest.spyOn(store, 'dispatch'); - it('should not set background to empty if its not available', () => { - getStateSpy.mockImplementation( - () => - ({ - map: initialMapStateFixture, - backgrounds: BACKGROUND_INITIAL_STATE_MOCK, - }) as RootState, - ); - - expect(store.getState().map.data.backgroundId).toBe(DEFAULT_BACKGROUND_ID); - - setBackgroundtoEmptyIfAvailable(); - - expect(dispatchSpy).not.toHaveBeenCalled(); - }); - - it('should set background to empty if its available', () => { - getStateSpy.mockImplementation( - () => - ({ - map: initialMapStateFixture, - backgrounds: { ...BACKGROUND_INITIAL_STATE_MOCK, data: BACKGROUNDS_MOCK }, - }) as RootState, - ); - - expect(store.getState().map.data.backgroundId).toBe(DEFAULT_BACKGROUND_ID); - - setBackgroundtoEmptyIfAvailable(); - - expect(dispatchSpy).toHaveBeenCalledWith({ - payload: EMPTY_BACKGROUND_ID, - type: 'map/setMapBackground', - }); - }); -}); diff --git a/src/services/pluginsManager/map/overlays/showDataOverlay/setBackgroundtoEmptyIfAvailable.ts b/src/services/pluginsManager/map/overlays/showDataOverlay/setBackgroundtoEmptyIfAvailable.ts deleted file mode 100644 index 59c6c061..00000000 --- a/src/services/pluginsManager/map/overlays/showDataOverlay/setBackgroundtoEmptyIfAvailable.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { emptyBackgroundIdSelector } from '@/redux/backgrounds/background.selectors'; -import { setMapBackground } from '@/redux/map/map.slice'; -import { store } from '@/redux/store'; - -export const setBackgroundtoEmptyIfAvailable = (): void => { - const { dispatch, getState } = store; - const emptyBackgroundId = emptyBackgroundIdSelector(getState()); - - if (emptyBackgroundId) { - dispatch(setMapBackground(emptyBackgroundId)); - } -}; diff --git a/src/services/pluginsManager/map/overlays/showDataOverlay/showDataOverlay.test.ts b/src/services/pluginsManager/map/overlays/showDataOverlay/showDataOverlay.test.ts index da92e7f9..7709f9ec 100644 --- a/src/services/pluginsManager/map/overlays/showDataOverlay/showDataOverlay.test.ts +++ b/src/services/pluginsManager/map/overlays/showDataOverlay/showDataOverlay.test.ts @@ -11,11 +11,9 @@ import { import { getOverlayBioEntityForAllModels } from '@/redux/overlayBioEntity/overlayBioEntity.thunk'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { showDataOverlay } from './showDataOverlay'; -import { setBackgroundtoEmptyIfAvailable } from './setBackgroundtoEmptyIfAvailable'; jest.mock('../../../../../redux/overlayBioEntity/overlayBioEntity.thunk'); jest.mock('../../../../../redux/store'); -jest.mock('./setBackgroundtoEmptyIfAvailable'); const OVERLAY_ID = overlaysPageFixture.content[0].idObject; @@ -110,45 +108,4 @@ describe('showDataOverlay function', () => { overlaysPageFixture.content[0], ); }); - - it('should not set empty background when it show overlay', () => { - getStateSpy.mockImplementation( - () => - ({ - overlays: { - ...OVERLAYS_INITIAL_STATE_MOCK, - userOverlays: { - data: overlaysPageFixture.content, - loading: 'idle', - error: DEFAULT_ERROR, - }, - }, - overlayBioEntity: { ...OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK }, - }) as RootState, - ); - - showDataOverlay(OVERLAY_ID); - - expect(setBackgroundtoEmptyIfAvailable).not.toHaveBeenCalled(); - }); - it('should set empty background when it show overlay if setBackgroundEmpty is true', () => { - getStateSpy.mockImplementation( - () => - ({ - overlays: { - ...OVERLAYS_INITIAL_STATE_MOCK, - userOverlays: { - data: overlaysPageFixture.content, - loading: 'idle', - error: DEFAULT_ERROR, - }, - }, - overlayBioEntity: { ...OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK }, - }) as RootState, - ); - - showDataOverlay(OVERLAY_ID, true); - - expect(setBackgroundtoEmptyIfAvailable).toHaveBeenCalled(); - }); }); diff --git a/src/services/pluginsManager/map/overlays/showDataOverlay/showDataOverlay.ts b/src/services/pluginsManager/map/overlays/showDataOverlay/showDataOverlay.ts index 8304beed..34359036 100644 --- a/src/services/pluginsManager/map/overlays/showDataOverlay/showDataOverlay.ts +++ b/src/services/pluginsManager/map/overlays/showDataOverlay/showDataOverlay.ts @@ -7,7 +7,8 @@ import { ERROR_OVERLAY_ID_ALREADY_ACTIVE, ERROR_OVERLAY_ID_NOT_FOUND, } from '@/services/pluginsManager/errorMessages'; -import { setBackgroundtoEmptyIfAvailable } from './setBackgroundtoEmptyIfAvailable'; +import { setMapBackground } from '@/redux/map/map.slice'; +import MapBackgroundsEnum from '@/redux/map/map.enums'; export const showDataOverlay = (overlayId: number, setBackgroundEmpty?: boolean): void => { const { dispatch, getState } = store; @@ -25,7 +26,7 @@ export const showDataOverlay = (overlayId: number, setBackgroundEmpty?: boolean) } if (setBackgroundEmpty) { - setBackgroundtoEmptyIfAvailable(); + dispatch(setMapBackground(MapBackgroundsEnum.SEMANTIC)); } dispatch(getOverlayBioEntityForAllModels({ overlayId })); diff --git a/src/services/pluginsManager/map/position/getCenter.test.ts b/src/services/pluginsManager/map/position/getCenter.test.ts index fe23d527..f9d9dd54 100644 --- a/src/services/pluginsManager/map/position/getCenter.test.ts +++ b/src/services/pluginsManager/map/position/getCenter.test.ts @@ -1,6 +1,5 @@ import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; import { RootState, store } from '@/redux/store'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { getCenter } from './getCenter'; jest.mock('../../../../redux/store'); @@ -26,7 +25,6 @@ describe('getCenter - plugin method', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }) as RootState, ); diff --git a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts index 293f9476..abb470aa 100644 --- a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts +++ b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts @@ -11,7 +11,6 @@ import { RootState, store } from '@/redux/store'; import { mockNetworkNewAPIResponse, mockNetworkResponse } from '@/utils/mockNetworkResponse'; import { waitFor } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { triggerSearch } from './triggerSearch'; import { ERROR_INVALID_MODEL_ID_TYPE } from '../../errorMessages'; @@ -30,7 +29,6 @@ const MOCK_STATE = { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, }; diff --git a/src/services/pluginsManager/map/zoom/getZoom.test.ts b/src/services/pluginsManager/map/zoom/getZoom.test.ts index 669d8773..b7808d53 100644 --- a/src/services/pluginsManager/map/zoom/getZoom.test.ts +++ b/src/services/pluginsManager/map/zoom/getZoom.test.ts @@ -1,7 +1,6 @@ /* eslint-disable no-magic-numbers */ import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; import { RootState, store } from '@/redux/store'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { getZoom } from './getZoom'; jest.mock('../../../../redux/store'); @@ -29,7 +28,6 @@ describe('getZoom - plugin method', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }) as RootState, ); @@ -59,7 +57,6 @@ describe('getZoom - plugin method', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }) as RootState, ); diff --git a/src/services/pluginsManager/map/zoom/setZoom.test.ts b/src/services/pluginsManager/map/zoom/setZoom.test.ts index 2d5f8a3d..55502f30 100644 --- a/src/services/pluginsManager/map/zoom/setZoom.test.ts +++ b/src/services/pluginsManager/map/zoom/setZoom.test.ts @@ -4,7 +4,6 @@ import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/ma import { setLastPositionZoom } from '@/redux/map/map.slice'; import { RootState, store } from '@/redux/store'; import { ZodError } from 'zod'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { setZoom } from './setZoom'; jest.mock('../../../../redux/store'); @@ -37,7 +36,6 @@ describe('setZoom - plugin method', () => { loading: 'succeeded', error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }) as RootState, ); diff --git a/src/types/mapLayers.ts b/src/types/mapLayers.ts deleted file mode 100644 index d5b7bb6a..00000000 --- a/src/types/mapLayers.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* excluded from map.ts due to depenceny cycle */ - -import { useOlMapOverlaysLayer } from '@/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer'; -import { useOlMapPinsLayer } from '@/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer'; -import { useOlMapReactionsLayer } from '@/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer'; -import { useOlMapTileLayer } from '@/components/Map/MapViewer/utils/config/useOlMapTileLayer'; - -export type MapLayers = - | { - tileLayer: ReturnType<typeof useOlMapTileLayer>; - reactionsLayer: ReturnType<typeof useOlMapReactionsLayer>; - pinsLayer: ReturnType<typeof useOlMapPinsLayer>; - overlaysLayer: ReturnType<typeof useOlMapOverlaysLayer>; - } - | undefined; diff --git a/src/types/models.ts b/src/types/models.ts index c70bb0b7..168c7fde 100644 --- a/src/types/models.ts +++ b/src/types/models.ts @@ -16,7 +16,6 @@ import { exportElementsSchema, exportNetworkchema } from '@/models/exportSchema' import { geneVariant } from '@/models/geneVariant'; import { lineSchema } from '@/models/lineSchema'; import { loginSchema } from '@/models/loginSchema'; -import { mapBackground } from '@/models/mapBackground'; import { createdOverlayFileSchema, createdOverlaySchema, @@ -116,7 +115,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 MapBackground = z.infer<typeof mapBackground>; export type Organism = z.infer<typeof organism>; export type Disease = z.infer<typeof disease>; export type Drug = z.infer<typeof drugSchema>; diff --git a/src/utils/initialize/useInitializeStore.test.ts b/src/utils/initialize/useInitializeStore.test.ts index 34a1e072..92b5d635 100644 --- a/src/utils/initialize/useInitializeStore.test.ts +++ b/src/utils/initialize/useInitializeStore.test.ts @@ -1,21 +1,18 @@ import { PROJECT_ID } from '@/constants'; -import { backgroundsFixture } from '@/models/fixtures/backgroundsFixture'; import { modelsFixture, modelsPageFixture } from '@/models/fixtures/modelsFixture'; import { overlaysPageFixture } from '@/models/fixtures/overlaysFixture'; import { projectFixture } from '@/models/fixtures/projectFixture'; import { apiPath } from '@/redux/apiPath'; -import { backgroundsDataSelector } from '@/redux/backgrounds/background.selectors'; import { modelsDataSelector } from '@/redux/models/models.selectors'; import { overlaysDataSelector } from '@/redux/overlays/overlays.selectors'; import { projectDataSelector } from '@/redux/project/project.selectors'; import { initDataLoadingInitialized } from '@/redux/root/init.selectors'; -import { mockNetworkNewAPIResponse, mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { renderHook, waitFor } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; import * as hook from './useInitializeStore'; -const mockedAxiosClient = mockNetworkResponse(); const mockedAxiosNewClient = mockNetworkNewAPIResponse(); describe('useInitializeStore - hook', () => { @@ -30,9 +27,6 @@ describe('useInitializeStore - hook', () => { mockedAxiosNewClient .onGet(apiPath.getProjectById(PROJECT_ID)) .reply(HttpStatusCode.Ok, projectFixture); - mockedAxiosClient - .onGet(apiPath.getAllBackgroundsByProjectIdQuery(PROJECT_ID)) - .reply(HttpStatusCode.Ok, backgroundsFixture); }); it('should fetch project data in store', async () => { @@ -45,16 +39,6 @@ describe('useInitializeStore - hook', () => { }); }); - it('should fetch backgrounds data in store', async () => { - const { Wrapper, store } = getReduxWrapperWithStore(); - renderHook(() => hook.useInitializeStore(), { wrapper: Wrapper }); - - await waitFor(() => { - const data = backgroundsDataSelector(store.getState()); - expect(data).toEqual(backgroundsFixture); - }); - }); - it('should fetch overlays data in store', async () => { const { Wrapper, store } = getReduxWrapperWithStore(); renderHook(() => hook.useInitializeStore(), { wrapper: Wrapper }); diff --git a/src/utils/initialize/useInitializeStore.ts b/src/utils/initialize/useInitializeStore.ts index c6481127..3c6ed389 100644 --- a/src/utils/initialize/useInitializeStore.ts +++ b/src/utils/initialize/useInitializeStore.ts @@ -10,7 +10,7 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { parseQueryToTypes } from '../parseQueryToTypes'; /** - * 1. Initialise all required data before app starts: Project info, available Backgrounds, available Overlays, available Models (maps,submaps) + * 1. Initialise all required data before app starts: Project info, available Overlays, available Models (maps,submaps) * 2. Based on that set required map data to correctly display view. If query params are available -> use them to set map data */ @@ -25,7 +25,6 @@ export const useInitializeStore = (): void => { if (isInitialized || !isQueryReady) { return; } - dispatch(fetchInitialAppData({ queryData: parseQueryToTypes(query) })); }, [dispatch, isInitialized, query, isQueryReady, isInitDataLoadingFinished]); }; diff --git a/src/utils/map/getUpdatedMapData.ts b/src/utils/map/getUpdatedMapData.ts index 1e4fc498..1d5632f8 100644 --- a/src/utils/map/getUpdatedMapData.ts +++ b/src/utils/map/getUpdatedMapData.ts @@ -1,14 +1,15 @@ import { DEFAULT_ZOOM } from '@/constants/map'; import { MAP_DATA_INITIAL_STATE } from '@/redux/map/map.constants'; import { GetUpdatedMapDataResult, MapData } from '@/redux/map/map.types'; -import { MapBackground, MapModel } from '@/types/models'; +import { MapModel } from '@/types/models'; import { DeepPartial } from '@reduxjs/toolkit'; +import MapBackgroundsEnum from '@/redux/map/map.enums'; import { getPointMerged } from '../object/getPointMerged'; interface GetUpdatedMapDataArgs { model: MapModel; position?: DeepPartial<MapData['position']>; - background?: MapBackground; + background?: MapBackgroundsEnum; } const HALF = 2; @@ -28,7 +29,7 @@ export const getUpdatedMapData = ({ return { modelId: model.id, - backgroundId: background?.id || MAP_DATA_INITIAL_STATE.backgroundId, + backgroundId: background || MAP_DATA_INITIAL_STATE.backgroundId, size: { width: model.width, height: model.height, diff --git a/src/utils/map/useSetBounds.test.ts b/src/utils/map/useSetBounds.test.ts index fde34efd..71ee1260 100644 --- a/src/utils/map/useSetBounds.test.ts +++ b/src/utils/map/useSetBounds.test.ts @@ -4,7 +4,6 @@ import { MAP_DATA_INITIAL_STATE } from '@/redux/map/map.constants'; import { renderHook } from '@testing-library/react'; import { Map } from 'ol'; import { Coordinate } from 'ol/coordinate'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { getReduxWrapperWithStore } from '../testing/getReduxWrapperWithStore'; import { useSetBounds } from './useSetBounds'; @@ -35,7 +34,6 @@ describe('useSetBounds - hook', () => { message: '', }, openedMaps: [], - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }, { @@ -81,7 +79,6 @@ describe('useSetBounds - hook', () => { message: '', }, openedMaps: [], - backgroundType: MapBackgroundsEnum.SEMANTIC, }, }, { diff --git a/src/utils/query-manager/useReduxBusQueryManager.test.ts b/src/utils/query-manager/useReduxBusQueryManager.test.ts index e71069d6..9283e65b 100644 --- a/src/utils/query-manager/useReduxBusQueryManager.test.ts +++ b/src/utils/query-manager/useReduxBusQueryManager.test.ts @@ -2,7 +2,6 @@ import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/m import { Loading } from '@/types/loadingState'; import { renderHook, waitFor } from '@testing-library/react'; import mockRouter from 'next-router-mock'; -import MapBackgroundsEnum from '@/redux/map/map.enums'; import { getReduxWrapperWithStore } from '../testing/getReduxWrapperWithStore'; import { useReduxBusQueryManager } from './useReduxBusQueryManager'; @@ -71,9 +70,7 @@ describe('useReduxBusQueryManager - util', () => { }, }, openedMaps: OPENED_MAPS_INITIAL_STATE, - backgroundType: MapBackgroundsEnum.SEMANTIC, }, - backgrounds: loadedDataMock, models: loadedDataMock, overlays: loadedDataMock, }); -- GitLab From 9d4a063dfa1373b06e03a3917e36eb370f1ce32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Tue, 21 Jan 2025 16:18:35 +0100 Subject: [PATCH 03/12] feat(clean-up): remove communication with backend about search by coordinates --- docs/plugins/search.md | 4 +- .../getReactionLineSegments.test.ts | 51 +++ .../reactionsLayer/getReactionLineSegments.ts | 19 ++ .../reactionsLayer/useOlMapReactionsLayer.ts | 2 +- .../handleBioEntityResults.test.ts | 47 --- .../mapRightClick/handleBioEntityResults.ts | 18 - ...dleSearchResultForRightClickAction.test.ts | 45 --- .../handleSearchResultForRightClickAction.ts | 24 -- .../mapRightClick/onMapRightClick.test.ts | 148 -------- .../mapRightClick/onMapRightClick.ts | 32 -- .../findClosestBioEntityPoint.test.ts | 54 --- .../findClosestBioEntityPoint.ts | 29 -- .../findClosestReactionPoint.test.ts | 49 --- .../findClosestReactionPoint.ts | 62 ---- .../getMaxClickDistance.test.ts | 26 -- .../mapSingleClick/getMaxClickDistance.ts | 21 -- .../mapSingleClick/getSearchResults.test.ts | 114 ------- .../mapSingleClick/getSearchResults.ts | 40 --- .../mapSingleClick/handleAliasResults.test.ts | 266 --------------- .../mapSingleClick/handleAliasResults.ts | 58 ---- .../handleReactionResults.test.ts | 323 ------------------ .../mapSingleClick/handleReactionResults.ts | 89 ----- .../handleReactionSearchClickFailure.ts | 15 - .../handleSearchResultAction.test.ts | 67 ---- .../handleSearchResultAction.ts | 49 --- .../mapSingleClick/onMapSingleClick.test.ts | 299 ---------------- .../mapSingleClick/onMapSingleClick.ts | 47 --- .../mouseClick/getFeatureAtCoordinate.test.ts | 85 +++++ .../mouseClick/getFeatureAtCoordinate.ts | 52 +++ .../handleDataReset.test.ts | 0 .../handleDataReset.ts | 0 .../handleFeaturesClick.test.ts | 0 .../mouseLeftClick}/handleFeaturesClick.ts | 0 .../mouseLeftClick/leftClickHandleAlias.ts | 5 +- .../mouseLeftClick/onMapLeftClick.test.ts | 4 +- .../mouseLeftClick/onMapLeftClick.ts | 51 +-- .../mouseRightClick/onMapRightClick.ts | 2 +- src/redux/apiPath.ts | 8 - .../configuration/configuration.selectors.ts | 11 - .../modelElements/modelElements.selector.ts | 5 + .../newReactions/newReactions.selectors.ts | 5 + .../map/triggerSearch/searchByCoordinates.ts | 68 ++-- .../map/triggerSearch/triggerSearch.test.ts | 112 +++--- .../map/triggerSearch/triggerSearch.ts | 10 +- .../map/triggerSearch/triggerSearch.types.ts | 1 - .../search/getElementsByCoordinates.test.ts | 54 --- src/utils/search/getElementsByCoordinates.ts | 101 ------ 47 files changed, 349 insertions(+), 2223 deletions(-) create mode 100644 src/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments.test.ts create mode 100644 src/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapRightClick/handleBioEntityResults.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapRightClick/handleBioEntityResults.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestBioEntityPoint.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestBioEntityPoint.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestReactionPoint.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestReactionPoint.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/getMaxClickDistance.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/getMaxClickDistance.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/getSearchResults.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/getSearchResults.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionSearchClickFailure.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.test.ts delete mode 100644 src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts create mode 100644 src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts create mode 100644 src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts rename src/components/Map/MapViewer/utils/listeners/{mapSingleClick => mouseClick}/handleDataReset.test.ts (100%) rename src/components/Map/MapViewer/utils/listeners/{mapSingleClick => mouseClick}/handleDataReset.ts (100%) rename src/components/Map/MapViewer/utils/listeners/{mapSingleClick => mouseClick/mouseLeftClick}/handleFeaturesClick.test.ts (100%) rename src/components/Map/MapViewer/utils/listeners/{mapSingleClick => mouseClick/mouseLeftClick}/handleFeaturesClick.ts (100%) delete mode 100644 src/utils/search/getElementsByCoordinates.test.ts delete mode 100644 src/utils/search/getElementsByCoordinates.ts diff --git a/docs/plugins/search.md b/docs/plugins/search.md index 05856f17..9401f1f6 100644 --- a/docs/plugins/search.md +++ b/docs/plugins/search.md @@ -24,7 +24,6 @@ If we want to search using coordinates, we need to provide an object with the fo - coordinates: this property should indicate the x and y coordinates on the map. Its value should be an object type with x and y properties - modelId: this property should indicate submap identifier. Its value should be a number type -- zoom: this property should indicate zoom level at which we want to trigger search. Its value should be a number type - fitBounds: should the map be resized to the rectangle fitting all results. Its value should be a boolean type. This property is optional, and by default, its value is `false`. ##### Example of search by query: @@ -38,12 +37,11 @@ window.minerva.map.triggerSearch({ fitBounds: true, }); -window.minerva.map.triggerSearch({ coordinates: { x: 1947, y: 5203 }, modelId: 60, zoom: 5 }); +window.minerva.map.triggerSearch({ coordinates: { x: 1947, y: 5203 }, modelId: 60 }); window.minerva.map.triggerSearch({ coordinates: { x: 1947, y: 5203 }, modelId: 51, fitBounds: true, - zoom: 6, }); ``` diff --git a/src/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments.test.ts b/src/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments.test.ts new file mode 100644 index 00000000..692f274d --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments.test.ts @@ -0,0 +1,51 @@ +/* eslint-disable no-magic-numbers */ +import { NewReaction } from '@/types/models'; +import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; +import { getReactionLineSegments } from '@/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments'; + +describe('getReactionLineSegments', () => { + it('should return all segments from reaction line and associated entities', () => { + const mockSegments1 = [ + { x1: 0, y1: 0, x2: 1, y2: 1 }, + { x1: 1, y1: 1, x2: 2, y2: 2 }, + ]; + const mockSegments2 = [ + { x1: 2, y1: 2, x2: 3, y2: 3 }, + { x1: 4, y1: 4, x2: 5, y2: 5 }, + ]; + const mockSegments3 = [ + { x1: 6, y1: 6, x2: 7, y2: 7 }, + { x1: 8, y1: 8, x2: 9, y2: 9 }, + ]; + const mockSegments4 = [ + { x1: 10, y1: 10, x2: 11, y2: 11 }, + { x1: 12, y1: 12, x2: 13, y2: 13 }, + ]; + const mockSegments5 = [ + { x1: 14, y1: 14, x2: 15, y2: 15 }, + { x1: 16, y1: 16, x2: 17, y2: 17 }, + ]; + + const mockReaction: NewReaction = newReactionFixture; + mockReaction.operators = [mockReaction.operators[0]]; + mockReaction.reactants = [mockReaction.reactants[0]]; + mockReaction.modifiers = [mockReaction.modifiers[0]]; + mockReaction.products = [mockReaction.products[0]]; + + mockReaction.line.segments = mockSegments1; + mockReaction.reactants[0].line.segments = mockSegments2; + mockReaction.products[0].line.segments = mockSegments3; + mockReaction.modifiers[0].line.segments = mockSegments4; + mockReaction.operators[0].line.segments = mockSegments5; + + const result = getReactionLineSegments(mockReaction); + + expect(result).toEqual([ + ...mockSegments1, + ...mockSegments2, + ...mockSegments3, + ...mockSegments4, + ...mockSegments5, + ]); + }); +}); diff --git a/src/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments.ts b/src/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments.ts new file mode 100644 index 00000000..eed454db --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments.ts @@ -0,0 +1,19 @@ +import { NewReaction, Segment } from '@/types/models'; + +export function getReactionLineSegments(reaction: NewReaction): Segment[] { + const result: Segment[] = []; + result.push(...reaction.line.segments); + reaction.reactants.forEach(reactant => { + result.push(...reactant.line.segments); + }); + reaction.products.forEach(product => { + result.push(...product.line.segments); + }); + reaction.modifiers.forEach(modifier => { + result.push(...modifier.line.segments); + }); + reaction.operators.forEach(operator => { + result.push(...operator.line.segments); + }); + return result; +} diff --git a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts index fa7c4196..cf4416f3 100644 --- a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts @@ -15,7 +15,7 @@ import { useEffect, useMemo } from 'react'; 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/listeners/mapSingleClick/findClosestReactionPoint'; +import { getReactionLineSegments } from '@/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments'; import { getLineFeature } from './getLineFeature'; const getReactionsLines = (reactions: NewReaction[]): LinePoint[] => diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleBioEntityResults.test.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleBioEntityResults.test.ts deleted file mode 100644 index 04a81b69..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleBioEntityResults.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { ELEMENT_SEARCH_RESULT_MOCK_ALIAS } from '@/models/mocks/elementSearchResultMock'; -import { apiPath } from '@/redux/apiPath'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; -import { HttpStatusCode } from 'axios'; -import { waitFor } from '@testing-library/react'; -import { FIRST_ARRAY_ELEMENT, SECOND_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; -import { handleBioEntityResults } from './handleBioEntityResults'; - -const mockedAxiosOldClient = mockNetworkResponse(); - -describe('handleBioEntityResults - util', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - - mockedAxiosOldClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - - beforeAll(async () => { - handleBioEntityResults(dispatch)(ELEMENT_SEARCH_RESULT_MOCK_ALIAS); - }); - - it('should run setCurrentSelectedBioEntityId as first action', async () => { - await waitFor(() => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - expect(actions[FIRST_ARRAY_ELEMENT].type).toEqual( - 'contextMenu/setCurrentSelectedBioEntityId', - ); - }); - }); - - it('should run getMultiBioEntity as second action', async () => { - await waitFor(() => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - expect(actions[SECOND_ARRAY_ELEMENT].type).toEqual('project/getMultiBioEntity/pending'); - }); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleBioEntityResults.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleBioEntityResults.ts deleted file mode 100644 index be06232a..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleBioEntityResults.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { getMultiBioEntity } from '@/redux/bioEntity/bioEntity.thunks'; -import { setCurrentSelectedBioEntityId } from '@/redux/contextMenu/contextMenu.slice'; -import { AppDispatch } from '@/redux/store'; -import { ElementSearchResult } from '@/types/models'; - -/* prettier-ignore */ -export const handleBioEntityResults = - (dispatch: AppDispatch) => - async ({ id }: ElementSearchResult): Promise<void> => { - - dispatch(setCurrentSelectedBioEntityId(id)); - dispatch( - getMultiBioEntity({ - searchQueries: [id.toString()], - isPerfectMatch: true - }), - ); - }; diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.test.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.test.ts deleted file mode 100644 index 161d96b5..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { - ELEMENT_SEARCH_RESULT_MOCK_ALIAS, - ELEMENT_SEARCH_RESULT_MOCK_REACTION, -} from '@/models/mocks/elementSearchResultMock'; -import * as handleReactionResults from '../mapSingleClick/handleReactionResults'; -import { handleSearchResultForRightClickAction } from './handleSearchResultForRightClickAction'; -import * as handleBioEntityResults from './handleBioEntityResults'; - -jest.mock('./handleBioEntityResults', () => ({ - __esModule: true, - handleBioEntityResults: jest.fn().mockImplementation(() => (): null => null), -})); -jest.mock('../mapSingleClick/handleReactionResults', () => ({ - __esModule: true, - handleReactionResults: jest.fn().mockImplementation(() => (): null => null), -})); - -const handleBioEntityResultsSpy = jest.spyOn(handleBioEntityResults, 'handleBioEntityResults'); -const handleReactionResultsSpy = jest.spyOn(handleReactionResults, 'handleReactionResults'); - -describe('handleSearchResultForRightClickAction - util', () => { - const dispatch = jest.fn(); - - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe('on ALIAS search results', () => { - const searchResults = [ELEMENT_SEARCH_RESULT_MOCK_ALIAS]; - - it('should fire handleBioEntityResults', async () => { - await handleSearchResultForRightClickAction({ searchResults, dispatch }); - expect(handleBioEntityResultsSpy).toBeCalled(); - }); - }); - - describe('on REACTION search results', () => { - const searchResults = [ELEMENT_SEARCH_RESULT_MOCK_REACTION]; - - it('should fire handleReactionResults', async () => { - await handleSearchResultForRightClickAction({ searchResults, dispatch }); - expect(handleReactionResultsSpy).toBeCalled(); - }); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.ts deleted file mode 100644 index 29056a8f..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/handleSearchResultForRightClickAction.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { AppDispatch } from '@/redux/store'; -import { ElementSearchResult } from '@/types/models'; -import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; -import { handleBioEntityResults } from './handleBioEntityResults'; -import { handleReactionResults } from '../mapSingleClick/handleReactionResults'; - -interface HandleSearchResultActionInput { - searchResults: ElementSearchResult[]; - dispatch: AppDispatch; -} - -export const handleSearchResultForRightClickAction = async ({ - searchResults, - dispatch, -}: HandleSearchResultActionInput): Promise<void> => { - const closestSearchResult = searchResults[FIRST_ARRAY_ELEMENT]; - const { type } = closestSearchResult; - const action = { - ALIAS: handleBioEntityResults, - REACTION: handleReactionResults, - }[type]; - - await action(dispatch, closestSearchResult)(closestSearchResult); -}; diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts deleted file mode 100644 index 33216241..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { apiPath } from '@/redux/apiPath'; -import { HttpStatusCode } from 'axios'; -import { - ELEMENT_SEARCH_RESULT_MOCK_ALIAS, - ELEMENT_SEARCH_RESULT_MOCK_REACTION, -} from '@/models/mocks/elementSearchResultMock'; -import { waitFor } from '@testing-library/react'; -import { FIRST_ARRAY_ELEMENT, SECOND_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; -import { onMapRightClick } from './onMapRightClick'; -import * as handleDataReset from '../mapSingleClick/handleDataReset'; -import * as handleSearchResultForRightClickAction from './handleSearchResultForRightClickAction'; - -jest.mock('./handleSearchResultForRightClickAction', () => ({ - __esModule: true, - ...jest.requireActual('./handleSearchResultForRightClickAction'), -})); -jest.mock('../mapSingleClick/handleDataReset', () => ({ - __esModule: true, - ...jest.requireActual('../mapSingleClick/handleDataReset'), -})); - -const mockedAxiosOldClient = mockNetworkResponse(); - -const handleSearchResultForRightClickActionSpy = jest.spyOn( - handleSearchResultForRightClickAction, - 'handleSearchResultForRightClickAction', -); -const handleDataResetSpy = jest.spyOn(handleDataReset, 'handleDataReset'); - -describe('onMapRightClick - util', () => { - beforeEach(() => { - jest.clearAllMocks(); - jest.resetAllMocks(); - }); - - describe('when always', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const modelId = 1000; - const mapSize = { - width: 90, - height: 90, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const handler = onMapRightClick(mapSize, modelId, dispatch, false); - const coordinate = [90, 90]; - const pixel = [250, 250]; - - it('should fire data reset handler', async () => { - await handler(coordinate, pixel); - expect(handleDataResetSpy).toBeCalled(); - }); - it('should fire open context menu handler', async () => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - expect(actions[FIRST_ARRAY_ELEMENT].type).toEqual('map/updateLastRightClick'); - expect(actions[SECOND_ARRAY_ELEMENT].type).toEqual('contextMenu/openContextMenu'); - }); - }); - - describe('when searchResults are undefined', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const modelId = 1000; - const mapSize = { - width: 90, - height: 90, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const handler = onMapRightClick(mapSize, modelId, dispatch, false); - const coordinate = [90, 90]; - const point = { x: 180.0008084837557, y: 179.99919151624428 }; - const pixel = [250, 250]; - - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, undefined); - - it('does not fire search result action', async () => { - await handler(coordinate, pixel); - expect(handleSearchResultForRightClickActionSpy).not.toBeCalled(); - }); - }); - - describe('when searchResults are valid', () => { - describe('when results type is ALIAS', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const { modelId } = ELEMENT_SEARCH_RESULT_MOCK_ALIAS; - const mapSize = { - width: 270, - height: 270, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const coordinate = [270, 270]; - const point = { x: 540.0072763538013, y: 539.9927236461986 }; - const pixel = [250, 250]; - - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, [ELEMENT_SEARCH_RESULT_MOCK_ALIAS]); - - it('does fire search result for right click action handler', async () => { - const handler = onMapRightClick(mapSize, modelId, dispatch, false); - await handler(coordinate, pixel); - await waitFor(() => expect(handleSearchResultForRightClickActionSpy).toBeCalled()); - }); - }); - - describe('when results type is REACTION', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const { modelId } = ELEMENT_SEARCH_RESULT_MOCK_REACTION; - const mapSize = { - width: 0, - height: 0, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const coordinate = [0, 0]; - const point = { - x: 0, - y: 0, - }; - const pixel = [0, 0]; - - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, [ELEMENT_SEARCH_RESULT_MOCK_REACTION]); - - it('does fire search result for right click action - handle reaction', async () => { - const handler = onMapRightClick(mapSize, modelId, dispatch, false); - await handler(coordinate, pixel); - await waitFor(() => expect(handleSearchResultForRightClickActionSpy).toBeCalled()); - }); - }); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts deleted file mode 100644 index a52cd458..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { openContextMenu } from '@/redux/contextMenu/contextMenu.slice'; -import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; -import { MapSize } from '@/redux/map/map.types'; -import { AppDispatch } from '@/redux/store'; -import { Coordinate } from 'ol/coordinate'; -import { Pixel } from 'ol/pixel'; -import { updateLastRightClick } from '@/redux/map/map.slice'; -import { toLonLat } from 'ol/proj'; -import { latLngToPoint } from '@/utils/map/latLngToPoint'; -import { getSearchResults } from '../mapSingleClick/getSearchResults'; -import { handleDataReset } from '../mapSingleClick/handleDataReset'; -import { handleSearchResultForRightClickAction } from './handleSearchResultForRightClickAction'; - -/* prettier-ignore */ -export const onMapRightClick = - (mapSize: MapSize, modelId: number,dispatch: AppDispatch, shouldConsiderZoomLevel:boolean, - considerZoomLevel?:number, ) => async (coordinate: Coordinate, pixel: Pixel): Promise<void> => { - const [lng, lat] = toLonLat(coordinate); - const point = latLngToPoint([lat, lng], mapSize); - - dispatch(updateLastRightClick({coordinates:point, modelId})); - - dispatch(handleDataReset); - dispatch(openContextMenu(pixel)); - - const { searchResults } = await getSearchResults({ coordinate, mapSize, modelId, shouldConsiderZoomLevel, considerZoomLevel }); - if (!searchResults || searchResults.length === SIZE_OF_EMPTY_ARRAY) { - return; - } - - handleSearchResultForRightClickAction({ searchResults, dispatch }); - }; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestBioEntityPoint.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestBioEntityPoint.test.ts deleted file mode 100644 index 44b10f68..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestBioEntityPoint.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; -import { findClosestBioEntityPoint } from './findClosestBioEntityPoint'; - -describe('findClosestBioEntityPoint', () => { - const bioEntityContents = [ - { - ...bioEntityFixture, - x: 10, - y: 10, - width: 20, - height: 20, - }, - { - ...bioEntityFixture, - x: 50, - y: 50, - width: 30, - height: 30, - }, - ]; - - const validPoint = { x: 15, y: 15 }; - const invalidPoint = { - x: 500, - y: 300, - }; - - const searchDistance = '10'; - const maxZoom = 5; - const zoom = 2; - - it('should return the closest bioEntity within the search distance', () => { - const result = findClosestBioEntityPoint( - bioEntityContents, - searchDistance, - maxZoom, - zoom, - validPoint, - ); - expect(result).toEqual(bioEntityContents[0]); - }); - - it('should return undefined if no matching bioEntity is found within the search distance', () => { - const result = findClosestBioEntityPoint( - bioEntityContents, - searchDistance, - maxZoom, - zoom, - invalidPoint, - ); - expect(result).toBeUndefined(); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestBioEntityPoint.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestBioEntityPoint.ts deleted file mode 100644 index 329f8452..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestBioEntityPoint.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Point as PointType } from '@/types/map'; -import { BioEntity } from '@/types/models'; -import { getMaxClickDistance } from './getMaxClickDistance'; - -export const findClosestBioEntityPoint = ( - bioEntityContents: BioEntity[], - searchDistance: string, - maxZoom: number, - zoom: number, - point: PointType, -): BioEntity | undefined => { - const maxDistance = getMaxClickDistance(maxZoom, zoom, searchDistance); - - const matchingBioEntityFound = bioEntityContents.find(bio => { - const { x, y, width, height } = bio; - - const minX = x - maxDistance; - const maxX = x + width + maxDistance; - const minY = y - maxDistance; - const maxY = y + height + maxDistance; - - const withinXRange = point.x >= minX && point.x <= maxX; - const withinYRange = point.y >= minY && point.y <= maxY; - - return withinXRange && withinYRange; - }); - - return matchingBioEntityFound; -}; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestReactionPoint.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestReactionPoint.test.ts deleted file mode 100644 index 94369919..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestReactionPoint.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; -import { ZOOM_RESCALING_FACTOR } from '@/constants/map'; -import { findClosestReactionPoint, getReactionLineSegments } from './findClosestReactionPoint'; - -describe('findClosestReactionPoint', () => { - const reaction = { - ...newReactionFixture, - }; - - const validPoint = { x: reaction.line.segments[0].x1, y: reaction.line.segments[0].y1 }; - - let x = reaction.line.segments[0].x1; - let y = reaction.line.segments[0].y1; - getReactionLineSegments(reaction).forEach(lineSegment => { - x = Math.min(x, lineSegment.x1); - x = Math.min(x, lineSegment.x2); - y = Math.min(y, lineSegment.y1); - y = Math.min(y, lineSegment.y2); - }); - const invalidPoint = { x: x - 1000, y: y - 1000 }; - const searchDistance = '10'; - const maxZoom = 10; - const zoom = ZOOM_RESCALING_FACTOR * 5; - - it('should return the matching line segment if a point within the search distance is found', () => { - const result = findClosestReactionPoint({ - reaction, - searchDistance, - maxZoom, - zoom, - point: validPoint, - }); - - expect(result).toEqual(reaction.line.segments[0]); - }); - - it('should return undefined if no point within the search distance is found', () => { - const result = findClosestReactionPoint({ - reaction, - searchDistance, - maxZoom, - zoom, - point: invalidPoint, - }); - - expect(result).toBeUndefined(); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestReactionPoint.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestReactionPoint.ts deleted file mode 100644 index 33fbd42f..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/findClosestReactionPoint.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { Point as PointType } from '@/types/map'; -import { NewReaction, Segment } from '@/types/models'; -import { distance } from 'ol/coordinate'; -import { LineString, Point } from 'ol/geom'; -import { getMaxClickDistance } from './getMaxClickDistance'; - -type ReactionLine = Segment; - -type FindClosestReactionArgs = { - reaction: NewReaction; - searchDistance: string; - maxZoom: number; - zoom: number; - point: PointType; -}; - -export function getReactionLineSegments(reaction: NewReaction): Segment[] { - const result: Segment[] = []; - result.push(...reaction.line.segments); - reaction.reactants.forEach(reactant => { - result.push(...reactant.line.segments); - }); - reaction.products.forEach(product => { - result.push(...product.line.segments); - }); - reaction.modifiers.forEach(modifier => { - result.push(...modifier.line.segments); - }); - reaction.operators.forEach(operator => { - result.push(...operator.line.segments); - }); - return result; -} - -export const findClosestReactionPoint = ({ - reaction, - searchDistance, - maxZoom, - zoom, - point, -}: FindClosestReactionArgs): ReactionLine | undefined => { - const maxDistance = getMaxClickDistance(maxZoom, zoom, searchDistance); - - const clickedPoint = new Point([point.x, point.y]); - - const lines = getReactionLineSegments(reaction); - - const closestLine = lines.find(line => { - const lineString = new LineString([ - [line.x1, line.y1], - [line.x2, line.y2], - ]); - - const closestPointOnLine = lineString.getClosestPoint(clickedPoint.getCoordinates()); - const distanceToLine = distance(closestPointOnLine, clickedPoint.getCoordinates()); - - return distanceToLine <= maxDistance; - }); - - return closestLine; -}; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getMaxClickDistance.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getMaxClickDistance.test.ts deleted file mode 100644 index 3425b442..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getMaxClickDistance.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { ZOOM_RESCALING_FACTOR } from '@/constants/map'; -import { getMaxClickDistance } from './getMaxClickDistance'; - -describe('getMaxClickDistance', () => { - it.each([ - [10, ZOOM_RESCALING_FACTOR * 5, '10', 320], - [10, ZOOM_RESCALING_FACTOR * 5, '20', 640], - [10, ZOOM_RESCALING_FACTOR * 2, '10', 2560], - [10, ZOOM_RESCALING_FACTOR * 3, '18', 2304], - ])( - 'should calculate the maximum click distance correctly', - (maxZoom, zoom, searchDistance, expected) => { - expect(getMaxClickDistance(maxZoom, zoom, searchDistance)).toBe(expected); - }, - ); - - it.each([['invalid'], [''], [' ']])( - 'should throw an error if the search distance "%s" is not a valid number', - invalidDistance => { - expect(() => getMaxClickDistance(10, 5, invalidDistance)).toThrow( - 'Invalid search distance. Please provide a valid number.', - ); - }, - ); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getMaxClickDistance.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getMaxClickDistance.ts deleted file mode 100644 index 42317465..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getMaxClickDistance.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable no-magic-numbers */ - -import { ZOOM_FACTOR } from '@/constants/common'; -import { ZOOM_RESCALING_FACTOR } from '@/constants/map'; - -export const getMaxClickDistance = ( - maxZoom: number, - zoom: number, - searchDistance: string, -): number => { - const distance = parseFloat(searchDistance); - - if (typeof distance !== 'number' || Number.isNaN(distance)) { - throw new Error('Invalid search distance. Please provide a valid number.'); - } - - const zoomDiff = (ZOOM_RESCALING_FACTOR * maxZoom - zoom) / ZOOM_RESCALING_FACTOR; - const maxDistance = distance * ZOOM_FACTOR ** zoomDiff; - - return maxDistance; -}; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getSearchResults.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getSearchResults.test.ts deleted file mode 100644 index 0fa4d06f..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getSearchResults.test.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { - ELEMENT_SEARCH_RESULT_MOCK_ALIAS, - ELEMENT_SEARCH_RESULT_MOCK_REACTION, -} from '@/models/mocks/elementSearchResultMock'; -import { apiPath } from '@/redux/apiPath'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { HttpStatusCode } from 'axios'; -import { getSearchResults } from './getSearchResults'; - -const mockedAxiosOldClient = mockNetworkResponse(); - -describe('getSearchResults - util', () => { - describe('when results type is ALIAS', () => { - const { modelId } = ELEMENT_SEARCH_RESULT_MOCK_ALIAS; - const mapSize = { - width: 270, - height: 270, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const coordinate = [270, 270]; - const point = { x: 540.0072763538013, y: 539.9927236461986 }; - - beforeAll(() => { - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, [ELEMENT_SEARCH_RESULT_MOCK_ALIAS]); - }); - - it('returns valid array of objects', async () => { - const result = await getSearchResults({ - coordinate, - mapSize, - modelId, - shouldConsiderZoomLevel: false, - }); - - expect(result).toEqual({ - point, - searchResults: [ELEMENT_SEARCH_RESULT_MOCK_ALIAS], - }); - }); - }); - - describe('when results type is REACTION', () => { - const { modelId } = ELEMENT_SEARCH_RESULT_MOCK_REACTION; - const mapSize = { - width: 270, - height: 270, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const coordinate = [270, 270]; - const point = { x: 540.0072763538013, y: 539.9927236461986 }; - - beforeAll(() => { - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, [ELEMENT_SEARCH_RESULT_MOCK_REACTION]); - }); - - it('returns valid array of objects', async () => { - const result = await getSearchResults({ - coordinate, - mapSize, - modelId, - shouldConsiderZoomLevel: false, - }); - - expect(result).toEqual({ - point, - searchResults: [ELEMENT_SEARCH_RESULT_MOCK_REACTION], - }); - }); - }); - - describe('when results type is invalid', () => { - const { modelId } = ELEMENT_SEARCH_RESULT_MOCK_ALIAS; - const mapSize = { - width: 270, - height: 270, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const coordinate = [270, 270]; - const point = { x: 540.0072763538013, y: 539.9927236461986 }; - - beforeAll(() => { - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, { - invalidObject: true, - }); - }); - - it('should return undefined', async () => { - const result = await getSearchResults({ - coordinate, - mapSize, - modelId, - shouldConsiderZoomLevel: false, - }); - - expect(result).toEqual({ - point, - searchResults: undefined, - }); - }); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getSearchResults.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getSearchResults.ts deleted file mode 100644 index f86ee0fe..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/getSearchResults.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { MapSize } from '@/redux/map/map.types'; -import { Point } from '@/types/map'; -import { ElementSearchResult } from '@/types/models'; -import { latLngToPoint } from '@/utils/map/latLngToPoint'; -import { getElementsByPoint } from '@/utils/search/getElementsByCoordinates'; -import { Coordinate } from 'ol/coordinate'; -import { toLonLat } from 'ol/proj'; - -interface GetSearchResultsInput { - coordinate: Coordinate; - mapSize: MapSize; - modelId: number; - shouldConsiderZoomLevel: boolean; - considerZoomLevel?: number; -} - -export const getSearchResults = async ({ - coordinate, - mapSize, - modelId, - shouldConsiderZoomLevel, - considerZoomLevel, -}: GetSearchResultsInput): Promise<{ - searchResults: ElementSearchResult[] | undefined; - point: Point; -}> => { - const [lng, lat] = toLonLat(coordinate); - const point = latLngToPoint([lat, lng], mapSize); - const searchResults = await getElementsByPoint({ - point, - currentModelId: modelId, - shouldConsiderZoomLevel, - considerZoomLevel, - }); - - return { - searchResults, - point, - }; -}; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.test.ts deleted file mode 100644 index a1dacb26..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.test.ts +++ /dev/null @@ -1,266 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { SIZE_OF_EMPTY_ARRAY, ZERO } from '@/constants/common'; -import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { ELEMENT_SEARCH_RESULT_MOCK_ALIAS } from '@/models/mocks/elementSearchResultMock'; -import { apiPath } from '@/redux/apiPath'; -import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; -import { mockNetworkNewAPIResponse, mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; -import { waitFor } from '@testing-library/react'; -import { HttpStatusCode } from 'axios'; -import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; -import { ZOOM_RESCALING_FACTOR } from '@/constants/map'; -import { isReactionBioEntity } from '@/redux/reactions/isReactionBioentity'; -import { handleAliasResults } from './handleAliasResults'; - -jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); - -const mockedAxiosClient = mockNetworkNewAPIResponse(); -const mockedAxiosOldClient = mockNetworkResponse(); - -const SEARCH_CONFIG_MOCK = { - point: { - x: 500, - y: 700, - }, - maxZoom: 9, - zoom: ZOOM_RESCALING_FACTOR * 5, - isResultDrawerOpen: false, -}; - -describe('handleAliasResults - util', () => { - beforeEach(() => { - jest.clearAllMocks(); - - const bioEntityWithIdReaction = bioEntityResponseFixture.content - .filter(c => isReactionBioEntity(c.bioEntity)) - ?.map(b => b.bioEntity || { id: ZERO }); - - mockedAxiosOldClient - .onGet( - apiPath.getReactionsWithIds( - bioEntityWithIdReaction.map(bioEntity => Number(`${bioEntity.id}`)), - ), - ) - .reply(HttpStatusCode.Ok, []); - }); - describe('when matching bioEntity not found', () => { - it('should clear bio entities and do not close drawer if result drawer is not open', async () => { - mockedAxiosClient - .onGet( - apiPath.getElementById( - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id, - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.modelId, - ), - ) - .reply(HttpStatusCode.Ok, { - ...bioEntityFixture, - idReaction: undefined, - }); - - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - - await handleAliasResults(dispatch, ELEMENT_SEARCH_RESULT_MOCK_ALIAS, { - ...SEARCH_CONFIG_MOCK, - searchDistance: '10', - })(ELEMENT_SEARCH_RESULT_MOCK_ALIAS); - - await waitFor(() => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - - const actionTypes = actions.map(action => action.type); - - expect(actionTypes).toEqual([ - 'project/getMultiBioEntity/pending', - 'project/getBioEntityById/pending', - 'project/getCommentElement/pending', - 'project/getCommentElement/fulfilled', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getBioEntityById/fulfilled', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getMultiBioEntity/fulfilled', - 'bioEntityContents/clearBioEntities', - ]); - }); - }); - it('should clear bio entities and close drawer if result drawer is already open', async () => { - mockedAxiosClient - .onGet( - apiPath.getElementById( - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id, - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.modelId, - ), - ) - .reply(HttpStatusCode.Ok, { - ...bioEntityFixture, - idReaction: undefined, - }); - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - - await handleAliasResults(dispatch, ELEMENT_SEARCH_RESULT_MOCK_ALIAS, { - ...SEARCH_CONFIG_MOCK, - searchDistance: '10', - isResultDrawerOpen: true, - })(ELEMENT_SEARCH_RESULT_MOCK_ALIAS); - - await waitFor(() => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - - const actionTypes = actions.map(action => action.type); - - expect(actionTypes).toEqual([ - 'project/getMultiBioEntity/pending', - 'project/getBioEntityById/pending', - 'project/getCommentElement/pending', - 'project/getCommentElement/fulfilled', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getBioEntityById/fulfilled', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getMultiBioEntity/fulfilled', - 'drawer/closeDrawer', - 'bioEntityContents/clearBioEntities', - ]); - }); - }); - }); - describe('when matching bioEntity found', () => { - it('should select tab and open bio entity drawer', async () => { - mockedAxiosClient - .onGet( - apiPath.getElementById( - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id, - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.modelId, - ), - ) - .reply(HttpStatusCode.Ok, { - ...bioEntityFixture, - x: 500, - y: 700, - width: 50, - height: 50, - idReaction: undefined, - }); - - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - - await handleAliasResults( - dispatch, - ELEMENT_SEARCH_RESULT_MOCK_ALIAS, - SEARCH_CONFIG_MOCK, - )(ELEMENT_SEARCH_RESULT_MOCK_ALIAS); - - await waitFor(() => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - - const actionTypes = actions.map(action => action.type); - - expect(actionTypes).toEqual([ - 'project/getMultiBioEntity/pending', - 'project/getBioEntityById/pending', - 'project/getCommentElement/pending', - 'project/getCommentElement/fulfilled', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getBioEntityById/fulfilled', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getMultiBioEntity/fulfilled', - 'drawer/selectTab', - 'drawer/openBioEntityDrawerById', - ]); - }); - }); - }); - - describe('when searchDistance is not provided', () => { - it('should select tab and open drawer without clearing bio entities', async () => { - mockedAxiosClient - .onGet( - apiPath.getElementById( - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id, - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.modelId, - ), - ) - .reply(HttpStatusCode.Ok, bioEntityFixture); - mockedAxiosOldClient - .onGet(apiPath.getReactionsWithIds([Number(bioEntityFixture.id)])) - .reply(HttpStatusCode.Ok, bioEntityFixture); - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - await handleAliasResults(dispatch, ELEMENT_SEARCH_RESULT_MOCK_ALIAS, { - ...SEARCH_CONFIG_MOCK, - isResultDrawerOpen: true, - })(ELEMENT_SEARCH_RESULT_MOCK_ALIAS); - - await waitFor(() => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - - const actionTypes = actions.map(action => action.type); - - expect(actionTypes).toEqual([ - 'project/getMultiBioEntity/pending', - 'project/getBioEntityById/pending', - 'project/getCommentElement/pending', - 'project/getCommentElement/fulfilled', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getBioEntityById/fulfilled', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getMultiBioEntity/fulfilled', - 'drawer/selectTab', - 'drawer/openBioEntityDrawerById', - ]); - }); - }); - - describe('fitBounds after search', () => { - it('should fit bounds after search when hasFitBounds is true', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - - await handleAliasResults(dispatch, ELEMENT_SEARCH_RESULT_MOCK_ALIAS, { - ...SEARCH_CONFIG_MOCK, - hasFitBounds: true, - })(ELEMENT_SEARCH_RESULT_MOCK_ALIAS); - - await waitFor(() => { - expect(searchFitBounds).toHaveBeenCalled(); - }); - }); - - it('should not fit bounds after search when hasFitBounds is false', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - - await handleAliasResults(dispatch, ELEMENT_SEARCH_RESULT_MOCK_ALIAS, { - ...SEARCH_CONFIG_MOCK, - hasFitBounds: false, - })(ELEMENT_SEARCH_RESULT_MOCK_ALIAS); - - await waitFor(() => { - expect(searchFitBounds).not.toHaveBeenCalled(); - }); - }); - }); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts deleted file mode 100644 index c3d05aba..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { closeDrawer, openBioEntityDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; -import { AppDispatch } from '@/redux/store'; -import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; -import { ElementSearchResult } from '@/types/models'; -import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; -import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; -import { Point } from '@/types/map'; -import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEntity'; -import { findClosestBioEntityPoint } from './findClosestBioEntityPoint'; - -type SearchConfig = { - point: Point; - searchDistance?: string; - maxZoom: number; - zoom: number; - hasFitBounds?: boolean; - isResultDrawerOpen?: boolean; -}; -/* prettier-ignore */ - -/* prettier-ignore */ -export const handleAliasResults = - (dispatch: AppDispatch, closestSearchResult: ElementSearchResult, { hasFitBounds, maxZoom, point, searchDistance, zoom, isResultDrawerOpen }: SearchConfig) => - async ({ id, modelId, type }: ElementSearchResult): Promise<void> => { - const bioEntities = await dispatch( - getMultiBioEntityByIds({ - elementsToFetch: [{elementId: id, type, modelId, addNumbersToEntityNumber: true}] - }), - ).unwrap(); - - if (searchDistance) { - - const matchingBioEntityFound = findClosestBioEntityPoint(bioEntities, searchDistance, maxZoom, zoom, point); - - if (!matchingBioEntityFound) { - if (isResultDrawerOpen) { - dispatch(closeDrawer()); - } - - dispatch(clearBioEntities()); - return; - } - } - - dispatch(selectTab(`${id}`)); - dispatch(openBioEntityDrawerById(id)); - - - PluginsEventBus.dispatchEvent('onSearch', { - type: 'bioEntity', - searchValues: [closestSearchResult], - results: [bioEntities.map((bioEntity)=>{return {perfect: true, bioEntity};})], - }); - - if (hasFitBounds) { - searchFitBounds(); - } - }; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts deleted file mode 100644 index b39bdca0..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts +++ /dev/null @@ -1,323 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; -import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { - ELEMENT_SEARCH_RESULT_MOCK_ALIAS, - ELEMENT_SEARCH_RESULT_MOCK_REACTION, -} from '@/models/mocks/elementSearchResultMock'; -import { apiPath } from '@/redux/apiPath'; -import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; -import { mockNetworkNewAPIResponse, mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; -import { HttpStatusCode } from 'axios'; -import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; -import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; -import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; -import { ZOOM_RESCALING_FACTOR } from '@/constants/map'; -import * as findClosestReactionPoint from './findClosestReactionPoint'; -import { handleReactionResults } from './handleReactionResults'; - -const mockedAxiosOldClient = mockNetworkResponse(); -const mockedAxiosNewClient = mockNetworkNewAPIResponse(); - -jest.mock('../../../../../../services/pluginsManager/pluginsEventBus'); - -jest.mock('./findClosestReactionPoint', () => ({ - __esModule: true, - ...jest.requireActual('./findClosestReactionPoint'), -})); - -const findClosestReactionPointSpy = jest.spyOn( - findClosestReactionPoint, - 'findClosestReactionPoint', -); - -const SEARCH_CONFIG_MOCK = { - point: { - x: 200, - y: 3012, - }, - maxZoom: 9, - zoom: ZOOM_RESCALING_FACTOR * 3, - isResultDrawerOpen: false, -}; - -const reaction = { - ...newReactionFixture, - id: ELEMENT_SEARCH_RESULT_MOCK_REACTION.id, - model: ELEMENT_SEARCH_RESULT_MOCK_REACTION.modelId, - products: [], - reactants: [], - modifiers: [], -}; - -describe('handleReactionResults - util', () => { - const searchDistance = '10'; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe('actions', () => { - const { store } = getReduxStoreWithActionsListener({ - ...INITIAL_STORE_STATE_MOCK, - }); - const { dispatch } = store; - - mockedAxiosNewClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - - mockedAxiosNewClient - .onGet( - apiPath.getElementById( - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id, - ELEMENT_SEARCH_RESULT_MOCK_ALIAS.modelId, - ), - ) - .reply(HttpStatusCode.Ok, bioEntityFixture); - - mockedAxiosNewClient - .onGet( - apiPath.getNewReaction( - ELEMENT_SEARCH_RESULT_MOCK_REACTION.modelId, - ELEMENT_SEARCH_RESULT_MOCK_REACTION.id, - ), - ) - .reply(HttpStatusCode.Ok, { - ...reaction, - reactants: [], - products: [], - modifiers: [ - { - ...newReactionFixture.modifiers[0], - element: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id, - }, - ], - }); - - beforeEach(async () => { - await handleReactionResults( - dispatch, - ELEMENT_SEARCH_RESULT_MOCK_REACTION, - )(ELEMENT_SEARCH_RESULT_MOCK_REACTION); - }); - - it('should run getReactionsByIds as first action', () => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - expect(actions[0].type).toEqual('reactions/getByIds/pending'); - expect(actions[1].type).toEqual('reactions/getByIds/fulfilled'); - }); - - it('should run openReactionDrawerById to empty array as third action', () => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - expect(actions[2].type).toEqual('drawer/openReactionDrawerById'); - expect(actions[2].payload).toEqual(reaction.id); - }); - - it('should run select tab as fourth action', () => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - expect(actions[3].type).toEqual('drawer/selectTab'); - }); - - it('should run getMultiBioEntity to empty array as fifth action', () => { - const actions = store.getActions(); - expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY); - expect(actions[4].type).toEqual('project/getMultiBioEntity/pending'); - }); - }); - describe('when search config provided but search distance is not provided', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - - it('should not find closest reaction', async () => { - await handleReactionResults( - dispatch, - ELEMENT_SEARCH_RESULT_MOCK_REACTION, - SEARCH_CONFIG_MOCK, - )(ELEMENT_SEARCH_RESULT_MOCK_REACTION); - - expect(findClosestReactionPointSpy).not.toHaveBeenCalled(); - }); - }); - - describe('when search config provided and matching reaction not found', () => { - mockedAxiosNewClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - - mockedAxiosNewClient - .onGet( - apiPath.getNewReaction( - ELEMENT_SEARCH_RESULT_MOCK_REACTION.modelId, - ELEMENT_SEARCH_RESULT_MOCK_REACTION.id, - ), - ) - .reply(HttpStatusCode.Ok, reaction); - - mockedAxiosOldClient - .onGet(apiPath.getReactionsWithIds([ELEMENT_SEARCH_RESULT_MOCK_REACTION.id])) - .reply(HttpStatusCode.Ok, [ - { - ...reaction, - reactants: [], - products: [], - modifiers: [ - { - ...newReactionFixture.modifiers[0], - element: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id, - }, - ], - }, - ]); - - const invalidPoint = { - x: 991, - y: 612, - }; - it('should close drawer and reset data if result drawer open', async () => { - const { store } = getReduxStoreWithActionsListener(); - - await handleReactionResults(store.dispatch, ELEMENT_SEARCH_RESULT_MOCK_REACTION, { - ...SEARCH_CONFIG_MOCK, - searchDistance, - point: invalidPoint, - isResultDrawerOpen: true, - })(ELEMENT_SEARCH_RESULT_MOCK_REACTION); - - const actions = store.getActions(); - const actionTypes = actions.map(action => action.type); - - expect(actionTypes).toStrictEqual([ - 'reactions/getByIds/pending', - 'reactions/getByIds/fulfilled', - 'drawer/closeDrawer', - 'reactions/resetReactionsData', - 'bioEntityContents/clearBioEntities', - ]); - }); - - it('should only reset data if result drawer is closed', async () => { - const { store } = getReduxStoreWithActionsListener(); - - const dispatchSpy = jest.spyOn(store, 'dispatch'); - - await handleReactionResults(store.dispatch, ELEMENT_SEARCH_RESULT_MOCK_REACTION, { - ...SEARCH_CONFIG_MOCK, - searchDistance, - point: invalidPoint, - isResultDrawerOpen: false, - })(ELEMENT_SEARCH_RESULT_MOCK_REACTION); - - expect(dispatchSpy).toHaveBeenCalledWith({ - payload: undefined, - type: 'reactions/resetReactionsData', - }); - - expect(dispatchSpy).toHaveBeenCalledWith({ - payload: undefined, - type: 'bioEntityContents/clearBioEntities', - }); - }); - }); - describe('when search config provided and matching reaction found', () => { - const point = { x: 1, y: 1 }; - const maxZoom = 10; - const zoom = ZOOM_RESCALING_FACTOR * 5; - - it('should open reaction drawer and fetch bio entities', async () => { - const { store } = getReduxStoreWithActionsListener(); - mockedAxiosNewClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, []); - - mockedAxiosNewClient - .onGet( - apiPath.getNewReaction( - ELEMENT_SEARCH_RESULT_MOCK_REACTION.modelId, - ELEMENT_SEARCH_RESULT_MOCK_REACTION.id, - ), - ) - .reply(HttpStatusCode.Ok, reaction); - - await handleReactionResults(store.dispatch, ELEMENT_SEARCH_RESULT_MOCK_REACTION, { - searchDistance, - maxZoom, - zoom, - point, - isResultDrawerOpen: false, - })(ELEMENT_SEARCH_RESULT_MOCK_REACTION); - - const actions = store.getActions(); - const actionTypes = actions.map(action => action.type); - - expect(actionTypes).toStrictEqual([ - 'reactions/getByIds/pending', - 'reactions/getByIds/fulfilled', - 'drawer/openReactionDrawerById', - 'drawer/selectTab', - 'project/getMultiBioEntity/pending', - 'entityNumber/addNumbersToEntityNumberData', - 'project/getMultiBioEntity/fulfilled', - ]); - }); - }); - describe('when matching reaction found', () => { - const point = { x: reaction.line.segments[0].x1, y: reaction.line.segments[0].y1 }; - const maxZoom = 10; - const zoom = ZOOM_RESCALING_FACTOR * 5; - - it('should dispatch onSearch event with reaction data', async () => { - const { store } = getReduxStoreWithActionsListener(); - mockedAxiosNewClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, []); - - mockedAxiosNewClient - .onGet( - apiPath.getNewReaction( - ELEMENT_SEARCH_RESULT_MOCK_REACTION.modelId, - ELEMENT_SEARCH_RESULT_MOCK_REACTION.id, - ), - ) - .reply(HttpStatusCode.Ok, reaction); - - await handleReactionResults(store.dispatch, ELEMENT_SEARCH_RESULT_MOCK_REACTION, { - searchDistance, - maxZoom, - zoom, - point, - isResultDrawerOpen: false, - })(ELEMENT_SEARCH_RESULT_MOCK_REACTION); - - expect(PluginsEventBus.dispatchEvent).toHaveBeenCalledWith('onSearch', { - results: [[{ bioEntity: reaction, perfect: true }]], - searchValues: [ELEMENT_SEARCH_RESULT_MOCK_REACTION], - type: 'reaction', - }); - }); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts deleted file mode 100644 index 5631573e..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { FIRST_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; -import { openReactionDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; -import { getReactionsByIds } from '@/redux/reactions/reactions.thunks'; -import { AppDispatch } from '@/redux/store'; -import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; -import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; -import { Point } from '@/types/map'; -import { BioEntity, ElementSearchResult } from '@/types/models'; -import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; -import { apiPath } from '@/redux/apiPath'; -import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEntity'; -import { newReactionSchema } from '@/models/newReactionSchema'; -import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction'; -import { handleReactionSearchClickFailure } from './handleReactionSearchClickFailure'; -import { findClosestReactionPoint } from './findClosestReactionPoint'; - -type SearchConfig = { - point: Point; - searchDistance?: string; - maxZoom: number; - zoom: number; - hasFitBounds?: boolean; - isResultDrawerOpen: boolean; -}; - -/* prettier-ignore */ -export const handleReactionResults = - (dispatch: AppDispatch, closestSearchResult: ElementSearchResult, searchConfig?: SearchConfig) => - async ({ id, modelId }: ElementSearchResult): Promise<void> => { - const data = await dispatch(getReactionsByIds({ ids: [{ id, modelId }] })); - const payload = data?.payload; - if (!data || !payload || typeof payload === 'string' || payload.data.length === SIZE_OF_EMPTY_ARRAY) { - return; - } - - const reaction = payload.data[FIRST_ARRAY_ELEMENT]; - const bioEntitiesIds = getModelElementsIdsFromReaction(reaction); - - if (searchConfig && searchConfig.searchDistance) { - const { maxZoom, point, searchDistance, zoom, isResultDrawerOpen } = searchConfig; - const matchingReactionFound = findClosestReactionPoint({ - reaction, searchDistance, maxZoom, zoom, point - }); - - if (!matchingReactionFound) { - handleReactionSearchClickFailure(dispatch, isResultDrawerOpen); - - return; - } - } - - dispatch(openReactionDrawerById(reaction.id)); - - dispatch(selectTab('')); - - const response = await axiosInstanceNewAPI.get<BioEntity>(apiPath.getNewReaction(reaction.model, reaction.id)); - const isDataValid = validateDataUsingZodSchema(response.data, newReactionSchema); - - if (isDataValid) { - const reactionNewApi = response.data; - - const bioEntities = await dispatch( - getMultiBioEntityByIds({ - elementsToFetch: bioEntitiesIds.map((bioEntityId) => { - return { - elementId: bioEntityId, - modelId, - type: 'ALIAS' - }; - }) - }) - ).unwrap(); - - if (bioEntities) { - const result = bioEntities.map((bioEntity) => {return { bioEntity, perfect: true };}); - result.push({ bioEntity: reactionNewApi, perfect: true }); - PluginsEventBus.dispatchEvent('onSearch', { - type: 'reaction', - searchValues: [closestSearchResult], - results: [result] - }); - - if (searchConfig && searchConfig.hasFitBounds) { - searchFitBounds(); - } - } - } - }; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionSearchClickFailure.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionSearchClickFailure.ts deleted file mode 100644 index 30c6178f..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionSearchClickFailure.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { AppDispatch } from '@/redux/store'; -import { closeDrawer } from '@/redux/drawer/drawer.slice'; -import { resetReactionsData } from '@/redux/reactions/reactions.slice'; -import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; - -export const handleReactionSearchClickFailure = ( - dispatch: AppDispatch, - isResultDrawerOpen: boolean, -): void => { - if (isResultDrawerOpen) { - dispatch(closeDrawer()); - } - dispatch(resetReactionsData()); - dispatch(clearBioEntities()); -}; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.test.ts deleted file mode 100644 index d07fe1be..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { - ELEMENT_SEARCH_RESULT_MOCK_ALIAS, - ELEMENT_SEARCH_RESULT_MOCK_REACTION, -} from '@/models/mocks/elementSearchResultMock'; -import * as handleAliasResults from './handleAliasResults'; -import * as handleReactionResults from './handleReactionResults'; -import { handleSearchResultAction } from './handleSearchResultAction'; - -jest.mock('./handleAliasResults', () => ({ - __esModule: true, - handleAliasResults: jest.fn().mockImplementation(() => (): null => null), -})); - -jest.mock('./handleReactionResults', () => ({ - __esModule: true, - handleReactionResults: jest.fn().mockImplementation(() => (): null => null), -})); - -const handleAliasResultsSpy = jest.spyOn(handleAliasResults, 'handleAliasResults'); -const handleReactionResultsSpy = jest.spyOn(handleReactionResults, 'handleReactionResults'); - -const POINT_MOCK = { - x: 1323, - y: 2000, -}; -const ZOOM_MOCK = 3; -const MAX_ZOOM_MOCK = 9; - -describe('handleSearchResultAction - util', () => { - const dispatch = jest.fn(); - - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe('on ALIAS search results', () => { - const searchResults = [ELEMENT_SEARCH_RESULT_MOCK_ALIAS]; - - it('should fire handleAliasResults', async () => { - await handleSearchResultAction({ - searchResults, - dispatch, - maxZoom: MAX_ZOOM_MOCK, - isResultDrawerOpen: false, - point: POINT_MOCK, - zoom: ZOOM_MOCK, - }); - expect(handleAliasResultsSpy).toBeCalled(); - }); - }); - - describe('on REACTION search results', () => { - const searchResults = [ELEMENT_SEARCH_RESULT_MOCK_REACTION]; - - it('should fire handleReactionResults', async () => { - await handleSearchResultAction({ - searchResults, - dispatch, - maxZoom: MAX_ZOOM_MOCK, - isResultDrawerOpen: false, - point: POINT_MOCK, - zoom: ZOOM_MOCK, - }); - expect(handleReactionResultsSpy).toBeCalled(); - }); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.ts deleted file mode 100644 index f85813b1..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; -import { AppDispatch } from '@/redux/store'; -import { ElementSearchResult } from '@/types/models'; -import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; -import { Point } from '@/types/map'; -import { handleAliasResults } from './handleAliasResults'; -import { handleReactionResults } from './handleReactionResults'; - -interface HandleSearchResultActionInput { - searchResults: ElementSearchResult[]; - dispatch: AppDispatch; - point: Point; - searchDistance?: string; - maxZoom: number; - zoom: number; - hasFitBounds?: boolean; - isResultDrawerOpen: boolean; -} - -export const handleSearchResultAction = async ({ - searchResults, - dispatch, - point, - searchDistance, - maxZoom, - zoom, - hasFitBounds, - isResultDrawerOpen, -}: HandleSearchResultActionInput): Promise<void> => { - const closestSearchResult = searchResults[FIRST_ARRAY_ELEMENT]; - const { type } = closestSearchResult; - const action = { - ALIAS: handleAliasResults, - REACTION: handleReactionResults, - }[type]; - - await action(dispatch, closestSearchResult, { - point, - searchDistance, - maxZoom, - zoom, - hasFitBounds, - isResultDrawerOpen, - })(closestSearchResult); - - if (type === 'ALIAS') { - PluginsEventBus.dispatchEvent('onBioEntityClick', closestSearchResult); - } -}; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.test.ts deleted file mode 100644 index b91b2b33..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.test.ts +++ /dev/null @@ -1,299 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable no-magic-numbers */ -import { FEATURE_TYPE } from '@/constants/features'; -import { - ELEMENT_SEARCH_RESULT_MOCK_ALIAS, - ELEMENT_SEARCH_RESULT_MOCK_REACTION, -} from '@/models/mocks/elementSearchResultMock'; -import { apiPath } from '@/redux/apiPath'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; -import { waitFor } from '@testing-library/react'; -import { HttpStatusCode } from 'axios'; -import { Feature, Map, MapBrowserEvent } from 'ol'; -import * as handleDataReset from './handleDataReset'; -import * as handleSearchResultAction from './handleSearchResultAction'; -import { onMapSingleClick } from './onMapSingleClick'; - -jest.mock('./handleSearchResultAction', () => ({ - __esModule: true, - ...jest.requireActual('./handleSearchResultAction'), -})); -jest.mock('./handleDataReset', () => ({ - __esModule: true, - ...jest.requireActual('./handleDataReset'), -})); - -const mockedAxiosOldClient = mockNetworkResponse(); - -const handleSearchResultActionSpy = jest.spyOn( - handleSearchResultAction, - 'handleSearchResultAction', -); -const handleDataResetSpy = jest.spyOn(handleDataReset, 'handleDataReset'); - -const getEvent = (coordinate: MapBrowserEvent<UIEvent>['coordinate']): MapBrowserEvent<UIEvent> => - ({ - coordinate, - }) as unknown as MapBrowserEvent<UIEvent>; - -const MAX_ZOOM_MOCK_MOCK = 9; -const ZOOM_MOCK = 3; -const SEARCH_DISTANCE_MOCK = '10'; -const IS_RESULT_DRAWER_OPEN_MOCK = true; - -describe('onMapSingleClick - util', () => { - beforeEach(() => { - jest.clearAllMocks(); - jest.resetAllMocks(); - }); - - describe('when always', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const modelId = 1000; - const mapSize = { - width: 90, - height: 90, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const handler = onMapSingleClick( - mapSize, - modelId, - dispatch, - SEARCH_DISTANCE_MOCK, - MAX_ZOOM_MOCK_MOCK, - ZOOM_MOCK, - IS_RESULT_DRAWER_OPEN_MOCK, - [], - false, - ); - const coordinate = [90, 90]; - const event = getEvent(coordinate); - - const mapInstanceMock = { - forEachFeatureAtPixel: (): void => {}, - } as unknown as Map; - - it('should fire data reset handler', async () => { - await handler(event, mapInstanceMock); - expect(handleDataResetSpy).toBeCalled(); - }); - }); - - describe('when searchResults are undefined', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const modelId = 1000; - const mapSize = { - width: 90, - height: 90, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const handler = onMapSingleClick( - mapSize, - modelId, - dispatch, - SEARCH_DISTANCE_MOCK, - MAX_ZOOM_MOCK_MOCK, - ZOOM_MOCK, - IS_RESULT_DRAWER_OPEN_MOCK, - [], - false, - ); - const coordinate = [90, 90]; - const point = { x: 180.0008084837557, y: 179.99919151624428 }; - const event = getEvent(coordinate); - - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, undefined); - - const mapInstanceMock = { - forEachFeatureAtPixel: (): void => {}, - } as unknown as Map; - - it('does not fire search result action', async () => { - await handler(event, mapInstanceMock); - expect(handleSearchResultActionSpy).not.toBeCalled(); - }); - }); - - describe('when searchResults are empty', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - - const modelId = 1000; - const mapSize = { - width: 180, - height: 180, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - - const handler = onMapSingleClick( - mapSize, - modelId, - dispatch, - SEARCH_DISTANCE_MOCK, - MAX_ZOOM_MOCK_MOCK, - ZOOM_MOCK, - IS_RESULT_DRAWER_OPEN_MOCK, - [], - false, - ); - const coordinate = [180, 180]; - const point = { x: 360.0032339350228, y: 359.9967660649771 }; - const event = getEvent(coordinate); - - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, []); - - const mapInstanceMock = { - forEachFeatureAtPixel: (): void => {}, - } as unknown as Map; - - it('does not fire search result action', async () => { - await handler(event, mapInstanceMock); - expect(handleSearchResultActionSpy).not.toBeCalled(); - }); - }); - - describe('when clicked on feature type = pin icon bioentity', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const { modelId } = ELEMENT_SEARCH_RESULT_MOCK_ALIAS; - const mapSize = { - width: 270, - height: 270, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const coordinate = [270, 270]; - const point = { x: 540.0072763538013, y: 539.9927236461986 }; - const event = getEvent(coordinate); - - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, [ELEMENT_SEARCH_RESULT_MOCK_ALIAS]); - - const mapInstanceMock = { - forEachFeatureAtPixel: (pixel: any, mappingFunction: (feature: Feature) => void): void => { - [ - new Feature({ - id: 1000, - type: FEATURE_TYPE.PIN_ICON_BIOENTITY, - }), - ].forEach(mappingFunction); - }, - } as unknown as Map; - - it('does NOT fire search result action handler', async () => { - const handler = onMapSingleClick( - mapSize, - modelId, - dispatch, - SEARCH_DISTANCE_MOCK, - MAX_ZOOM_MOCK_MOCK, - ZOOM_MOCK, - IS_RESULT_DRAWER_OPEN_MOCK, - [], - false, - ); - await handler(event, mapInstanceMock); - await waitFor(() => expect(handleSearchResultActionSpy).not.toBeCalled()); - }); - }); - - describe('when searchResults are valid', () => { - describe('when results type is ALIAS', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const { modelId } = ELEMENT_SEARCH_RESULT_MOCK_ALIAS; - const mapSize = { - width: 270, - height: 270, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const coordinate = [270, 270]; - const point = { x: 540.0072763538013, y: 539.9927236461986 }; - const event = getEvent(coordinate); - - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, [ELEMENT_SEARCH_RESULT_MOCK_ALIAS]); - - const mapInstanceMock = { - forEachFeatureAtPixel: (): void => {}, - } as unknown as Map; - - it('does fire search result action handler', async () => { - const handler = onMapSingleClick( - mapSize, - modelId, - dispatch, - SEARCH_DISTANCE_MOCK, - MAX_ZOOM_MOCK_MOCK, - ZOOM_MOCK, - IS_RESULT_DRAWER_OPEN_MOCK, - [], - false, - ); - await handler(event, mapInstanceMock); - await waitFor(() => expect(handleSearchResultActionSpy).toBeCalled()); - }); - }); - - describe('when results type is REACTION', () => { - const { store } = getReduxStoreWithActionsListener(); - const { dispatch } = store; - const { modelId } = ELEMENT_SEARCH_RESULT_MOCK_REACTION; - const mapSize = { - width: 0, - height: 0, - tileSize: 256, - minZoom: 2, - maxZoom: 9, - }; - const coordinate = [0, 0]; - const point = { - x: 0, - y: 0, - }; - const event = getEvent(coordinate); - - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, [ELEMENT_SEARCH_RESULT_MOCK_REACTION]); - - const mapInstanceMock = { - forEachFeatureAtPixel: (): void => {}, - } as unknown as Map; - - it('does fire search result action - handle reaction', async () => { - const handler = onMapSingleClick( - mapSize, - modelId, - dispatch, - SEARCH_DISTANCE_MOCK, - MAX_ZOOM_MOCK_MOCK, - ZOOM_MOCK, - IS_RESULT_DRAWER_OPEN_MOCK, - [], - false, - ); - await handler(event, mapInstanceMock); - await waitFor(() => expect(handleSearchResultActionSpy).toBeCalled()); - }); - }); - }); -}); diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts deleted file mode 100644 index 44e9d10b..00000000 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; -import { MapSize } from '@/redux/map/map.types'; -import { AppDispatch } from '@/redux/store'; -import { Map, MapBrowserEvent } from 'ol'; -import { FeatureLike } from 'ol/Feature'; -import { Comment } from '@/types/models'; -import { updateLastClick } from '@/redux/map/map.slice'; -import { toLonLat } from 'ol/proj'; -import { latLngToPoint } from '@/utils/map/latLngToPoint'; -import { getSearchResults } from './getSearchResults'; -import { handleDataReset } from './handleDataReset'; -import { handleFeaturesClick } from './handleFeaturesClick'; -import { handleSearchResultAction } from './handleSearchResultAction'; - -/* prettier-ignore */ -export const onMapSingleClick = - (mapSize: MapSize, modelId: number, dispatch: AppDispatch, searchDistance: string | undefined, maxZoom: number, zoom: number, isResultDrawerOpen: boolean, - comments: Comment[], shouldConsiderZoomLevel:boolean, - considerZoomLevel?:number, - ) => - async ({ coordinate, pixel }: Pick<MapBrowserEvent<UIEvent>, 'coordinate' | 'pixel'>, mapInstance: Map): Promise<void> => { - const [lng, lat] = toLonLat(coordinate); - const point = latLngToPoint([lat, lng], mapSize); - - dispatch(updateLastClick({coordinates:point, modelId})); - - const featuresAtPixel: FeatureLike[] = []; - mapInstance.forEachFeatureAtPixel(pixel, (feature) => featuresAtPixel.push(feature)); - - const { shouldBlockCoordSearch } = handleFeaturesClick(featuresAtPixel, dispatch, comments); - - if (shouldBlockCoordSearch) { - return; - } - - // side-effect below is to prevent complications with data update - old data may conflict with new data - // so we need to reset all the data before updating - dispatch(handleDataReset); - - const {searchResults} = await getSearchResults({ coordinate, mapSize, modelId, shouldConsiderZoomLevel, - considerZoomLevel, - }); - if (!searchResults || searchResults.length === SIZE_OF_EMPTY_ARRAY) { - return; - } - handleSearchResultAction({ searchResults, dispatch, point, searchDistance, maxZoom, zoom, isResultDrawerOpen }); - }; diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts new file mode 100644 index 00000000..edc575be --- /dev/null +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts @@ -0,0 +1,85 @@ +/* eslint-disable no-magic-numbers */ +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 { FEATURE_TYPE } from '@/constants/features'; +import getFeatureAtCoordinate from '@/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate'; +import SimpleGeometry from 'ol/geom/SimpleGeometry'; + +describe('getFeatureAtCoordinate', () => { + let mapInstance: Map; + const coordinate = [100, 50]; + const vectorLayer = new VectorLayer({}); + vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + + beforeEach(() => { + const dummyElement = document.createElement('div'); + mapInstance = new Map({ target: dummyElement }); + jest.clearAllMocks(); + }); + + it('returns undefined if mapInstance is not provided', () => { + const result = getFeatureAtCoordinate({ + mapInstance: undefined, + coordinate, + }); + expect(result).toBeUndefined(); + }); + + it('returns undefined if no feature is found at the pixel', () => { + jest.spyOn(mapInstance, 'getPixelFromCoordinate').mockReturnValue([200, 100]); + jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation(() => {}); + + const result = getFeatureAtCoordinate({ + mapInstance, + coordinate, + }); + expect(result).toBeUndefined(); + }); + + it('returns the feature if a filled compartment feature is found', () => { + const feature = new Feature({ type: FEATURE_TYPE.COMPARTMENT, filled: true, zIndex: 1 }); + + jest.spyOn(mapInstance, 'getPixelFromCoordinate').mockReturnValue([200, 100]); + jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { + callback(feature, vectorLayer, new SimpleGeometry()); + }); + + const result = getFeatureAtCoordinate({ + mapInstance, + coordinate, + }); + expect(result).toBe(feature); + }); + + it('returns the feature if a non-compartment feature is found', () => { + const feature = new Feature({ type: FEATURE_TYPE.ALIAS, zIndex: 1 }); + + jest.spyOn(mapInstance, 'getPixelFromCoordinate').mockReturnValue([200, 100]); + jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { + callback(feature, vectorLayer, new SimpleGeometry()); + }); + + const result = getFeatureAtCoordinate({ + mapInstance, + coordinate, + }); + expect(result).toBe(feature); + }); + + it('ignores features with invalid zIndex', () => { + const feature = new Feature({ type: FEATURE_TYPE.ALIAS, zIndex: -1 }); + + jest.spyOn(mapInstance, 'getPixelFromCoordinate').mockReturnValue([200, 100]); + jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { + callback(feature, vectorLayer, new SimpleGeometry()); + }); + + const result = getFeatureAtCoordinate({ + mapInstance, + coordinate, + }); + expect(result).toBeUndefined(); + }); +}); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts new file mode 100644 index 00000000..5c1fc99e --- /dev/null +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts @@ -0,0 +1,52 @@ +/* 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'; + +function isFeatureFilledCompartment(feature: FeatureLike): boolean { + return feature.get('type') === FEATURE_TYPE.COMPARTMENT && feature.get('filled'); +} + +function isFeatureNotCompartment(feature: FeatureLike): boolean { + return ( + [...Object.values(FEATURE_TYPE)].includes(feature.get('type')) && + feature.get('type') !== FEATURE_TYPE.COMPARTMENT + ); +} + +export default function getFeatureAtCoordinate({ + mapInstance, + coordinate, + hitTolerance = 10, +}: { + mapInstance: MapInstance; + coordinate: Coordinate; + multiple?: boolean; + hitTolerance?: number; +}): FeatureLike | undefined { + let featureAtPixel: FeatureLike | undefined; + if (!mapInstance) { + return featureAtPixel; + } + const pixel = mapInstance.getPixelFromCoordinate(coordinate); + mapInstance.forEachFeatureAtPixel( + pixel, + (feature, layer) => { + const featureZIndex = feature.get('zIndex'); + if ( + layer && + layer.get('type') === VECTOR_MAP_LAYER_TYPE && + (isFeatureFilledCompartment(feature) || isFeatureNotCompartment(feature)) && + (featureZIndex === undefined || featureZIndex >= 0) + ) { + featureAtPixel = feature; + return true; + } + return false; + }, + { hitTolerance }, + ); + return featureAtPixel; +} diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/handleDataReset.test.ts similarity index 100% rename from src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.test.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/handleDataReset.test.ts diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/handleDataReset.ts similarity index 100% rename from src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/handleDataReset.ts diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.test.ts similarity index 100% rename from src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick.test.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.test.ts diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts similarity index 100% rename from src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick.ts rename to src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts 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 f5d678d9..06a4e4d1 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts @@ -19,15 +19,18 @@ export const leftClickHandleAlias = dispatch(selectTab(`${id}`)); dispatch(openBioEntityDrawerById(id)); + const searchValue = { id, modelId, type: FEATURE_TYPE.ALIAS }; PluginsEventBus.dispatchEvent('onSearch', { type: 'bioEntity', - searchValues: [{ id, modelId, type: FEATURE_TYPE.ALIAS }], + searchValues: [searchValue], results: [ bioEntities.map(bioEntity => { return { perfect: true, bioEntity }; }), ], }); + PluginsEventBus.dispatchEvent('onBioEntityClick', searchValue); + if (hasFitBounds) { searchFitBounds(); 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 2ef85495..deb19107 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 @@ -3,7 +3,7 @@ import { updateLastClick } from '@/redux/map/map.slice'; import { closeDrawer } from '@/redux/drawer/drawer.slice'; import { resetReactionsData } from '@/redux/reactions/reactions.slice'; import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; -import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick'; +import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick'; import Map from 'ol/Map'; import { onMapLeftClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; import { Comment } from '@/types/models'; @@ -15,7 +15,7 @@ import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.cons import * as leftClickHandleAlias from './leftClickHandleAlias'; import * as clickHandleReaction from '../clickHandleReaction'; -jest.mock('../../mapSingleClick/handleFeaturesClick', () => ({ +jest.mock('./handleFeaturesClick', () => ({ handleFeaturesClick: jest.fn(), })); jest.mock('./leftClickHandleAlias', () => ({ 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 fdca7e96..0c01e4a2 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts @@ -6,27 +6,15 @@ import { Comment, ModelElement, NewReaction } from '@/types/models'; import { updateLastClick } from '@/redux/map/map.slice'; import { toLonLat } from 'ol/proj'; import { latLngToPoint } from '@/utils/map/latLngToPoint'; -import { FeatureLike } from 'ol/Feature'; import { closeDrawer } from '@/redux/drawer/drawer.slice'; import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; import { leftClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; -import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleFeaturesClick'; +import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick'; import { resetReactionsData } from '@/redux/reactions/reactions.slice'; -import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset'; +import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mouseClick/handleDataReset'; import { FEATURE_TYPE } from '@/constants/features'; import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; - -function isFeatureFilledCompartment(feature: FeatureLike): boolean { - return feature.get('type') === FEATURE_TYPE.COMPARTMENT && feature.get('filled'); -} - -function isFeatureNotCompartment(feature: FeatureLike): boolean { - return ( - [...Object.values(FEATURE_TYPE)].includes(feature.get('type')) && - feature.get('type') !== FEATURE_TYPE.COMPARTMENT - ); -} +import getFeatureAtCoordinate from '@/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate'; /* prettier-ignore */ export const onMapLeftClick = @@ -40,34 +28,17 @@ export const onMapLeftClick = reactions: Array<NewReaction>, ) => async ( - { coordinate, pixel }: Pick<MapBrowserEvent<UIEvent>, 'coordinate' | 'pixel'>, + { coordinate }: Pick<MapBrowserEvent<UIEvent>, 'coordinate' | 'pixel'>, mapInstance: Map, ): Promise<void> => { const [lng, lat] = toLonLat(coordinate); const point = latLngToPoint([lat, lng], mapSize); dispatch(updateLastClick({ coordinates: point, modelId })); + const featureAtCoordinate = getFeatureAtCoordinate({mapInstance, coordinate, multiple: false}); - let featureAtPixel: FeatureLike | undefined; - mapInstance.forEachFeatureAtPixel( - pixel, - (feature, layer) => { - const featureZIndex = feature.get('zIndex'); - if ( - layer && layer.get('type') === VECTOR_MAP_LAYER_TYPE && - (isFeatureFilledCompartment(feature) || isFeatureNotCompartment(feature)) && - (featureZIndex === undefined || featureZIndex >= 0) - ) { - featureAtPixel = feature; - return true; - } - return false; - }, - { hitTolerance: 10 }, - ); - - if (featureAtPixel) { - const { shouldBlockCoordSearch } = handleFeaturesClick([featureAtPixel], dispatch, comments); + if (featureAtCoordinate) { + const { shouldBlockCoordSearch } = handleFeaturesClick([featureAtCoordinate], dispatch, comments); if (shouldBlockCoordSearch) { return; } @@ -75,7 +46,7 @@ export const onMapLeftClick = dispatch(handleDataReset); - if (!featureAtPixel) { + if (!featureAtCoordinate) { if (isResultDrawerOpen) { dispatch(closeDrawer()); } @@ -85,10 +56,10 @@ export const onMapLeftClick = return; } - const type = featureAtPixel.get('type'); - const id = featureAtPixel.get('id'); + 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)(featureAtPixel, modelId); + await leftClickHandleAlias(dispatch)(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.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts index 9773b48e..0daefedd 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts @@ -5,7 +5,7 @@ import { Feature, Map, MapBrowserEvent } from 'ol'; import { updateLastRightClick } from '@/redux/map/map.slice'; import { toLonLat } from 'ol/proj'; import { latLngToPoint } from '@/utils/map/latLngToPoint'; -import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset'; +import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mouseClick/handleDataReset'; import { FEATURE_TYPE } from '@/constants/features'; import VectorLayer from 'ol/layer/Vector'; import VectorSource from 'ol/source/Vector'; diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index 1e0c81b8..9f81dab4 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -1,5 +1,4 @@ import { PROJECT_ID } from '@/constants'; -import { Point } from '@/types/map'; import { PerfectSearchParams } from '@/types/search'; import { GetPublicationsParams, PublicationsQueryParams } from './publications/publications.types'; @@ -28,13 +27,6 @@ export const apiPath = { isPerfectMatch, }: PerfectSearchParams): string => `projects/${PROJECT_ID}/models/*/bioEntities/:search?query=${searchQuery}&size=1000&perfectMatch=${isPerfectMatch}`, - getSingleBioEntityContentsStringWithCoordinates: ( - { x, y }: Point, - currentModelId: number, - ): string => { - const coordinates = [x, y].join(); - return `projects/${PROJECT_ID}/models/${currentModelId}/bioEntities:search/?coordinates=${coordinates}&count=1`; - }, getReactionsWithIds: (ids: number[]): string => `projects/${PROJECT_ID}/models/*/bioEntities/reactions/?id=${ids.join(',')}&size=1000`, getDrugsStringWithQuery: (searchQuery: string): string => diff --git a/src/redux/configuration/configuration.selectors.ts b/src/redux/configuration/configuration.selectors.ts index 158ac404..7a8009e4 100644 --- a/src/redux/configuration/configuration.selectors.ts +++ b/src/redux/configuration/configuration.selectors.ts @@ -16,7 +16,6 @@ import { SBML_HANDLER_NAME_ID, SIMPLE_COLOR_VAL_NAME_ID, SVG_IMAGE_HANDLER_NAME_ID, - SEARCH_DISTANCE_NAME_ID, REQUEST_ACCOUNT_EMAIL, TERMS_OF_SERVICE_ID, COOKIE_POLICY_URL, @@ -62,11 +61,6 @@ export const simpleColorValSelector = createSelector( state => configurationAdapterSelectors.selectById(state, SIMPLE_COLOR_VAL_NAME_ID)?.value, ); -export const searchDistanceValSelector = createSelector( - configurationOptionsSelector, - state => configurationAdapterSelectors.selectById(state, SEARCH_DISTANCE_NAME_ID)?.value, -); - export const matomoUrlSelector = createSelector( configurationOptionsSelector, state => configurationAdapterSelectors.selectById(state, MATOMO_URL)?.value, @@ -93,11 +87,6 @@ export const defaultLegendImagesSelector = createSelector(configurationOptionsSe ).filter(legendImage => Boolean(legendImage)), ); -export const elementTypesSelector = createSelector( - configurationMainSelector, - state => state?.elementTypes, -); - export const modelFormatsSelector = createSelector( configurationMainSelector, state => state?.modelFormats, diff --git a/src/redux/modelElements/modelElements.selector.ts b/src/redux/modelElements/modelElements.selector.ts index 4be70ab4..b31fd45f 100644 --- a/src/redux/modelElements/modelElements.selector.ts +++ b/src/redux/modelElements/modelElements.selector.ts @@ -10,6 +10,11 @@ export const modelElementsStateForCurrentModelSelector = createSelector( (state, currentModelId) => state[currentModelId], ); +export const modelElementsByModelIdSelector = createSelector( + [modelElementsSelector, (_state, modelId: number): number => modelId], + (state, modelId) => state[modelId]?.data || [], +); + export const modelElementsLoadingSelector = createSelector( modelElementsStateForCurrentModelSelector, state => state?.loading, diff --git a/src/redux/newReactions/newReactions.selectors.ts b/src/redux/newReactions/newReactions.selectors.ts index 6bf11f0e..a17245b4 100644 --- a/src/redux/newReactions/newReactions.selectors.ts +++ b/src/redux/newReactions/newReactions.selectors.ts @@ -19,3 +19,8 @@ export const newReactionsForCurrentModelSelector = createSelector( newReactionsStateForCurrentModelSelector, state => state?.data || [], ); + +export const newReactionsByModelIdSelector = createSelector( + [newReactionsSelector, (_state, modelId: number): number => modelId], + (state, modelId) => state[modelId]?.data || [], +); diff --git a/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts b/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts index 6b7a9b9d..235bf0f5 100644 --- a/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts +++ b/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts @@ -1,51 +1,59 @@ -import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset'; -import { handleSearchResultAction } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction'; -import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; +import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mouseClick/handleDataReset'; import { store } from '@/redux/store'; -import { getElementsByPoint } from '@/utils/search/getElementsByCoordinates'; -import { mapDataLastZoomValue, mapDataMaxZoomValue } from '@/redux/map/map.selectors'; -import { searchDistanceValSelector } from '@/redux/configuration/configuration.selectors'; -import { DEFAULT_ZOOM } from '@/constants/map'; +import { mapDataSizeSelector } from '@/redux/map/map.selectors'; import { resultDrawerOpen } from '@/redux/drawer/drawer.selectors'; +import { MapInstance } from '@/types/map'; +import getFeatureAtCoordinate from '@/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate'; +import { pointToLngLat } from '@/utils/map/pointToLatLng'; +import { fromLonLat } from 'ol/proj'; +import { FEATURE_TYPE } from '@/constants/features'; +import { leftClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; +import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; +import { modelElementsByModelIdSelector } from '@/redux/modelElements/modelElements.selector'; +import { newReactionsByModelIdSelector } from '@/redux/newReactions/newReactions.selectors'; +import { closeDrawer } from '@/redux/drawer/drawer.slice'; +import { resetReactionsData } from '@/redux/reactions/reactions.slice'; +import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; import { Coordinates } from './triggerSearch.types'; export const searchByCoordinates = async ( + mapInstance: MapInstance, coordinates: Coordinates, modelId: number, - shouldConsiderZoomLevel: boolean, hasFitBounds?: boolean, - fitBoundsZoom?: number, - considerZoomLevel?: number, ): Promise<void> => { const { dispatch, getState } = store; // side-effect below is to prevent complications with data update - old data may conflict with new data // so we need to reset all the data before updating dispatch(handleDataReset); - const maxZoom = mapDataMaxZoomValue(getState()); - const lastZoom = mapDataLastZoomValue(getState()); - const searchDistance = searchDistanceValSelector(getState()); + const mapSize = mapDataSizeSelector(getState()); const isResultDrawerOpen = resultDrawerOpen(getState()); - - const searchResults = await getElementsByPoint({ - point: coordinates, - currentModelId: modelId, - shouldConsiderZoomLevel, - considerZoomLevel, + const newReactions = newReactionsByModelIdSelector(getState(), modelId); + const modelElements = modelElementsByModelIdSelector(getState(), modelId); + const [lng, lat] = pointToLngLat(coordinates, mapSize); + const projection = fromLonLat([lng, lat]); + const coordinate = projection.map(v => Math.round(v)); + const searchResultVector = getFeatureAtCoordinate({ + mapInstance, + coordinate, }); - if (!searchResults || searchResults?.length === SIZE_OF_EMPTY_ARRAY) { + if (!searchResultVector) { + if (isResultDrawerOpen) { + dispatch(closeDrawer()); + } + + dispatch(resetReactionsData()); + dispatch(clearBioEntities()); return; } - handleSearchResultAction({ - searchResults, - dispatch, - hasFitBounds, - zoom: fitBoundsZoom || lastZoom || DEFAULT_ZOOM, - maxZoom, - point: coordinates, - searchDistance, - isResultDrawerOpen, - }); + 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); + } 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 abb470aa..adba6dd6 100644 --- a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts +++ b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts @@ -1,21 +1,27 @@ /* eslint-disable no-magic-numbers */ -import { handleSearchResultAction } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction'; import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; import { CONFIGURATION_INITIAL_STORE_MOCKS } from '@/redux/configuration/configuration.mock'; import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { chemicalsFixture } from '@/models/fixtures/chemicalsFixture'; import { drugsFixture } from '@/models/fixtures/drugFixtures'; -import { ELEMENT_SEARCH_RESULT_MOCK_ALIAS } from '@/models/mocks/elementSearchResultMock'; import { apiPath } from '@/redux/apiPath'; import { RootState, store } from '@/redux/store'; -import { mockNetworkNewAPIResponse, mockNetworkResponse } from '@/utils/mockNetworkResponse'; +import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { waitFor } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; -import { triggerSearch } from './triggerSearch'; +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 { ERROR_INVALID_MODEL_ID_TYPE } from '../../errorMessages'; +import { triggerSearch } from './triggerSearch'; const mockedAxiosClient = mockNetworkNewAPIResponse(); -const mockedAxiosOldClient = mockNetworkResponse(); const SEARCH_QUERY = 'park7'; const point = { x: 545.8013, y: 500.9926 }; const modelId = 1000; @@ -30,18 +36,54 @@ const MOCK_STATE = { error: { message: '', name: '' }, openedMaps: openedMapsThreeSubmapsFixture, }, + modelElements: { + 0: { + data: [], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, + newReactions: { + 0: { + data: [], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as NewReactionsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, }; jest.mock('../../../../redux/store'); jest.mock( - '../../../../components/Map/MapViewer/utils/listeners/mapSingleClick/handleSearchResultAction', + '../../../../components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias', + () => ({ + __esModule: true, + ...jest.requireActual( + '../../../../components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias', + ), + }), +); +const leftClickHandleAliasSpy = jest.spyOn(leftClickHandleAlias, 'leftClickHandleAlias'); + +jest.mock( + '../../../../components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick', + () => ({ + handleFeaturesClick: jest.fn(), + }), ); describe('triggerSearch', () => { + let mapInstance: Map; + const vectorLayer = new VectorLayer({}); + vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + beforeEach(() => { + const dummyElement = document.createElement('div'); + mapInstance = new Map({ target: dummyElement }); + MapManager.setMapInstance(mapInstance); jest.clearAllMocks(); }); + describe('search by query', () => { it('should throw error if query param is wrong type', async () => { jest.spyOn(store, 'getState').mockImplementation(() => MOCK_STATE as RootState); @@ -142,7 +184,8 @@ describe('triggerSearch', () => { getState.mockRestore(); }); }); - describe('search by coordinations', () => { + + describe('search by coordinates', () => { it('should throw error if coordinates param is wrong type', async () => { jest.spyOn(store, 'getState').mockImplementation(() => MOCK_STATE as RootState); const invalidParams = { @@ -155,6 +198,7 @@ describe('triggerSearch', () => { 'Invalid coordinates type or values', ); }); + it('should throw error if model id param is wrong type', async () => { jest.spyOn(store, 'getState').mockImplementation(() => MOCK_STATE as RootState); const invalidParams = { @@ -165,20 +209,20 @@ describe('triggerSearch', () => { await expect(triggerSearch(invalidParams)).rejects.toThrowError(ERROR_INVALID_MODEL_ID_TYPE); }); + it('should search result with proper data', async () => { + const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }]; jest.spyOn(store, 'getState').mockImplementation(() => MOCK_STATE as RootState); - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, [ELEMENT_SEARCH_RESULT_MOCK_ALIAS]); + jest.spyOn(store, 'dispatch').mockImplementation( + jest.fn(() => ({ + unwrap: jest.fn().mockResolvedValue(mockBioEntities), + })), + ); + const feature = new Feature({ id: 1, type: FEATURE_TYPE.ALIAS, zIndex: 1 }); + jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { + callback(feature, vectorLayer, null as unknown as SimpleGeometry); + }); - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); const params = { coordinates: point, modelId, @@ -187,35 +231,15 @@ describe('triggerSearch', () => { await expect(triggerSearch(params)).resolves.toBe(undefined); await waitFor(() => { - expect(handleSearchResultAction).toHaveBeenCalledWith({ - searchResults: [ELEMENT_SEARCH_RESULT_MOCK_ALIAS], - dispatch: store.dispatch, - hasFitBounds: undefined, - isResultDrawerOpen: false, - maxZoom: 9, - point: { - x: 545.8013, - y: 500.9926, - }, - searchDistance: '10', - zoom: 5, - }); + expect(leftClickHandleAliasSpy).toHaveBeenCalledWith(store.dispatch, undefined); }); }); + it('should not search result if there is no bio entity with specific coordinates', async () => { jest.spyOn(store, 'getState').mockImplementation(() => MOCK_STATE as RootState); - mockedAxiosOldClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, modelId)) - .reply(HttpStatusCode.Ok, []); - - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: ELEMENT_SEARCH_RESULT_MOCK_ALIAS.id.toString(), - isPerfectMatch: true, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); + jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { + callback(new Feature({ zIndex: 1 }), vectorLayer, null as unknown as SimpleGeometry); + }); const params = { coordinates: point, modelId, @@ -223,7 +247,7 @@ describe('triggerSearch', () => { await expect(triggerSearch(params)).resolves.toBe(undefined); - expect(handleSearchResultAction).not.toHaveBeenCalled(); + expect(leftClickHandleAliasSpy).not.toHaveBeenCalled(); }); }); }); diff --git a/src/services/pluginsManager/map/triggerSearch/triggerSearch.ts b/src/services/pluginsManager/map/triggerSearch/triggerSearch.ts index 363a0155..01b1cdad 100644 --- a/src/services/pluginsManager/map/triggerSearch/triggerSearch.ts +++ b/src/services/pluginsManager/map/triggerSearch/triggerSearch.ts @@ -1,3 +1,4 @@ +import { MapManager } from '@/services/pluginsManager/map/mapManager'; import { SearchParams } from './triggerSearch.types'; import { searchByQuery } from './searchByQuery'; import { searchByCoordinates } from './searchByCoordinates'; @@ -8,6 +9,10 @@ import { } from '../../errorMessages'; export async function triggerSearch(params: SearchParams): Promise<void> { + const mapInstance = MapManager.getMapInstance(); + if (!mapInstance) { + return; + } if ('query' in params) { if (typeof params.query !== 'string') { throw new Error(ERROR_INVALID_QUERY_TYPE); @@ -19,15 +24,12 @@ export async function triggerSearch(params: SearchParams): Promise<void> { const areCoordinatesMissingKeys = !('x' in params.coordinates) || !('y' in params.coordinates); const areCoordinatesValuesInvalid = typeof params.coordinates.x !== 'number' || typeof params.coordinates.y !== 'number'; - if (areCoordinatesInvalidType || areCoordinatesMissingKeys || areCoordinatesValuesInvalid) { throw new Error(ERROR_INVALID_COORDINATES); } - if (typeof params.modelId !== 'number') { throw new Error(ERROR_INVALID_MODEL_ID_TYPE); } - - searchByCoordinates(params.coordinates, params.modelId, false, params.fitBounds, params.zoom); + await searchByCoordinates(mapInstance, params.coordinates, params.modelId, params.fitBounds); } } diff --git a/src/services/pluginsManager/map/triggerSearch/triggerSearch.types.ts b/src/services/pluginsManager/map/triggerSearch/triggerSearch.types.ts index fa6cd67a..c4302364 100644 --- a/src/services/pluginsManager/map/triggerSearch/triggerSearch.types.ts +++ b/src/services/pluginsManager/map/triggerSearch/triggerSearch.types.ts @@ -13,7 +13,6 @@ export type SearchByCoordinatesParams = { coordinates: Coordinates; modelId: number; fitBounds?: boolean; - zoom?: number; }; export type SearchParams = SearchByCoordinatesParams | SearchByQueryParams; diff --git a/src/utils/search/getElementsByCoordinates.test.ts b/src/utils/search/getElementsByCoordinates.test.ts deleted file mode 100644 index d24ece7c..00000000 --- a/src/utils/search/getElementsByCoordinates.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { elementSearchResultFixture } from '@/models/fixtures/elementSearchResultFixture'; -import { apiPath } from '@/redux/apiPath'; -import { HttpStatusCode } from 'axios'; -import { mockNetworkResponse } from '../mockNetworkResponse'; -import { getElementsByPoint } from './getElementsByCoordinates'; - -const mockedAxiosClient = mockNetworkResponse(); - -describe('getElementsByPoint - utils', () => { - const point = { - x: 0, - y: 0, - }; - const currentModelId = 1000; - - it('should return data when data response from API is valid', async () => { - mockedAxiosClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, currentModelId)) - .reply(HttpStatusCode.Ok, elementSearchResultFixture); - - const response = await getElementsByPoint({ - point, - currentModelId, - shouldConsiderZoomLevel: false, - }); - expect(response).toEqual(elementSearchResultFixture); - }); - - it('should return undefined when data response from API is not valid ', async () => { - mockedAxiosClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, currentModelId)) - .reply(HttpStatusCode.Ok, { randomProperty: 'randomValue' }); - - const response = await getElementsByPoint({ - point, - currentModelId, - shouldConsiderZoomLevel: false, - }); - expect(response).toEqual(undefined); - }); - - it('should return empty array when data response from API is empty', async () => { - mockedAxiosClient - .onGet(apiPath.getSingleBioEntityContentsStringWithCoordinates(point, currentModelId)) - .reply(HttpStatusCode.Ok, []); - - const response = await getElementsByPoint({ - point, - currentModelId, - shouldConsiderZoomLevel: false, - }); - expect(response).toEqual([]); - }); -}); diff --git a/src/utils/search/getElementsByCoordinates.ts b/src/utils/search/getElementsByCoordinates.ts deleted file mode 100644 index fa54f1de..00000000 --- a/src/utils/search/getElementsByCoordinates.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { elementSearchResult } from '@/models/elementSearchResult'; -import { apiPath } from '@/redux/apiPath'; -import { axiosInstance, axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; -import { Point } from '@/types/map'; -import { BioEntity, ElementSearchResult } from '@/types/models'; -import { z } from 'zod'; -import { ONE, ZERO } from '@/constants/common'; -import { validateDataUsingZodSchema } from '../validateDataUsingZodSchema'; - -interface FirstVisibleParentArgs { - bioEntity: BioEntity; - considerZoomLevel: number; -} - -export const getFirstVisibleParent = async ({ - bioEntity, - considerZoomLevel, -}: FirstVisibleParentArgs): Promise<BioEntity> => { - let parentId = bioEntity.complex; - if (!parentId) { - parentId = bioEntity.compartment; - } - if (parentId) { - const parentResponse = await axiosInstanceNewAPI.get<BioEntity>( - apiPath.getElementById(parentId, bioEntity.model), - ); - const parent = parentResponse.data; - if ( - parent.visibilityLevel !== null && - parseInt(parent.visibilityLevel, 10) > Math.ceil(considerZoomLevel) - ) { - return getFirstVisibleParent({ - bioEntity: parent, - considerZoomLevel, - }); - } - return parent; - } - // eslint-disable-next-line no-console - console.log(`Cannot find visible parent for object. (zoomLevel=${considerZoomLevel})`, bioEntity); - return bioEntity; -}; - -interface Args { - point: Point; - currentModelId: number; - shouldConsiderZoomLevel: boolean; - considerZoomLevel?: number; -} - -const FRACTIONAL_ZOOM_AT_WHICH_IMAGE_LAYER_CHANGE = 0.415; - -export const getElementsByPoint = async ({ - point, - currentModelId, - shouldConsiderZoomLevel, - considerZoomLevel, -}: Args): Promise<ElementSearchResult[] | undefined> => { - let result: ElementSearchResult[]; - const response = await axiosInstance.get<ElementSearchResult[]>( - apiPath.getSingleBioEntityContentsStringWithCoordinates(point, currentModelId), - ); - const isDataValid = validateDataUsingZodSchema(response.data, z.array(elementSearchResult)); - - if (!isDataValid) { - return undefined; - } - result = response.data; - - if (shouldConsiderZoomLevel && result.length > ZERO && result[ZERO].type === 'ALIAS') { - const elementResponse = await axiosInstanceNewAPI.get<BioEntity>( - apiPath.getElementById(result[ZERO].id, result[ZERO].modelId), - ); - const element = elementResponse.data; - if ( - element.visibilityLevel != null && - parseInt(element.visibilityLevel, 10) - (ONE - FRACTIONAL_ZOOM_AT_WHICH_IMAGE_LAYER_CHANGE) > - (considerZoomLevel || Number.MAX_SAFE_INTEGER) - ) { - const visibleParent = await getFirstVisibleParent({ - bioEntity: element, - considerZoomLevel: considerZoomLevel || Number.MAX_SAFE_INTEGER, - }); - let id: number; - if (typeof visibleParent.id === 'string') { - id = parseInt(visibleParent.id, 10); - } else { - id = visibleParent.id; - } - result = [ - { - id, - type: 'ALIAS', - modelId: visibleParent.model, - }, - ]; - } - } - - return result; -}; -- GitLab From cb867685ed2c5b86200ebb5c6b41e07c3cee6722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Thu, 23 Jan 2025 14:06:04 +0100 Subject: [PATCH 04/12] feat(cleanup): access to element via store --- .../MapNavigation.component.test.tsx | 40 ++- .../AssociatedSubmap.component.test.tsx | 40 +++ .../BioEntityDrawer.component.test.tsx | 274 ++++++------------ .../BioEntityDrawer.component.tsx | 37 +-- .../Map/Drawer/Drawer.component.test.tsx | 7 + .../Elements/Elements.component.test.tsx | 49 ++-- ...udedCompartmentPathways.component.test.tsx | 95 +++--- .../ExcludedCompartmentPathways.component.tsx | 13 +- ...udedCompartmentPathways.component.test.tsx | 97 ++++--- .../IncludedCompartmentPathways.component.tsx | 13 +- ...ompartmentPathwaysCheckboxElements.test.ts | 8 +- .../getCompartmentPathwaysCheckboxElements.ts | 10 +- .../ExportDrawer/ExportDrawer.component.tsx | 13 +- .../Network/Network.component.test.tsx | 49 ++-- .../ReactionDrawer.component.test.tsx | 7 + .../ReactionDrawer.component.tsx | 6 +- .../MapLoader/MapLoader.component.test.tsx | 14 +- .../Map/MapLoader/MapLoader.component.tsx | 38 +-- .../Map/MapViewer/MapViewer.constants.ts | 12 +- .../commentsLayer/useOlMapCommentsLayer.ts | 17 +- .../config/mapCardLayer/useOlMapCardLayer.ts | 21 +- .../useBioEntitiesWithSubmapLinks.test.ts | 41 +++ .../overlaysLayer/useOlMapOverlaysLayer.ts | 17 +- .../config/pinsLayer/useOlMapPinsLayer.ts | 15 +- .../processLayer/processModelElements.ts | 3 +- .../processLayer/useOlMapProcessLayer.ts | 37 ++- .../reactionsLayer/useOlMapReactionsLayer.ts | 21 +- .../mouseClick/clickHandleReaction.test.ts | 20 +- .../mouseClick/getFeatureAtCoordinate.test.ts | 4 +- .../mouseClick/getFeatureAtCoordinate.ts | 4 +- .../mouseLeftClick/handleFeaturesClick.ts | 7 +- .../leftClickHandleAlias.test.ts | 11 +- .../mouseLeftClick/leftClickHandleAlias.ts | 30 +- .../mouseLeftClick/onMapLeftClick.test.ts | 4 +- .../mouseLeftClick/onMapLeftClick.ts | 2 +- .../mouseRightClick/onMapRightClick.test.ts | 4 +- .../mouseRightClick/onMapRightClick.ts | 4 +- .../Map/MapViewer/utils/shapes/layer/Layer.ts | 2 + src/models/bioEntitySchema.ts | 2 +- src/models/compartmentPathwaySchema.ts | 51 ---- src/models/fixtures/compartmentPathways.ts | 29 -- src/redux/apiPath.ts | 8 - src/redux/bioEntity/bioEntity.reducers.ts | 57 ---- src/redux/bioEntity/bioEntity.selectors.ts | 88 +----- src/redux/bioEntity/bioEntity.slice.ts | 2 - src/redux/bioEntity/thunks/getBioEntity.ts | 38 +-- .../bioEntity/thunks/getMultiBioEntity.ts | 52 +--- .../thunks/getSubmapConnectionsBioEntity.ts | 43 --- src/redux/comment/comment.reducers.ts | 23 +- src/redux/comment/comment.selectors.ts | 5 - src/redux/comment/comment.slice.ts | 2 - src/redux/comment/thunks/getComments.ts | 20 +- .../comparmentPathways.constants.ts | 3 - .../compartmentPathways.mock.ts | 65 ----- .../compartmentPathways.reducers.test.ts | 127 -------- .../compartmentPathways.reducers.ts | 20 -- .../compartmentPathways.selectors.ts | 17 -- .../compartmentPathways.slice.ts | 20 -- .../compartmentPathways.thunks.test.ts | 127 -------- .../compartmentPathways.thunks.ts | 129 --------- .../compartmentPathways.types.ts | 4 - src/redux/drawer/drawer.selectors.ts | 5 - .../entityNumber/entityNumber.reducers.ts | 1 - .../modelElements/modelElements.constants.ts | 2 + .../modelElements.reducers.test.ts | 4 +- .../modelElements/modelElements.selector.ts | 55 +++- .../modelElements/modelElements.thunks.ts | 2 +- .../newReactions/newReactions.selectors.ts | 10 + .../overlayBioEntity.selector.ts | 4 +- src/redux/root/init.thunks.ts | 3 - src/redux/root/root.fixtures.ts | 2 - src/redux/selectors/index.ts | 33 +++ src/redux/store.ts | 2 - .../map/triggerSearch/searchByCoordinates.ts | 2 +- .../map/triggerSearch/triggerSearch.test.ts | 4 +- src/types/models.ts | 24 +- 76 files changed, 693 insertions(+), 1478 deletions(-) delete mode 100644 src/models/compartmentPathwaySchema.ts delete mode 100644 src/models/fixtures/compartmentPathways.ts delete mode 100644 src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts delete mode 100644 src/redux/compartmentPathways/comparmentPathways.constants.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.mock.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.reducers.test.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.reducers.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.selectors.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.slice.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.thunks.test.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.thunks.ts delete mode 100644 src/redux/compartmentPathways/compartmentPathways.types.ts create mode 100644 src/redux/selectors/index.ts diff --git a/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx b/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx index 22c43bc9..d08b0e9b 100644 --- a/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx +++ b/src/components/FunctionalArea/MapNavigation/MapNavigation.component.test.tsx @@ -1,5 +1,4 @@ /* eslint-disable no-magic-numbers */ -import { MODELS_MOCK } from '@/redux/compartmentPathways/compartmentPathways.mock'; import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; import { StoreType } from '@/redux/store'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; @@ -9,7 +8,7 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { act, render, screen, within } from '@testing-library/react'; import { HISTAMINE_MAP_ID, MAIN_MAP_ID } from '@/constants/mocks'; -import { Project } from '@/types/models'; +import { MapModel, Project } from '@/types/models'; import { projectFixture } from '@/models/fixtures/projectFixture'; import { ProjectState } from '@/redux/project/project.types'; import { PROJECT_STATE_INITIAL_MOCK } from '@/redux/project/project.mock'; @@ -17,6 +16,43 @@ import { ModelsState } from '@/redux/models/models.types'; import { DEFAULT_ERROR } from '@/constants/errors'; import { MapNavigation } from './MapNavigation.component'; +const MODELS_MOCK: MapModel[] = [ + { + id: MAIN_MAP_ID, + width: 26779.25, + height: 13503.0, + defaultCenterX: null, + defaultCenterY: null, + description: '', + name: 'Core PD map', + defaultZoomLevel: null, + tileSize: 256, + references: [], + authors: [], + creationDate: null, + modificationDates: [], + minZoom: 2, + maxZoom: 9, + }, + { + id: 5054, + width: 26779.25, + height: 13503.0, + defaultCenterX: null, + defaultCenterY: null, + description: '', + name: 'Core PD map', + defaultZoomLevel: null, + tileSize: 256, + references: [], + authors: [], + creationDate: null, + modificationDates: [], + minZoom: 2, + maxZoom: 9, + }, +]; + export const MODELS_DATA: ModelsState = { data: [ { diff --git a/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx b/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx index 84ff3087..73231d8d 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx @@ -4,6 +4,7 @@ import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; import { BIOENTITY_INITIAL_STATE_MOCK, BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, + BIO_ENTITY_LINKING_TO_SUBMAP, } from '@/redux/bioEntity/bioEntity.mock'; import { DRAWER_INITIAL_STATE } from '@/redux/drawer/drawer.constants'; import { @@ -19,6 +20,7 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { act, render, screen } from '@testing-library/react'; import { HISTAMINE_MAP_ID, MAIN_MAP_ID } from '@/constants/mocks'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { AssociatedSubmap } from './AssociatedSubmap.component'; const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { @@ -51,6 +53,13 @@ describe('AssociatedSubmap - component', () => { chemicals: {}, }, }, + modelElements: { + [MAIN_MAP_ID]: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, models: { ...MODELS_INITIAL_STATE_MOCK, }, @@ -58,8 +67,18 @@ describe('AssociatedSubmap - component', () => { expect(screen.queryByTestId('associated-submap')).not.toBeInTheDocument(); }); + it('should render component when associated map model is found', () => { renderComponent({ + map: { + data: { + ...initialMapDataFixture, + modelId: MAIN_MAP_ID, + }, + loading: 'succeeded', + error: { name: '', message: '' }, + openedMaps: openedMapsThreeSubmapsFixture, + }, bioEntity: { ...BIOENTITY_INITIAL_STATE_MOCK, data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, @@ -72,6 +91,13 @@ describe('AssociatedSubmap - component', () => { chemicals: {}, }, }, + modelElements: { + [MAIN_MAP_ID]: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, models: { ...MODELS_INITIAL_STATE_MOCK, data: MODELS_MOCK_SHORT, @@ -94,6 +120,13 @@ describe('AssociatedSubmap - component', () => { ...BIOENTITY_INITIAL_STATE_MOCK, data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, }, + modelElements: { + 0: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -153,6 +186,13 @@ describe('AssociatedSubmap - component', () => { ...BIOENTITY_INITIAL_STATE_MOCK, data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, }, + modelElements: { + [MAIN_MAP_ID]: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { diff --git a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx index d72d546a..7ae2a243 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx @@ -1,14 +1,6 @@ /* eslint-disable no-magic-numbers */ -import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; -import { - bioEntitiesContentFixture, - bioEntityContentFixture, -} from '@/models/fixtures/bioEntityContentsFixture'; import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; -import { - BIOENTITY_INITIAL_STATE_MOCK, - BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, -} from '@/redux/bioEntity/bioEntity.mock'; +import { BIO_ENTITY_LINKING_TO_SUBMAP } from '@/redux/bioEntity/bioEntity.mock'; import { DRAWER_INITIAL_STATE } from '@/redux/drawer/drawer.constants'; import { MODELS_INITIAL_STATE_MOCK } from '@/redux/models/models.mock'; import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; @@ -18,6 +10,8 @@ import { InitialStoreState } from '@/utils/testing/getReduxWrapperWithStore'; import { act, render, screen } from '@testing-library/react'; import { MockStoreEnhanced } from 'redux-mock-store'; import { getTypeBySBOTerm } from '@/utils/bioEntity/getTypeBySBOTerm'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { BioEntityDrawer } from './BioEntityDrawer.component'; const renderComponent = ( @@ -65,65 +59,48 @@ describe('BioEntityDrawer - component', () => { expect(screen.queryByText('Source:')).toBeNull(); }); }); + describe('when there IS a matching bioEntity', () => { - const { bioEntity } = bioEntitiesContentFixture[FIRST_ARRAY_ELEMENT]; + const bioEntityName = 'test'; + const bioEntityFullName = 'BioEntity Full Name'; it('should show drawer header', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, }, }); - const bioEntityType = getTypeBySBOTerm(bioEntity.sboTerm); - + const bioEntityType = getTypeBySBOTerm(modelElementFixture.sboTerm); expect(screen.getByText(bioEntityType, { exact: false })).toBeInTheDocument(); - expect(screen.getByText(bioEntity.name, { exact: false })).toBeInTheDocument(); + expect(screen.getByText(bioEntityName, { exact: false })).toBeInTheDocument(); }); it('should show drawer bioEntity full name', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: 'BioEntity Full Name', - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: bioEntityFullName }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -131,35 +108,22 @@ describe('BioEntityDrawer - component', () => { }); expect(screen.getByText('Full name:', { exact: false })).toBeInTheDocument(); - expect(screen.getByText('BioEntity Full Name', { exact: false })).toBeInTheDocument(); + expect(screen.getByText(bioEntityFullName, { exact: false })).toBeInTheDocument(); }); it("should not show drawer bioEntity full name if it doesn't exists", () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -171,22 +135,17 @@ describe('BioEntityDrawer - component', () => { it('should show list of annotations ', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -194,22 +153,27 @@ describe('BioEntityDrawer - component', () => { }); expect(screen.getByText('Annotations:')).toBeInTheDocument(); - expect(screen.getByText(bioEntity.references[0].type, { exact: false })).toBeInTheDocument(); expect( - screen.getByText(bioEntity.references[0].resource, { exact: false }), + screen.getByText(modelElementFixture.references[0].type, { exact: false }), + ).toBeInTheDocument(); + expect( + screen.getByText(modelElementFixture.references[0].resource, { exact: false }), ).toBeInTheDocument(); }); it('should display associated submaps if bio entity links to submap', () => { renderComponent({ - bioEntity: { - ...BIOENTITY_INITIAL_STATE_MOCK, - data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, - }, + modelElements: { + 0: { + data: [{ ...BIO_ENTITY_LINKING_TO_SUBMAP, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: BIO_ENTITY_LINKING_TO_SUBMAP.id, drugs: {}, chemicals: {}, }, @@ -225,30 +189,17 @@ describe('BioEntityDrawer - component', () => { it('should display chemicals list header', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -260,30 +211,17 @@ describe('BioEntityDrawer - component', () => { it('should display drugs list header', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -293,86 +231,60 @@ describe('BioEntityDrawer - component', () => { expect(screen.getByText('Chemicals for target', { exact: false })).toBeInTheDocument(); }); - it('should fetch drugs on drugs for target click', () => { + it('should fetch chemicals on chemicals for target click', () => { const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, }, }); - const button = screen.getByText('Drugs for target', { exact: false }); + const button = screen.getByText('Chemicals for target', { exact: false }); act(() => { button.click(); }); - expect(store.getActions()[0].type).toBe('drawer/getDrugsForBioEntityDrawerTarget/pending'); + expect(store.getActions()[0].type).toBe( + 'drawer/getChemicalsForBioEntityDrawerTarget/pending', + ); }); - it('should fetch chemicals on chemicals for target click', () => { + it('should fetch drugs on drugs for target click', () => { const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, }, }); - const button = screen.getByText('Chemicals for target', { exact: false }); + const button = screen.getByText('Drugs for target', { exact: false }); act(() => { button.click(); }); - expect(store.getActions()[0].type).toBe( - 'drawer/getChemicalsForBioEntityDrawerTarget/pending', - ); + expect(store.getActions()[0].type).toBe('drawer/getDrugsForBioEntityDrawerTarget/pending'); }); }); }); diff --git a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx index 7b3e3ba1..48ac8915 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx @@ -1,7 +1,6 @@ import { ZERO } from '@/constants/common'; import { currentDrawerBioEntityRelatedSubmapSelector, - currentDrawerBioEntitySelector, currentDrawerElementCommentsSelector, } from '@/redux/bioEntity/bioEntity.selectors'; import { @@ -17,6 +16,10 @@ import { getTypeBySBOTerm } from '@/utils/bioEntity/getTypeBySBOTerm'; import { ModificationResidueItem } from '@/components/Map/Drawer/BioEntityDrawer/ModificationResidueItem'; import React from 'react'; import { AnnotationItemList } from '@/components/Map/Drawer/BioEntityDrawer/AnnotationItem/AnnotationItemList.component'; +import { + compartmentNameByIdSelector, + currentDrawerModelElementSelector, +} from '@/redux/modelElements/modelElements.selector'; import { CollapsibleSection } from '../ExportDrawer/CollapsibleSection'; import { AssociatedSubmap } from './AssociatedSubmap'; import { ChemicalsList } from './ChemicalsList'; @@ -27,28 +30,31 @@ const TARGET_PREFIX: ElementSearchResultType = `ALIAS`; export const BioEntityDrawer = (): React.ReactNode => { const dispatch = useAppDispatch(); - const bioEntityData = useAppSelector(currentDrawerBioEntitySelector); + const modelElement = useAppSelector(currentDrawerModelElementSelector); const commentsData = useAppSelector(currentDrawerElementCommentsSelector); const relatedSubmap = useAppSelector(currentDrawerBioEntityRelatedSubmapSelector); - const currentTargetId = bioEntityData?.id ? `${TARGET_PREFIX}:${bioEntityData.id}` : ''; + const currentTargetId = modelElement?.id ? `${TARGET_PREFIX}:${modelElement.id}` : ''; const fetchChemicalsForTarget = (): void => { dispatch(getChemicalsForBioEntityDrawerTarget(currentTargetId)); }; + const compartmentName = useAppSelector(state => + compartmentNameByIdSelector(state, modelElement?.compartment), + ); + const fetchDrugsForTarget = (): void => { dispatch(getDrugsForBioEntityDrawerTarget(currentTargetId)); }; - - if (!bioEntityData) { + if (!modelElement) { return null; } const isCommentAvailable = commentsData.length > ZERO; const modificationResidues = ( - bioEntityData.modificationResidues ? bioEntityData.modificationResidues : [] + modelElement.modificationResidues ? modelElement.modificationResidues : [] ).filter(modificationResidue => modificationResidue.state && modificationResidue.state !== ''); const isModificationAvailable = modificationResidues.length > ZERO; - const type = getTypeBySBOTerm(bioEntityData.sboTerm, bioEntityData.shape); + const type = getTypeBySBOTerm(modelElement.sboTerm, modelElement.shape); return ( <div className="h-calc-drawer" data-testid="bioentity-drawer"> @@ -56,29 +62,26 @@ export const BioEntityDrawer = (): React.ReactNode => { title={ <> <span className="font-normal">{type}:</span> - {bioEntityData.name} + {modelElement.name} </> } /> <div className="flex max-h-full flex-col gap-6 overflow-y-auto p-6"> <div className="text-sm font-normal"> - Compartment:{' '} - <b className="font-semibold"> - {bioEntityData.compartmentName ? bioEntityData.compartmentName : 'default'} - </b> + Compartment: <b className="font-semibold">{compartmentName || 'default'}</b> </div> - {bioEntityData.fullName && ( + {modelElement.fullName && ( <div className="text-sm font-normal"> - Full name: <b className="font-semibold">{bioEntityData.fullName}</b> + Full name: <b className="font-semibold">{modelElement.fullName}</b> </div> )} - {bioEntityData.notes && ( + {modelElement.notes && ( <span> <hr className="border-b border-b-divide" /> <div className="text-sm font-normal" /* eslint-disable-next-line react/no-danger */ - dangerouslySetInnerHTML={{ __html: bioEntityData.notes }} + dangerouslySetInnerHTML={{ __html: modelElement.notes }} /> </span> )} @@ -92,7 +95,7 @@ export const BioEntityDrawer = (): React.ReactNode => { ))} </ul> )} - <AnnotationItemList references={bioEntityData.references} /> + <AnnotationItemList references={modelElement.references} /> <AssociatedSubmap /> {!relatedSubmap && ( <> diff --git a/src/components/Map/Drawer/Drawer.component.test.tsx b/src/components/Map/Drawer/Drawer.component.test.tsx index eb258f9d..b677519d 100644 --- a/src/components/Map/Drawer/Drawer.component.test.tsx +++ b/src/components/Map/Drawer/Drawer.component.test.tsx @@ -101,6 +101,13 @@ describe('Drawer - component', () => { loading: 'succeeded', error: { message: '', name: '' }, }, + newReactions: { + 0: { + data: [newReactionFixture], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, }); expect(screen.queryByTestId('reaction-drawer')).not.toBeInTheDocument(); diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx index e3307241..d0e0d9b6 100644 --- a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx @@ -1,5 +1,4 @@ /* eslint-disable no-magic-numbers */ -import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways'; import { configurationFixture } from '@/models/fixtures/configurationFixture'; import { modelsFixture } from '@/models/fixtures/modelsFixture'; import { statisticsFixture } from '@/models/fixtures/statisticsFixture'; @@ -14,6 +13,9 @@ import { render, screen } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; import { act } from 'react-dom/test-utils'; import { MockStoreEnhanced } from 'redux-mock-store'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; +import { COMPARTMENT_SBO_TERM } from '@/components/Map/MapViewer/MapViewer.constants'; import { ELEMENTS_COLUMNS } from '../ExportCompound/ExportCompound.constant'; import { Elements } from './Elements.component'; @@ -70,14 +72,6 @@ describe('Elements - component', () => { name: '', }, }, - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, }); const annotations = screen.getByText('Select annotations'); @@ -90,12 +84,13 @@ describe('Elements - component', () => { expect(excludedCompartmentPathways).toBeVisible(); expect(downloadButton).toBeVisible(); }); + it('should handle download button click and dispatch proper data', async () => { mockedAxiosClient.onPost(apiPath.downloadElementsCsv()).reply(HttpStatusCode.Ok, 'test'); - const FIRST_COMPARMENT_PATHWAY_NAME = compartmentPathwaysDetailsFixture[0].name; - const FIRST_COMPARMENT_PATHWAY_ID = compartmentPathwaysDetailsFixture[0].id; - const SECOND_COMPARMENT_PATHWAY_NAME = compartmentPathwaysDetailsFixture[1].name; - const SECOND_COMPARMENT_PATHWAY_ID = compartmentPathwaysDetailsFixture[1].id; + const FIRST_COMPARMENT_PATHWAY_NAME = 'test1'; + const FIRST_COMPARMENT_PATHWAY_ID = 1; + const SECOND_COMPARMENT_PATHWAY_NAME = 'test2'; + const SECOND_COMPARMENT_PATHWAY_ID = 2; const { store } = renderComponent({ ...INITIAL_STORE_STATE_MOCK, configuration: { @@ -129,14 +124,6 @@ describe('Elements - component', () => { name: '', }, }, - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, models: { data: modelsFixture, loading: 'succeeded', @@ -145,6 +132,26 @@ describe('Elements - component', () => { name: '', }, }, + modelElements: { + 0: { + data: [ + { + ...modelElementFixture, + id: FIRST_COMPARMENT_PATHWAY_ID, + name: FIRST_COMPARMENT_PATHWAY_NAME, + sboTerm: COMPARTMENT_SBO_TERM, + }, + { + ...modelElementFixture, + id: SECOND_COMPARMENT_PATHWAY_ID, + name: SECOND_COMPARMENT_PATHWAY_NAME, + sboTerm: COMPARTMENT_SBO_TERM, + }, + ], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, }); const annotations = screen.getByText('Select annotations'); diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx index ded8e680..82d39b1e 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx @@ -6,9 +6,20 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { StoreType } from '@/redux/store'; import { act } from 'react-dom/test-utils'; -import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { ModelElement } from '@/types/models'; +import { + compartmentPathwaysSelector, + modelElementsAnyModelLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; import { ExcludedCompartmentPathways } from './ExcludedCompartmentPathways.component'; +jest.mock('../../../../../../redux/hooks/useAppSelector', () => ({ + useAppSelector: jest.fn(), +})); +type SelectorFunction = (state: never) => ModelElement[] | boolean; + const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); @@ -24,20 +35,28 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St ); }; -const CHECKBOX_ELEMENT_NAME = compartmentPathwaysDetailsFixture[0].name; +const CHECKBOX_ELEMENT_NAME = modelElementFixture.name; describe('ExcludedCompartmentPathways - component', () => { + const mockUseAppSelector = useAppSelector as jest.Mock; + it('should display compartment / pathways checkboxes when fetching data is successful', async () => { - renderComponent({ - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [ + compartmentPathwaysSelector, + [ + { + ...modelElementFixture, + }, + ], + ], + [modelElementsAnyModelLoadingSelector, false], + ]); + + return selectorMap.get(selector) ?? false; }); + renderComponent({}); expect(screen.queryByTestId('checkbox-filter')).not.toBeVisible(); @@ -55,36 +74,18 @@ describe('ExcludedCompartmentPathways - component', () => { expect(screen.getByLabelText(CHECKBOX_ELEMENT_NAME)).toBeInTheDocument(); }); }); - it('should not display compartment / pathways checkboxes when fetching data fails', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'failed', - error: { - message: '', - name: '', - }, - }, - }); - expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument(); - const navigationButton = screen.getByTestId('accordion-item-button'); - act(() => { - navigationButton.click(); - }); - expect(screen.queryByTestId('checkbox-filter')).not.toBeInTheDocument(); - }); it('should not display compartment / pathways checkboxes when fetched data is empty', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [compartmentPathwaysSelector, []], + [modelElementsAnyModelLoadingSelector, false], + ]); + + return selectorMap.get(selector) ?? false; }); + + renderComponent({}); expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { @@ -95,16 +96,16 @@ describe('ExcludedCompartmentPathways - component', () => { }); it('should display loading message when fetching data is pending', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'pending', - error: { - message: '', - name: '', - }, - }, + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [compartmentPathwaysSelector, []], + [modelElementsAnyModelLoadingSelector, true], + ]); + + return selectorMap.get(selector) ?? false; }); + + renderComponent({}); expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx index 89007fae..131819ac 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx @@ -1,10 +1,10 @@ import { ZERO } from '@/constants/common'; -import { - compartmentPathwaysDataSelector, - loadingCompartmentPathwaysSelector, -} from '@/redux/compartmentPathways/compartmentPathways.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { useContext } from 'react'; +import { + compartmentPathwaysSelector, + modelElementsAnyModelLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; import { CheckboxFilter } from '../../CheckboxFilter'; import { CollapsibleSection } from '../../CollapsibleSection'; import { ExportContext } from '../ExportCompound.context'; @@ -13,9 +13,8 @@ import { getCompartmentPathwaysCheckboxElements } from '../utils/getCompartmentP export const ExcludedCompartmentPathways = (): React.ReactNode => { const { setExcludedCompartmentPathways, data } = useContext(ExportContext); const currentExcludedCompartmentPathways = data.excludedCompartmentPathways; - const loadingCompartmentPathways = useAppSelector(loadingCompartmentPathwaysSelector); - const isPending = loadingCompartmentPathways === 'pending'; - const compartmentPathways = useAppSelector(compartmentPathwaysDataSelector); + const compartmentPathways = useAppSelector(compartmentPathwaysSelector); + const isPending = useAppSelector(modelElementsAnyModelLoadingSelector); const checkboxElements = getCompartmentPathwaysCheckboxElements('excluded', compartmentPathways); const isCheckboxFilterVisible = !isPending && checkboxElements && checkboxElements.length > ZERO; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx index 59a59c99..29ce2f87 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx @@ -6,9 +6,20 @@ import { } from '@/utils/testing/getReduxWrapperWithStore'; import { StoreType } from '@/redux/store'; import { act } from 'react-dom/test-utils'; -import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { + compartmentPathwaysSelector, + modelElementsAnyModelLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; +import { ModelElement } from '@/types/models'; import { IncludedCompartmentPathways } from './IncludedCompartmentPathways.component'; +jest.mock('../../../../../../redux/hooks/useAppSelector', () => ({ + useAppSelector: jest.fn(), +})); +type SelectorFunction = (state: never) => ModelElement[] | boolean; + const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); @@ -24,21 +35,29 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St ); }; -const CHECKBOX_ELEMENT_NAME = compartmentPathwaysDetailsFixture[0].name; +const CHECKBOX_ELEMENT_NAME = modelElementFixture.name; describe('IncludedCompartmentPathways - component', () => { it('should display compartment / pathways checkboxes when fetching data is successful', async () => { - renderComponent({ - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, + const mockUseAppSelector = useAppSelector as jest.Mock; + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [ + compartmentPathwaysSelector, + [ + { + ...modelElementFixture, + }, + ], + ], + [modelElementsAnyModelLoadingSelector, false], + ]); + + return selectorMap.get(selector) ?? false; }); + renderComponent({}); + expect(screen.queryByTestId('checkbox-filter')).not.toBeVisible(); const navigationButton = screen.getByTestId('accordion-item-button'); @@ -55,36 +74,19 @@ describe('IncludedCompartmentPathways - component', () => { expect(screen.getByLabelText(CHECKBOX_ELEMENT_NAME)).toBeInTheDocument(); }); }); - it('should not display compartment / pathways checkboxes when fetching data fails', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'failed', - error: { - message: '', - name: '', - }, - }, - }); - expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument(); - const navigationButton = screen.getByTestId('accordion-item-button'); - act(() => { - navigationButton.click(); - }); - expect(screen.queryByTestId('checkbox-filter')).not.toBeInTheDocument(); - }); it('should not display compartment / pathways checkboxes when fetched data is empty', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, + const mockUseAppSelector = useAppSelector as jest.Mock; + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [compartmentPathwaysSelector, []], + [modelElementsAnyModelLoadingSelector, false], + ]); + + return selectorMap.get(selector) ?? false; }); + + renderComponent({}); expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { @@ -95,16 +97,17 @@ describe('IncludedCompartmentPathways - component', () => { }); it('should display loading message when fetching data is pending', async () => { - renderComponent({ - compartmentPathways: { - data: [], - loading: 'pending', - error: { - message: '', - name: '', - }, - }, + const mockUseAppSelector = useAppSelector as jest.Mock; + mockUseAppSelector.mockImplementation(selector => { + const selectorMap = new Map<SelectorFunction, ModelElement[] | boolean>([ + [compartmentPathwaysSelector, []], + [modelElementsAnyModelLoadingSelector, true], + ]); + + return selectorMap.get(selector) ?? false; }); + + renderComponent({}); expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument(); const navigationButton = screen.getByTestId('accordion-item-button'); act(() => { diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx index 4ef2cee4..509a8636 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx @@ -1,10 +1,10 @@ import { ZERO } from '@/constants/common'; -import { - compartmentPathwaysDataSelector, - loadingCompartmentPathwaysSelector, -} from '@/redux/compartmentPathways/compartmentPathways.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { useContext } from 'react'; +import { + compartmentPathwaysSelector, + modelElementsAnyModelLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; import { CheckboxFilter } from '../../CheckboxFilter'; import { CollapsibleSection } from '../../CollapsibleSection'; import { ExportContext } from '../ExportCompound.context'; @@ -13,9 +13,8 @@ import { getCompartmentPathwaysCheckboxElements } from '../utils/getCompartmentP export const IncludedCompartmentPathways = (): React.ReactNode => { const { setIncludedCompartmentPathways, data } = useContext(ExportContext); const currentIncludedCompartmentPathways = data.includedCompartmentPathways; - const loadingCompartmentPathways = useAppSelector(loadingCompartmentPathwaysSelector); - const isPending = loadingCompartmentPathways === 'pending'; - const compartmentPathways = useAppSelector(compartmentPathwaysDataSelector); + const compartmentPathways = useAppSelector(compartmentPathwaysSelector); + const isPending = useAppSelector(modelElementsAnyModelLoadingSelector); const checkboxElements = getCompartmentPathwaysCheckboxElements('included', compartmentPathways); return ( diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.test.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.test.ts index 6254cd6b..893b0367 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.test.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.test.ts @@ -1,10 +1,10 @@ /* eslint-disable no-magic-numbers */ -import { CompartmentPathwayDetails } from '@/types/models'; +import { ModelElement } from '@/types/models'; import { getCompartmentPathwaysCheckboxElements } from './getCompartmentPathwaysCheckboxElements'; describe('getCompartmentPathwaysCheckboxElements', () => { it('should return an empty array when given an empty items array', () => { - const items: CompartmentPathwayDetails[] = []; + const items: ModelElement[] = []; const result = getCompartmentPathwaysCheckboxElements('include', items); expect(result).toEqual([]); }); @@ -15,7 +15,7 @@ describe('getCompartmentPathwaysCheckboxElements', () => { { id: 2, name: 'Compartment B' }, { id: 3, name: 'Compartment A' }, { id: 4, name: 'Compartment C' }, - ] as CompartmentPathwayDetails[]; + ] as ModelElement[]; const result = getCompartmentPathwaysCheckboxElements('test', items); @@ -32,7 +32,7 @@ describe('getCompartmentPathwaysCheckboxElements', () => { { id: 3, name: 'Compartment B' }, { id: 4, name: 'Compartment A' }, { id: 5, name: 'Compartment D' }, - ] as CompartmentPathwayDetails[]; + ] as ModelElement[]; const result = getCompartmentPathwaysCheckboxElements('prefix', items); diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.ts index 9a807f04..86147944 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.ts +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/utils/getCompartmentPathwaysCheckboxElements.ts @@ -1,5 +1,5 @@ /* eslint-disable no-magic-numbers */ -import { CompartmentPathwayDetails } from '@/types/models'; +import { ModelElement } from '@/types/models'; type AddedNames = { [key: string]: number }; @@ -9,11 +9,11 @@ type CheckboxElements = CheckboxElement[]; export const getCompartmentPathwaysCheckboxElements = ( prefix: string, - items: CompartmentPathwayDetails[], + items: ModelElement[], ): CheckboxElements => { const addedNames: AddedNames = {}; - const setNameToIdIfUndefined = (item: CompartmentPathwayDetails): void => { + const setNameToIdIfUndefined = (item: ModelElement): void => { if (addedNames[item.name] === undefined) { addedNames[item.name] = item.id; } @@ -31,7 +31,5 @@ export const getCompartmentPathwaysCheckboxElements = ( return -1; }; - const elements = Object.entries(addedNames).map(parseIdAndLabel).sort(sortByLabel); - - return elements; + return Object.entries(addedNames).map(parseIdAndLabel).sort(sortByLabel); }; diff --git a/src/components/Map/Drawer/ExportDrawer/ExportDrawer.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportDrawer.component.tsx index 64d3ddfd..6847bd99 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportDrawer.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportDrawer.component.tsx @@ -1,9 +1,5 @@ -import { getCompartmentPathways } from '@/redux/compartmentPathways/compartmentPathways.thunks'; -import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; -import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { modelsIdsSelector } from '@/redux/models/models.selectors'; import { DrawerHeading } from '@/shared/DrawerHeading'; -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { CurrentView } from './CurrentView'; import { Elements } from './Elements'; import { Graphics } from './Graphics'; @@ -13,18 +9,11 @@ import { TAB_NAMES } from './TabNavigator/TabNavigator.constants'; import { TabNames } from './TabNavigator/TabNavigator.types'; export const ExportDrawer = (): React.ReactNode => { - const modelsIds = useAppSelector(modelsIdsSelector); - const dispatch = useAppDispatch(); const [activeTab, setActiveTab] = useState<TabNames>(TAB_NAMES.ELEMENTS); const handleTabChange = (tabName: TabNames): void => { setActiveTab(tabName); }; - - useEffect(() => { - dispatch(getCompartmentPathways(modelsIds)); - }, [dispatch, modelsIds]); - return ( <div data-testid="export-drawer" className="h-full max-h-full"> <DrawerHeading title="Export" /> diff --git a/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx index 2fddcfed..88243df1 100644 --- a/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx @@ -1,5 +1,4 @@ /* eslint-disable no-magic-numbers */ -import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways'; import { configurationFixture } from '@/models/fixtures/configurationFixture'; import { modelsFixture } from '@/models/fixtures/modelsFixture'; import { statisticsFixture } from '@/models/fixtures/statisticsFixture'; @@ -14,6 +13,9 @@ import { render, screen } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; import { act } from 'react-dom/test-utils'; import { MockStoreEnhanced } from 'redux-mock-store'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { COMPARTMENT_SBO_TERM } from '@/components/Map/MapViewer/MapViewer.constants'; import { NETWORK_COLUMNS } from '../ExportCompound/ExportCompound.constant'; import { Network } from './Network.component'; @@ -70,14 +72,6 @@ describe('Network - component', () => { name: '', }, }, - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, }); const annotations = screen.getByText('Select annotations'); const includedCompartmentPathways = screen.getByText('Select included compartment / pathways'); @@ -89,12 +83,13 @@ describe('Network - component', () => { expect(excludedCompartmentPathways).toBeVisible(); expect(downloadButton).toBeVisible(); }); + it('should handle download button click and dispatch proper data', async () => { + const FIRST_COMPARMENT_PATHWAY_NAME = 'test1'; + const FIRST_COMPARMENT_PATHWAY_ID = 1; + const SECOND_COMPARMENT_PATHWAY_NAME = 'test2'; + const SECOND_COMPARMENT_PATHWAY_ID = 2; mockedAxiosClient.onPost(apiPath.downloadNetworkCsv()).reply(HttpStatusCode.Ok, 'test'); - const FIRST_COMPARMENT_PATHWAY_NAME = compartmentPathwaysDetailsFixture[0].name; - const FIRST_COMPARMENT_PATHWAY_ID = compartmentPathwaysDetailsFixture[0].id; - const SECOND_COMPARMENT_PATHWAY_NAME = compartmentPathwaysDetailsFixture[1].name; - const SECOND_COMPARMENT_PATHWAY_ID = compartmentPathwaysDetailsFixture[1].id; const { store } = renderComponent({ ...INITIAL_STORE_STATE_MOCK, configuration: { @@ -132,14 +127,6 @@ describe('Network - component', () => { name: '', }, }, - compartmentPathways: { - data: compartmentPathwaysDetailsFixture, - loading: 'succeeded', - error: { - message: '', - name: '', - }, - }, models: { data: modelsFixture, loading: 'succeeded', @@ -148,6 +135,26 @@ describe('Network - component', () => { name: '', }, }, + modelElements: { + 0: { + data: [ + { + ...modelElementFixture, + id: FIRST_COMPARMENT_PATHWAY_ID, + name: FIRST_COMPARMENT_PATHWAY_NAME, + sboTerm: COMPARTMENT_SBO_TERM, + }, + { + ...modelElementFixture, + id: SECOND_COMPARMENT_PATHWAY_ID, + name: SECOND_COMPARMENT_PATHWAY_NAME, + sboTerm: COMPARTMENT_SBO_TERM, + }, + ], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, }); const annotations = screen.getByText('Select annotations'); diff --git a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx index 1a76eeea..283dd29f 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx @@ -71,6 +71,13 @@ describe('ReactionDrawer - component', () => { loading: 'succeeded', error: { message: '', name: '' }, }, + newReactions: { + 0: { + data: [reaction], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, drawer: { ...DRAWER_INITIAL_STATE, reactionDrawerState: { diff --git a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx index 00d2128e..633c55a8 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx @@ -1,6 +1,4 @@ -import { currentDrawerReactionSelector } from '@/redux/reactions/reactions.selector'; import { DrawerHeading } from '@/shared/DrawerHeading'; -import { useSelector } from 'react-redux'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { currentDrawerReactionCommentsSelector } from '@/redux/bioEntity/bioEntity.selectors'; import { CommentItem } from '@/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component'; @@ -8,11 +6,11 @@ import { ZERO } from '@/constants/common'; import ReactionTypeEnum from '@/utils/reaction/ReactionTypeEnum'; import React from 'react'; import { AnnotationItemList } from '@/components/Map/Drawer/BioEntityDrawer/AnnotationItem/AnnotationItemList.component'; +import { currentDrawerNewReactionSelector } from '@/redux/newReactions/newReactions.selectors'; import { ConnectedBioEntitiesList } from './ConnectedBioEntitiesList'; export const ReactionDrawer = (): React.ReactNode => { - const reaction = useSelector(currentDrawerReactionSelector); - + const reaction = useAppSelector(currentDrawerNewReactionSelector); const commentsData = useAppSelector(currentDrawerReactionCommentsSelector); if (!reaction) { diff --git a/src/components/Map/MapLoader/MapLoader.component.test.tsx b/src/components/Map/MapLoader/MapLoader.component.test.tsx index 7f8fb00b..ec4c2e1b 100644 --- a/src/components/Map/MapLoader/MapLoader.component.test.tsx +++ b/src/components/Map/MapLoader/MapLoader.component.test.tsx @@ -7,7 +7,7 @@ import { import { StoreType } from '@/redux/store'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { newReactionsLoadingSelector } from '@/redux/newReactions/newReactions.selectors'; -import { modelElementsLoadingSelector } from '@/redux/modelElements/modelElements.selector'; +import { modelElementsCurrentModelLoadingSelector } from '@/redux/modelElements/modelElements.selector'; import { isDrawerOpenSelector } from '@/redux/drawer/drawer.selectors'; import { arrowTypesLoadingSelector, @@ -15,6 +15,7 @@ import { lineTypesLoadingSelector, } from '@/redux/shapes/shapes.selectors'; import { layersLoadingSelector } from '@/redux/layers/layers.selectors'; +import { modelLoadingSelector } from '@/redux/selectors'; import { MapLoader } from './MapLoader.component'; jest.mock('../../../redux/hooks/useAppSelector', () => ({ @@ -48,7 +49,7 @@ describe('MapLoader', () => { mockUseAppSelector.mockImplementation(selector => { const selectorMap = new Map<SelectorFunction, string | boolean>([ [newReactionsLoadingSelector, 'succeeded'], - [modelElementsLoadingSelector, 'succeeded'], + [modelElementsCurrentModelLoadingSelector, 'succeeded'], [bioShapesLoadingSelector, 'succeeded'], [lineTypesLoadingSelector, 'succeeded'], [arrowTypesLoadingSelector, 'succeeded'], @@ -65,13 +66,8 @@ describe('MapLoader', () => { it('should render the LoadingIndicator when data is loading', () => { mockUseAppSelector.mockImplementation(selector => { - const selectorMap = new Map<SelectorFunction, string | boolean>([ - [newReactionsLoadingSelector, 'pending'], - [modelElementsLoadingSelector, 'succeeded'], - [bioShapesLoadingSelector, 'succeeded'], - [lineTypesLoadingSelector, 'succeeded'], - [arrowTypesLoadingSelector, 'succeeded'], - [layersLoadingSelector, 'succeeded'], + const selectorMap = new Map<SelectorFunction, boolean>([ + [modelLoadingSelector, true], [isDrawerOpenSelector, false], ]); diff --git a/src/components/Map/MapLoader/MapLoader.component.tsx b/src/components/Map/MapLoader/MapLoader.component.tsx index a521a7f5..1e3b4e05 100644 --- a/src/components/Map/MapLoader/MapLoader.component.tsx +++ b/src/components/Map/MapLoader/MapLoader.component.tsx @@ -1,48 +1,16 @@ import { LoadingIndicator } from '@/shared/LoadingIndicator'; -import { useMemo } from 'react'; -import { newReactionsLoadingSelector } from '@/redux/newReactions/newReactions.selectors'; -import { modelElementsLoadingSelector } from '@/redux/modelElements/modelElements.selector'; -import { - arrowTypesLoadingSelector, - bioShapesLoadingSelector, - lineTypesLoadingSelector, -} from '@/redux/shapes/shapes.selectors'; -import { layersLoadingSelector } from '@/redux/layers/layers.selectors'; import './MapLoader.styles.css'; import { isDrawerOpenSelector } from '@/redux/drawer/drawer.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { modelLoadingSelector } from '@/redux/selectors'; export const MapLoader = (): JSX.Element => { - const reactionsFetching = useAppSelector(newReactionsLoadingSelector); - const modelElementsFetching = useAppSelector(modelElementsLoadingSelector); - const bioShapesFetching = useAppSelector(bioShapesLoadingSelector); - const lineTypesFetching = useAppSelector(lineTypesLoadingSelector); - const arrowTypesFetching = useAppSelector(arrowTypesLoadingSelector); - const layersLoading = useAppSelector(layersLoadingSelector); - + const isModelLoading = useAppSelector(modelLoadingSelector); const isDrawerOpen = useAppSelector(isDrawerOpenSelector); - const showLoader = useMemo(() => { - return [ - reactionsFetching, - modelElementsFetching, - bioShapesFetching, - lineTypesFetching, - arrowTypesFetching, - layersLoading, - ].includes('pending'); - }, [ - reactionsFetching, - modelElementsFetching, - bioShapesFetching, - lineTypesFetching, - arrowTypesFetching, - layersLoading, - ]); - return ( <div className={`map-loader transition-all duration-500 ${isDrawerOpen ? 'move-right' : ''}`}> - {showLoader && <LoadingIndicator width={48} height={48} />} + {isModelLoading && <LoadingIndicator width={48} height={48} />} </div> ); }; diff --git a/src/components/Map/MapViewer/MapViewer.constants.ts b/src/components/Map/MapViewer/MapViewer.constants.ts index 2d047265..e8492ee3 100644 --- a/src/components/Map/MapViewer/MapViewer.constants.ts +++ b/src/components/Map/MapViewer/MapViewer.constants.ts @@ -2,10 +2,20 @@ import { Color, ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models'; export const MAP_VIEWER_ROLE = 'map-viewer'; -export const VECTOR_MAP_LAYER_TYPE = 'vectorMapLayer'; +export const LAYER_TYPE = { + PROCESS_LAYER: 'PROCESS_LAYER', + COMMENTS_LAYER: 'COMMENTS_LAYER', + ADDITIONAL_LAYER: 'ADDITIONAL_LAYER', + MAP_CARD_LAYER: 'MAP_CARD_LAYER', + OVERLAYS_LAYER: 'OVERLAYS_LAYER', + PINS_LAYER: 'PINS_LAYER', + REACTIONS_LAYER: 'REACTIONS_LAYER', +} as const; export const COMPLEX_SBO_TERMS = ['SBO:0000253', 'SBO:0000297', 'SBO:0000289']; +export const COMPARTMENT_SBO_TERM = 'SBO:0000290'; + export const TEXT_CUTOFF_SCALE = 0.34; export const OUTLINE_CUTOFF_SCALE = 0.18; export const COMPLEX_CONTENTS_CUTOFF_SCALE = 0.215; diff --git a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts index 6eb9e2cb..7ac3b73b 100644 --- a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts @@ -11,6 +11,7 @@ import { } from '@/redux/comment/comment.selectors'; import { getCommentsFeatures } from '@/components/Map/MapViewer/utils/config/commentsLayer/getCommentsFeatures'; import { useMemo } from 'react'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; export const useOlMapCommentsLayer = (): VectorLayer<VectorSource<Feature<Geometry>>> => { const pointToProjection = usePointToProjection(); @@ -33,13 +34,11 @@ export const useOlMapCommentsLayer = (): VectorLayer<VectorSource<Feature<Geomet }); }, [elementsFeatures]); - const pinsLayer = useMemo( - () => - new VectorLayer({ - source: vectorSource, - }), - [vectorSource], - ); - - return pinsLayer; + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + }); + vectorLayer.set('type', LAYER_TYPE.COMMENTS_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts index e1fb741b..69cec807 100644 --- a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts +++ b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts @@ -8,6 +8,7 @@ import { mapDataSizeSelector } from '@/redux/map/map.selectors'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; import Style from 'ol/style/Style'; import { Fill } from 'ol/style'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; export const useOlMapCardLayer = (): VectorLayer<VectorSource<Feature<Polygon>>> => { const mapSize = useSelector(mapDataSizeSelector); @@ -35,16 +36,16 @@ export const useOlMapCardLayer = (): VectorLayer<VectorSource<Feature<Polygon>>> }); }, [rectangleFeature]); - return useMemo( - () => - new VectorLayer({ - source: vectorSource, - style: new Style({ - fill: new Fill({ - color: '#fff', - }), + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + style: new Style({ + fill: new Fill({ + color: '#fff', }), }), - [vectorSource], - ); + }); + vectorLayer.set('type', LAYER_TYPE.MAP_CARD_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts index 788b89f2..7a0643c5 100644 --- a/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts @@ -10,6 +10,9 @@ import { OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK, } from '@/redux/overlayBioEntity/overlayBioEntity.mock'; import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock'; +import { MAIN_MAP_ID } from '@/constants/mocks'; +import { BIO_ENTITY_LINKING_TO_SUBMAP } from '@/redux/bioEntity/bioEntity.mock'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { useBioEntitiesWithSubmapsLinks } from './useBioEntitiesWithSubmapLinks'; const RESULT_SUBMAP_LINKS_DIFFERENT_VALUES = [ @@ -180,6 +183,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { overlaysId: PUBLIC_OVERLAYS_MOCK.map(o => o.idObject), }, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, + modelElements: { + [MAIN_MAP_ID]: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, map: mapStateWithCurrentlySelectedMainMapFixture, }); @@ -203,6 +213,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, }, + modelElements: { + 52: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -233,6 +250,7 @@ describe('useBioEntitiesWithSubmapsLinks', () => { color: null, }); }); + it('should modify height, coordinates and return in sorted order to create submap link from several submap link rectangles', () => { const { Wrapper } = getReduxStoreWithActionsListener({ overlayBioEntity: { @@ -243,6 +261,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, }, + modelElements: { + 52: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -260,6 +285,7 @@ describe('useBioEntitiesWithSubmapsLinks', () => { expect(current).toStrictEqual(RESULT_SUBMAP_LINKS_DIFFERENT_VALUES); }); }); + describe('submap links with the same ID and overlayID and the same values or colors', () => { it('should create submap link with Infinity value, for displaying black border of submap link', () => { const { Wrapper } = getReduxStoreWithActionsListener({ @@ -271,6 +297,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, }, + modelElements: { + 52: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -301,6 +334,7 @@ describe('useBioEntitiesWithSubmapsLinks', () => { color: null, }); }); + it('should modify height, coordinates and return in sorted order to create submap link from several submap link rectangles', () => { const { Wrapper } = getReduxStoreWithActionsListener({ overlayBioEntity: { @@ -311,6 +345,13 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, }, + modelElements: { + 52: { + data: [BIO_ENTITY_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + } as ModelElementsState, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer.ts index 9d3489b4..c24250e2 100644 --- a/src/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer.ts +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/useOlMapOverlaysLayer.ts @@ -3,6 +3,7 @@ import VectorLayer from 'ol/layer/Vector'; import VectorSource from 'ol/source/Vector'; import { Feature } from 'ol'; import { useMemo } from 'react'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { useOverlayFeatures } from './useOverlayFeatures'; /** @@ -28,13 +29,11 @@ export const useOlMapOverlaysLayer = (): VectorLayer<VectorSource<Feature<Simple }); }, [overlaysFeatures]); - const overlaysLayer = useMemo( - () => - new VectorLayer({ - source: vectorSource, - }), - [vectorSource], - ); - - return overlaysLayer; + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + }); + vectorLayer.set('type', LAYER_TYPE.OVERLAYS_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts index 641b537d..c2e6d908 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts @@ -13,6 +13,7 @@ import VectorLayer from 'ol/layer/Vector'; import VectorSource from 'ol/source/Vector'; import { useCallback, useEffect, useMemo } from 'react'; import { useSelector } from 'react-redux'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { getBioEntitiesFeatures } from './getBioEntitiesFeatures'; import { getMarkersFeatures } from './getMarkersFeatures'; import { getMultipinsBioEntities } from './getMultipinsBioEntities'; @@ -74,11 +75,11 @@ export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>> vectorSource.addFeatures(elementsFeatures); }, [elementsFeatures, vectorSource]); - return useMemo( - () => - new VectorLayer({ - source: vectorSource, - }), - [vectorSource], - ); + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + }); + vectorLayer.set('type', LAYER_TYPE.PINS_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts index 87c6d666..b4c0b876 100644 --- a/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts @@ -13,6 +13,7 @@ import CompartmentPathway from '@/components/Map/MapViewer/utils/shapes/elements import CompartmentSquare from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare'; import CompartmentCircle from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle'; import MapElement from '@/components/Map/MapViewer/utils/shapes/elements/MapElement'; +import { COMPARTMENT_SBO_TERM } from '@/components/Map/MapViewer/MapViewer.constants'; export default function processModelElements( modelElements: Array<ModelElement>, @@ -49,7 +50,7 @@ export default function processModelElements( return; } - if (element.sboTerm === 'SBO:0000290') { + if (element.sboTerm === COMPARTMENT_SBO_TERM) { const compartmentProps = { id: element.id, sboTerm: element.sboTerm, diff --git a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts index 2837c80b..2811ec30 100644 --- a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts @@ -13,9 +13,9 @@ import { import { MapInstance } from '@/types/map'; import { modelElementsForCurrentModelSelector, - modelElementsLoadingSelector, + modelElementsCurrentModelLoadingSelector, } from '@/redux/modelElements/modelElements.selector'; -import { currentModelIdSelector } from '@/redux/models/models.selectors'; +import { currentModelIdSelector, modelsIdsSelector } from '@/redux/models/models.selectors'; import { getModelElementsForModel } from '@/redux/modelElements/modelElements.thunks'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { @@ -23,7 +23,6 @@ import { newReactionsLoadingSelector, } from '@/redux/newReactions/newReactions.selectors'; import { getNewReactionsForModel } from '@/redux/newReactions/newReactions.thunks'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { getOverlayOrderSelector, overlayBioEntitiesForCurrentModelSelector, @@ -48,6 +47,8 @@ import CompartmentCircle from '@/components/Map/MapViewer/utils/shapes/elements/ import CompartmentSquare from '@/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare'; import MapElement from '@/components/Map/MapViewer/utils/shapes/elements/MapElement'; import areOverlayOrdersNotEqual from '@/components/Map/MapViewer/utils/shapes/overlay/areOverlayOrdersNotEqual'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { modelLoadedSuccessfullySelector, modelLoadingSelector } from '@/redux/selectors'; export const useOlMapProcessLayer = ({ mapInstance, @@ -57,6 +58,7 @@ export const useOlMapProcessLayer = ({ const dispatch = useAppDispatch(); const [overlaysOrderState, setOverlaysOrderState] = useState<Array<OverlayOrder>>([]); + const [allModelElementsLoaded, setAllModelElementsLoaded] = useState<boolean>(false); const currentModelId = useSelector(currentModelIdSelector); const shapes = useSelector(bioShapesSelector); const mapSize = useSelector(mapDataSizeSelector); @@ -71,13 +73,38 @@ export const useOlMapProcessLayer = ({ const bioEntities = useAppSelector(overlayBioEntitiesForCurrentModelSelector); const reactionsForCurrentModel = useAppSelector(newReactionsForCurrentModelSelector); - const modelElementsLoading = useAppSelector(modelElementsLoadingSelector); + const modelElementsLoading = useAppSelector(modelElementsCurrentModelLoadingSelector); const reactionsLoading = useAppSelector(newReactionsLoadingSelector); const modelElementsForCurrentModel = useAppSelector(modelElementsForCurrentModelSelector); const debouncedBioEntities = useDebouncedValue(bioEntities, 1000); const { getOverlayBioEntityColorByAvailableProperties } = useGetOverlayColor(); + const modelsIds = useAppSelector(modelsIdsSelector); + const isModelLoading = useAppSelector(modelLoadingSelector); + const modelLoadedSuccessfully = useAppSelector(modelLoadedSuccessfullySelector); + useEffect(() => { + const fetchModelElements = async (): Promise<void> => { + if (!isModelLoading && modelLoadedSuccessfully && !allModelElementsLoaded) { + const modelsIdsToFetch = modelsIds.filter(id => id !== currentModelId); + const modelElementsPromises = modelsIdsToFetch.map(modelId => { + return dispatch(getModelElementsForModel(modelId)); + }); + await Promise.all(modelElementsPromises); + setAllModelElementsLoaded(true); + } + }; + + fetchModelElements(); + }, [ + modelLoadedSuccessfully, + isModelLoading, + modelsIds, + currentModelId, + dispatch, + allModelElementsLoaded, + ]); + const pointToProjection = usePointToProjection(); const vectorSource = useMemo(() => new VectorSource(), []); @@ -251,7 +278,7 @@ export const useOlMapProcessLayer = ({ updateWhileAnimating: true, updateWhileInteracting: true, }); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); return vectorLayer; }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts index cf4416f3..bfb2668e 100644 --- a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts @@ -16,6 +16,7 @@ import { useSelector } from 'react-redux'; import { createOverlayLineFeature } from '@/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayLineFeature'; import { Geometry } from 'ol/geom'; import { getReactionLineSegments } from '@/components/Map/MapViewer/utils/config/reactionsLayer/getReactionLineSegments'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { getLineFeature } from './getLineFeature'; const getReactionsLines = (reactions: NewReaction[]): LinePoint[] => @@ -60,15 +61,15 @@ export const useOlMapReactionsLayer = (): VectorLayer<VectorSource<Feature<Geome vectorSource.addFeatures(markerLinesFeatures); }, [reactionsLinesFeatures, markerLinesFeatures, vectorSource]); - return useMemo( - () => - new VectorLayer({ - source: vectorSource, - style: new Style({ - fill: new Fill({ color: LINE_COLOR }), - stroke: new Stroke({ color: LINE_COLOR, width: LINE_WIDTH }), - }), + return useMemo(() => { + const vectorLayer = new VectorLayer({ + source: vectorSource, + style: new Style({ + fill: new Fill({ color: LINE_COLOR }), + stroke: new Stroke({ color: LINE_COLOR, width: LINE_WIDTH }), }), - [vectorSource], - ); + }); + vectorLayer.set('type', LAYER_TYPE.REACTIONS_LAYER); + return vectorLayer; + }, [vectorSource]); }; diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts index d809149e..ef42a0aa 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.test.ts @@ -2,14 +2,9 @@ import { openReactionDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; -import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; -import { apiPath } from '@/redux/apiPath'; -import { HttpStatusCode } from 'axios'; -import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; -const mockedAxiosClient = mockNetworkNewAPIResponse(); jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); const eventBusDispatchEventSpy = jest.spyOn(PluginsEventBus, 'dispatchEvent'); @@ -24,7 +19,7 @@ describe('clickHandleReaction', () => { dispatch = jest.fn(); }); - it('dispatches getMultiBioEntityByIds, selectTab, and openBioEntityDrawerById, then triggers PluginsEventBus and searchFitBounds when hasFitBounds is true', async () => { + it('dispatches selectTab and openBioEntityDrawerById, then triggers PluginsEventBus and searchFitBounds when hasFitBounds is true', async () => { dispatch = jest.fn(() => { return { unwrap: jest.fn().mockResolvedValue([]), @@ -36,19 +31,6 @@ describe('clickHandleReaction', () => { reactionId = newReactionFixture.id; modelId = newReactionFixture.model; - mockedAxiosClient - .onGet(apiPath.getNewReaction(modelId, reactionId)) - .reply(HttpStatusCode.Ok, bioEntityFixture); - - [ - ...newReactionFixture.products, - ...newReactionFixture.reactants, - ...newReactionFixture.modifiers, - ].forEach(element => { - mockedAxiosClient - .onGet(apiPath.getElementById(element.element, modelId)) - .reply(HttpStatusCode.Ok, bioEntityFixture); - }); clickHandleReaction(dispatch, hasFitBounds)( [], [{ ...newReactionFixture, id: reactionId }], diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts index edc575be..34e57854 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.test.ts @@ -2,7 +2,7 @@ import { Feature } from 'ol'; import VectorLayer from 'ol/layer/Vector'; import Map from 'ol/Map'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { FEATURE_TYPE } from '@/constants/features'; import getFeatureAtCoordinate from '@/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate'; import SimpleGeometry from 'ol/geom/SimpleGeometry'; @@ -11,7 +11,7 @@ describe('getFeatureAtCoordinate', () => { let mapInstance: Map; const coordinate = [100, 50]; const vectorLayer = new VectorLayer({}); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); beforeEach(() => { const dummyElement = document.createElement('div'); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts index 5c1fc99e..88417316 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate.ts @@ -1,9 +1,9 @@ /* eslint-disable no-magic-numbers */ -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { MapInstance } from '@/types/map'; import { Coordinate } from 'ol/coordinate'; import { FeatureLike } from 'ol/Feature'; import { FEATURE_TYPE } from '@/constants/features'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; function isFeatureFilledCompartment(feature: FeatureLike): boolean { return feature.get('type') === FEATURE_TYPE.COMPARTMENT && feature.get('filled'); @@ -37,7 +37,7 @@ export default function getFeatureAtCoordinate({ const featureZIndex = feature.get('zIndex'); if ( layer && - layer.get('type') === VECTOR_MAP_LAYER_TYPE && + layer.get('type') !== LAYER_TYPE.ADDITIONAL_LAYER && (isFeatureFilledCompartment(feature) || isFeatureNotCompartment(feature)) && (featureZIndex === undefined || featureZIndex >= 0) ) { diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts index f1b980a9..ad75ed8f 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick.ts @@ -9,7 +9,6 @@ import { AppDispatch } from '@/redux/store'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { FeatureLike } from 'ol/Feature'; import { Comment } from '@/types/models'; -import { getCommentElement, getCommentReaction } from '@/redux/comment/thunks/getComments'; interface HandleFeaturesClickResult { shouldBlockCoordSearch: boolean; @@ -23,22 +22,18 @@ export const handleFeaturesClick = ( const pinFeatures = features.filter(feature => PIN_ICON_ANY.includes(feature.get('type'))); const surfaceFeatures = features.filter(feature => SURFACE_ANY.includes(feature.get('type'))); const shouldBlockCoordSearch = pinFeatures.length > SIZE_OF_EMPTY_ARRAY; - pinFeatures.forEach(pin => { const pinId = pin.get('id') as string | number; PluginsEventBus.dispatchEvent('onPinIconClick', { id: pinId }); - if (pin.get('type') === FEATURE_TYPE.PIN_ICON_BIOENTITY) { dispatch(openBioEntityDrawerById(pinId)); } else if (pin.get('type') === FEATURE_TYPE.PIN_ICON_COMMENT) { const filteredComments = comments.filter(comment => comment.id === pinId); if (filteredComments.length > ZERO) { - const { elementId, modelId, type } = filteredComments[ZERO]; + const { elementId, type } = filteredComments[ZERO]; if (type === 'ALIAS') { - dispatch(getCommentElement({ elementId: Number(elementId), modelId })); dispatch(openBioEntityDrawerById(Number(elementId))); } else if (type === 'REACTION') { - dispatch(getCommentReaction({ elementId: Number(elementId), modelId })); dispatch(openReactionDrawerById(Number(elementId))); } else if (type === 'POINT') { dispatch(openCommentDrawerById(Number(pinId))); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts index df86f0a2..17b253ef 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.test.ts @@ -5,6 +5,7 @@ import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; import { Feature } from 'ol'; import { FEATURE_TYPE } from '@/constants/features'; +import { ModelElement } from '@/types/models'; jest.mock('../../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); const eventBusDispatchEventSpy = jest.spyOn(PluginsEventBus, 'dispatchEvent'); @@ -21,13 +22,13 @@ describe('leftClickHandleAlias', () => { }); it('dispatches getMultiBioEntityByIds, selectTab, and openBioEntityDrawerById, then triggers PluginsEventBus and searchFitBounds when hasFitBounds is true', async () => { - const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }]; + const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }] as Array<ModelElement>; dispatch = jest.fn(() => ({ unwrap: jest.fn().mockResolvedValue(mockBioEntities), })); - await leftClickHandleAlias(dispatch, hasFitBounds)(feature, modelId); - expect(dispatch).toHaveBeenCalledTimes(3); + await leftClickHandleAlias(dispatch, hasFitBounds)(mockBioEntities, feature, modelId); + expect(dispatch).toHaveBeenCalledTimes(4); expect(dispatch).toHaveBeenCalledWith(selectTab('1')); expect(dispatch).toHaveBeenCalledWith(openBioEntityDrawerById(1)); @@ -47,12 +48,12 @@ describe('leftClickHandleAlias', () => { }); it('does not call searchFitBounds when hasFitBounds is false', async () => { - const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }]; + const mockBioEntities = [{ id: 1, name: 'BioEntity 1' }] as Array<ModelElement>; dispatch.mockImplementation(() => ({ unwrap: jest.fn().mockResolvedValue(mockBioEntities), })); - await leftClickHandleAlias(dispatch, false)(feature, modelId); + await leftClickHandleAlias(dispatch, false)(mockBioEntities, feature, modelId); expect(searchFitBounds).not.toHaveBeenCalled(); }); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts index 06a4e4d1..4abbb3e1 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts @@ -1,32 +1,40 @@ import { openBioEntityDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; import { AppDispatch } from '@/redux/store'; -import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEntity'; import { FeatureLike } from 'ol/Feature'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; import { FEATURE_TYPE } from '@/constants/features'; +import { ModelElement } from '@/types/models'; +import { setMultipleBioEntityContents } from '@/redux/bioEntity/bioEntity.slice'; +import { addNumbersToEntityNumberData } from '@/redux/entityNumber/entityNumber.slice'; /* prettier-ignore */ export const leftClickHandleAlias = (dispatch: AppDispatch, hasFitBounds = false) => - async (feature: FeatureLike, modelId: number): Promise<void> => { + async (modelElements: Array<ModelElement>, feature: FeatureLike, modelId: number): Promise<void> => { const id = feature.get('id'); - const bioEntities = await dispatch( - getMultiBioEntityByIds({ - elementsToFetch: [{ elementId: id, type: FEATURE_TYPE.ALIAS, modelId, addNumbersToEntityNumber: true }], - }), - ).unwrap(); + + const modelElement = modelElements.find(element => + element.id === id + ); + if(!modelElement) { + return; + } + dispatch(selectTab(`${id}`)); dispatch(openBioEntityDrawerById(id)); + dispatch(setMultipleBioEntityContents([modelElement])); + dispatch(addNumbersToEntityNumberData([modelElement.elementId])); + const searchValue = { id, modelId, type: FEATURE_TYPE.ALIAS }; PluginsEventBus.dispatchEvent('onSearch', { type: 'bioEntity', searchValues: [searchValue], - results: [ - bioEntities.map(bioEntity => { - return { perfect: true, bioEntity }; - }), + results: [[{ + perfect: true, + bioEntity: modelElement + }] ], }); PluginsEventBus.dispatchEvent('onBioEntityClick', searchValue); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts index deb19107..6cf59664 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts @@ -11,7 +11,7 @@ import SimpleGeometry from 'ol/geom/SimpleGeometry'; import { Feature } from 'ol'; import { FEATURE_TYPE } from '@/constants/features'; import VectorLayer from 'ol/layer/Vector'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import * as leftClickHandleAlias from './leftClickHandleAlias'; import * as clickHandleReaction from '../clickHandleReaction'; @@ -35,7 +35,7 @@ describe('onMapLeftClick', () => { const comments: Array<Comment> = []; let mapInstance: Map; const vectorLayer = new VectorLayer({}); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); const event = { coordinate: [100, 50], pixel: [200, 100] }; const mapSize = { width: 90, diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts index 0c01e4a2..c62b97bf 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts @@ -59,7 +59,7 @@ export const onMapLeftClick = const type = featureAtCoordinate.get('type'); const id = featureAtCoordinate.get('id'); if ([FEATURE_TYPE.ALIAS, FEATURE_TYPE.GLYPH, FEATURE_TYPE.COMPARTMENT].includes(type)) { - await leftClickHandleAlias(dispatch)(featureAtCoordinate, modelId); + await leftClickHandleAlias(dispatch)(modelElements, featureAtCoordinate, modelId); } else if (type === FEATURE_TYPE.REACTION) { clickHandleReaction(dispatch)(modelElements, reactions, id, modelId); } diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts index fa6a3f17..de2c8849 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.test.ts @@ -11,7 +11,7 @@ import { Feature } from 'ol'; import { FEATURE_TYPE } from '@/constants/features'; import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import * as rightClickHandleAlias from './rightClickHandleAlias'; import * as clickHandleReaction from '../clickHandleReaction'; @@ -47,7 +47,7 @@ describe('onMapRightClick', () => { vectorLayer = new VectorLayer({ source: vectorSource, }); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); jest.clearAllMocks(); }); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts index 0daefedd..68658424 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/onMapRightClick.ts @@ -13,7 +13,7 @@ import { openContextMenu } from '@/redux/contextMenu/contextMenu.slice'; import { ModelElement, NewReaction } from '@/types/models'; import { rightClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias'; import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; /* prettier-ignore */ export const onMapRightClick = @@ -29,7 +29,7 @@ export const onMapRightClick = let foundFeature: Feature | undefined; mapInstance.getAllLayers().forEach(layer => { if(layer.isVisible() && layer instanceof VectorLayer) { - if (layer.get('type') === VECTOR_MAP_LAYER_TYPE) { + if (layer.get('type') === LAYER_TYPE.PROCESS_LAYER) { const source = layer.getSource(); if (source instanceof VectorSource) { foundFeature = source.getClosestFeatureToCoordinate(coordinate, (feature) => { diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts index ed6acbf4..b9070811 100644 --- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts @@ -13,6 +13,7 @@ import Style from 'ol/style/Style'; import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types'; import { LAYER_ELEMENT_TYPES, + LAYER_TYPE, REACTION_ELEMENT_CUTOFF_SCALE, TRANSPARENT_COLOR, } from '@/components/Map/MapViewer/MapViewer.constants'; @@ -116,6 +117,7 @@ export default class Layer { updateWhileAnimating: true, updateWhileInteracting: true, }); + this.vectorLayer.set('type', LAYER_TYPE.ADDITIONAL_LAYER); this.vectorLayer.set('id', layerId); this.vectorLayer.set('imagesFeatures', imagesFeatures); diff --git a/src/models/bioEntitySchema.ts b/src/models/bioEntitySchema.ts index db8670b8..a52c3aff 100644 --- a/src/models/bioEntitySchema.ts +++ b/src/models/bioEntitySchema.ts @@ -51,7 +51,7 @@ export const bioEntitySchema = z.object({ initialAmount: z.number().nullable().optional(), initialConcentration: z.number().nullable().optional(), charge: z.number().nullable().optional(), - substanceUnits: z.string().nullable().optional(), + substanceUnits: z.boolean().nullable().optional(), onlySubstanceUnits: z.boolean().optional().nullable(), shape: z.string().nullable().optional(), modificationResidues: z.optional(z.array(modificationResiduesSchema)), diff --git a/src/models/compartmentPathwaySchema.ts b/src/models/compartmentPathwaySchema.ts deleted file mode 100644 index 1259fa87..00000000 --- a/src/models/compartmentPathwaySchema.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { z } from 'zod'; - -export const compartmentPathwaySchema = z.object({ - id: z.number(), -}); - -export const boundsSchema = z.object({ - height: z.number(), - width: z.number(), - x: z.number(), - y: z.number(), - z: z.number(), -}); - -export const otherSchema = z.object({ - modifications: z.array(z.unknown()), - structuralState: z.null(), - structures: z.object({}), -}); - -export const compartmentPathwayDetailsSchema = z.object({ - abbreviation: z.null(), - activity: z.null(), - boundaryCondition: z.null(), - bounds: boundsSchema, - compartmentId: z.number().nullable(), - complexId: z.null(), - constant: z.null(), - elementId: z.string(), - formerSymbols: z.array(z.unknown()), - formula: z.null(), - fullName: z.string().nullable(), - glyph: z.any(), - hierarchyVisibilityLevel: z.string().nullable(), - homomultimer: z.null(), - hypothetical: z.null(), - id: z.number().gt(-1), - initialAmount: z.null(), - initialConcentration: z.null(), - linkedSubmodel: z.null(), - modelId: z.number(), - name: z.string(), - notes: z.string(), - other: otherSchema, - references: z.array(z.unknown()), - symbol: z.null(), - synonyms: z.array(z.unknown()), - transparencyLevel: z.string(), - type: z.string(), -}); diff --git a/src/models/fixtures/compartmentPathways.ts b/src/models/fixtures/compartmentPathways.ts deleted file mode 100644 index c93b4dc0..00000000 --- a/src/models/fixtures/compartmentPathways.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ZOD_SEED } from '@/constants'; -// eslint-disable-next-line import/no-extraneous-dependencies -import { createFixture } from 'zod-fixture'; -import { z } from 'zod'; -import { - compartmentPathwayDetailsSchema, - compartmentPathwaySchema, -} from '../compartmentPathwaySchema'; - -export const compartmentPathwaysFixture = createFixture(z.array(compartmentPathwaySchema), { - seed: ZOD_SEED, - array: { min: 3, max: 3 }, -}); - -export const compartmentPathwaysOverLimitFixture = createFixture( - z.array(compartmentPathwaySchema), - { - seed: ZOD_SEED, - array: { min: 101, max: 101 }, - }, -); - -export const compartmentPathwaysDetailsFixture = createFixture( - z.array(compartmentPathwayDetailsSchema), - { - seed: ZOD_SEED, - array: { min: 3, max: 3 }, - }, -); diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index 9f81dab4..93d49308 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -19,9 +19,6 @@ const getPublicationsURLSearchParams = ( }; export const apiPath = { - getElementById: (elementId: number, modelId: number): string => - `projects/${PROJECT_ID}/models/${modelId}/bioEntities/elements/${elementId}`, - getBioEntityContentsStringWithQuery: ({ searchQuery, isPerfectMatch, @@ -93,11 +90,6 @@ export const apiPath = { createOverlayFile: (): string => `files/`, uploadOverlayFileContent: (fileId: number): string => `files/${fileId}:uploadContent`, getStatisticsById: (projectId: string): string => `projects/${projectId}/statistics/`, - getCompartmentPathwaysIds: (objectId: number): string => - `projects/${PROJECT_ID}/models/${objectId}/bioEntities/elements/?columns=id&type=Compartment,Pathway`, - getCompartmentPathwayDetails: (ids: number[]): string => - `projects/${PROJECT_ID}/models/*/bioEntities/elements/?id=${ids.join(',')}`, - sendCompartmentPathwaysIds: (): string => `projects/${PROJECT_ID}/models/*/bioEntities/elements/`, downloadNetworkCsv: (): string => `projects/${PROJECT_ID}/models/*/bioEntities/reactions/:downloadCsv`, getAllUserOverlaysByCreatorQuery: ({ diff --git a/src/redux/bioEntity/bioEntity.reducers.ts b/src/redux/bioEntity/bioEntity.reducers.ts index bab876f9..b24e17c1 100644 --- a/src/redux/bioEntity/bioEntity.reducers.ts +++ b/src/redux/bioEntity/bioEntity.reducers.ts @@ -1,11 +1,8 @@ import { DEFAULT_ERROR } from '@/constants/errors'; import { ActionReducerMapBuilder, PayloadAction } from '@reduxjs/toolkit'; -import { getBioEntityById } from '@/redux/bioEntity/thunks/getBioEntity'; import { BioEntity, BioEntityContent } from '@/types/models'; -import { BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE } from './bioEntity.constants'; import { getBioEntity, getMultiBioEntity } from './bioEntity.thunks'; import { BioEntityContentsState } from './bioEntity.types'; -import { getSubmapConnectionsBioEntity } from './thunks/getSubmapConnectionsBioEntity'; export const getBioEntityContentsReducer = ( builder: ActionReducerMapBuilder<BioEntityContentsState>, @@ -18,14 +15,6 @@ export const getBioEntityContentsReducer = ( error: DEFAULT_ERROR, }); }); - builder.addCase(getBioEntityById.pending, (state, action) => { - state.data.push({ - searchQueryElement: `${action.meta.arg.elementId}`, - data: undefined, - loading: 'pending', - error: DEFAULT_ERROR, - }); - }); builder.addCase(getBioEntity.fulfilled, (state, action) => { const bioEntities = state.data.find( bioEntity => bioEntity.searchQueryElement === action.meta.arg.searchQuery, @@ -35,15 +24,6 @@ export const getBioEntityContentsReducer = ( bioEntities.loading = 'succeeded'; } }); - builder.addCase(getBioEntityById.fulfilled, (state, action) => { - const bioEntities = state.data.find( - bioEntity => bioEntity.searchQueryElement === `${action.meta.arg.elementId}`, - ); - if (bioEntities) { - bioEntities.data = action.payload ? [{ perfect: true, bioEntity: action.payload }] : []; - bioEntities.loading = 'succeeded'; - } - }); builder.addCase(getBioEntity.rejected, (state, action) => { const bioEntities = state.data.find( bioEntity => bioEntity.searchQueryElement === action.meta.arg.searchQuery, @@ -53,15 +33,6 @@ export const getBioEntityContentsReducer = ( // TODO: error management to be discussed in the team } }); - builder.addCase(getBioEntityById.rejected, (state, action) => { - const bioEntities = state.data.find( - bioEntity => bioEntity.searchQueryElement === `${action.meta.arg.elementId}`, - ); - if (bioEntities) { - bioEntities.loading = 'failed'; - // TODO: error management to be discussed in the team - } - }); }; export const getMultiBioEntityContentsReducer = ( @@ -80,34 +51,6 @@ export const getMultiBioEntityContentsReducer = ( }); }; -export const getSubmapConnectionsBioEntityReducer = ( - builder: ActionReducerMapBuilder<BioEntityContentsState>, -): void => { - builder.addCase(getSubmapConnectionsBioEntity.pending, state => { - state.submapConnections = { - ...BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE, - ...(state?.submapConnections ? state?.submapConnections : {}), - data: [], - loading: 'pending', - }; - }); - builder.addCase(getSubmapConnectionsBioEntity.fulfilled, (state, action) => { - state.submapConnections = { - ...BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE, - ...(state?.submapConnections ? state?.submapConnections : {}), - data: action.payload, - loading: 'succeeded', - }; - }); - builder.addCase(getSubmapConnectionsBioEntity.rejected, state => { - state.submapConnections = { - ...BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE, - ...(state?.submapConnections ? state?.submapConnections : {}), - loading: 'failed', - }; - }); -}; - export const clearBioEntitiesReducer = (state: BioEntityContentsState): void => { state.data = []; state.loading = 'idle'; diff --git a/src/redux/bioEntity/bioEntity.selectors.ts b/src/redux/bioEntity/bioEntity.selectors.ts index eb4e8f21..d9c63a0a 100644 --- a/src/redux/bioEntity/bioEntity.selectors.ts +++ b/src/redux/bioEntity/bioEntity.selectors.ts @@ -1,29 +1,25 @@ import { ONE, SIZE_OF_EMPTY_ARRAY, ZERO } from '@/constants/common'; -import { - allCommentsSelectorOfCurrentMap, - commentElementSelector, -} from '@/redux/comment/comment.selectors'; -import { currentDrawerReactionSelector } from '@/redux/reactions/reactions.selector'; +import { allCommentsSelectorOfCurrentMap } from '@/redux/comment/comment.selectors'; import { rootSelector } from '@/redux/root/root.selectors'; import { BioEntityWithPinType } from '@/types/bioEntity'; import { ElementIdTabObj } from '@/types/elements'; import { MultiSearchData } from '@/types/fetchDataState'; -import { BioEntity, BioEntityContent, Comment, MapModel } from '@/types/models'; +import { BioEntity, BioEntityContent, Comment, MapModel, ModelElement } from '@/types/models'; import { createSelector } from '@reduxjs/toolkit'; import { - allChemicalsBioEntitesOfAllMapsSelector, + currentDrawerModelElementSelector, + modelElementsWithSubmapConnectionForCurrentModelSelector, +} from '@/redux/modelElements/modelElements.selector'; +import { currentDrawerNewReactionSelector } from '@/redux/newReactions/newReactions.selectors'; +import { allChemicalsBioEntitesOfCurrentMapSelector, allChemicalsIdTabSelectorOfCurrentMap, chemicalsBioEntitiesForSelectedSearchElementSelector, searchedChemicalsBioEntitesOfCurrentMapSelector, } from '../chemicals/chemicals.selectors'; import { currentSelectedBioEntityIdSelector } from '../contextMenu/contextMenu.selector'; +import { currentSelectedSearchElement } from '../drawer/drawer.selectors'; import { - currentSearchedBioEntityId, - currentSelectedSearchElement, -} from '../drawer/drawer.selectors'; -import { - allDrugsBioEntitesOfAllMapsSelector, allDrugsBioEntitesOfCurrentMapSelector, allDrugsIdTabSelectorOfCurrentMap, drugsBioEntitiesForSelectedSearchElementSelector, @@ -49,15 +45,10 @@ export const bioEntityDataListSelector = createSelector(bioEntityDataSelector, b bioEntityData.map(b => b.data || []).flat(), ); -export const allSubmapConnectionsBioEntitySelector = createSelector( - bioEntitySelector, - (bioEntityData): BioEntity[] => bioEntityData?.submapConnections?.data || [], -); - export const allSubmapConnectionsBioEntityOfCurrentSubmapSelector = createSelector( - allSubmapConnectionsBioEntitySelector, + modelElementsWithSubmapConnectionForCurrentModelSelector, currentModelIdSelector, - (submapConnectionsBioEntity, currentModel): BioEntity[] => + (submapConnectionsBioEntity, currentModel): ModelElement[] => submapConnectionsBioEntity.filter(({ model }) => model === currentModel), ); @@ -70,14 +61,6 @@ export const bioEntitiesForSelectedSearchElement = createSelector( ), ); -export const searchedFromMapBioEntityElement = createSelector( - bioEntitiesForSelectedSearchElement, - currentSearchedBioEntityId, - (bioEntitiesState, currentBioEntityId): BioEntity | undefined => - bioEntitiesState && - bioEntitiesState.data?.find(({ bioEntity }) => bioEntity.id === currentBioEntityId)?.bioEntity, -); - export const searchedBioEntityElementForContextMapSelector = createSelector( bioEntitySelector, currentSelectedBioEntityIdSelector, @@ -95,13 +78,6 @@ export const searchedBioEntityElementUniProtIdSelector = createSelector( }, ); -export const searchedFromMapBioEntityElementRelatedSubmapSelector = createSelector( - searchedFromMapBioEntityElement, - modelsDataSelector, - (bioEntity, models): MapModel | undefined => - models.find(({ id }) => id === bioEntity?.submodel?.mapId), -); - export const loadingBioEntityStatusSelector = createSelector( bioEntitiesForSelectedSearchElement, state => state?.loading, @@ -226,30 +202,6 @@ export const allElementsForSearchElementNumberByModelId = createSelector( }, ); -export const allContentBioEntitesSelectorOfAllMaps = createSelector( - bioEntitySelector, - (bioEntities): BioEntity[] => { - if (!bioEntities) { - return []; - } - - return (bioEntities?.data || []) - .map(({ data }) => data || []) - .flat() - .map(({ bioEntity }) => bioEntity); - }, -); - -export const allBioEntitiesSelector = createSelector( - allContentBioEntitesSelectorOfAllMaps, - allChemicalsBioEntitesOfAllMapsSelector, - allDrugsBioEntitesOfAllMapsSelector, - allSubmapConnectionsBioEntitySelector, - (content, chemicals, drugs, submapConnections): BioEntity[] => { - return [content, chemicals, drugs, submapConnections].flat(); - }, -); - export const allBioEntitiesElementsIdsSelector = createSelector( allBioEntitesIdTabSelectorOfCurrentMap, allChemicalsIdTabSelectorOfCurrentMap, @@ -263,20 +215,8 @@ export const allBioEntitiesElementsIdsSelector = createSelector( }, ); -export const currentDrawerBioEntitySelector = createSelector( - allBioEntitiesSelector, - commentElementSelector, - currentSearchedBioEntityId, - (bioEntities, commentElement, currentBioEntityId): BioEntity | undefined => { - if (commentElement && commentElement.id === currentBioEntityId) { - return commentElement; - } - return bioEntities.find(({ id }) => id === currentBioEntityId); - }, -); - export const currentDrawerBioEntityRelatedSubmapSelector = createSelector( - currentDrawerBioEntitySelector, + currentDrawerModelElementSelector, modelsDataSelector, (bioEntity, models): MapModel | undefined => models.find(({ id }) => id === bioEntity?.submodel?.mapId), @@ -286,7 +226,7 @@ export const allSubmapConnectionsBioEntityOfCurrentSubmapWithRealConnectionsSele createSelector( allSubmapConnectionsBioEntityOfCurrentSubmapSelector, allElementsForSearchElementNumberByModelId, - (submapConnectionsBioEntity, modelElementsNumber): BioEntity[] => { + (submapConnectionsBioEntity, modelElementsNumber): ModelElement[] => { return submapConnectionsBioEntity.filter( ({ submodel }) => submodel && modelElementsNumber?.[submodel.mapId] > ZERO, ); @@ -317,7 +257,7 @@ export const allVisibleBioEntitiesIdsSelector = createSelector( ); export const currentDrawerElementCommentsSelector = createSelector( - currentDrawerBioEntitySelector, + currentDrawerModelElementSelector, allCommentsSelectorOfCurrentMap, (element, comments): Comment[] => { if (element) { @@ -333,7 +273,7 @@ export const currentDrawerElementCommentsSelector = createSelector( ); export const currentDrawerReactionCommentsSelector = createSelector( - currentDrawerReactionSelector, + currentDrawerNewReactionSelector, allCommentsSelectorOfCurrentMap, (reaction, comments): Comment[] => { if (reaction) { diff --git a/src/redux/bioEntity/bioEntity.slice.ts b/src/redux/bioEntity/bioEntity.slice.ts index 74dcffaa..8e40b023 100644 --- a/src/redux/bioEntity/bioEntity.slice.ts +++ b/src/redux/bioEntity/bioEntity.slice.ts @@ -4,7 +4,6 @@ import { clearBioEntitiesReducer, getBioEntityContentsReducer, getMultiBioEntityContentsReducer, - getSubmapConnectionsBioEntityReducer, setBioEntityContentsReducer, setMultipleBioEntityContentsReducer, toggleIsContentTabOpenedReducer, @@ -22,7 +21,6 @@ export const bioEntityContentsSlice = createSlice({ extraReducers: builder => { getBioEntityContentsReducer(builder); getMultiBioEntityContentsReducer(builder); - getSubmapConnectionsBioEntityReducer(builder); }, }); diff --git a/src/redux/bioEntity/thunks/getBioEntity.ts b/src/redux/bioEntity/thunks/getBioEntity.ts index c89cc25d..bf54870a 100644 --- a/src/redux/bioEntity/thunks/getBioEntity.ts +++ b/src/redux/bioEntity/thunks/getBioEntity.ts @@ -1,13 +1,12 @@ import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema'; import { apiPath } from '@/redux/apiPath'; import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; -import { BioEntity, BioEntityContent, BioEntityResponse } from '@/types/models'; -import { IdSearchQuery, PerfectSearchParams } from '@/types/search'; +import { BioEntityContent, BioEntityResponse } from '@/types/models'; +import { PerfectSearchParams } from '@/types/search'; import { ThunkConfig } from '@/types/store'; import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '@reduxjs/toolkit'; import { getError } from '@/utils/error-report/getError'; -import { getCommentElement } from '@/redux/comment/thunks/getComments'; import { addNumbersToEntityNumberData } from '../../entityNumber/entityNumber.slice'; import { BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants'; @@ -41,34 +40,3 @@ export const getBioEntity = createAsyncThunk< } }, ); - -type GetBioEntityByIdProps = IdSearchQuery; -type GetBioEntityByIdAction = PayloadAction<BioEntity | null>; // if error thrown, string containing error message is returned - -export const getBioEntityById = createAsyncThunk< - BioEntity | null, - GetBioEntityByIdProps, - ThunkConfig ->( - 'project/getBioEntityById', - async ({ elementId, modelId, type, addNumbersToEntityNumber }, { dispatch }) => { - try { - if (type === 'ALIAS') { - const elementAction = (await dispatch( - getCommentElement({ elementId, modelId }), - )) as GetBioEntityByIdAction; - - const element = elementAction.payload; - - if (addNumbersToEntityNumber && element) { - dispatch(addNumbersToEntityNumberData([element.elementId])); - } - - return element; - } - throw new Error('Not implemented'); - } catch (error) { - return Promise.reject(getError({ error, prefix: BIO_ENTITY_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/bioEntity/thunks/getMultiBioEntity.ts b/src/redux/bioEntity/thunks/getMultiBioEntity.ts index 2b84e65a..cddf3ff1 100644 --- a/src/redux/bioEntity/thunks/getMultiBioEntity.ts +++ b/src/redux/bioEntity/thunks/getMultiBioEntity.ts @@ -1,13 +1,13 @@ import { ZERO } from '@/constants/common'; import type { AppDispatch, store } from '@/redux/store'; -import { BioEntity, BioEntityContent } from '@/types/models'; -import { MultiSearchByIdParams, PerfectMultiSearchParams } from '@/types/search'; +import { BioEntityContent } from '@/types/models'; +import { PerfectMultiSearchParams } from '@/types/search'; import { ThunkConfig } from '@/types/store'; import { PayloadAction, createAsyncThunk } from '@reduxjs/toolkit'; import { getError } from '@/utils/error-report/getError'; import { addNumbersToEntityNumberData } from '../../entityNumber/entityNumber.slice'; import { MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants'; -import { getBioEntity, getBioEntityById } from './getBioEntity'; +import { getBioEntity } from './getBioEntity'; import { fetchReactionsAndGetBioEntitiesIds } from './utils/fetchReactionsAndGetBioEntitiesIds'; type GetMultiBioEntityProps = PerfectMultiSearchParams; @@ -57,49 +57,3 @@ export const getMultiBioEntity = createAsyncThunk< } }, ); - -type GetMultiBioEntityByIdProps = MultiSearchByIdParams; -type GetMultiBioEntityByIdActions = PayloadAction<BioEntity[] | undefined>[]; // if error thrown, string containing error message is returned - -export const getMultiBioEntityByIds = createAsyncThunk< - BioEntity[], - GetMultiBioEntityByIdProps, - ThunkConfig ->( - 'project/getMultiBioEntity', - // eslint-disable-next-line consistent-return - async ({ elementsToFetch }, { dispatch, getState }) => { - try { - const asyncGetBioEntityFunctions = elementsToFetch.map(elementToFetch => - dispatch(getBioEntityById(elementToFetch)), - ); - - const bioEntityContentsActions = (await Promise.all( - asyncGetBioEntityFunctions, - )) as GetMultiBioEntityByIdActions; - - const bioEntities = bioEntityContentsActions - .map(bioEntityContentsAction => bioEntityContentsAction?.payload || []) - .flat(); - - const bioEntityIds = bioEntities.map(b => b.elementId); - dispatch(addNumbersToEntityNumberData(bioEntityIds)); - - const bioEntitiesIds = await fetchReactionsAndGetBioEntitiesIds({ - bioEntityContents: bioEntities.map(bioEntity => { - return { perfect: true, bioEntity }; - }), - dispatch: dispatch as AppDispatch, - getState: getState as typeof store.getState, - }); - if (bioEntitiesIds.length > ZERO) { - const searchQueries = bioEntitiesIds.map(id => String(id)); - await dispatch(getMultiBioEntity({ searchQueries, isPerfectMatch: true })); - } - - return bioEntities; - } catch (error) { - return Promise.reject(getError({ error, prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts b/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts deleted file mode 100644 index 554dfde5..00000000 --- a/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { submapConnection } from '@/models/submapConnection'; -import { apiPath } from '@/redux/apiPath'; -import { axiosInstance, axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; -import { BioEntity, SubmapConnection } from '@/types/models'; -import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { createAsyncThunk } from '@reduxjs/toolkit'; -import { z } from 'zod'; -import { getError } from '@/utils/error-report/getError'; -import { bioEntitySchema } from '@/models/bioEntitySchema'; -import { MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants'; - -export const getSubmapConnectionsBioEntity = createAsyncThunk<BioEntity[]>( - 'project/getSubmapConnectionsBioEntity', - async () => { - try { - const response = await axiosInstance.get<SubmapConnection[]>(apiPath.getSubmapConnections()); - - const isDataValid = validateDataUsingZodSchema(response.data, z.array(submapConnection)); - if (!isDataValid) { - throw new Error('Submap connections validation error'); - } - - const targetElements = response.data.map(({ from }) => from); - - const asyncFetchBioEntityFunctions = targetElements.map(targetElement => - axiosInstanceNewAPI.get<BioEntity>( - apiPath.getElementById(targetElement.id, targetElement.modelId), - ), - ); - - const bioEntityContentResponse = await Promise.all(asyncFetchBioEntityFunctions); - - const bioEntityContents = bioEntityContentResponse - .map(contentResponse => contentResponse.data) - .flat() - .filter(content => bioEntitySchema.safeParse(content).success); - - return bioEntityContents; - } catch (error) { - return Promise.reject(getError({ error, prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/comment/comment.reducers.ts b/src/redux/comment/comment.reducers.ts index b113cdfd..55057923 100644 --- a/src/redux/comment/comment.reducers.ts +++ b/src/redux/comment/comment.reducers.ts @@ -1,10 +1,6 @@ import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { CommentsState } from '@/redux/comment/comment.types'; -import { - getCommentElement, - getCommentReaction, - getComments, -} from '@/redux/comment/thunks/getComments'; +import { getCommentReaction, getComments } from '@/redux/comment/thunks/getComments'; export const getCommentsReducer = (builder: ActionReducerMapBuilder<CommentsState>): void => { builder.addCase(getComments.pending, state => { @@ -21,23 +17,6 @@ export const getCommentsReducer = (builder: ActionReducerMapBuilder<CommentsStat }); }; -export const getCommentElementReducer = (builder: ActionReducerMapBuilder<CommentsState>): void => { - builder.addCase(getCommentElement.pending, state => { - state.loading = 'pending'; - state.commentElement = null; - }); - - builder.addCase(getCommentElement.fulfilled, (state, action) => { - state.loading = 'succeeded'; - state.commentElement = action.payload; - }); - - builder.addCase(getCommentElement.rejected, state => { - state.loading = 'failed'; - state.commentElement = null; - }); -}; - export const getCommentReactionReducer = ( builder: ActionReducerMapBuilder<CommentsState>, ): void => { diff --git a/src/redux/comment/comment.selectors.ts b/src/redux/comment/comment.selectors.ts index 7af687a2..587cf360 100644 --- a/src/redux/comment/comment.selectors.ts +++ b/src/redux/comment/comment.selectors.ts @@ -5,11 +5,6 @@ import { currentModelIdSelector } from '../models/models.selectors'; export const commentSelector = createSelector(rootSelector, state => state.comment); -export const commentElementSelector = createSelector( - commentSelector, - commentState => commentState.commentElement, -); - export const commentReactionSelector = createSelector( commentSelector, commentState => commentState.commentReaction, diff --git a/src/redux/comment/comment.slice.ts b/src/redux/comment/comment.slice.ts index ae4efb81..c426a46c 100644 --- a/src/redux/comment/comment.slice.ts +++ b/src/redux/comment/comment.slice.ts @@ -1,7 +1,6 @@ import { createSlice } from '@reduxjs/toolkit'; import { COMMENT_INITIAL_STATE } from '@/redux/comment/comment.constants'; import { - getCommentElementReducer, getCommentReactionReducer, getCommentsReducer, hideCommentsReducer, @@ -17,7 +16,6 @@ export const commentsSlice = createSlice({ }, extraReducers: builder => { getCommentsReducer(builder); - getCommentElementReducer(builder); getCommentReactionReducer(builder); }, }); diff --git a/src/redux/comment/thunks/getComments.ts b/src/redux/comment/thunks/getComments.ts index abf2d96e..df34a4f3 100644 --- a/src/redux/comment/thunks/getComments.ts +++ b/src/redux/comment/thunks/getComments.ts @@ -4,9 +4,8 @@ import { axiosInstance, axiosInstanceNewAPI } from '@/services/api/utils/axiosIn import { ThunkConfig } from '@/types/store'; import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; import { createAsyncThunk } from '@reduxjs/toolkit'; -import { BioEntity, Comment, NewReaction } from '@/types/models'; +import { Comment, NewReaction } from '@/types/models'; import { z } from 'zod'; -import { bioEntitySchema } from '@/models/bioEntitySchema'; import { GetElementProps } from '@/redux/comment/comment.types'; import { getError } from '@/utils/error-report/getError'; import { newReactionSchema } from '@/models/newReactionSchema'; @@ -26,23 +25,6 @@ export const getComments = createAsyncThunk<Comment[], void, ThunkConfig>( }, ); -export const getCommentElement = createAsyncThunk<BioEntity | null, GetElementProps, ThunkConfig>( - 'project/getCommentElement', - async ({ elementId, modelId }) => { - try { - const response = await axiosInstanceNewAPI.get<BioEntity>( - apiPath.getElementById(elementId, modelId), - ); - - const isDataValid = validateDataUsingZodSchema(response.data, bioEntitySchema); - - return isDataValid ? response.data : null; - } catch (error) { - return Promise.reject(getError({ error })); - } - }, -); - export const getCommentReaction = createAsyncThunk< NewReaction | null, GetElementProps, diff --git a/src/redux/compartmentPathways/comparmentPathways.constants.ts b/src/redux/compartmentPathways/comparmentPathways.constants.ts deleted file mode 100644 index cc54322a..00000000 --- a/src/redux/compartmentPathways/comparmentPathways.constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const MAX_NUMBER_OF_IDS_IN_GET_QUERY = 100; - -export const COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX = 'Failed to fetch compartment pathways'; diff --git a/src/redux/compartmentPathways/compartmentPathways.mock.ts b/src/redux/compartmentPathways/compartmentPathways.mock.ts deleted file mode 100644 index 8d088c4c..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.mock.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { MapModel } from '@/types/models'; -import { MAIN_MAP_ID } from '@/constants/mocks'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; - -export const COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK: CompartmentPathwaysState = { - loading: 'idle', - data: [], - error: { name: '', message: '' }, -}; -export const MODELS_MOCK: MapModel[] = [ - { - id: MAIN_MAP_ID, - width: 26779.25, - height: 13503.0, - defaultCenterX: null, - defaultCenterY: null, - description: '', - name: 'Core PD map', - defaultZoomLevel: null, - tileSize: 256, - references: [], - authors: [], - creationDate: null, - modificationDates: [], - minZoom: 2, - maxZoom: 9, - }, - { - id: 5054, - width: 26779.25, - height: 13503.0, - defaultCenterX: null, - defaultCenterY: null, - description: '', - name: 'Core PD map', - defaultZoomLevel: null, - tileSize: 256, - references: [], - authors: [], - creationDate: null, - modificationDates: [], - minZoom: 2, - maxZoom: 9, - }, -]; - -export const MODELS_MOCK_SHORT: MapModel[] = [ - { - id: 5050, - width: 26779.25, - height: 13503.0, - defaultCenterX: null, - defaultCenterY: null, - description: '', - name: 'Core PD map', - defaultZoomLevel: null, - tileSize: 256, - references: [], - authors: [], - creationDate: null, - modificationDates: [], - minZoom: 2, - maxZoom: 9, - }, -]; diff --git a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts b/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts deleted file mode 100644 index 8cfdf6ee..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { - ToolkitStoreWithSingleSlice, - createStoreInstanceUsingSliceReducer, -} from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { HttpStatusCode } from 'axios'; -import { - compartmentPathwaysDetailsFixture, - compartmentPathwaysFixture, - compartmentPathwaysOverLimitFixture, -} from '@/models/fixtures/compartmentPathways'; -import { getModelsIds } from '@/components/Map/Drawer/ExportDrawer/ExportDrawer.component.utils'; -import { unwrapResult } from '@reduxjs/toolkit'; -import { MAIN_MAP_ID } from '@/constants/mocks'; -import { apiPath } from '../apiPath'; -import compartmentPathwaysReducer from './compartmentPathways.slice'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; -import { getCompartmentPathways } from './compartmentPathways.thunks'; -import { MODELS_MOCK } from './compartmentPathways.mock'; - -const mockedAxiosClient = mockNetworkResponse(); -const MODELS_MOCK_IDS = getModelsIds(MODELS_MOCK); -const INITIAL_STATE: CompartmentPathwaysState = { - loading: 'idle', - error: { name: '', message: '' }, - data: [], -}; - -describe('compartmentPathways reducer', () => { - let store = {} as ToolkitStoreWithSingleSlice<CompartmentPathwaysState>; - beforeEach(() => { - store = createStoreInstanceUsingSliceReducer('compartmentPathways', compartmentPathwaysReducer); - }); - - it('should match initial state', () => { - const action = { type: 'unknown' }; - expect(compartmentPathwaysReducer(undefined, action)).toEqual(INITIAL_STATE); - }); - it('should update store on loading getCompartmentPathways query', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(52)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails([1, 2, 3])) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('idle'); - expect(data).toEqual([]); - - store.dispatch(getCompartmentPathways()); - - const { loading: loadingPending, data: dataPending } = store.getState().compartmentPathways; - - expect(loadingPending).toEqual('pending'); - expect(dataPending).toEqual([]); - }); - - it('should update store after succesful getCompartmentPathways query', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(MAIN_MAP_ID)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(5054)) - .reply(HttpStatusCode.Ok, compartmentPathwaysOverLimitFixture); - - const ids = compartmentPathwaysFixture.map(el => el.id); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails(ids)) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS)); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('pending'); - expect(data).toEqual([]); - - const { type } = await compartmentPathwaysPromise; - - expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled'); - - const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(dataFulfilled).toEqual([ - ...compartmentPathwaysDetailsFixture, - ...compartmentPathwaysDetailsFixture, - ]); - expect(promiseFulfilled).toEqual('succeeded'); - }); - - it('should update store after failed getCompartmentPathways query', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(MAIN_MAP_ID)) - .reply(HttpStatusCode.NotFound, []); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails([])) - .reply(HttpStatusCode.NotFound, []); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.NotFound, []); - - const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS)); - - const { loading, data } = store.getState().compartmentPathways; - expect(loading).toEqual('pending'); - expect(data).toEqual([]); - - const dispatchData = await compartmentPathwaysPromise; - - expect(() => unwrapResult(dispatchData)).toThrow( - "Failed to fetch compartment pathways: The page you're looking for doesn't exist. Please verify the URL and try again.", - ); - const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(promiseFulfilled).toEqual('failed'); - expect(dataFulfilled).toEqual([]); - }); -}); diff --git a/src/redux/compartmentPathways/compartmentPathways.reducers.ts b/src/redux/compartmentPathways/compartmentPathways.reducers.ts deleted file mode 100644 index 8010fbc0..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.reducers.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; -import { getCompartmentPathways } from './compartmentPathways.thunks'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; - -export const getCompartmentPathwaysReducer = ( - builder: ActionReducerMapBuilder<CompartmentPathwaysState>, -): void => { - builder - .addCase(getCompartmentPathways.pending, state => { - state.loading = 'pending'; - }) - .addCase(getCompartmentPathways.fulfilled, (state, action) => { - state.data = action.payload; - state.loading = 'succeeded'; - }) - .addCase(getCompartmentPathways.rejected, state => { - state.loading = 'failed'; - // TODO: error management to be discussed in the team - }); -}; diff --git a/src/redux/compartmentPathways/compartmentPathways.selectors.ts b/src/redux/compartmentPathways/compartmentPathways.selectors.ts deleted file mode 100644 index d6c82942..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.selectors.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { rootSelector } from '@/redux/root/root.selectors'; -import { createSelector } from '@reduxjs/toolkit'; - -export const compartmentPathwaysSelector = createSelector( - rootSelector, - state => state.compartmentPathways, -); - -export const compartmentPathwaysDataSelector = createSelector( - compartmentPathwaysSelector, - state => state.data, -); - -export const loadingCompartmentPathwaysSelector = createSelector( - compartmentPathwaysSelector, - state => state.loading, -); diff --git a/src/redux/compartmentPathways/compartmentPathways.slice.ts b/src/redux/compartmentPathways/compartmentPathways.slice.ts deleted file mode 100644 index 3cc1b375..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.slice.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createSlice } from '@reduxjs/toolkit'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; -import { getCompartmentPathwaysReducer } from './compartmentPathways.reducers'; - -export const initialState: CompartmentPathwaysState = { - loading: 'idle', - error: { name: '', message: '' }, - data: [], -}; - -export const compartmentPathwaysSlice = createSlice({ - name: 'compartmentPathways', - initialState, - reducers: {}, - extraReducers: builder => { - getCompartmentPathwaysReducer(builder); - }, -}); - -export default compartmentPathwaysSlice.reducer; diff --git a/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts b/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts deleted file mode 100644 index 891eeb38..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import { - ToolkitStoreWithSingleSlice, - createStoreInstanceUsingSliceReducer, -} from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkResponse } from '@/utils/mockNetworkResponse'; -import { HttpStatusCode } from 'axios'; -import { - compartmentPathwaysDetailsFixture, - compartmentPathwaysFixture, - compartmentPathwaysOverLimitFixture, -} from '@/models/fixtures/compartmentPathways'; -import { getModelsIds } from '@/components/Map/Drawer/ExportDrawer/ExportDrawer.component.utils'; -import { MAIN_MAP_ID } from '@/constants/mocks'; -import { apiPath } from '../apiPath'; -import compartmentPathwaysReducer from './compartmentPathways.slice'; -import { CompartmentPathwaysState } from './compartmentPathways.types'; -import { getCompartmentPathways } from './compartmentPathways.thunks'; -import { MODELS_MOCK, MODELS_MOCK_SHORT } from './compartmentPathways.mock'; - -const mockedAxiosClient = mockNetworkResponse(); -const MODELS_MOCK_IDS = getModelsIds(MODELS_MOCK); - -describe('compartmentPathways thunk', () => { - let store = {} as ToolkitStoreWithSingleSlice<CompartmentPathwaysState>; - beforeEach(() => { - store = createStoreInstanceUsingSliceReducer('compartmentPathways', compartmentPathwaysReducer); - }); - - it('should handle query getCompartmentPathways properly when models are undefined', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(52)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails([1, 2, 3])) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('idle'); - expect(data).toEqual([]); - - const comparmentPathwaysPromise = store.dispatch(getCompartmentPathways()); - - const { loading: loadingPending, data: dataPending } = store.getState().compartmentPathways; - - expect(loadingPending).toEqual('pending'); - expect(dataPending).toEqual([]); - - await comparmentPathwaysPromise; - const { loading: loadingFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(loadingFulfilled).toEqual('succeeded'); - expect(dataFulfilled).toEqual([]); - }); - it('should handle sendCompartmentPathwaysIds request properly if it is more than 100 ids', async () => { - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(MAIN_MAP_ID)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(5054)) - .reply(HttpStatusCode.Ok, compartmentPathwaysOverLimitFixture); - - const ids = compartmentPathwaysFixture.map(el => el.id); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails(ids)) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS)); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('pending'); - expect(data).toEqual([]); - - const { type } = await compartmentPathwaysPromise; - - expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled'); - - const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(dataFulfilled).toEqual([ - ...compartmentPathwaysDetailsFixture, - ...compartmentPathwaysDetailsFixture, - ]); - expect(promiseFulfilled).toEqual('succeeded'); - }); - - it('should not do a network request sendCompartmentPathwaysIds if it is less than 100 ids', async () => { - const ONE_MODEL = MODELS_MOCK_SHORT[0]; - const ID = ONE_MODEL.id; - - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwaysIds(ID)) - .reply(HttpStatusCode.Ok, compartmentPathwaysFixture); - - const ids = compartmentPathwaysFixture.map(el => el.id); - mockedAxiosClient - .onGet(apiPath.getCompartmentPathwayDetails(ids)) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - mockedAxiosClient - .onPost(apiPath.sendCompartmentPathwaysIds()) - .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture); - - const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways([ONE_MODEL.id])); - - const { loading, data } = store.getState().compartmentPathways; - - expect(loading).toEqual('pending'); - expect(data).toEqual([]); - - const { type } = await compartmentPathwaysPromise; - - expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled'); - - const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways; - - expect(dataFulfilled).toEqual(compartmentPathwaysDetailsFixture); - expect(promiseFulfilled).toEqual('succeeded'); - }); -}); diff --git a/src/redux/compartmentPathways/compartmentPathways.thunks.ts b/src/redux/compartmentPathways/compartmentPathways.thunks.ts deleted file mode 100644 index 8f1bd216..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.thunks.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* eslint-disable no-restricted-syntax */ -import { axiosInstance } from '@/services/api/utils/axiosInstance'; -import { createAsyncThunk } from '@reduxjs/toolkit'; -import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { CompartmentPathway, CompartmentPathwayDetails } from '@/types/models'; -import { - compartmentPathwayDetailsSchema, - compartmentPathwaySchema, -} from '@/models/compartmentPathwaySchema'; -import { z } from 'zod'; -import { getError } from '@/utils/error-report/getError'; -import { - COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX, - MAX_NUMBER_OF_IDS_IN_GET_QUERY, -} from './comparmentPathways.constants'; -import { apiPath } from '../apiPath'; - -/** UTILS */ - -const fetchCompartmentPathwaysIds = async ( - modelsIds: number[] | undefined, -): Promise<number[][]> => { - if (!modelsIds) return []; - - const compartmentIds = []; - - for (const modelId of modelsIds) { - /* eslint-disable no-await-in-loop */ - const response = await axiosInstance<CompartmentPathway[]>( - apiPath.getCompartmentPathwaysIds(modelId), - ); - - const isDataValid = validateDataUsingZodSchema( - response.data, - z.array(compartmentPathwaySchema), - ); - - if (isDataValid) { - const result = response.data; - const ids: number[] = []; - - result.forEach(item => { - ids.push(item.id); - }); - - compartmentIds.push(ids); - } - } - - return compartmentIds; -}; - -const fetchCompartmentPathwayDetailsByPost = async ( - compartmentPathwayIds: number[], -): Promise<CompartmentPathwayDetails[]> => { - const params = { - id: compartmentPathwayIds.join(','), - }; - const body = new URLSearchParams(params); - - const response = await axiosInstance.post<CompartmentPathwayDetails[]>( - apiPath.sendCompartmentPathwaysIds(), - body, - ); - - return response.data; -}; - -const fetchCompartmentPathwayDetailsByGet = async ( - compartmentPathwayIds: number[], -): Promise<CompartmentPathwayDetails[]> => { - const response = await axiosInstance.get<CompartmentPathwayDetails[]>( - apiPath.getCompartmentPathwayDetails(compartmentPathwayIds), - ); - - return response.data; -}; - -const fetchCompartmentPathwayDetails = async ( - compartmentPathwayIds: number[], -): Promise<CompartmentPathwayDetails[]> => { - if (compartmentPathwayIds.length) { - let compartmentPathwayDetails; - if (compartmentPathwayIds.length > MAX_NUMBER_OF_IDS_IN_GET_QUERY) { - compartmentPathwayDetails = await fetchCompartmentPathwayDetailsByPost(compartmentPathwayIds); - } else { - compartmentPathwayDetails = await fetchCompartmentPathwayDetailsByGet(compartmentPathwayIds); - } - - const isDataValid = validateDataUsingZodSchema( - compartmentPathwayDetails, - z.array(compartmentPathwayDetailsSchema), - ); - - if (isDataValid) return compartmentPathwayDetails; - } - return []; -}; - -export const fetchCompartmentPathways = async ( - compartmentPathwaysData: number[][], -): Promise<CompartmentPathwayDetails[]> => { - const compartments = []; - - /* eslint-disable no-await-in-loop */ - for (const compartmentPathwayIds of compartmentPathwaysData) { - const compartmentPathwayDetails = await fetchCompartmentPathwayDetails(compartmentPathwayIds); - - if (compartmentPathwayDetails) compartments.push(...compartmentPathwayDetails); - } - - return compartments; -}; - -/** UTILS */ - -export const getCompartmentPathways = createAsyncThunk( - 'compartmentPathways/getCompartmentPathways', - async (modelsIds: number[] | undefined) => { - try { - const compartmentIds = await fetchCompartmentPathwaysIds(modelsIds); - const comparmentPathways = await fetchCompartmentPathways(compartmentIds); - - return comparmentPathways; - } catch (error) { - return Promise.reject(getError({ error, prefix: COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/compartmentPathways/compartmentPathways.types.ts b/src/redux/compartmentPathways/compartmentPathways.types.ts deleted file mode 100644 index 76718b54..00000000 --- a/src/redux/compartmentPathways/compartmentPathways.types.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { FetchDataState } from '@/types/fetchDataState'; -import { CompartmentPathwayDetails } from '@/types/models'; - -export type CompartmentPathwaysState = FetchDataState<CompartmentPathwayDetails[], []>; diff --git a/src/redux/drawer/drawer.selectors.ts b/src/redux/drawer/drawer.selectors.ts index 05a64d2e..a5f109ea 100644 --- a/src/redux/drawer/drawer.selectors.ts +++ b/src/redux/drawer/drawer.selectors.ts @@ -18,11 +18,6 @@ export const currentStepDrawerStateSelector = createSelector( state => state.currentStep, ); -export const selectedValueDrawerSelector = createSelector( - searchDrawerStateSelector, - state => state.selectedValue, -); - export const stepTypeDrawerSelector = createSelector( searchDrawerStateSelector, state => state.stepType, diff --git a/src/redux/entityNumber/entityNumber.reducers.ts b/src/redux/entityNumber/entityNumber.reducers.ts index 15662170..2c114e95 100644 --- a/src/redux/entityNumber/entityNumber.reducers.ts +++ b/src/redux/entityNumber/entityNumber.reducers.ts @@ -15,7 +15,6 @@ export const addNumbersToEntityNumberDataReducer = ( ): void => { const { payload: ids } = action; const uniqueIds = [...new Set(ids)]; - const lastNumber = Object.keys(state.data).length || ONE; // min num = 1 const newEntityNumber: EntityNumber = Object.fromEntries( uniqueIds.map((id, index) => [id, lastNumber + index]), diff --git a/src/redux/modelElements/modelElements.constants.ts b/src/redux/modelElements/modelElements.constants.ts index c3b221d3..42427c11 100644 --- a/src/redux/modelElements/modelElements.constants.ts +++ b/src/redux/modelElements/modelElements.constants.ts @@ -1 +1,3 @@ export const MODEL_ELEMENTS_FETCHING_ERROR_PREFIX = 'Failed to fetch model elements'; + +export const MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME = 'default'; diff --git a/src/redux/modelElements/modelElements.reducers.test.ts b/src/redux/modelElements/modelElements.reducers.test.ts index c6c51637..8c499a6d 100644 --- a/src/redux/modelElements/modelElements.reducers.test.ts +++ b/src/redux/modelElements/modelElements.reducers.test.ts @@ -34,7 +34,7 @@ describe('model elements reducer', () => { const { type } = await store.dispatch(getModelElementsForModel(0)); const { data, loading, error } = store.getState().modelElements[0]; - expect(type).toBe('vectorMap/getModelElementsForModel/fulfilled'); + expect(type).toBe('modelElements/getModelElementsForModel/fulfilled'); expect(loading).toEqual('succeeded'); expect(error).toEqual({ message: '', name: '' }); expect(data).toEqual(modelElementsFixture.content); @@ -46,7 +46,7 @@ describe('model elements reducer', () => { const action = await store.dispatch(getModelElementsForModel(0)); const { data, loading, error } = store.getState().modelElements[0]; - expect(action.type).toBe('vectorMap/getModelElementsForModel/rejected'); + expect(action.type).toBe('modelElements/getModelElementsForModel/rejected'); expect(() => unwrapResult(action)).toThrow( "Failed to fetch model elements: The page you're looking for doesn't exist. Please verify the URL and try again.", ); diff --git a/src/redux/modelElements/modelElements.selector.ts b/src/redux/modelElements/modelElements.selector.ts index b31fd45f..55c08d7a 100644 --- a/src/redux/modelElements/modelElements.selector.ts +++ b/src/redux/modelElements/modelElements.selector.ts @@ -1,6 +1,10 @@ import { createSelector } from '@reduxjs/toolkit'; import { rootSelector } from '@/redux/root/root.selectors'; import { currentModelIdSelector } from '@/redux/models/models.selectors'; +import { currentSearchedBioEntityId } from '@/redux/drawer/drawer.selectors'; +import { ModelElement } from '@/types/models'; +import { MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME } from '@/redux/modelElements/modelElements.constants'; +import { COMPARTMENT_SBO_TERM } from '@/components/Map/MapViewer/MapViewer.constants'; export const modelElementsSelector = createSelector(rootSelector, state => state.modelElements); @@ -15,12 +19,61 @@ export const modelElementsByModelIdSelector = createSelector( (state, modelId) => state[modelId]?.data || [], ); -export const modelElementsLoadingSelector = createSelector( +export const modelElementsCurrentModelLoadingSelector = createSelector( modelElementsStateForCurrentModelSelector, state => state?.loading, ); +export const modelElementsAnyModelLoadingSelector = createSelector(modelElementsSelector, state => + Object.values(state).some(modelElementState => modelElementState.loading === 'pending'), +); + export const modelElementsForCurrentModelSelector = createSelector( modelElementsStateForCurrentModelSelector, state => state?.data || [], ); + +export const modelElementsWithSubmapConnectionForCurrentModelSelector = createSelector( + modelElementsForCurrentModelSelector, + modelElements => modelElements.filter(modelElement => Boolean(modelElement.submodel)) || [], +); + +export const compartmentNameByIdSelector = createSelector( + [ + modelElementsForCurrentModelSelector, + (_state, compartmentId: number | undefined | null): number | undefined | null => compartmentId, + ], + (modelElements, compartmentId) => { + if (!compartmentId) { + return MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME; + } + return ( + modelElements.find(modelElement => { + return modelElement.sboTerm === COMPARTMENT_SBO_TERM && modelElement.id === compartmentId; + })?.name || MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME + ); + }, +); + +export const currentDrawerModelElementSelector = createSelector( + modelElementsForCurrentModelSelector, + currentSearchedBioEntityId, + (modelElements, currentBioEntityId): ModelElement | undefined => { + return modelElements.find(modelElement => modelElement.id === currentBioEntityId); + }, +); + +export const compartmentPathwaysSelector = createSelector( + modelElementsSelector, + (state): ModelElement[] => { + const pathways: ModelElement[] = []; + Object.values(state).forEach(modelState => { + pathways.push( + ...(modelState.data || []).filter( + modelElement => modelElement.sboTerm === COMPARTMENT_SBO_TERM, + ), + ); + }); + return pathways; + }, +); diff --git a/src/redux/modelElements/modelElements.thunks.ts b/src/redux/modelElements/modelElements.thunks.ts index fb1a3c2e..68f2419e 100644 --- a/src/redux/modelElements/modelElements.thunks.ts +++ b/src/redux/modelElements/modelElements.thunks.ts @@ -13,7 +13,7 @@ export const getModelElementsForModel = createAsyncThunk< Array<ModelElement> | undefined, number, ThunkConfig ->('vectorMap/getModelElementsForModel', async (modelId: number) => { +>('modelElements/getModelElementsForModel', async (modelId: number) => { try { const { data } = await axiosInstanceNewAPI.get<ModelElements>( apiPath.getModelElements(modelId), diff --git a/src/redux/newReactions/newReactions.selectors.ts b/src/redux/newReactions/newReactions.selectors.ts index a17245b4..b8ba305f 100644 --- a/src/redux/newReactions/newReactions.selectors.ts +++ b/src/redux/newReactions/newReactions.selectors.ts @@ -1,5 +1,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { currentModelIdSelector } from '@/redux/models/models.selectors'; +import { currentDrawerReactionIdSelector } from '@/redux/drawer/drawer.selectors'; +import { NewReaction } from '@/types/models'; import { rootSelector } from '../root/root.selectors'; export const newReactionsSelector = createSelector(rootSelector, state => state.newReactions); @@ -24,3 +26,11 @@ export const newReactionsByModelIdSelector = createSelector( [newReactionsSelector, (_state, modelId: number): number => modelId], (state, modelId) => state[modelId]?.data || [], ); + +export const currentDrawerNewReactionSelector = createSelector( + newReactionsForCurrentModelSelector, + currentDrawerReactionIdSelector, + (newReactions, currentDrawerReactionId): NewReaction | undefined => { + return newReactions.find(newReaction => newReaction.id === currentDrawerReactionId); + }, +); diff --git a/src/redux/overlayBioEntity/overlayBioEntity.selector.ts b/src/redux/overlayBioEntity/overlayBioEntity.selector.ts index 94616fd8..a7c7e93b 100644 --- a/src/redux/overlayBioEntity/overlayBioEntity.selector.ts +++ b/src/redux/overlayBioEntity/overlayBioEntity.selector.ts @@ -1,7 +1,7 @@ import { OverlayBioEntityRender } from '@/types/OLrendering'; import { createSelector } from '@reduxjs/toolkit'; -import { allSubmapConnectionsBioEntitySelector } from '@/redux/bioEntity/bioEntity.selectors'; import { mapModelIdSelector } from '@/redux/map/map.selectors'; +import { modelElementsWithSubmapConnectionForCurrentModelSelector } from '@/redux/modelElements/modelElements.selector'; import { currentSearchedBioEntityId } from '../drawer/drawer.selectors'; import { currentModelIdSelector } from '../models/models.selectors'; import { @@ -36,7 +36,7 @@ export const overlayBioEntitiesForCurrentModelSelector = createSelector( overlayBioEntityDataSelector, activeOverlaysIdSelector, currentModelIdSelector, - allSubmapConnectionsBioEntitySelector, + modelElementsWithSubmapConnectionForCurrentModelSelector, (data, activeOverlaysIds, currentModelId, submapConnections) => { const result: OverlayBioEntityRender[] = []; diff --git a/src/redux/root/init.thunks.ts b/src/redux/root/init.thunks.ts index 562789dc..4514bd87 100644 --- a/src/redux/root/init.thunks.ts +++ b/src/redux/root/init.thunks.ts @@ -15,7 +15,6 @@ import { } from '@/redux/autocomplete/autocomplete.thunks'; import { openSelectProjectModal } from '@/redux/modal/modal.slice'; import { getProjects } from '@/redux/projects/projects.thunks'; -import { getSubmapConnectionsBioEntity } from '@/redux/bioEntity/thunks/getSubmapConnectionsBioEntity'; import { getArrowTypes, getLineTypes, getShapes } from '@/redux/shapes/shapes.thunks'; import { MATOMO_URL } from '@/redux/configuration/configuration.constants'; import { @@ -133,8 +132,6 @@ export const fetchInitialAppData = createAsyncThunk< dispatch(getDrugAutocomplete()); dispatch(getChemicalAutocomplete()); - dispatch(getSubmapConnectionsBioEntity()); - /** Trigger search */ if (queryData.searchValue) { dispatch(setPerfectMatch(queryData.perfectMatch)); diff --git a/src/redux/root/root.fixtures.ts b/src/redux/root/root.fixtures.ts index f6d6110c..e21a9a9a 100644 --- a/src/redux/root/root.fixtures.ts +++ b/src/redux/root/root.fixtures.ts @@ -11,7 +11,6 @@ import { GLYPHS_STATE_INITIAL_MOCK } from '@/redux/glyphs/glyphs.mock'; import { MAP_EDIT_TOOLS_STATE_INITIAL_MOCK } from '@/redux/mapEditTools/mapEditTools.mock'; import { BIOENTITY_INITIAL_STATE_MOCK } from '../bioEntity/bioEntity.mock'; import { CHEMICALS_INITIAL_STATE_MOCK } from '../chemicals/chemicals.mock'; -import { COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK } from '../compartmentPathways/compartmentPathways.mock'; import { CONFIGURATION_INITIAL_STATE } from '../configuration/configuration.adapter'; import { CONTEXT_MENU_INITIAL_STATE } from '../contextMenu/contextMenu.constants'; import { COOKIE_BANNER_INITIAL_STATE_MOCK } from '../cookieBanner/cookieBanner.mock'; @@ -65,7 +64,6 @@ export const INITIAL_STORE_STATE_MOCK: RootState = { user: USER_INITIAL_STATE_MOCK, legend: LEGEND_INITIAL_STATE_MOCK, statistics: STATISTICS_STATE_INITIAL_MOCK, - compartmentPathways: COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK, publications: PUBLICATIONS_INITIAL_STATE_MOCK, export: EXPORT_INITIAL_STATE_MOCK, plugins: PLUGINS_INITIAL_STATE_MOCK, diff --git a/src/redux/selectors/index.ts b/src/redux/selectors/index.ts new file mode 100644 index 00000000..f1cbd61d --- /dev/null +++ b/src/redux/selectors/index.ts @@ -0,0 +1,33 @@ +import { createSelector } from '@reduxjs/toolkit'; +import { newReactionsLoadingSelector } from '@/redux/newReactions/newReactions.selectors'; +import { modelElementsCurrentModelLoadingSelector } from '@/redux/modelElements/modelElements.selector'; +import { + arrowTypesLoadingSelector, + bioShapesLoadingSelector, + lineTypesLoadingSelector, +} from '@/redux/shapes/shapes.selectors'; +import { layersLoadingSelector } from '@/redux/layers/layers.selectors'; + +export const modelLoadingSelector = createSelector( + [ + newReactionsLoadingSelector, + modelElementsCurrentModelLoadingSelector, + bioShapesLoadingSelector, + lineTypesLoadingSelector, + arrowTypesLoadingSelector, + layersLoadingSelector, + ], + (...loadingStates) => loadingStates.includes('pending'), +); + +export const modelLoadedSuccessfullySelector = createSelector( + [ + newReactionsLoadingSelector, + modelElementsCurrentModelLoadingSelector, + bioShapesLoadingSelector, + lineTypesLoadingSelector, + arrowTypesLoadingSelector, + layersLoadingSelector, + ], + (...loadingStates) => loadingStates.every(state => state === 'succeeded'), +); diff --git a/src/redux/store.ts b/src/redux/store.ts index a98370bc..3d2cc350 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -36,7 +36,6 @@ import { configureStore, } from '@reduxjs/toolkit'; import commentReducer from '@/redux/comment/comment.slice'; -import compartmentPathwaysReducer from './compartmentPathways/compartmentPathways.slice'; import entityNumberReducer from './entityNumber/entityNumber.slice'; import exportReducer from './export/export.slice'; import legendReducer from './legend/legend.slice'; @@ -78,7 +77,6 @@ export const reducers = { overlayBioEntity: overlayBioEntityReducer, legend: legendReducer, statistics: statisticsReducer, - compartmentPathways: compartmentPathwaysReducer, publications: publicationsReducer, export: exportReducer, plugins: pluginsReducer, diff --git a/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts b/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts index 235bf0f5..4a1bcd16 100644 --- a/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts +++ b/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts @@ -52,7 +52,7 @@ export const searchByCoordinates = async ( const type = searchResultVector.get('type'); const id = searchResultVector.get('id'); if ([FEATURE_TYPE.ALIAS, FEATURE_TYPE.GLYPH, FEATURE_TYPE.COMPARTMENT].includes(type)) { - await leftClickHandleAlias(dispatch, hasFitBounds)(searchResultVector, modelId); + await leftClickHandleAlias(dispatch, hasFitBounds)(modelElements, searchResultVector, modelId); } else if (type === FEATURE_TYPE.REACTION) { clickHandleReaction(dispatch)(modelElements, newReactions, id, modelId); } diff --git a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts index adba6dd6..0b3e97df 100644 --- a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts +++ b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts @@ -12,12 +12,12 @@ import { HttpStatusCode } from 'axios'; import { Feature, Map } from 'ol'; import SimpleGeometry from 'ol/geom/SimpleGeometry'; import VectorLayer from 'ol/layer/Vector'; -import { VECTOR_MAP_LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { FEATURE_TYPE } from '@/constants/features'; import * as leftClickHandleAlias from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; import { MapManager } from '@/services/pluginsManager/map/mapManager'; import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { NewReactionsState } from '@/redux/newReactions/newReactions.types'; +import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; import { ERROR_INVALID_MODEL_ID_TYPE } from '../../errorMessages'; import { triggerSearch } from './triggerSearch'; @@ -75,7 +75,7 @@ jest.mock( describe('triggerSearch', () => { let mapInstance: Map; const vectorLayer = new VectorLayer({}); - vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE); + vectorLayer.set('type', LAYER_TYPE.PROCESS_LAYER); beforeEach(() => { const dummyElement = document.createElement('div'); diff --git a/src/types/models.ts b/src/types/models.ts index 168c7fde..756f345a 100644 --- a/src/types/models.ts +++ b/src/types/models.ts @@ -3,35 +3,23 @@ import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema'; import { bioEntitySchema } from '@/models/bioEntitySchema'; import { chemicalSchema } from '@/models/chemicalSchema'; import { colorSchema } from '@/models/colorSchema'; -import { - compartmentPathwayDetailsSchema, - compartmentPathwaySchema, -} from '@/models/compartmentPathwaySchema'; import { configurationOptionSchema } from '@/models/configurationOptionSchema'; import { configurationSchema, formatSchema, miriamTypesSchema } from '@/models/configurationSchema'; -import { disease } from '@/models/disease'; import { drugSchema } from '@/models/drugSchema'; import { elementSearchResult, elementSearchResultType } from '@/models/elementSearchResult'; import { exportElementsSchema, exportNetworkchema } from '@/models/exportSchema'; import { geneVariant } from '@/models/geneVariant'; import { lineSchema } from '@/models/lineSchema'; import { loginSchema } from '@/models/loginSchema'; -import { - createdOverlayFileSchema, - createdOverlaySchema, - mapOverlay, - uploadedOverlayFileContentSchema, -} from '@/models/mapOverlay'; +import { createdOverlayFileSchema, createdOverlaySchema, mapOverlay } from '@/models/mapOverlay'; import { markerLineSchema, markerPinSchema, markerSchema, markerSurfaceSchema, - markerTypeSchema, markerWithPositionSchema, } from '@/models/markerSchema'; import { mapModelSchema, mapModelsSchema } from '@/models/modelSchema'; -import { organism } from '@/models/organism'; import { overlayBioEntitySchema, overlayElementWithBioEntitySchema, @@ -52,8 +40,6 @@ import { publicationSchema } from '@/models/publicationsSchema'; import { referenceSchema } from '@/models/referenceSchema'; import { sessionSchemaValid } from '@/models/sessionValidSchema'; import { statisticsSchema } from '@/models/statisticsSchema'; -import { submapConnection } from '@/models/submapConnection'; -import { targetElementSchema } from '@/models/targetElementSchema'; import { targetSchema } from '@/models/targetSchema'; import { targetSearchNameResult } from '@/models/targetSearchNameResult'; import { userPrivilegeSchema } from '@/models/userPrivilegesSchema'; @@ -115,8 +101,6 @@ export type ShapeRelAbs = z.infer<typeof shapeRelAbsSchema>; export type ShapeRelAbsBezierPoint = z.infer<typeof shapeRelAbsBezierPointSchema>; export type Modification = z.infer<typeof modelElementModificationSchema>; export type MapOverlay = z.infer<typeof mapOverlay>; -export type Organism = z.infer<typeof organism>; -export type Disease = z.infer<typeof disease>; export type Drug = z.infer<typeof drugSchema>; export type PinDetailsItem = z.infer<typeof targetSchema>; export type BioEntity = z.infer<typeof bioEntitySchema>; @@ -145,23 +129,17 @@ export type OverlayLeftBioEntity = z.infer<typeof overlayLeftBioEntitySchema>; export type OverlayLeftReaction = z.infer<typeof overlayLeftReactionSchema>; export type Line = z.infer<typeof lineSchema>; export type CreatedOverlayFile = z.infer<typeof createdOverlayFileSchema>; -export type UploadedOverlayFileContent = z.infer<typeof uploadedOverlayFileContentSchema>; export type CreatedOverlay = z.infer<typeof createdOverlaySchema>; export type Color = z.infer<typeof colorSchema>; export type Statistics = z.infer<typeof statisticsSchema>; -export type CompartmentPathway = z.infer<typeof compartmentPathwaySchema>; -export type CompartmentPathwayDetails = z.infer<typeof compartmentPathwayDetailsSchema>; export type Publication = z.infer<typeof publicationSchema>; export type ExportNetwork = z.infer<typeof exportNetworkchema>; export type ExportElements = z.infer<typeof exportElementsSchema>; export type MinervaPlugin = z.infer<typeof pluginSchema>; // Plugin type interferes with global Plugin type export type GeneVariant = z.infer<typeof geneVariant>; export type TargetSearchNameResult = z.infer<typeof targetSearchNameResult>; -export type TargetElement = z.infer<typeof targetElementSchema>; -export type SubmapConnection = z.infer<typeof submapConnection>; export type UserPrivilege = z.infer<typeof userPrivilegeSchema>; export type User = z.infer<typeof userSchema>; -export type MarkerType = z.infer<typeof markerTypeSchema>; export type MarkerPin = z.infer<typeof markerPinSchema>; export type MarkerSurface = z.infer<typeof markerSurfaceSchema>; export type MarkerLine = z.infer<typeof markerLineSchema>; -- GitLab From 11548092da2456be696767614c8aeb000890807a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Fri, 31 Jan 2025 16:15:09 +0100 Subject: [PATCH 05/12] feat(modelElements): merge modelElements and bioEntity stores --- .../ContextMenu.component.test.tsx | 112 ++++---- .../ContextMenu/ContextMenu.component.tsx | 11 +- .../ElementLink.component.test.tsx | 36 +-- .../ElementLink/ElementLink.component.tsx | 8 +- .../ElementsOnMapCell.component.test.tsx | 14 +- .../ElementsOnMapCell.component.tsx | 4 +- .../PublicationsTable.component.tsx | 6 +- .../ClearAnchorsButton.component.test.tsx | 4 +- .../ClearAnchorsButton.component.tsx | 4 +- .../AssociatedSubmap.component.test.tsx | 86 +++--- .../AssociatedSubmap.component.tsx | 4 +- .../BioEntityDrawer.component.test.tsx | 138 ++++++---- .../BioEntityDrawer.component.tsx | 8 +- .../OverlayData.component.test.tsx | 61 ----- .../Map/Drawer/Drawer.component.test.tsx | 24 +- .../Elements/Elements.component.test.tsx | 38 +-- .../ExportCompound.component.tsx | 2 +- ...udedCompartmentPathways.component.test.tsx | 0 .../IncludedCompartmentPathways.component.tsx | 0 .../index.ts | 0 .../Network/Network.component.test.tsx | 38 +-- ...onnectedBioEntitiesList.component.test.tsx | 52 ++-- .../ConnectedBioEntitiesList.component.tsx | 22 +- .../ReactionDrawer.component.tsx | 6 +- .../BioEntitiesPinsList.component.tsx | 25 +- ...BioEntitiesPinsListItem.component.test.tsx | 6 +- .../BioEntitiesPinsListItem.component.tsx | 6 +- .../BioEntitiesPinsListItem.types.ts | 22 +- .../BioEntitiesPinsListItem.utils.ts | 9 +- .../BioEntitiesAccordion.component.test.tsx | 106 ++++---- .../BioEntitiesAccordion.component.tsx | 28 +- .../BioEntitiesSubmapItem.component.test.tsx | 83 +++--- .../BioEntitiesSubmapItem.component.tsx | 14 +- .../PinsList/PinsList.component.test.tsx | 4 +- .../PinsList/PinsList.component.tsx | 2 +- .../ResultsList/PinsList/PinsList.types.tsx | 4 +- .../PinsListItem.component.test.tsx | 31 +-- .../PinsListItem/PinsListItem.component.tsx | 4 +- .../PinsListItem.component.utils.ts | 2 +- .../SearchDrawerWrapper.component.test.tsx | 2 +- .../SearchDrawerWrapper.component.tsx | 4 +- ...sibleBioEntitiesPolygonCoordinates.test.ts | 53 ++-- .../useBioEntitiesWithSubmapLinks.test.ts | 72 +++-- .../pinsLayer/getBioEntitiesFeatures.ts | 8 +- .../pinsLayer/getBioEntititesFeatures.test.ts | 7 +- .../pinsLayer/getMarkerSingleFeature.ts | 2 +- ...s => getModelElementSingleFeature.test.ts} | 15 +- ...ure.ts => getModelElementSingleFeature.ts} | 8 +- .../config/pinsLayer/getMultipinCanvasArgs.ts | 4 +- .../getMultipinSingleFeature.test.ts | 6 +- .../pinsLayer/getMultipinSingleFeature.ts | 6 +- .../pinsLayer/getMultipinsBioEntities.test.ts | 76 ------ .../pinsLayer/getMultipinsBioEntitiesIds.ts | 7 +- .../config/pinsLayer/getMultipinsFeatures.ts | 4 +- .../getMultipinsModelElements.test.ts | 76 ++++++ ...tities.ts => getMultipinsModelElements.ts} | 28 +- .../config/pinsLayer/getPinFeature.test.ts | 4 +- .../utils/config/pinsLayer/getPinFeature.ts | 4 +- .../config/pinsLayer/useOlMapPinsLayer.ts | 18 +- .../mapSingleClick/handleOpenImmediateLink.ts | 4 +- .../mouseClick/clickHandleReaction.ts | 21 +- .../leftClickHandleAlias.test.ts | 4 +- .../mouseLeftClick/leftClickHandleAlias.ts | 4 +- .../mouseLeftClick/onMapLeftClick.test.ts | 4 +- .../mouseLeftClick/onMapLeftClick.ts | 4 +- .../rightClickHandleAlias.test.ts | 4 +- .../mouseRightClick/rightClickHandleAlias.ts | 8 +- .../useHandlePinIconClick.test.ts | 193 ++++++++------ src/constants/canvas.ts | 2 +- src/constants/index.ts | 2 +- src/constants/pin.ts | 3 - src/models/bioEntitySchema.ts | 42 +-- ...ixture.ts => publicationElementFixture.ts} | 4 +- src/models/mocks/publicationsResponseMock.ts | 32 +-- src/models/modelElementSchema.ts | 4 +- src/models/publicationElementSchema.ts | 35 +++ src/models/publicationsSchema.ts | 4 +- src/models/targetSchema.ts | 4 +- src/redux/apiPath.ts | 7 +- src/redux/bioEntity/bioEntity.constants.ts | 17 -- src/redux/bioEntity/bioEntity.mock.ts | 31 +-- .../bioEntity/bioEntity.reducers.test.ts | 151 ----------- src/redux/bioEntity/bioEntity.reducers.ts | 92 +------ src/redux/bioEntity/bioEntity.selectors.ts | 249 +++--------------- src/redux/bioEntity/bioEntity.slice.ts | 23 +- src/redux/bioEntity/bioEntity.thunks.test.ts | 129 --------- src/redux/bioEntity/bioEntity.thunks.ts | 4 - src/redux/bioEntity/bioEntity.types.ts | 18 +- src/redux/bioEntity/thunks/getBioEntity.ts | 42 --- .../bioEntity/thunks/getMultiBioEntity.ts | 59 ----- .../fetchReactionsAndGetBioEntitiesIds.ts | 98 ------- src/redux/chemicals/chemicals.selectors.ts | 36 +-- src/redux/comment/comment.types.ts | 4 +- src/redux/contextMenu/contextMenu.selector.ts | 2 - src/redux/drawer/drawer.reducers.ts | 2 +- src/redux/drawer/drawer.selectors.ts | 2 +- src/redux/drawer/drawer.types.ts | 8 +- src/redux/drugs/drugs.reducers.test.ts | 8 +- src/redux/drugs/drugs.selectors.ts | 36 +-- .../modelElements/modelElements.constants.ts | 4 + src/redux/modelElements/modelElements.mock.ts | 41 ++- .../modelElements.reducers.test.ts | 132 +++++++++- .../modelElements/modelElements.reducers.ts | 125 ++++++++- .../modelElements/modelElements.selector.ts | 195 +++++++++++++- .../modelElements/modelElements.slice.ts | 20 +- .../modelElements.thunks.test.ts | 117 +++++++- .../modelElements/modelElements.thunks.ts | 75 +++++- .../modelElements/modelElements.types.ts | 24 +- .../newReactions/newReactions.selectors.ts | 19 +- src/redux/reactions/isReactionBioentity.ts | 5 - src/redux/reactions/isReactionElement.ts | 5 + src/redux/search/search.thunks.ts | 6 +- src/redux/search/search.thunks.utils.ts | 15 +- .../bioEntities/clearAllElements.ts | 4 +- .../bioEntities/getAllContent.ts | 8 +- .../bioEntities/getShownElements.ts | 12 +- .../bioEntities/getShownElements.types.ts | 8 +- ...sibleBioEntitiesPolygonCoordinates.test.ts | 71 +++-- .../map/triggerSearch/searchByCoordinates.ts | 4 +- .../map/triggerSearch/searchByQuery.test.ts | 4 - .../map/triggerSearch/triggerSearch.test.ts | 12 +- .../pluginsContextMenu.types.ts | 12 +- .../pluginsEventBus/pluginsEventBus.types.ts | 16 +- src/types/bioEntity.ts | 8 - src/types/modelElement.ts | 8 + src/types/models.ts | 4 +- src/types/pin.ts | 2 +- .../bioEntity/mapModelElementToBioEntity.ts | 51 ---- ...Entity.ts => mapReactionToModelElement.ts} | 6 +- 129 files changed, 1886 insertions(+), 1951 deletions(-) rename src/components/Map/Drawer/ExportDrawer/ExportCompound/{IncludedCompartmentPathways => IncludedCompartmentPathways}/IncludedCompartmentPathways.component.test.tsx (100%) rename src/components/Map/Drawer/ExportDrawer/ExportCompound/{IncludedCompartmentPathways => IncludedCompartmentPathways}/IncludedCompartmentPathways.component.tsx (100%) rename src/components/Map/Drawer/ExportDrawer/ExportCompound/{IncludedCompartmentPathways => IncludedCompartmentPathways}/index.ts (100%) rename src/components/Map/MapViewer/utils/config/pinsLayer/{getBioEntitySingleFeature.test.ts => getModelElementSingleFeature.test.ts} (83%) rename src/components/Map/MapViewer/utils/config/pinsLayer/{getBioEntitySingleFeature.ts => getModelElementSingleFeature.ts} (83%) delete mode 100644 src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntities.test.ts create mode 100644 src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsModelElements.test.ts rename src/components/Map/MapViewer/utils/config/pinsLayer/{getMultipinsBioEntities.ts => getMultipinsModelElements.ts} (53%) delete mode 100644 src/constants/pin.ts rename src/models/fixtures/{bioEntityFixture.ts => publicationElementFixture.ts} (55%) create mode 100644 src/models/publicationElementSchema.ts delete mode 100644 src/redux/bioEntity/bioEntity.reducers.test.ts delete mode 100644 src/redux/bioEntity/bioEntity.thunks.test.ts delete mode 100644 src/redux/bioEntity/bioEntity.thunks.ts delete mode 100644 src/redux/bioEntity/thunks/getBioEntity.ts delete mode 100644 src/redux/bioEntity/thunks/getMultiBioEntity.ts delete mode 100644 src/redux/bioEntity/thunks/utils/fetchReactionsAndGetBioEntitiesIds.ts delete mode 100644 src/redux/reactions/isReactionBioentity.ts create mode 100644 src/redux/reactions/isReactionElement.ts delete mode 100644 src/types/bioEntity.ts create mode 100644 src/types/modelElement.ts delete mode 100644 src/utils/bioEntity/mapModelElementToBioEntity.ts rename src/utils/bioEntity/{mapReactionToBioEntity.ts => mapReactionToModelElement.ts} (72%) diff --git a/src/components/FunctionalArea/ContextMenu/ContextMenu.component.test.tsx b/src/components/FunctionalArea/ContextMenu/ContextMenu.component.test.tsx index 0e83701b..c0051a13 100644 --- a/src/components/FunctionalArea/ContextMenu/ContextMenu.component.test.tsx +++ b/src/components/FunctionalArea/ContextMenu/ContextMenu.component.test.tsx @@ -8,6 +8,8 @@ import { act, render, screen } from '@testing-library/react'; import { CONTEXT_MENU_INITIAL_STATE } from '@/redux/contextMenu/contextMenu.constants'; import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { PluginsContextMenu } from '@/services/pluginsManager/pluginContextMenu/pluginsContextMenu'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { DEFAULT_ERROR } from '@/constants/errors'; import { ContextMenu } from './ContextMenu.component'; const renderComponent = (initialStore?: InitialStoreState): { store: StoreType } => { @@ -97,31 +99,40 @@ describe('ContextMenu - Component', () => { it('should display uniprot id as option if it is provided', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: bioEntityContentFixture.bioEntity.id.toString(), + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: 'BioEntity Full Name', - references: [ - { - ...bioEntityContentFixture.bioEntity.references[0], - type: 'UNIPROT', - }, - ], - }, - }, - ], + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, + }, + search: { + data: [ + { + searchQueryElement: modelElementFixture.id.toString(), + loading: 'succeeded', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { + ...modelElementFixture, + fullName: 'BioEntity Full Name', + references: [ + { + ...bioEntityContentFixture.bioEntity.references[0], + type: 'UNIPROT', + }, + ], + }, + perfect: true, + }, + ], + }, + ], + loading: 'pending', + error: DEFAULT_ERROR, + }, }, contextMenu: { ...CONTEXT_MENU_INITIAL_STATE, @@ -144,31 +155,40 @@ describe('ContextMenu - Component', () => { it('should open molart modal when clicking on uniprot', async () => { const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: bioEntityContentFixture.bioEntity.id.toString(), + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: 'BioEntity Full Name', - references: [ - { - ...bioEntityContentFixture.bioEntity.references[0], - type: 'UNIPROT', - }, - ], - }, - }, - ], + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, + }, + search: { + data: [ + { + searchQueryElement: modelElementFixture.id.toString(), + loading: 'succeeded', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { + ...modelElementFixture, + fullName: 'BioEntity Full Name', + references: [ + { + ...bioEntityContentFixture.bioEntity.references[0], + type: 'UNIPROT', + }, + ], + }, + perfect: true, + }, + ], + }, + ], + loading: 'pending', + error: DEFAULT_ERROR, + }, }, contextMenu: { ...CONTEXT_MENU_INITIAL_STATE, diff --git a/src/components/FunctionalArea/ContextMenu/ContextMenu.component.tsx b/src/components/FunctionalArea/ContextMenu/ContextMenu.component.tsx index 1e4d612b..fe738b51 100644 --- a/src/components/FunctionalArea/ContextMenu/ContextMenu.component.tsx +++ b/src/components/FunctionalArea/ContextMenu/ContextMenu.component.tsx @@ -1,4 +1,3 @@ -import { searchedBioEntityElementUniProtIdSelector } from '@/redux/bioEntity/bioEntity.selectors'; import { contextMenuSelector } from '@/redux/contextMenu/contextMenu.selector'; import { closeContextMenu } from '@/redux/contextMenu/contextMenu.slice'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; @@ -9,12 +8,13 @@ import { twMerge } from 'tailwind-merge'; import { FIRST_ARRAY_ELEMENT, SECOND_ARRAY_ELEMENT, ZERO } from '@/constants/common'; import { PluginsContextMenu } from '@/services/pluginsManager/pluginContextMenu/pluginsContextMenu'; -import { BioEntity, NewReaction } from '@/types/models'; +import { ModelElement, NewReaction } from '@/types/models'; import { ClickCoordinates } from '@/services/pluginsManager/pluginContextMenu/pluginsContextMenu.types'; import { currentModelSelector } from '@/redux/models/models.selectors'; import { mapDataLastPositionSelector } from '@/redux/map/map.selectors'; import { DEFAULT_ZOOM } from '@/constants/map'; import { OutsideClickWrapper } from '@/shared/OutsideClickWrapper'; +import { searchedModelElementUniProtIdSelector } from '@/redux/modelElements/modelElements.selector'; export const ContextMenu = (): React.ReactNode => { const pluginContextMenu = PluginsContextMenu.menuItems; @@ -22,7 +22,7 @@ export const ContextMenu = (): React.ReactNode => { const lastPosition = useAppSelector(mapDataLastPositionSelector); const dispatch = useAppDispatch(); const { isOpen, coordinates } = useAppSelector(contextMenuSelector); - const unitProtId = useAppSelector(searchedBioEntityElementUniProtIdSelector); + const unitProtId = useAppSelector(searchedModelElementUniProtIdSelector); const isUnitProtIdAvailable = (): boolean => unitProtId !== undefined; @@ -49,7 +49,10 @@ export const ContextMenu = (): React.ReactNode => { const modelId = model ? model.id : ZERO; const handleCallback = ( - callback: (coordinates: ClickCoordinates, element: BioEntity | NewReaction | undefined) => void, + callback: ( + coordinates: ClickCoordinates, + element: ModelElement | NewReaction | undefined, + ) => void, ) => { return () => { closeContextMenuFunction(); diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.test.tsx b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.test.tsx index ea4fe1f6..22beff1a 100644 --- a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.test.tsx +++ b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.test.tsx @@ -5,7 +5,7 @@ import { apiPath } from '@/redux/apiPath'; import { DEFAULT_POSITION } from '@/redux/map/map.constants'; import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; import { AppDispatch, RootState } from '@/redux/store'; -import { BioEntity, MapModel } from '@/types/models'; +import { MapModel, PublicationElement } from '@/types/models'; import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { InitialStoreState, @@ -14,12 +14,12 @@ import { import { render, screen, waitFor } from '@testing-library/react'; import { HttpStatusCode } from 'axios'; import { MockStoreEnhanced } from 'redux-mock-store'; -import { isReactionBioEntity } from '@/redux/reactions/isReactionBioentity'; +import { isReactionElement } from '@/redux/reactions/isReactionElement'; import { ElementLink } from './ElementLink.component'; const mockedAxiosNewClient = mockNetworkNewAPIResponse(); -const TARGET_ELEMENT: BioEntity = { +const TARGET_ELEMENT: PublicationElement = { ...bioEntityResponseFixture.content[FIRST_ARRAY_ELEMENT].bioEntity, id: 123, model: 52, @@ -36,20 +36,20 @@ const OTHER_MODEL: MapModel = { }; interface Props { - target: BioEntity; + target: PublicationElement; } -const getElementText = (bioEntity: BioEntity): string => { - const isReaction = isReactionBioEntity(bioEntity); +const getElementText = (element: PublicationElement): string => { + const isReaction = isReactionElement(element); const prefix = isReaction ? 'Reaction: ' : 'Element: '; - return prefix + bioEntity.elementId; + return prefix + element.elementId; }; -const getSearchQuery = (bioEntity: BioEntity): string => { - const isReaction = isReactionBioEntity(bioEntity); +const getSearchQuery = (element: PublicationElement): string => { + const isReaction = isReactionElement(element); - return (isReaction ? 'reaction:' : 'element:') + bioEntity.id; + return (isReaction ? 'reaction:' : 'element:') + element.id; }; const renderComponent = ( @@ -86,10 +86,10 @@ describe('ElementLink - component', () => { }); it('should should show element id', async () => { - const bioEntity = TARGET_ELEMENT; + const element = TARGET_ELEMENT; await waitFor(() => { - expect(screen.getByText(getElementText(bioEntity))).toBeInTheDocument(); + expect(screen.getByText(getElementText(element))).toBeInTheDocument(); }); }); }); @@ -116,10 +116,10 @@ describe('ElementLink - component', () => { }, ); - const bioEntity = TARGET_ELEMENT; + const element = TARGET_ELEMENT; await waitFor(() => { - const link = screen.getByText(getElementText(bioEntity)); + const link = screen.getByText(getElementText(element)); link.click(); const actions = store.getActions(); @@ -148,7 +148,7 @@ describe('ElementLink - component', () => { expect(actions).toEqual( expect.arrayContaining([ expect.objectContaining({ - payload: getSearchQuery(bioEntity), + payload: getSearchQuery(element), type: 'drawer/openSearchDrawerWithSelectedTab', }), ]), @@ -206,10 +206,10 @@ describe('ElementLink - component', () => { }, ); - const bioEntity = TARGET_ELEMENT; + const element = TARGET_ELEMENT; await waitFor(() => { - const link = screen.getByText(getElementText(bioEntity)); + const link = screen.getByText(getElementText(element)); link.click(); const actions = store.getActions(); @@ -238,7 +238,7 @@ describe('ElementLink - component', () => { expect(actions).toEqual( expect.arrayContaining([ expect.objectContaining({ - payload: getSearchQuery(bioEntity), + payload: getSearchQuery(element), type: 'drawer/openSearchDrawerWithSelectedTab', }), ]), diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.tsx b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.tsx index 8bf24727..baad3d08 100644 --- a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.tsx +++ b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementLink/ElementLink.component.tsx @@ -13,11 +13,11 @@ import { closeModal } from '@/redux/modal/modal.slice'; import { modelsNameMapSelector } from '@/redux/models/models.selectors'; import { getSearchData } from '@/redux/search/search.thunks'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; -import { BioEntity } from '@/types/models'; -import { isReactionBioEntity } from '@/redux/reactions/isReactionBioentity'; +import { PublicationElement } from '@/types/models'; +import { isReactionElement } from '@/redux/reactions/isReactionElement'; interface Props { - target: BioEntity; + target: PublicationElement; } export const ElementLink = ({ target }: Props): JSX.Element => { @@ -26,7 +26,7 @@ export const ElementLink = ({ target }: Props): JSX.Element => { const currentModelId = useAppSelector(mapModelIdSelector); const mapsNames = useAppSelector(modelsNameMapSelector); - const isReaction = isReactionBioEntity(target); + const isReaction = isReactionElement(target); const isMapAlreadyOpened = (modelId: number): boolean => openedMaps.some(map => map.modelId === modelId); diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementsOnMapCell.component.test.tsx b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementsOnMapCell.component.test.tsx index 2e7349c6..84798d95 100644 --- a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementsOnMapCell.component.test.tsx +++ b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementsOnMapCell.component.test.tsx @@ -1,18 +1,18 @@ import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; import { AppDispatch, RootState } from '@/redux/store'; -import { BioEntity } from '@/types/models'; +import { PublicationElement } from '@/types/models'; import { InitialStoreState, getReduxStoreWithActionsListener, } from '@/utils/testing/getReduxStoreActionsListener'; import { render, screen, waitFor } from '@testing-library/react'; import { MockStoreEnhanced } from 'redux-mock-store'; -import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; -import { isReactionBioEntity } from '@/redux/reactions/isReactionBioentity'; +import { isReactionElement } from '@/redux/reactions/isReactionElement'; +import { publicationElementFixture } from '@/models/fixtures/publicationElementFixture'; import { ElementsOnMapCell } from './ElementsOnMapCell.component'; interface Props { - targets: BioEntity[]; + targets: PublicationElement[]; } const renderComponent = ( @@ -33,8 +33,8 @@ const renderComponent = ( ); }; -const elementFixture = { ...bioEntityFixture, idReaction: undefined }; -const reactionFixture = { ...bioEntityFixture, idReaction: '123' }; +const elementFixture = { ...publicationElementFixture, idReaction: undefined }; +const reactionFixture = { ...publicationElementFixture, idReaction: '123' }; const mockTargets = [{ ...elementFixture }, { ...reactionFixture }]; @@ -49,7 +49,7 @@ describe('ElementsOnMapCell - component', () => { await waitFor(() => { // type as elementId - const isReaction = isReactionBioEntity(bioEntity); + const isReaction = isReactionElement(bioEntity); const prefix = isReaction ? 'Reaction: ' : 'Element: '; expect(screen.getByText(prefix + bioEntity.elementId)).toBeInTheDocument(); }); diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementsOnMapCell.component.tsx b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementsOnMapCell.component.tsx index 13c1269f..36d7a247 100644 --- a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementsOnMapCell.component.tsx +++ b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/ElementsOnMapCell/ElementsOnMapCell.component.tsx @@ -1,9 +1,9 @@ import { ONE } from '@/constants/common'; -import { BioEntity } from '@/types/models'; +import { PublicationElement } from '@/types/models'; import { ElementLink } from './ElementLink'; interface Props { - targets: BioEntity[]; + targets: PublicationElement[]; } export const ElementsOnMapCell = ({ targets }: Props): JSX.Element => { diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/PublicationsTable.component.tsx b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/PublicationsTable.component.tsx index cc0db919..562ccefa 100644 --- a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/PublicationsTable.component.tsx +++ b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsTable/PublicationsTable.component.tsx @@ -23,7 +23,7 @@ import { } from '@tanstack/react-table'; import { useRef, useState } from 'react'; import { z } from 'zod'; -import { bioEntitySchema } from '@/models/bioEntitySchema'; +import { publicationElementSchema } from '@/models/publicationElementSchema'; import { ElementsOnMapCell } from './ElementsOnMapCell'; import { FilterBySubmapHeader } from './FilterBySubmapHeader/FilterBySubmapHeader.component'; import { DEFAULT_PAGE_SIZE } from './PublicationsTable.constants'; @@ -74,9 +74,7 @@ const columns = [ cell: ({ getValue }): JSX.Element => { try { const valueObject: unknown = JSON.parse(getValue()); - // eslint-disable-next-line no-console - console.log(valueObject); - const targets = z.array(bioEntitySchema).parse(valueObject); + const targets = z.array(publicationElementSchema).parse(valueObject); return <ElementsOnMapCell targets={targets} />; } catch (error) { diff --git a/src/components/FunctionalArea/TopBar/ClearAnchorsButton/ClearAnchorsButton.component.test.tsx b/src/components/FunctionalArea/TopBar/ClearAnchorsButton/ClearAnchorsButton.component.test.tsx index b8bc885a..494e4e37 100644 --- a/src/components/FunctionalArea/TopBar/ClearAnchorsButton/ClearAnchorsButton.component.test.tsx +++ b/src/components/FunctionalArea/TopBar/ClearAnchorsButton/ClearAnchorsButton.component.test.tsx @@ -49,7 +49,7 @@ describe('ClearAnchorsButton - component', () => { { payload: undefined, type: 'contextMenu/closeContextMenu' }, { payload: undefined, type: 'reactions/resetReactionsData' }, { payload: undefined, type: 'search/clearSearchData' }, - { payload: undefined, type: 'bioEntityContents/clearBioEntities' }, + { payload: undefined, type: 'modelElements/clearSearchModelElements' }, { payload: undefined, type: 'drugs/clearDrugsData' }, { payload: undefined, type: 'chemicals/clearChemicalsData' }, ]); @@ -75,7 +75,7 @@ describe('ClearAnchorsButton - component', () => { { payload: undefined, type: 'contextMenu/closeContextMenu' }, { payload: undefined, type: 'reactions/resetReactionsData' }, { payload: undefined, type: 'search/clearSearchData' }, - { payload: undefined, type: 'bioEntityContents/clearBioEntities' }, + { payload: undefined, type: 'modelElements/clearSearchModelElements' }, { payload: undefined, type: 'drugs/clearDrugsData' }, { payload: undefined, type: 'chemicals/clearChemicalsData' }, ]); diff --git a/src/components/FunctionalArea/TopBar/ClearAnchorsButton/ClearAnchorsButton.component.tsx b/src/components/FunctionalArea/TopBar/ClearAnchorsButton/ClearAnchorsButton.component.tsx index 0cb34178..c370829b 100644 --- a/src/components/FunctionalArea/TopBar/ClearAnchorsButton/ClearAnchorsButton.component.tsx +++ b/src/components/FunctionalArea/TopBar/ClearAnchorsButton/ClearAnchorsButton.component.tsx @@ -1,4 +1,3 @@ -import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; import { clearChemicalsData } from '@/redux/chemicals/chemicals.slice'; import { closeContextMenu } from '@/redux/contextMenu/contextMenu.slice'; import { resultDrawerOpen } from '@/redux/drawer/drawer.selectors'; @@ -11,6 +10,7 @@ import { Button } from '@/shared/Button'; import { Icon } from '@/shared/Icon'; import React from 'react'; import { useSelector } from 'react-redux'; +import { clearSearchModelElements } from '@/redux/modelElements/modelElements.slice'; export const ClearAnchorsButton = (): React.ReactNode => { const dispatch = useAppDispatch(); @@ -31,7 +31,7 @@ export const ClearAnchorsButton = (): React.ReactNode => { dispatch(clearSearchData()); // Reset old pins data - dispatch(clearBioEntities()); + dispatch(clearSearchModelElements()); dispatch(clearDrugsData()); dispatch(clearChemicalsData()); }; 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 73231d8d..ed18ca49 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.test.tsx @@ -1,11 +1,6 @@ import { SIZE_OF_ARRAY_WITH_ONE_ELEMENT, ZERO } from '@/constants/common'; -import { 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, - BIO_ENTITY_LINKING_TO_SUBMAP, -} from '@/redux/bioEntity/bioEntity.mock'; +import { BIOENTITY_INITIAL_STATE_MOCK } from '@/redux/bioEntity/bioEntity.mock'; import { DRAWER_INITIAL_STATE } from '@/redux/drawer/drawer.constants'; import { initialMapDataFixture, @@ -21,6 +16,12 @@ import { 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 { + MODEL_ELEMENT_LINKING_TO_SUBMAP, + MODEL_ELEMENTS_SEARCH_LINKING_TO_SUBMAP_DATA_MOCK, +} from '@/redux/modelElements/modelElements.mock'; +import { DEFAULT_ERROR } from '@/constants/errors'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { AssociatedSubmap } from './AssociatedSubmap.component'; const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { @@ -43,21 +44,27 @@ describe('AssociatedSubmap - component', () => { renderComponent({ bioEntity: { ...BIOENTITY_INITIAL_STATE_MOCK, - data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, }, modelElements: { - [MAIN_MAP_ID]: { - data: [BIO_ENTITY_LINKING_TO_SUBMAP], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + [MAIN_MAP_ID]: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, + search: { + data: MODEL_ELEMENTS_SEARCH_LINKING_TO_SUBMAP_DATA_MOCK, + loading: 'idle', + error: DEFAULT_ERROR, }, } as ModelElementsState, models: { @@ -81,21 +88,27 @@ describe('AssociatedSubmap - component', () => { }, bioEntity: { ...BIOENTITY_INITIAL_STATE_MOCK, - data: BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK, }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, }, modelElements: { - [MAIN_MAP_ID]: { - data: [BIO_ENTITY_LINKING_TO_SUBMAP], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + [MAIN_MAP_ID]: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, + search: { + data: MODEL_ELEMENTS_SEARCH_LINKING_TO_SUBMAP_DATA_MOCK, + loading: 'idle', + error: DEFAULT_ERROR, }, } as ModelElementsState, models: { @@ -118,19 +131,25 @@ describe('AssociatedSubmap - component', () => { }, bioEntity: { ...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: '' }, + data: { + 0: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, + search: { + data: MODEL_ELEMENTS_SEARCH_LINKING_TO_SUBMAP_DATA_MOCK, + loading: 'idle', + error: DEFAULT_ERROR, }, } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, @@ -151,7 +170,6 @@ describe('AssociatedSubmap - component', () => { modelName: 'Histamine signaling', lastPosition: { x: 0, y: 0, z: 0 }, }); - const openSubmapButton = screen.getByRole('button', { name: 'Open submap' }); await act(() => { openSubmapButton.click(); @@ -184,19 +202,25 @@ describe('AssociatedSubmap - component', () => { }, bioEntity: { ...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: '' }, + data: { + [MAIN_MAP_ID]: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, + search: { + data: MODEL_ELEMENTS_SEARCH_LINKING_TO_SUBMAP_DATA_MOCK, + loading: 'idle', + error: DEFAULT_ERROR, }, } as ModelElementsState, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: bioEntityContentFixture.bioEntity.id, + bioentityId: modelElementFixture.id, drugs: {}, chemicals: {}, }, diff --git a/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.tsx b/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.tsx index ae421606..22c6c449 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/AssociatedSubmap/AssociatedSubmap.component.tsx @@ -1,10 +1,10 @@ import { useOpenSubmap } from '@/hooks/useOpenSubmaps'; -import { currentDrawerBioEntityRelatedSubmapSelector } from '@/redux/bioEntity/bioEntity.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { Button } from '@/shared/Button'; +import { currentDrawerModelElementRelatedSubmapSelector } from '@/redux/modelElements/modelElements.selector'; export const AssociatedSubmap = (): React.ReactNode => { - const relatedSubmap = useAppSelector(currentDrawerBioEntityRelatedSubmapSelector); + const relatedSubmap = useAppSelector(currentDrawerModelElementRelatedSubmapSelector); const { openSubmap } = useOpenSubmap({ modelId: relatedSubmap?.id, modelName: relatedSubmap?.name, diff --git a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx index 7ae2a243..c0bb5058 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.test.tsx @@ -1,6 +1,5 @@ /* eslint-disable no-magic-numbers */ import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; -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'; @@ -10,8 +9,11 @@ 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 { + MODEL_ELEMENT_LINKING_TO_SUBMAP, + MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, +} from '@/redux/modelElements/modelElements.mock'; import { BioEntityDrawer } from './BioEntityDrawer.component'; const renderComponent = ( @@ -43,10 +45,15 @@ describe('BioEntityDrawer - component', () => { describe("when there's NO matching bioEntity", () => { beforeEach(() => renderComponent({ - bioEntity: { - data: [], - loading: 'succeeded', - error: { message: '', name: '' }, + modelElements: { + data: { + 0: { + data: [], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, }, drawer: DRAWER_INITIAL_STATE, }), @@ -67,12 +74,15 @@ describe('BioEntityDrawer - component', () => { it('should show drawer header', () => { renderComponent({ modelElements: { - 0: { - data: [{ ...modelElementFixture, name: bioEntityName }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -91,12 +101,15 @@ describe('BioEntityDrawer - component', () => { it('should show drawer bioEntity full name', () => { renderComponent({ modelElements: { - 0: { - data: [{ ...modelElementFixture, name: bioEntityName, fullName: bioEntityFullName }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: bioEntityFullName }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -114,12 +127,15 @@ describe('BioEntityDrawer - component', () => { it("should not show drawer bioEntity full name if it doesn't exists", () => { renderComponent({ modelElements: { - 0: { - data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -136,12 +152,15 @@ describe('BioEntityDrawer - component', () => { it('should show list of annotations ', () => { renderComponent({ modelElements: { - 0: { - data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -164,16 +183,19 @@ describe('BioEntityDrawer - component', () => { it('should display associated submaps if bio entity links to submap', () => { renderComponent({ modelElements: { - 0: { - data: [{ ...BIO_ENTITY_LINKING_TO_SUBMAP, name: bioEntityName, fullName: null }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...MODEL_ELEMENT_LINKING_TO_SUBMAP, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { - bioentityId: BIO_ENTITY_LINKING_TO_SUBMAP.id, + bioentityId: MODEL_ELEMENT_LINKING_TO_SUBMAP.id, drugs: {}, chemicals: {}, }, @@ -190,12 +212,15 @@ describe('BioEntityDrawer - component', () => { it('should display chemicals list header', () => { renderComponent({ modelElements: { - 0: { - data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -212,12 +237,15 @@ describe('BioEntityDrawer - component', () => { it('should display drugs list header', () => { renderComponent({ modelElements: { - 0: { - data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -234,12 +262,15 @@ describe('BioEntityDrawer - component', () => { it('should fetch chemicals on chemicals for target click', () => { const { store } = renderComponent({ modelElements: { - 0: { - data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { @@ -263,12 +294,15 @@ describe('BioEntityDrawer - component', () => { it('should fetch drugs on drugs for target click', () => { const { store } = renderComponent({ modelElements: { - 0: { - data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [{ ...modelElementFixture, name: bioEntityName, fullName: null }], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, drawer: { ...DRAWER_INITIAL_STATE, bioEntityDrawerState: { diff --git a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx index 1cf3684d..259e7ac6 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/BioEntityDrawer.component.tsx @@ -1,8 +1,4 @@ import { ZERO } from '@/constants/common'; -import { - currentDrawerBioEntityRelatedSubmapSelector, - currentDrawerElementCommentsSelector, -} from '@/redux/bioEntity/bioEntity.selectors'; import { getChemicalsForBioEntityDrawerTarget, getDrugsForBioEntityDrawerTarget, @@ -18,6 +14,8 @@ import React from 'react'; import { AnnotationItemList } from '@/components/Map/Drawer/BioEntityDrawer/AnnotationItem/AnnotationItemList.component'; import { compartmentNameByIdSelector, + currentDrawerElementCommentsSelector, + currentDrawerModelElementRelatedSubmapSelector, currentDrawerModelElementSelector, } from '@/redux/modelElements/modelElements.selector'; import { CollapsibleSection } from '../ExportDrawer/CollapsibleSection'; @@ -32,7 +30,7 @@ export const BioEntityDrawer = (): React.ReactNode => { const dispatch = useAppDispatch(); const modelElement = useAppSelector(currentDrawerModelElementSelector); const commentsData = useAppSelector(currentDrawerElementCommentsSelector); - const relatedSubmap = useAppSelector(currentDrawerBioEntityRelatedSubmapSelector); + const relatedSubmap = useAppSelector(currentDrawerModelElementRelatedSubmapSelector); const currentTargetId = modelElement?.id ? `${TARGET_PREFIX}:${modelElement.id}` : ''; const fetchChemicalsForTarget = (): void => { dispatch(getChemicalsForBioEntityDrawerTarget(currentTargetId)); diff --git a/src/components/Map/Drawer/BioEntityDrawer/OverlayData/OverlayData.component.test.tsx b/src/components/Map/Drawer/BioEntityDrawer/OverlayData/OverlayData.component.test.tsx index c03ea142..80c68778 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/OverlayData/OverlayData.component.test.tsx +++ b/src/components/Map/Drawer/BioEntityDrawer/OverlayData/OverlayData.component.test.tsx @@ -1,6 +1,5 @@ /* eslint-disable no-magic-numbers */ import { ZERO } from '@/constants/common'; -import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { overlayFixture } from '@/models/fixtures/overlaysFixture'; import { GENE_VARIANTS_MOCK } from '@/models/mocks/geneVariantsMock'; import { CORE_PD_MODEL_MOCK } from '@/models/mocks/modelsMock'; @@ -61,26 +60,6 @@ describe('OverlayData - component', () => { ...INITIAL_STORE_STATE_MOCK.overlays, data: [{ ...overlayFixture, name: 'axis name' }], }, - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'pending', - error: { name: '', message: '' }, - data: [ - { - ...bioEntitiesContentFixture[0], - bioEntity: { - ...bioEntitiesContentFixture[0].bioEntity, - id: BIO_ENTITY.id, - }, - }, - ], - }, - ], - loading: 'pending', - error: { name: '', message: '' }, - }, overlayBioEntity: { ...OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK, overlaysId: [OVERLAY_ID], @@ -133,26 +112,6 @@ describe('OverlayData - component', () => { ...INITIAL_STORE_STATE_MOCK.overlays, data: [{ ...overlayFixture, name: 'overlay name' }], }, - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'pending', - error: { name: '', message: '' }, - data: [ - { - ...bioEntitiesContentFixture[0], - bioEntity: { - ...bioEntitiesContentFixture[0].bioEntity, - id: BIO_ENTITY.id, - }, - }, - ], - }, - ], - loading: 'pending', - error: { name: '', message: '' }, - }, overlayBioEntity: { ...OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK, overlaysId: [OVERLAY_ID], @@ -209,26 +168,6 @@ describe('OverlayData - component', () => { ...INITIAL_STORE_STATE_MOCK.overlays, data: [{ ...overlayFixture, name: 'overlay name' }], }, - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'pending', - error: { name: '', message: '' }, - data: [ - { - ...bioEntitiesContentFixture[0], - bioEntity: { - ...bioEntitiesContentFixture[0].bioEntity, - id: BIO_ENTITY.id, - }, - }, - ], - }, - ], - loading: 'pending', - error: { name: '', message: '' }, - }, overlayBioEntity: { ...OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK, overlaysId: [OVERLAY_ID], diff --git a/src/components/Map/Drawer/Drawer.component.test.tsx b/src/components/Map/Drawer/Drawer.component.test.tsx index b677519d..200c4fc4 100644 --- a/src/components/Map/Drawer/Drawer.component.test.tsx +++ b/src/components/Map/Drawer/Drawer.component.test.tsx @@ -1,4 +1,3 @@ -import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; import { openBioEntityDrawerById, openReactionDrawerById, @@ -12,10 +11,11 @@ import { getReduxWrapperWithStore, } from '@/utils/testing/getReduxWrapperWithStore'; import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; -import type {} from 'redux-thunk/extend-redux'; -import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { newReactionFixture } from '@/models/fixtures/newReactionFixture'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK } from '@/redux/modelElements/modelElements.mock'; import { Drawer } from './Drawer.component'; +import type {} from 'redux-thunk/extend-redux'; const renderComponent = (initialStore?: InitialStoreState): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore(initialStore); @@ -121,20 +121,18 @@ describe('Drawer - component', () => { describe('bioEntity drawer', () => { it.skip('should open drawer and display bioEntity', async () => { - const { id } = bioEntitiesContentFixture[FIRST_ARRAY_ELEMENT].bioEntity; + const { id } = modelElementFixture; const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, + }, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, }, }); 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 d0e0d9b6..12684db7 100644 --- a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.test.tsx @@ -16,6 +16,7 @@ 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 { MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK } from '@/redux/modelElements/modelElements.mock'; import { ELEMENTS_COLUMNS } from '../ExportCompound/ExportCompound.constant'; import { Elements } from './Elements.component'; @@ -133,24 +134,27 @@ describe('Elements - component', () => { }, }, 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: '' }, + data: { + 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: '' }, + }, }, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, } as ModelElementsState, }); diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx index 1a60d63d..ce08ff15 100644 --- a/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx +++ b/src/components/Map/Drawer/ExportDrawer/ExportCompound/ExportCompound.component.tsx @@ -24,7 +24,7 @@ import { ImageFormat } from './ImageFormat'; import { ImageSize } from './ImageSize'; import { DEFAULT_IMAGE_SIZE } from './ImageSize/ImageSize.constants'; import { ImageSize as ImageSizeType } from './ImageSize/ImageSize.types'; -import { IncludedCompartmentPathways } from './IncludedCompartmentPathways '; +import { IncludedCompartmentPathways } from './IncludedCompartmentPathways'; import { Submap } from './Submap'; import { getDownloadElementsBodyRequest } from './utils/getDownloadElementsBodyRequest'; import { getGraphicsDownloadUrl } from './utils/getGraphicsDownloadUrl'; 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 similarity index 100% rename from src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx rename to src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways/IncludedCompartmentPathways.component.test.tsx diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways/IncludedCompartmentPathways.component.tsx similarity index 100% rename from src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx rename to src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways/IncludedCompartmentPathways.component.tsx diff --git a/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /index.ts b/src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways/index.ts similarity index 100% rename from src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways /index.ts rename to src/components/Map/Drawer/ExportDrawer/ExportCompound/IncludedCompartmentPathways/index.ts 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 88243df1..6241bcd2 100644 --- a/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx +++ b/src/components/Map/Drawer/ExportDrawer/Network/Network.component.test.tsx @@ -16,6 +16,7 @@ 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 { MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK } from '@/redux/modelElements/modelElements.mock'; import { NETWORK_COLUMNS } from '../ExportCompound/ExportCompound.constant'; import { Network } from './Network.component'; @@ -136,24 +137,27 @@ describe('Network - component', () => { }, }, 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: '' }, + data: { + 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: '' }, + }, }, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, } as ModelElementsState, }); diff --git a/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.test.tsx b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.test.tsx index 0fe3a588..96eea1f9 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.test.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.test.tsx @@ -3,8 +3,8 @@ import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithSto import { InitialStoreState } from '@/utils/testing/getReduxStoreActionsListener'; import { StoreType } from '@/redux/store'; import { render, screen } from '@testing-library/react'; -import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { BIOENTITY_INITIAL_STATE_MOCK } from '@/redux/bioEntity/bioEntity.mock'; +import { DEFAULT_ERROR } from '@/constants/errors'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { ConnectedBioEntitiesList } from './ConnectedBioEntitiesList.component'; const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { @@ -27,11 +27,21 @@ describe('ConnectedBioEntitiesList', () => { jest.clearAllMocks(); }); - it('renders loading indicator when bioEntityLoading is pending', () => { + it('renders loading indicator when searchModelElementLoading is pending', () => { renderComponent({ - bioEntity: { - ...BIOENTITY_INITIAL_STATE_MOCK, - loading: 'pending', + modelElements: { + data: { + 0: { + data: [modelElementFixture], + loading: 'pending', + error: { message: '', name: '' }, + }, + }, + search: { + data: [], + loading: 'pending', + error: DEFAULT_ERROR, + }, }, }); @@ -41,23 +51,31 @@ describe('ConnectedBioEntitiesList', () => { }); it('renders list of bio entities when bioEntityData is available', () => { - const bioEntityData = [bioEntitiesContentFixture[0]]; - renderComponent({ - bioEntity: { - ...BIOENTITY_INITIAL_STATE_MOCK, - data: [ - { - searchQueryElement: '', + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntityData, + error: { message: '', name: '' }, }, - ], + }, + search: { + data: [ + { + searchQueryElement: '', + loading: 'idle', + error: DEFAULT_ERROR, + data: [{ modelElement: modelElementFixture, perfect: true }], + }, + ], + loading: 'idle', + error: DEFAULT_ERROR, + }, }, }); expect(screen.queryByTestId('loading-indicator')).not.toBeInTheDocument(); - expect(screen.queryByText(bioEntitiesContentFixture[0].bioEntity.name)).toBeVisible(); + expect(screen.queryByText(modelElementFixture.name)).toBeVisible(); }); }); diff --git a/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.tsx b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.tsx index ea016f66..28121e3b 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ConnectedBioEntitiesList/ConnectedBioEntitiesList.component.tsx @@ -1,15 +1,15 @@ -import { - bioEntityDataListSelector, - bioEntityLoadingSelector, -} from '@/redux/bioEntity/bioEntity.selectors'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { LoadingIndicator } from '@/shared/LoadingIndicator'; import React from 'react'; +import { + searchModelElementsListSelector, + searchModelElementsLoadingSelector, +} from '@/redux/modelElements/modelElements.selector'; import { BioEntitiesPinsListItem } from '../../SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem'; export const ConnectedBioEntitiesList = (): React.ReactNode => { - const bioEntityLoading = useAppSelector(bioEntityLoadingSelector); - const bioEntityData = useAppSelector(bioEntityDataListSelector); + const bioEntityLoading = useAppSelector(searchModelElementsLoadingSelector); + const searchModelElements = useAppSelector(searchModelElementsListSelector); const isPending = bioEntityLoading === 'pending'; if (isPending) { @@ -19,12 +19,12 @@ export const ConnectedBioEntitiesList = (): React.ReactNode => { return ( <div> <h3 className="mb-1 font-semibold">Reaction elements:</h3> - {bioEntityData && - bioEntityData.map(item => ( + {searchModelElements && + searchModelElements.map(item => ( <BioEntitiesPinsListItem - name={item.bioEntity.name} - pin={item.bioEntity} - key={item.bioEntity.name} + name={item.modelElement.name} + pin={item.modelElement} + key={item.modelElement.name} /> ))} </div> diff --git a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx index 633c55a8..4d65a3b3 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.tsx @@ -1,12 +1,14 @@ import { DrawerHeading } from '@/shared/DrawerHeading'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; -import { currentDrawerReactionCommentsSelector } from '@/redux/bioEntity/bioEntity.selectors'; import { CommentItem } from '@/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component'; 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 { + currentDrawerNewReactionSelector, + currentDrawerReactionCommentsSelector, +} from '@/redux/newReactions/newReactions.selectors'; import { ConnectedBioEntitiesList } from './ConnectedBioEntitiesList'; export const ReactionDrawer = (): React.ReactNode => { diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsList.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsList.component.tsx index 1a45d108..bfe1f365 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsList.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsList.component.tsx @@ -1,21 +1,30 @@ import { BioEntityContent } from '@/types/models'; +import { SearchModelElementDataState } from '@/redux/modelElements/modelElements.types'; import { BioEntitiesPinsListItem } from './BioEntitiesPinsListItem'; interface BioEntitiesPinsListProps { - bioEnititesPins: BioEntityContent[]; + bioEnititesPins: Array<BioEntityContent | SearchModelElementDataState>; } export const BioEntitiesPinsList = ({ bioEnititesPins }: BioEntitiesPinsListProps): JSX.Element => { return ( <ul className="h-[calc(100%-224px)] max-h-[calc(100%-224px)] overflow-auto px-6 py-2"> {bioEnititesPins && - bioEnititesPins.map(result => ( - <BioEntitiesPinsListItem - key={result.bioEntity.name} - name={result.bioEntity.name} - pin={result.bioEntity} - /> - ))} + bioEnititesPins.map(result => + 'bioEntity' in result ? ( + <BioEntitiesPinsListItem + key={result.bioEntity.name} + name={result.bioEntity.name} + pin={result.bioEntity} + /> + ) : ( + <BioEntitiesPinsListItem + key={result.modelElement.name} + name={result.modelElement.name} + pin={result.modelElement} + /> + ), + )} </ul> ); }; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.test.tsx index f5f24509..e56049b5 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.test.tsx @@ -16,7 +16,7 @@ import { getTypeBySBOTerm } from '@/utils/bioEntity/getTypeBySBOTerm'; import { newReactionsFixture } from '@/models/fixtures/newReactionsFixture'; import { HISTAMINE_MAP_ID } from '@/constants/mocks'; import { BioEntitiesPinsListItem } from './BioEntitiesPinsListItem.component'; -import { PinListBioEntity } from './BioEntitiesPinsListItem.types'; +import { PinListModelElement } from './BioEntitiesPinsListItem.types'; const BIO_ENTITY = { ...bioEntitiesContentFixture[0].bioEntity, @@ -35,7 +35,7 @@ const INITIAL_STORE_WITH_ENTITY_NUMBER: InitialStoreState = { const renderComponent = ( name: string, - pin: PinListBioEntity, + pin: PinListModelElement, initialStoreState: InitialStoreState = {}, ): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); @@ -54,7 +54,7 @@ const renderComponent = ( const renderComponentWithActionListener = ( name: string, - pin: PinListBioEntity, + pin: PinListModelElement, initialStoreState: InitialStoreState = {}, ): { store: MockStoreEnhanced<Partial<RootState>, AppDispatch> } => { const { Wrapper, store } = getReduxStoreWithActionsListener(initialStoreState); diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.tsx index d5764b93..e48cef38 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.component.tsx @@ -20,12 +20,12 @@ import { getTypeBySBOTerm } from '@/utils/bioEntity/getTypeBySBOTerm'; import { ZERO } from '@/constants/common'; import React from 'react'; import { AnnotationItemList } from '@/components/Map/Drawer/BioEntityDrawer/AnnotationItem/AnnotationItemList.component'; -import { PinListBioEntity } from './BioEntitiesPinsListItem.types'; +import { PinListModelElement } from './BioEntitiesPinsListItem.types'; import { isPinWithCoordinates } from './BioEntitiesPinsListItem.utils'; interface BioEntitiesPinsListItemProps { name: string; - pin: PinListBioEntity; + pin: PinListModelElement; } export const BioEntitiesPinsListItem = ({ @@ -38,7 +38,7 @@ export const BioEntitiesPinsListItem = ({ numberByEntityNumberIdSelector(state, pin.elementId || ''), ); const pinIconCanvas = getCanvasIcon({ - color: PINS_COLORS.bioEntity, + color: PINS_COLORS.modelElement, value: pinIconValue, }); diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.types.ts b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.types.ts index a916a1dc..a2114d00 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.types.ts +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.types.ts @@ -1,15 +1,15 @@ -import { BioEntity } from '@/types/models'; +import { ModelElement } from '@/types/models'; -export type PinListBioEntity = Pick<BioEntity, 'synonyms' | 'references'> & { - symbol?: BioEntity['symbol']; - fullName?: BioEntity['fullName']; - x?: BioEntity['x']; - y?: BioEntity['y']; - elementId?: BioEntity['elementId']; - sboTerm?: BioEntity['sboTerm']; +export type PinListModelElement = Pick<ModelElement, 'synonyms' | 'references'> & { + symbol?: ModelElement['symbol']; + fullName?: ModelElement['fullName']; + x?: ModelElement['x']; + y?: ModelElement['y']; + elementId?: ModelElement['elementId']; + sboTerm?: ModelElement['sboTerm']; }; -export type PinListBioEntityWithCoords = PinListBioEntity & { - x: BioEntity['x']; - y: BioEntity['y']; +export type PinListModelElementWithCoords = PinListModelElement & { + x: ModelElement['x']; + y: ModelElement['y']; }; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.utils.ts b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.utils.ts index af28a4c6..c1b483d2 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.utils.ts +++ b/src/components/Map/Drawer/SearchDrawerWrapper/BioEntitiesResultsList/BioEntitiesPinsList/BioEntitiesPinsListItem/BioEntitiesPinsListItem.utils.ts @@ -1,5 +1,10 @@ -import { PinListBioEntity, PinListBioEntityWithCoords } from './BioEntitiesPinsListItem.types'; +import { + PinListModelElement, + PinListModelElementWithCoords, +} from './BioEntitiesPinsListItem.types'; -export const isPinWithCoordinates = (pin: PinListBioEntity): pin is PinListBioEntityWithCoords => { +export const isPinWithCoordinates = ( + pin: PinListModelElement, +): pin is PinListModelElementWithCoords => { return Boolean('x' in pin && 'y' in pin); }; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.test.tsx index 2f20b71d..ddd82ee2 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.test.tsx @@ -1,5 +1,4 @@ -import { FIRST_ARRAY_ELEMENT, ZERO } from '@/constants/common'; -import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; +import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; import { MODELS_MOCK } from '@/models/mocks/modelsMock'; import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; import { AppDispatch, RootState, StoreType } from '@/redux/store'; @@ -12,6 +11,8 @@ import { import { render, screen } from '@testing-library/react'; import { MockStoreEnhanced } from 'redux-mock-store'; import { HISTAMINE_MAP_ID, MAIN_MAP_ID, PRKN_SUBSTRATES_MAP_ID } from '@/constants/mocks'; +import { DEFAULT_ERROR } from '@/constants/errors'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { BioEntitiesAccordion } from './BioEntitiesAccordion.component'; const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { @@ -53,17 +54,26 @@ const renderComponentWithActionListener = ( describe('BioEntitiesAccordion - component', () => { it('should display loading indicator when bioEntity search is pending', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'pending', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, + modelElements: { + data: { + 0: { + data: [modelElementFixture], + loading: 'succeeded', + error: { message: '', name: '' }, }, - ], - loading: 'pending', - error: { name: '', message: '' }, + }, + search: { + data: [ + { + searchQueryElement: '', + loading: 'pending', + error: DEFAULT_ERROR, + data: [{ modelElement: modelElementFixture, perfect: true }], + }, + ], + loading: 'pending', + error: DEFAULT_ERROR, + }, }, models: { data: [], @@ -77,17 +87,39 @@ describe('BioEntitiesAccordion - component', () => { it('should render list of maps with number of entities after succeeded bio entity search', () => { renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { name: '', message: '' }, + }, + search: { + data: [ + { + searchQueryElement: '', + loading: 'succeeded', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { ...modelElementFixture, model: HISTAMINE_MAP_ID }, + perfect: true, + }, + { + modelElement: { ...modelElementFixture, model: MAIN_MAP_ID }, + perfect: true, + }, + { + modelElement: { ...modelElementFixture, model: PRKN_SUBSTRATES_MAP_ID }, + perfect: true, + }, + ], + }, + ], + loading: 'succeeded', + error: DEFAULT_ERROR, + }, }, models: { data: MODELS_MOCK, @@ -96,40 +128,16 @@ describe('BioEntitiesAccordion - component', () => { }, }); - const countHistamine = bioEntitiesContentFixture.filter( - content => content.bioEntity.model === HISTAMINE_MAP_ID, - ).length; - const countCore = bioEntitiesContentFixture.filter( - content => content.bioEntity.model === MAIN_MAP_ID, - ).length; - const countPrkn = bioEntitiesContentFixture.filter( - content => content.bioEntity.model === PRKN_SUBSTRATES_MAP_ID, - ).length; - - const countAll = bioEntitiesContentFixture.length; - - expect(screen.getByText(`Content (${countAll})`)).toBeInTheDocument(); - expect(screen.getByText(`Core PD map (${countCore})`)).toBeInTheDocument(); - if (countHistamine > ZERO) { - expect(screen.getByText(`Histamine signaling (${countHistamine})`)).toBeInTheDocument(); - } - expect(screen.getByText(`PRKN substrates (${countPrkn})`)).toBeInTheDocument(); + expect(screen.getByText(`Content (3)`)).toBeInTheDocument(); + expect(screen.getByText(`Core PD map (1)`)).toBeInTheDocument(); + expect(screen.getByText(`Histamine signaling (1)`)).toBeInTheDocument(); + expect(screen.getByText(`PRKN substrates (1)`)).toBeInTheDocument(); }); it('should fire toggleIsContentTabOpened on accordion item button click', () => { const { store } = renderComponentWithActionListener({ ...INITIAL_STORE_STATE_MOCK, bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, - }, - ], - loading: 'succeeded', - error: { name: '', message: '' }, isContentTabOpened: false, }, models: { diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx index 8754b663..cc4d65aa 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.tsx @@ -1,9 +1,4 @@ -import { - bioEntitiesPerModelSelector, - bioEntityIsContentTabOpenedSelector, - loadingBioEntityStatusSelector, - numberOfBioEntitiesSelector, -} from '@/redux/bioEntity/bioEntity.selectors'; +import { bioEntityIsContentTabOpenedSelector } from '@/redux/bioEntity/bioEntity.selectors'; import { toggleIsContentTabOpened } from '@/redux/bioEntity/bioEntity.slice'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; @@ -13,13 +8,18 @@ import { AccordionItemHeading, AccordionItemPanel, } from '@/shared/Accordion'; +import { + numberOfSearchModelElementsSelector, + searchModelElementsLoadingStatusSelector, + searchModelElementsPerModelSelector, +} from '@/redux/modelElements/modelElements.selector'; import { BioEntitiesSubmapItem } from './BioEntitiesSubmapItem'; export const BioEntitiesAccordion = (): JSX.Element => { const dispatch = useAppDispatch(); - const bioEntitiesNumber = useAppSelector(numberOfBioEntitiesSelector); - const bioEntitiesState = useAppSelector(loadingBioEntityStatusSelector); - const bioEntitiesPerModel = useAppSelector(bioEntitiesPerModelSelector); + const searchModelElementsNumber = useAppSelector(numberOfSearchModelElementsSelector); + const searchModelElementsLoadingStatus = useAppSelector(searchModelElementsLoadingStatusSelector); + const searchModelElementsPerModel = useAppSelector(searchModelElementsPerModelSelector); const isContentTabOpened = useAppSelector(bioEntityIsContentTabOpenedSelector); const toggleTabOpened = (): void => { @@ -30,18 +30,18 @@ export const BioEntitiesAccordion = (): JSX.Element => { <AccordionItem dangerouslySetExpanded={isContentTabOpened}> <AccordionItemHeading> <AccordionItemButton onClick={toggleTabOpened}> - Content {bioEntitiesState === 'pending' && ' (Loading...)'} - {bioEntitiesState === 'succeeded' && ` (${bioEntitiesNumber})`} + Content {searchModelElementsLoadingStatus === 'pending' && ' (Loading...)'} + {searchModelElementsLoadingStatus === 'succeeded' && ` (${searchModelElementsNumber})`} </AccordionItemButton> </AccordionItemHeading> <AccordionItemPanel> - {bioEntitiesPerModel.map(model => ( + {searchModelElementsPerModel.map(model => ( <BioEntitiesSubmapItem key={model.modelName} mapName={model.modelName} mapId={model.modelId} - numberOfEntities={model.numberOfEntities} - bioEntities={model.bioEntities} + numberOfModelElements={model.numberOfModelElements} + modelElements={model.modelElements} /> ))} </AccordionItemPanel> diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx index a93282db..6b0d1c35 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.test.tsx @@ -1,7 +1,6 @@ /* eslint-disable no-magic-numbers */ import { act, render, screen } from '@testing-library/react'; import { StoreType } from '@/redux/store'; -import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { InitialStoreState, getReduxWrapperWithStore, @@ -14,6 +13,8 @@ import { openedMapsThreeSubmapsFixture, } from '@/redux/map/map.fixtures'; import { MAIN_MAP_ID } from '@/constants/mocks'; +import { DEFAULT_ERROR } from '@/constants/errors'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { BioEntitiesSubmapItem } from './BioEntitiesSubmapItem.component'; const SECOND_STEP = 2; @@ -27,8 +28,8 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St <BioEntitiesSubmapItem mapName={MODELS_MOCK_SHORT[0].name} mapId={MODELS_MOCK_SHORT[0].id} - numberOfEntities={21} - bioEntities={bioEntitiesContentFixture} + numberOfModelElements={21} + modelElements={[{ modelElement: modelElementFixture, perfect: true }]} /> </Wrapper>, ), @@ -47,17 +48,26 @@ describe('BioEntitiesSubmapItem - component', () => { }); it('should navigate user to bio enitites results list after clicking button', async () => { const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { name: '', message: '' }, + }, + search: { + data: [ + { + searchQueryElement: '', + loading: 'idle', + error: DEFAULT_ERROR, + data: [{ modelElement: modelElementFixture, perfect: true }], + }, + ], + loading: 'idle', + error: DEFAULT_ERROR, + }, }, drawer: drawerSearchStepOneFixture, }); @@ -73,25 +83,13 @@ describe('BioEntitiesSubmapItem - component', () => { }, } = store.getState(); - expect(stepType).toBe('bioEntity'); + expect(stepType).toBe('modelElement'); expect(selectedValue).toBe(undefined); expect(currentStep).toBe(SECOND_STEP); - expect(listOfBioEnitites).toBe(bioEntitiesContentFixture); + expect(listOfBioEnitites).toStrictEqual([{ modelElement: modelElementFixture, perfect: true }]); }); it("should open submap and set it to active if it's not already opened", async () => { const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, - }, - ], - loading: 'succeeded', - error: { name: '', message: '' }, - }, drawer: drawerSearchStepOneFixture, models: { data: MODELS_MOCK_SHORT, loading: 'succeeded', error: { name: '', message: '' } }, map: { @@ -100,6 +98,27 @@ describe('BioEntitiesSubmapItem - component', () => { error: { name: '', message: '' }, openedMaps: openedMapsInitialValueFixture, }, + modelElements: { + data: { + 0: { + data: [modelElementFixture], + loading: 'succeeded', + error: { message: '', name: '' }, + }, + }, + search: { + data: [ + { + searchQueryElement: '', + loading: 'idle', + error: DEFAULT_ERROR, + data: [{ modelElement: modelElementFixture, perfect: true }], + }, + ], + loading: 'idle', + error: DEFAULT_ERROR, + }, + }, }); const { @@ -134,18 +153,6 @@ describe('BioEntitiesSubmapItem - component', () => { }); it("should set map active if it's already opened", async () => { const { store } = renderComponent({ - bioEntity: { - data: [ - { - searchQueryElement: '', - loading: 'succeeded', - error: { name: '', message: '' }, - data: bioEntitiesContentFixture, - }, - ], - loading: 'succeeded', - error: { name: '', message: '' }, - }, drawer: drawerSearchStepOneFixture, models: { data: MODELS_MOCK_SHORT, loading: 'succeeded', error: { name: '', message: '' } }, map: { diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.tsx index 47f2e4b2..086ae4ce 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesSubmapItem/BioEntitiesSubmapItem.component.tsx @@ -7,20 +7,20 @@ import { mapModelIdSelector, mapOpenedMapsSelector } from '@/redux/map/map.selec import { openMapAndSetActive, setActiveMap } from '@/redux/map/map.slice'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { Icon } from '@/shared/Icon'; -import { BioEntityContent } from '@/types/models'; +import { SearchModelElementDataState } from '@/redux/modelElements/modelElements.types'; export interface BioEntitiesSubmapItemProps { mapName: string; mapId: number; - numberOfEntities: string | number; - bioEntities: BioEntityContent[]; + numberOfModelElements: string | number; + modelElements: SearchModelElementDataState[]; } export const BioEntitiesSubmapItem = ({ mapName, mapId, - numberOfEntities, - bioEntities, + numberOfModelElements, + modelElements, }: BioEntitiesSubmapItemProps): JSX.Element => { const dispatch = useAppDispatch(); const openedMaps = useAppSelector(mapOpenedMapsSelector); @@ -43,7 +43,7 @@ export const BioEntitiesSubmapItem = ({ const onSubmapClick = (): void => { openSubmap(); - dispatch(displayBioEntitiesList(bioEntities)); + dispatch(displayBioEntitiesList(modelElements)); const locationButton = document.querySelector<HTMLButtonElement>(`#${LOCATION_BTN_ID}`); if (locationButton) { @@ -59,7 +59,7 @@ export const BioEntitiesSubmapItem = ({ data-testid="bio-entites-submap-button" > <p className="text-sm font-normal"> - {mapName} ({numberOfEntities}) + {mapName} ({numberOfModelElements}) </p> <Icon name="arrow" className="h-6 w-6 fill-font-500" data-testid="arrow-icon" /> </button> diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.test.tsx index ec423275..1835a35a 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.test.tsx @@ -61,8 +61,8 @@ describe('PinsList - component ', () => { expect(screen.getByTestId('accordions-details')).toBeInTheDocument(); }); - it('should not display list of bio enities when bioEntity is searched', () => { - renderComponent([], 'bioEntity'); + it('should not display list of bio enities when modelElement is searched', () => { + renderComponent([], 'modelElement'); expect(screen.queryByTestId('pins-list')).toBeNull(); }); diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.tsx index d612aae3..931d6f33 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.component.tsx @@ -37,7 +37,7 @@ export const PinsList = ({ pinsList, type }: PinsListProps): JSX.Element => { </div> ); } - case 'bioEntity': + case 'modelElement': return <div />; case 'comment': return <div />; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.types.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.types.tsx index a72f8629..a72a61ed 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.types.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.types.tsx @@ -1,4 +1,4 @@ -import { BioEntity, Chemical, Drug, PinDetailsItem } from '@/types/models'; +import { Chemical, Drug, ModelElement, PinDetailsItem } from '@/types/models'; import { PinType } from '@/types/pin'; export type PinItem = { @@ -17,5 +17,5 @@ export type AvailableSubmaps = { export type TargetElement = { target: PinDetailsItem; - element: BioEntity; + element: ModelElement; }; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.test.tsx index ce80ff1c..d6a031e9 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.test.tsx @@ -3,15 +3,15 @@ import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFi import { chemicalsFixture } from '@/models/fixtures/chemicalsFixture'; import { drugsFixture } from '@/models/fixtures/drugFixtures'; import { AppDispatch, RootState } from '@/redux/store'; -import { BioEntity, PinDetailsItem } from '@/types/models'; +import { ModelElement, PinDetailsItem } from '@/types/models'; import { InitialStoreState } from '@/utils/testing/getReduxWrapperWithStore'; import { render, screen } from '@testing-library/react'; -// import { MODELS_MOCK_SHORT } from '@/models/mocks/modelsMock'; import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures'; import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock'; import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; import { MockStoreEnhanced } from 'redux-mock-store'; import { MAIN_MAP_ID } from '@/constants/mocks'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; import { PinTypeWithNone } from '../PinsList.types'; import { PinsListItem } from './PinsListItem.component'; @@ -26,10 +26,7 @@ const CHEMICALS_PIN = { }; const PIN_NUMBER = 10; -const BIO_ENTITY = { - ...bioEntitiesContentFixture[0].bioEntity, - model: 5053, -}; +const MODEL_ELEMENT = modelElementFixture; const INITIAL_STORE_STATE: InitialStoreState = { models: MODELS_DATA_MOCK_WITH_MAIN_MAP, @@ -48,7 +45,7 @@ const renderComponent = ( name: string, pin: PinDetailsItem, type: PinTypeWithNone, - element: BioEntity, + element: ModelElement, initialStoreState: InitialStoreState = {}, ): { store: MockStoreEnhanced<Partial<RootState>, AppDispatch> } => { const { Wrapper, store } = getReduxStoreWithActionsListener(initialStoreState); @@ -72,14 +69,14 @@ describe('PinsListItem - component ', () => { chemicalsFixture[0].targets[0].targetParticipants[1].link = 'https://example.com/plugin.js'; it('should display full name of pin', () => { - renderComponent(DRUGS_PIN.name, DRUGS_PIN.pin, 'drugs', BIO_ENTITY, INITIAL_STORE_STATE); + renderComponent(DRUGS_PIN.name, DRUGS_PIN.pin, 'drugs', MODEL_ELEMENT, INITIAL_STORE_STATE); const drugName = drugsFixture[0].targets[0].name; expect(screen.getByText(drugName)).toBeInTheDocument(); }); it('should display list of elements for pin for drugs', () => { - renderComponent(DRUGS_PIN.name, DRUGS_PIN.pin, 'drugs', BIO_ENTITY, INITIAL_STORE_STATE); + renderComponent(DRUGS_PIN.name, DRUGS_PIN.pin, 'drugs', MODEL_ELEMENT, INITIAL_STORE_STATE); const firstPinElementType = drugsFixture[0].targets[0].targetParticipants[0].type; const firstPinElementResource = drugsFixture[0].targets[0].targetParticipants[0].resource; @@ -95,7 +92,7 @@ describe('PinsListItem - component ', () => { } }); it('should display list of references for pin', () => { - renderComponent(DRUGS_PIN.name, DRUGS_PIN.pin, 'drugs', BIO_ENTITY, INITIAL_STORE_STATE); + renderComponent(DRUGS_PIN.name, DRUGS_PIN.pin, 'drugs', MODEL_ELEMENT, INITIAL_STORE_STATE); const firstPinReferenceType = drugsFixture[0].targets[0].references[0].type; const firstPinReferenceResource = drugsFixture[0].targets[0].references[0].resource; @@ -112,7 +109,7 @@ describe('PinsListItem - component ', () => { CHEMICALS_PIN.name, CHEMICALS_PIN.pin, 'chemicals', - BIO_ENTITY, + MODEL_ELEMENT, INITIAL_STORE_STATE, ); @@ -129,7 +126,7 @@ describe('PinsListItem - component ', () => { // TODO - it's probably flacky test it.skip('should not display list of elements for pin for bioentities', () => { - renderComponent(CHEMICALS_PIN.name, CHEMICALS_PIN.pin, 'drugs', BIO_ENTITY); + renderComponent(CHEMICALS_PIN.name, CHEMICALS_PIN.pin, 'drugs', MODEL_ELEMENT); const bioEntityName = bioEntitiesContentFixture[2].bioEntity.fullName ? bioEntitiesContentFixture[2].bioEntity.fullName @@ -147,7 +144,7 @@ describe('PinsListItem - component ', () => { CHEMICALS_PIN.name, chemicalWithoutSubmaps, 'chemicals', - BIO_ENTITY, + MODEL_ELEMENT, INITIAL_STORE_STATE, ); @@ -159,7 +156,7 @@ describe('PinsListItem - component ', () => { DRUGS_PIN.pin, 'drugs', { - ...BIO_ENTITY, + ...MODEL_ELEMENT, x: 1000, y: 500, }, @@ -168,7 +165,7 @@ describe('PinsListItem - component ', () => { map: { data: { ...initialMapDataFixture, - modelId: BIO_ENTITY.model, + modelId: MODEL_ELEMENT.model, }, loading: 'succeeded', error: { message: '', name: '' }, @@ -191,7 +188,7 @@ describe('PinsListItem - component ', () => { DRUGS_PIN.pin, 'drugs', { - ...BIO_ENTITY, + ...MODEL_ELEMENT, x: 1000, y: 500, model: 52, @@ -201,7 +198,7 @@ describe('PinsListItem - component ', () => { map: { data: { ...initialMapDataFixture, - modelId: BIO_ENTITY.model, + modelId: MODEL_ELEMENT.model, }, loading: 'succeeded', error: { message: '', name: '' }, diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.tsx index 510763ad..880561da 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.tsx @@ -9,7 +9,7 @@ import { mapModelIdSelector, mapOpenedMapsSelector } from '@/redux/map/map.selec import { openMapAndSetActive, setActiveMap, setMapPosition } from '@/redux/map/map.slice'; import { modelsDataSelector, modelsNameMapSelector } from '@/redux/models/models.selectors'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; -import { BioEntity, PinDetailsItem } from '@/types/models'; +import { ModelElement, PinDetailsItem } from '@/types/models'; import { AvailableSubmaps, PinTypeWithNone } from '../PinsList.types'; import { getListOfAvailableSubmaps } from './PinsListItem.component.utils'; @@ -17,7 +17,7 @@ interface PinsListItemProps { name: string; type: PinTypeWithNone; pin: PinDetailsItem; - element: BioEntity; + element: ModelElement; number: number; } diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.utils.ts b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.utils.ts index 26f45776..7a0bffd5 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.utils.ts +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsListItem/PinsListItem.component.utils.ts @@ -5,7 +5,7 @@ const MAIN_MAP_ID = 52; export const getPinColor = (type: PinTypeWithNone): string => { const pinColors: Record<PinTypeWithNone, string> = { - bioEntity: 'fill-primary-500', + modelElement: 'fill-primary-500', drugs: 'fill-orange', chemicals: 'fill-purple', comment: 'fill-blue', diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.test.tsx index 3d5b627b..a55ff780 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.test.tsx @@ -38,7 +38,7 @@ describe('SearchDrawerWrapper - component', () => { drawerName: 'search', searchDrawerState: { currentStep: 2, - stepType: 'bioEntity', + stepType: 'modelElement', selectedValue: undefined, listOfBioEnitites: [], selectedSearchElement: '', diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.tsx index 573435d0..66912c6d 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/SearchDrawerWrapper.component.tsx @@ -1,4 +1,4 @@ -import { BIO_ENTITY, DRUGS_CHEMICALS } from '@/constants'; +import { MODEL_ELEMENT, DRUGS_CHEMICALS } from '@/constants'; import { STEP } from '@/constants/searchDrawer'; import { currentStepDrawerStateSelector, @@ -15,7 +15,7 @@ export const SearchDrawerWrapper = (): JSX.Element => { const currentStep = useSelector(currentStepDrawerStateSelector); const stepType = useSelector(stepTypeDrawerSelector); - const isBioEntityType = stepType === BIO_ENTITY; + const isBioEntityType = stepType === MODEL_ELEMENT; const isChemicalsOrDrugsType = DRUGS_CHEMICALS.includes(stepType); return ( diff --git a/src/components/Map/MapAdditionalActions/utils/useVisibleBioEntitiesPolygonCoordinates.test.ts b/src/components/Map/MapAdditionalActions/utils/useVisibleBioEntitiesPolygonCoordinates.test.ts index 7cfb9304..0e377e4f 100644 --- a/src/components/Map/MapAdditionalActions/utils/useVisibleBioEntitiesPolygonCoordinates.test.ts +++ b/src/components/Map/MapAdditionalActions/utils/useVisibleBioEntitiesPolygonCoordinates.test.ts @@ -1,6 +1,5 @@ import { drugsFixture } from '@/models/fixtures/drugFixtures'; /* eslint-disable no-magic-numbers */ -import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { chemicalsFixture } from '@/models/fixtures/chemicalsFixture'; import { modelsFixture } from '@/models/fixtures/modelsFixture'; import { BIOENTITY_INITIAL_STATE_MOCK } from '@/redux/bioEntity/bioEntity.mock'; @@ -10,6 +9,9 @@ import { RootState } from '@/redux/store'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { renderHook } from '@testing-library/react'; import { HISTAMINE_MAP_ID } from '@/constants/mocks'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { DEFAULT_ERROR } from '@/constants/errors'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { CHEMICALS_INITIAL_STATE_MOCK } from '../../../../redux/chemicals/chemicals.mock'; import { DRUGS_INITIAL_STATE_MOCK } from '../../../../redux/drugs/drugs.mock'; import { DEFAULT_POSITION, MAIN_MAP, MAP_INITIAL_STATE } from '../../../../redux/map/map.constants'; @@ -65,28 +67,39 @@ const getInitalState = ( { modelId: HISTAMINE_MAP_ID, modelName: MAIN_MAP, lastPosition: DEFAULT_POSITION }, ], }, - bioEntity: { - ...BIOENTITY_INITIAL_STATE_MOCK, - data: [ - { - searchQueryElement: 'search', - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - model: HISTAMINE_MAP_ID, - x: 16, - y: 16, - z: 1, - }, - }, - ].slice(0, elementsLimit), + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', error: { message: '', name: '' }, }, - ], - }, + }, + search: { + data: [ + { + searchQueryElement: 'search', + loading: 'pending', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { + ...modelElementFixture, + model: HISTAMINE_MAP_ID, + x: 16, + y: 16, + z: 1, + }, + perfect: true, + }, + ], + }, + ].slice(0, elementsLimit), + loading: 'pending', + error: DEFAULT_ERROR, + }, + } as ModelElementsState, + bioEntity: BIOENTITY_INITIAL_STATE_MOCK, chemicals: { ...CHEMICALS_INITIAL_STATE_MOCK, data: [ 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 7a0643c5..f8e49762 100644 --- a/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/useBioEntitiesWithSubmapLinks.test.ts @@ -10,9 +10,10 @@ 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 { + MODEL_ELEMENT_LINKING_TO_SUBMAP, + MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, +} from '@/redux/modelElements/modelElements.mock'; import { useBioEntitiesWithSubmapsLinks } from './useBioEntitiesWithSubmapLinks'; const RESULT_SUBMAP_LINKS_DIFFERENT_VALUES = [ @@ -184,12 +185,15 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, modelElements: { - [MAIN_MAP_ID]: { - data: [BIO_ENTITY_LINKING_TO_SUBMAP], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 52: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, map: mapStateWithCurrentlySelectedMainMapFixture, }); @@ -214,12 +218,15 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, modelElements: { - 52: { - data: [BIO_ENTITY_LINKING_TO_SUBMAP], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 52: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -262,12 +269,15 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, modelElements: { - 52: { - data: [BIO_ENTITY_LINKING_TO_SUBMAP], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 52: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -298,12 +308,15 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, modelElements: { - 52: { - data: [BIO_ENTITY_LINKING_TO_SUBMAP], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 52: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, @@ -346,12 +359,15 @@ describe('useBioEntitiesWithSubmapsLinks', () => { }, }, modelElements: { - 52: { - data: [BIO_ENTITY_LINKING_TO_SUBMAP], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 52: { + data: [MODEL_ELEMENT_LINKING_TO_SUBMAP], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, - } as ModelElementsState, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, + }, configuration: CONFIGURATION_INITIAL_STORE_MOCKS, map: mapStateWithCurrentlySelectedMainMapFixture, diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitiesFeatures.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitiesFeatures.ts index 4103719a..0514e367 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitiesFeatures.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitiesFeatures.ts @@ -1,11 +1,11 @@ import { EntityNumber } from '@/redux/entityNumber/entityNumber.types'; -import { BioEntityWithPinType } from '@/types/bioEntity'; +import { ModelElementWithPinType } from '@/types/modelElement'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { Feature } from 'ol'; -import { getBioEntitySingleFeature } from './getBioEntitySingleFeature'; +import { getModelElementSingleFeature } from './getModelElementSingleFeature'; export const getBioEntitiesFeatures = ( - bioEntites: BioEntityWithPinType[], + bioEntites: ModelElementWithPinType[], { pointToProjection, entityNumber, @@ -17,7 +17,7 @@ export const getBioEntitiesFeatures = ( }, ): Feature[] => { return bioEntites.map(bioEntity => - getBioEntitySingleFeature(bioEntity, { + getModelElementSingleFeature(bioEntity, { pointToProjection, type: bioEntity.type, // pin's index number diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntititesFeatures.test.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntititesFeatures.test.ts index ea28c254..dc7c44c5 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntititesFeatures.test.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntititesFeatures.test.ts @@ -2,7 +2,7 @@ import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; import { bioEntitiesContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; import { PinType } from '@/types/pin'; -import { UsePointToProjectionResult, usePointToProjection } from '@/utils/map/usePointToProjection'; +import { usePointToProjection, UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { GetReduxWrapperUsingSliceReducer, getReduxWrapperWithStore, @@ -26,10 +26,9 @@ describe('getBioEntitiesFeatures - subUtil', () => { const { Wrapper } = getReduxWrapperWithStore({ map: initialMapStateFixture, }); - const bioEntititesContent = bioEntitiesContentFixture; - const bioEntities = bioEntititesContent.map(({ bioEntity }) => ({ + const bioEntities = bioEntitiesContentFixture.map(({ bioEntity }) => ({ ...bioEntity, - type: 'bioEntity' as PinType, + type: 'modelElement' as PinType, })); const pointToProjection = getPointToProjection(Wrapper); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.ts index c4114ff5..2313616d 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.ts @@ -13,7 +13,7 @@ export const getMarkerSingleFeature = ( pointToProjection: UsePointToProjectionResult; }, ): Feature => { - const feature = getPinFeature(marker, pointToProjection, 'bioEntity'); + const feature = getPinFeature(marker, pointToProjection, 'modelElement'); const style = getPinStyle({ color: addAlphaToHexString(marker.color, marker.opacity), value: marker.number, diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitySingleFeature.test.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getModelElementSingleFeature.test.ts similarity index 83% rename from src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitySingleFeature.test.ts rename to src/components/Map/MapViewer/utils/config/pinsLayer/getModelElementSingleFeature.test.ts index 2455acf1..23b9cdd9 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitySingleFeature.test.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getModelElementSingleFeature.test.ts @@ -1,6 +1,5 @@ /* eslint-disable no-magic-numbers */ import { PINS_COLORS, TEXT_COLOR } from '@/constants/canvas'; -import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; import { PinType } from '@/types/pin'; import { addAlphaToHexString } from '@/utils/convert/addAlphaToHexString'; @@ -12,7 +11,8 @@ import { import { renderHook } from '@testing-library/react'; import { Feature } from 'ol'; import Style from 'ol/style/Style'; -import { getBioEntitySingleFeature } from './getBioEntitySingleFeature'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { getModelElementSingleFeature } from './getModelElementSingleFeature'; import * as getPinStyle from './getPinStyle'; jest.mock('./getPinStyle', () => ({ @@ -30,18 +30,17 @@ const getPointToProjection = ( return usePointToProjectionHook.current; }; -describe('getBioEntitySingleFeature - subUtil', () => { +describe('getModelElementSingleFeature - subUtil', () => { const { Wrapper } = getReduxWrapperWithStore({ map: initialMapStateFixture, }); - const { bioEntity } = bioEntityContentFixture; const pointToProjection = getPointToProjection(Wrapper); const value = 1448; - const pinTypes: PinType[] = ['bioEntity', 'drugs', 'chemicals']; + const pinTypes: PinType[] = ['modelElement', 'drugs', 'chemicals']; it.each(pinTypes)('should return instance of Feature with Style type=%s', type => { - const result = getBioEntitySingleFeature(bioEntity, { + const result = getModelElementSingleFeature(modelElementFixture, { pointToProjection, type, value, @@ -57,7 +56,7 @@ describe('getBioEntitySingleFeature - subUtil', () => { it.each(pinTypes)('should run getPinStyle with valid args for type=%s', type => { const getPinStyleSpy = jest.spyOn(getPinStyle, 'getPinStyle'); - getBioEntitySingleFeature(bioEntity, { + getModelElementSingleFeature(modelElementFixture, { pointToProjection, type, value, @@ -76,7 +75,7 @@ describe('getBioEntitySingleFeature - subUtil', () => { type => { const getPinStyleSpy = jest.spyOn(getPinStyle, 'getPinStyle'); - getBioEntitySingleFeature(bioEntity, { + getModelElementSingleFeature(modelElementFixture, { pointToProjection, type, value, diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitySingleFeature.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getModelElementSingleFeature.ts similarity index 83% rename from src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitySingleFeature.ts rename to src/components/Map/MapViewer/utils/config/pinsLayer/getModelElementSingleFeature.ts index 4fd44473..18a6f337 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getBioEntitySingleFeature.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getModelElementSingleFeature.ts @@ -1,5 +1,5 @@ import { PINS_COLORS, TEXT_COLOR } from '@/constants/canvas'; -import { BioEntity } from '@/types/models'; +import { ModelElement } from '@/types/models'; import { PinType } from '@/types/pin'; import { addAlphaToHexString } from '@/utils/convert/addAlphaToHexString'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; @@ -9,8 +9,8 @@ import { getPinStyle } from './getPinStyle'; const INACTIVE_ELEMENT_OPACITY = 0.5; -export const getBioEntitySingleFeature = ( - bioEntity: BioEntity, +export const getModelElementSingleFeature = ( + modelElement: ModelElement, { pointToProjection, type, @@ -31,7 +31,7 @@ export const getBioEntitySingleFeature = ( ? TEXT_COLOR : addAlphaToHexString(TEXT_COLOR, INACTIVE_ELEMENT_OPACITY); - const feature = getPinFeature(bioEntity, pointToProjection, type); + const feature = getPinFeature(modelElement, pointToProjection, type); const style = getPinStyle({ color, value, diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinCanvasArgs.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinCanvasArgs.ts index 61726c49..104839b6 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinCanvasArgs.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinCanvasArgs.ts @@ -1,6 +1,6 @@ import { PINS_COLORS, TEXT_COLOR } from '@/constants/canvas'; import { EntityNumber } from '@/redux/entityNumber/entityNumber.types'; -import { BioEntityWithPinType } from '@/types/bioEntity'; +import { ModelElementWithPinType } from '@/types/modelElement'; import { addAlphaToHexString } from '@/utils/convert/addAlphaToHexString'; import { mix } from 'polished'; import { GetCanvasIconArgs } from '../getCanvasIcon'; @@ -15,7 +15,7 @@ interface Options { } export const getMultipinCanvasArgs = ( - { type, ...element }: BioEntityWithPinType, + { type, ...element }: ModelElementWithPinType, { entityNumber, activeIds, isDarkColor }: Options, ): GetCanvasIconArgs => { const value = entityNumber?.[element.elementId]; diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinSingleFeature.test.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinSingleFeature.test.ts index 10906ccf..d4ffaacb 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinSingleFeature.test.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinSingleFeature.test.ts @@ -2,7 +2,7 @@ import { FIRST_ARRAY_ELEMENT } from '@/constants/common'; import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { EntityNumber } from '@/redux/entityNumber/entityNumber.types'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; -import { MultiPinBioEntity } from '@/types/bioEntity'; +import { MultiPinModelElement } from '@/types/modelElement'; import { PinType } from '@/types/pin'; import { UsePointToProjectionResult, usePointToProjection } from '@/utils/map/usePointToProjection'; import { @@ -20,10 +20,10 @@ jest.mock('./getMultipinStyle', () => ({ ...jest.requireActual('./getMultipinStyle'), })); -const ONE_MULTI_BIO_ENTITIES: MultiPinBioEntity = [ +const ONE_MULTI_BIO_ENTITIES: MultiPinModelElement = [ { ...bioEntityContentFixture.bioEntity, - type: 'bioEntity' as PinType, + type: 'modelElement' as PinType, x: 100, y: 100, }, diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinSingleFeature.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinSingleFeature.ts index d7280c47..cc9e5a78 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinSingleFeature.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinSingleFeature.ts @@ -1,6 +1,6 @@ import { ONE, ZERO } from '@/constants/common'; import { EntityNumber } from '@/redux/entityNumber/entityNumber.types'; -import { BioEntityWithPinType, MultiPinBioEntity } from '@/types/bioEntity'; +import { ModelElementWithPinType, MultiPinModelElement } from '@/types/modelElement'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { Feature } from 'ol'; import { getMultipinCanvasArgs } from './getMultipinCanvasArgs'; @@ -8,7 +8,7 @@ import { getMultipinStyle } from './getMultipinStyle'; import { getPinFeature } from './getPinFeature'; export const getMultipinSingleFeature = ( - multipin: MultiPinBioEntity, + multipin: MultiPinModelElement, { pointToProjection, entityNumber, @@ -30,7 +30,7 @@ export const getMultipinSingleFeature = ( isDarkColor: true, }); - const canvasPinsArgs = sortedElements.map((element: BioEntityWithPinType) => + const canvasPinsArgs = sortedElements.map((element: ModelElementWithPinType) => getMultipinCanvasArgs(element, { activeIds, entityNumber: {}, // additional elements id's should be not visible diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntities.test.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntities.test.ts deleted file mode 100644 index 3c5778de..00000000 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntities.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { MultiPinBioEntity } from '@/types/bioEntity'; -import { PinType } from '@/types/pin'; -import { getMultipinsBioEntities } from './getMultipinsBioEntities'; - -const ZERO_MULTI_BIO_ENTITIES: MultiPinBioEntity = [ - { - ...bioEntityContentFixture.bioEntity, - type: 'bioEntity' as PinType, - }, - { - ...bioEntityContentFixture.bioEntity, - x: 1000, - type: 'bioEntity' as PinType, - }, -]; - -const ONE_MULTI_BIO_ENTITIES: MultiPinBioEntity = [ - { - ...bioEntityContentFixture.bioEntity, - type: 'bioEntity' as PinType, - x: 100, - y: 100, - }, - { - ...bioEntityContentFixture.bioEntity, - type: 'drugs' as PinType, - x: 100, - y: 100, - }, -]; - -const FEW_MULTI_BIO_ENTITIES_WITH_MULTIPLIED_TYPE: MultiPinBioEntity = [ - { - ...bioEntityContentFixture.bioEntity, - type: 'bioEntity' as PinType, - x: 100, - y: 100, - }, - { - ...bioEntityContentFixture.bioEntity, - type: 'drugs' as PinType, - x: 100, - y: 100, - }, - { - ...bioEntityContentFixture.bioEntity, - type: 'drugs' as PinType, - x: 100, - y: 100, - }, - { - ...bioEntityContentFixture.bioEntity, - type: 'drugs' as PinType, - x: 100, - y: 100, - }, -]; - -describe('getMultipinsBioEntities - util', () => { - it('should return empty array if theres no multi pins', () => { - expect(getMultipinsBioEntities({ bioEntities: ZERO_MULTI_BIO_ENTITIES })).toStrictEqual([]); - }); - - it('should return valid multi pins', () => { - expect(getMultipinsBioEntities({ bioEntities: ONE_MULTI_BIO_ENTITIES })).toStrictEqual([ - ONE_MULTI_BIO_ENTITIES, - ]); - }); - - it('should return valid multi pins if theres few types of pins', () => { - expect( - getMultipinsBioEntities({ bioEntities: FEW_MULTI_BIO_ENTITIES_WITH_MULTIPLIED_TYPE }), - ).toStrictEqual([ONE_MULTI_BIO_ENTITIES]); - }); -}); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntitiesIds.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntitiesIds.ts index ffe07c3a..385e0c95 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntitiesIds.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntitiesIds.ts @@ -1,4 +1,5 @@ -import { MultiPinBioEntity } from '@/types/bioEntity'; +import { MultiPinModelElement } from '@/types/modelElement'; -export const getMultipinBioEntititesIds = (multipins: MultiPinBioEntity[]): (string | number)[] => - multipins.flat().map(({ id }) => id); +export const getMultipinBioEntititesIds = ( + multipins: MultiPinModelElement[], +): (string | number)[] => multipins.flat().map(({ id }) => id); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsFeatures.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsFeatures.ts index 4ebcb067..01b26958 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsFeatures.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsFeatures.ts @@ -1,11 +1,11 @@ import { EntityNumber } from '@/redux/entityNumber/entityNumber.types'; -import { MultiPinBioEntity } from '@/types/bioEntity'; +import { MultiPinModelElement } from '@/types/modelElement'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { Feature } from 'ol'; import { getMultipinSingleFeature } from './getMultipinSingleFeature'; export const getMultipinFeatures = ( - multipins: MultiPinBioEntity[], + multipins: MultiPinModelElement[], { pointToProjection, entityNumber, diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsModelElements.test.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsModelElements.test.ts new file mode 100644 index 00000000..a5287405 --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsModelElements.test.ts @@ -0,0 +1,76 @@ +import { MultiPinModelElement } from '@/types/modelElement'; +import { PinType } from '@/types/pin'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { getMultipinsModelElements } from './getMultipinsModelElements'; + +const ZERO_MULTI_BIO_ENTITIES: MultiPinModelElement = [ + { + ...modelElementFixture, + type: 'modelElement' as PinType, + }, + { + ...modelElementFixture, + x: 1000, + type: 'modelElement' as PinType, + }, +]; + +const ONE_MULTI_BIO_ENTITIES: MultiPinModelElement = [ + { + ...modelElementFixture, + type: 'modelElement' as PinType, + x: 100, + y: 100, + }, + { + ...modelElementFixture, + type: 'drugs' as PinType, + x: 100, + y: 100, + }, +]; + +const FEW_MULTI_BIO_ENTITIES_WITH_MULTIPLIED_TYPE: MultiPinModelElement = [ + { + ...modelElementFixture, + type: 'modelElement' as PinType, + x: 100, + y: 100, + }, + { + ...modelElementFixture, + type: 'drugs' as PinType, + x: 100, + y: 100, + }, + { + ...modelElementFixture, + type: 'drugs' as PinType, + x: 100, + y: 100, + }, + { + ...modelElementFixture, + type: 'drugs' as PinType, + x: 100, + y: 100, + }, +]; + +describe('getMultipinsBioEntities - util', () => { + it('should return empty array if theres no multi pins', () => { + expect(getMultipinsModelElements({ modelElements: ZERO_MULTI_BIO_ENTITIES })).toStrictEqual([]); + }); + + it('should return valid multi pins', () => { + expect(getMultipinsModelElements({ modelElements: ONE_MULTI_BIO_ENTITIES })).toStrictEqual([ + ONE_MULTI_BIO_ENTITIES, + ]); + }); + + it('should return valid multi pins if theres few types of pins', () => { + expect( + getMultipinsModelElements({ modelElements: FEW_MULTI_BIO_ENTITIES_WITH_MULTIPLIED_TYPE }), + ).toStrictEqual([ONE_MULTI_BIO_ENTITIES]); + }); +}); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntities.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsModelElements.ts similarity index 53% rename from src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntities.ts rename to src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsModelElements.ts index 2ee7139c..651bf605 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsBioEntities.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMultipinsModelElements.ts @@ -1,16 +1,16 @@ import { ONE } from '@/constants/common'; -import { BioEntityWithPinType, MultiPinBioEntity } from '@/types/bioEntity'; -import { BioEntity } from '@/types/models'; +import { ModelElementWithPinType, MultiPinModelElement } from '@/types/modelElement'; +import { ModelElement } from '@/types/models'; import { PinType } from '@/types/pin'; interface Args { - bioEntities: MultiPinBioEntity; + modelElements: MultiPinModelElement; } const SEPARATOR = '-'; const POSITION_PRESCISION_SEPERATOR = '.'; -const getUniqueKey = (element: Pick<BioEntity, 'x' | 'y'>): string => { +const getUniqueKey = (element: Pick<ModelElement, 'x' | 'y'>): string => { const [x] = `${element.x}`.split(POSITION_PRESCISION_SEPERATOR); const [y] = `${element.y}`.split(POSITION_PRESCISION_SEPERATOR); @@ -18,9 +18,9 @@ const getUniqueKey = (element: Pick<BioEntity, 'x' | 'y'>): string => { }; const groupByPosition = ( - accumulator: Record<string, MultiPinBioEntity>, - element: BioEntityWithPinType, -): Record<string, MultiPinBioEntity> => { + accumulator: Record<string, MultiPinModelElement>, + element: ModelElementWithPinType, +): Record<string, MultiPinModelElement> => { const key = getUniqueKey(element); return { @@ -29,25 +29,25 @@ const groupByPosition = ( }; }; -const toUniqueTypeMultipin = (multipin: MultiPinBioEntity): MultiPinBioEntity => { +const toUniqueTypeMultipin = (multipin: MultiPinModelElement): MultiPinModelElement => { const allTypes: PinType[] = multipin.map(pin => pin.type); const uniqueTypes = [...new Set(allTypes)]; return uniqueTypes .map(type => multipin.find(pin => pin.type === type)) - .filter((value): value is BioEntityWithPinType => value !== undefined); + .filter((value): value is ModelElementWithPinType => value !== undefined); }; -export const getMultipinsBioEntities = ({ bioEntities }: Args): MultiPinBioEntity[] => { - const multipiledBioEntities = bioEntities.filter( +export const getMultipinsModelElements = ({ modelElements }: Args): MultiPinModelElement[] => { + const multipiledModelElements = modelElements.filter( baseElement => - bioEntities.filter(element => getUniqueKey(baseElement) === getUniqueKey(element)).length > + modelElements.filter(element => getUniqueKey(baseElement) === getUniqueKey(element)).length > ONE, ); - const duplicatedMultipinsGroupedByPosition = multipiledBioEntities.reduce( + const duplicatedMultipinsGroupedByPosition = multipiledModelElements.reduce( groupByPosition, - {} as Record<string, MultiPinBioEntity>, + {} as Record<string, MultiPinModelElement>, ); const allGroupedMultipins = Object.values(duplicatedMultipinsGroupedByPosition); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.test.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.test.ts index c6ab6781..fd525724 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.test.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.test.ts @@ -17,7 +17,7 @@ describe('getPinFeature - subUtil', () => { wrapper: Wrapper, }); const pointToProjection = usePointToProjectionHook.current; - const result = getPinFeature(bioEntity, pointToProjection, 'bioEntity'); + const result = getPinFeature(bioEntity, pointToProjection, 'modelElement'); it('should return instance of Feature', () => { expect(result).toBeInstanceOf(Feature); @@ -38,7 +38,7 @@ describe('getPinFeature - subUtil', () => { }); describe('when is Marker Pin', () => { - const pinMarkerResult = getPinFeature(PIN_MARKER, pointToProjection, 'bioEntity'); + const pinMarkerResult = getPinFeature(PIN_MARKER, pointToProjection, 'modelElement'); it('should return point parsed with point to projection', () => { const [x, y] = pinMarkerResult.getGeometry()?.getExtent() || []; diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts index 5113acc7..ae2e8d05 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts @@ -1,7 +1,7 @@ import { ZERO } from '@/constants/common'; import { HALF } from '@/constants/dividers'; import { FEATURE_TYPE } from '@/constants/features'; -import { BioEntity, MarkerWithPosition } from '@/types/models'; +import { ModelElement, MarkerWithPosition } from '@/types/models'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import isUUID from 'is-uuid'; import { Feature } from 'ol'; @@ -15,7 +15,7 @@ export const getPinFeature = ( width, height, id, - }: Pick<BioEntity, 'id' | 'width' | 'height' | 'x' | 'y'> | MarkerWithPosition, + }: Pick<ModelElement, 'id' | 'width' | 'height' | 'x' | 'y'> | MarkerWithPosition, pointToProjection: UsePointToProjectionResult, pinType: PinType, ): Feature => { diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts index c2e6d908..f7b6001c 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts @@ -5,7 +5,7 @@ import { } from '@/redux/bioEntity/bioEntity.selectors'; import { entityNumberDataSelector } from '@/redux/entityNumber/entityNumber.selectors'; import { markersPinsOfCurrentMapDataSelector } from '@/redux/markers/markers.selectors'; -import { BioEntity } from '@/types/models'; +import { ModelElement } from '@/types/models'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; import Feature from 'ol/Feature'; import { Geometry } from 'ol/geom'; @@ -16,26 +16,26 @@ 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'; +import { getMultipinsModelElements } from './getMultipinsModelElements'; import { getMultipinBioEntititesIds } from './getMultipinsBioEntitiesIds'; import { getMultipinFeatures } from './getMultipinsFeatures'; export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>>> => { const pointToProjection = usePointToProjection(); const activeIds = useSelector(allVisibleBioEntitiesIdsSelector); - const bioEntities = useSelector(allBioEntitiesWithTypeOfCurrentMapSelector); + const modelElements = useSelector(allBioEntitiesWithTypeOfCurrentMapSelector); const markersEntities = useSelector(markersPinsOfCurrentMapDataSelector); const entityNumber = useSelector(entityNumberDataSelector); const multiPinsBioEntities = useMemo( () => - getMultipinsBioEntities({ - bioEntities, + getMultipinsModelElements({ + modelElements, }), - [bioEntities], + [modelElements], ); const multipinsIds = getMultipinBioEntititesIds(multiPinsBioEntities); const isMultiPin = useCallback( - (b: BioEntity): boolean => multipinsIds.includes(b.id), + (b: ModelElement): boolean => multipinsIds.includes(b.id), [multipinsIds], ); @@ -43,7 +43,7 @@ export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>> () => [ getBioEntitiesFeatures( - bioEntities.filter(b => !isMultiPin(b)), + modelElements.filter(b => !isMultiPin(b)), { pointToProjection, entityNumber, @@ -58,7 +58,7 @@ export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>> getMarkersFeatures(markersEntities, { pointToProjection }), ].flat(), [ - bioEntities, + modelElements, pointToProjection, entityNumber, activeIds, diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleOpenImmediateLink.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleOpenImmediateLink.ts index 360df8c0..503b0f69 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleOpenImmediateLink.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleOpenImmediateLink.ts @@ -1,7 +1,7 @@ -import { BioEntity } from '@/types/models'; import { showToast } from '@/utils/showToast'; +import { ModelElement } from '@/types/models'; -export const handleOpenImmediateLink = (bioEntity: BioEntity): void => { +export const handleOpenImmediateLink = (bioEntity: ModelElement): void => { const link = bioEntity.immediateLink; if (link !== null) { const tab = window.open(link, '_blank'); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.ts index 2cd86bfa..9cca9135 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction.ts @@ -2,21 +2,20 @@ import { openReactionDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; import { AppDispatch } from '@/redux/store'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; -import { BioEntity, ModelElement, NewReaction } from '@/types/models'; +import { ModelElement, NewReaction } from '@/types/models'; import { FEATURE_TYPE } from '@/constants/features'; -import { setMultipleBioEntityContents } from '@/redux/bioEntity/bioEntity.slice'; import { addNumbersToEntityNumberData } from '@/redux/entityNumber/entityNumber.slice'; import { setReactions } from '@/redux/reactions/reactions.slice'; -import { mapReactionToBioEntity } from '@/utils/bioEntity/mapReactionToBioEntity'; +import { mapReactionToModelElement } from '@/utils/bioEntity/mapReactionToModelElement'; import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction'; -import { mapModelElementToBioEntity } from '@/utils/bioEntity/mapModelElementToBioEntity'; +import { setMultipleModelElementSearch } from '@/redux/modelElements/modelElements.slice'; /* prettier-ignore */ export const clickHandleReaction = (dispatch: AppDispatch, hasFitBounds = false) => ( modelElements: Array<ModelElement>, reactions: Array<NewReaction>, reactionId: number, modelId: number): void => { - const reactionBioEntities: Array<BioEntity> = []; + const reactionModelElements: Array<ModelElement> = []; const reaction = reactions.find(newReaction => newReaction.id === reactionId); if(!reaction) { return; @@ -29,20 +28,20 @@ export const clickHandleReaction = if(!modelElement) { return; } - reactionBioEntities.push(mapModelElementToBioEntity(modelElement)); + reactionModelElements.push(modelElement); }); dispatch(openReactionDrawerById(reactionId)); dispatch(selectTab('')); - const bioEntityReaction = mapReactionToBioEntity(reaction); - dispatch(setMultipleBioEntityContents(reactionBioEntities)); - dispatch(addNumbersToEntityNumberData(reactionBioEntities.map(reactionBioEntity => reactionBioEntity.elementId))); + const reactionModelElement = mapReactionToModelElement(reaction); + dispatch(setMultipleModelElementSearch(reactionModelElements)); + dispatch(addNumbersToEntityNumberData(reactionModelElements.map(modelElement => modelElement.elementId))); dispatch(setReactions([reaction])); - const result = reactionBioEntities.map((bioEntity) => {return { bioEntity, perfect: true };}); - result.push({ bioEntity: bioEntityReaction, perfect: true }); + const result = reactionModelElements.map((modelElement) => {return { modelElement, perfect: true };}); + result.push({ modelElement: reactionModelElement, perfect: true }); PluginsEventBus.dispatchEvent('onSearch', { type: 'reaction', searchValues: [{ id: reactionId, modelId, type: FEATURE_TYPE.REACTION }], 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 17b253ef..a27080be 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 @@ -37,9 +37,9 @@ describe('leftClickHandleAlias', () => { type: 'bioEntity', searchValues: [{ id: 1, modelId, type: FEATURE_TYPE.ALIAS }], results: [ - mockBioEntities.map(bioEntity => ({ + mockBioEntities.map(modelElement => ({ perfect: true, - bioEntity, + bioEntity: modelElement, })), ], }); 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 50d3f5b6..2ce079a2 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias.ts @@ -5,8 +5,8 @@ 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 { setModelElementSearch } from '@/redux/modelElements/modelElements.slice'; import { handleOpenImmediateLink } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleOpenImmediateLink'; /* prettier-ignore */ @@ -26,7 +26,7 @@ export const leftClickHandleAlias = dispatch(selectTab(`${id}`)); dispatch(openBioEntityDrawerById(id)); - dispatch(setMultipleBioEntityContents([modelElement])); + dispatch(setModelElementSearch({ modelElement, perfect: true })); dispatch(addNumbersToEntityNumberData([modelElement.elementId])); const searchValue = { id, modelId, type: FEATURE_TYPE.ALIAS }; 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 6cf59664..a47c88a2 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 @@ -2,7 +2,6 @@ import { updateLastClick } from '@/redux/map/map.slice'; import { closeDrawer } from '@/redux/drawer/drawer.slice'; import { resetReactionsData } from '@/redux/reactions/reactions.slice'; -import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick'; import Map from 'ol/Map'; import { onMapLeftClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick'; @@ -12,6 +11,7 @@ import { Feature } from 'ol'; import { FEATURE_TYPE } from '@/constants/features'; import VectorLayer from 'ol/layer/Vector'; import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { clearSearchModelElements } from '@/redux/modelElements/modelElements.slice'; import * as leftClickHandleAlias from './leftClickHandleAlias'; import * as clickHandleReaction from '../clickHandleReaction'; @@ -69,7 +69,7 @@ describe('onMapLeftClick', () => { expect(dispatch).toHaveBeenCalledWith(updateLastClick(expect.any(Object))); expect(dispatch).toHaveBeenCalledWith(closeDrawer()); expect(dispatch).toHaveBeenCalledWith(resetReactionsData()); - expect(dispatch).toHaveBeenCalledWith(clearBioEntities()); + expect(dispatch).toHaveBeenCalledWith(clearSearchModelElements()); }); it('calls leftClickHandleAlias if feature type is ALIAS', async () => { 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 c62b97bf..3502d52e 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts @@ -7,7 +7,6 @@ import { updateLastClick } from '@/redux/map/map.slice'; import { toLonLat } from 'ol/proj'; import { latLngToPoint } from '@/utils/map/latLngToPoint'; import { closeDrawer } from '@/redux/drawer/drawer.slice'; -import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; import { leftClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/leftClickHandleAlias'; import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseLeftClick/handleFeaturesClick'; import { resetReactionsData } from '@/redux/reactions/reactions.slice'; @@ -15,6 +14,7 @@ import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mous import { FEATURE_TYPE } from '@/constants/features'; import { clickHandleReaction } from '@/components/Map/MapViewer/utils/listeners/mouseClick/clickHandleReaction'; import getFeatureAtCoordinate from '@/components/Map/MapViewer/utils/listeners/mouseClick/getFeatureAtCoordinate'; +import { clearSearchModelElements } from '@/redux/modelElements/modelElements.slice'; /* prettier-ignore */ export const onMapLeftClick = @@ -52,7 +52,7 @@ export const onMapLeftClick = } dispatch(resetReactionsData()); - dispatch(clearBioEntities()); + dispatch(clearSearchModelElements()); return; } diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts index ae53b95c..9aa9dea6 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.test.ts @@ -1,9 +1,9 @@ /* eslint-disable no-magic-numbers */ import { rightClickHandleAlias } from '@/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias'; import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; -import { setBioEntityContents } from '@/redux/bioEntity/bioEntity.slice'; import { addNumbersToEntityNumberData } from '@/redux/entityNumber/entityNumber.slice'; import { setCurrentSelectedBioEntityId } from '@/redux/contextMenu/contextMenu.slice'; +import { setModelElementSearch } from '@/redux/modelElements/modelElements.slice'; jest.mock('../../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); @@ -19,7 +19,7 @@ describe('rightClickHandleAlias', () => { await rightClickHandleAlias(dispatch)(modelElementFixture.id, modelElementFixture); expect(dispatch).toHaveBeenCalledTimes(3); - expect(dispatch).toHaveBeenCalledWith(setBioEntityContents(expect.any(Object))); + expect(dispatch).toHaveBeenCalledWith(setModelElementSearch(expect.any(Object))); expect(dispatch).toHaveBeenCalledWith( addNumbersToEntityNumberData([modelElementFixture.elementId]), ); diff --git a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts index 4968eea6..05acb8af 100644 --- a/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts +++ b/src/components/Map/MapViewer/utils/listeners/mouseClick/mouseRightClick/rightClickHandleAlias.ts @@ -1,16 +1,14 @@ import { setCurrentSelectedBioEntityId } from '@/redux/contextMenu/contextMenu.slice'; import { AppDispatch } from '@/redux/store'; import { ModelElement } from '@/types/models'; -import { setBioEntityContents } from '@/redux/bioEntity/bioEntity.slice'; import { addNumbersToEntityNumberData } from '@/redux/entityNumber/entityNumber.slice'; -import { mapModelElementToBioEntity } from '@/utils/bioEntity/mapModelElementToBioEntity'; +import { setModelElementSearch } from '@/redux/modelElements/modelElements.slice'; /* prettier-ignore */ export const rightClickHandleAlias = (dispatch: AppDispatch) => async (id: number, modelElement: ModelElement): Promise<void> => { - const bioEntity = mapModelElementToBioEntity(modelElement); - dispatch(setBioEntityContents({ bioEntity, perfect: true })); - dispatch(addNumbersToEntityNumberData([bioEntity.elementId])); + dispatch(setModelElementSearch({ modelElement, perfect: true })); + dispatch(addNumbersToEntityNumberData([modelElement.elementId])); dispatch(setCurrentSelectedBioEntityId(id)); }; diff --git a/src/components/Map/MapViewer/utils/listeners/pinIconClick/useHandlePinIconClick.test.ts b/src/components/Map/MapViewer/utils/listeners/pinIconClick/useHandlePinIconClick.test.ts index 9f65d1d9..5f69920e 100644 --- a/src/components/Map/MapViewer/utils/listeners/pinIconClick/useHandlePinIconClick.test.ts +++ b/src/components/Map/MapViewer/utils/listeners/pinIconClick/useHandlePinIconClick.test.ts @@ -1,9 +1,10 @@ import { ZERO } from '@/constants/common'; -import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { initialStateFixture } from '@/redux/drawer/drawerFixture'; import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures'; import { getReduxStoreWithActionsListener } from '@/utils/testing/getReduxStoreActionsListener'; import { renderHook } from '@testing-library/react'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { DEFAULT_ERROR } from '@/constants/errors'; import { useHandlePinIconClick } from './useHandlePinIconClick'; describe('useHandlePinIconClick - util', () => { @@ -12,27 +13,36 @@ describe('useHandlePinIconClick - util', () => { const pinId = 123; const { Wrapper, store } = getReduxStoreWithActionsListener({ ...INITIAL_STORE_STATE_MOCK, - bioEntity: { - data: [ - { - searchQueryElement: '', + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - id: pinId, - model: ZERO, - }, - }, - ], + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, + }, + search: { + data: [ + { + searchQueryElement: '', + loading: 'succeeded', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { + ...modelElementFixture, + fullName: null, + id: pinId, + model: ZERO, + }, + perfect: true, + }, + ], + }, + ], + loading: 'pending', + error: DEFAULT_ERROR, + }, }, }); @@ -64,27 +74,36 @@ describe('useHandlePinIconClick - util', () => { selectedSearchElement: 'search-tab', }, }, - bioEntity: { - data: [ - { - searchQueryElement: 'search-tab', + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - id: pinId, - model: ZERO, - }, - }, - ], + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, + }, + search: { + data: [ + { + searchQueryElement: 'search-tab', + loading: 'succeeded', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { + ...modelElementFixture, + fullName: null, + id: pinId, + model: ZERO, + }, + perfect: true, + }, + ], + }, + ], + loading: 'pending', + error: DEFAULT_ERROR, + }, }, }); @@ -104,7 +123,7 @@ describe('useHandlePinIconClick - util', () => { }); describe('when pin is marker', () => { - const pinId = 'af57c6ce-8b83-47e4-a7eb-9511634c7c5f'; + const pinId = 1; const { Wrapper, store } = getReduxStoreWithActionsListener({ ...INITIAL_STORE_STATE_MOCK, drawer: { @@ -116,27 +135,36 @@ describe('useHandlePinIconClick - util', () => { selectedSearchElement: 'search-tab', }, }, - bioEntity: { - data: [ - { - searchQueryElement: 'search-tab', + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - id: pinId, - model: ZERO, - }, - }, - ], + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, + }, + search: { + data: [ + { + searchQueryElement: 'search-tab', + loading: 'succeeded', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { + ...modelElementFixture, + fullName: null, + id: pinId, + model: ZERO, + }, + perfect: true, + }, + ], + }, + ], + loading: 'pending', + error: DEFAULT_ERROR, + }, }, }); @@ -168,27 +196,36 @@ describe('useHandlePinIconClick - util', () => { selectedSearchElement: 'search-tab-2', }, }, - bioEntity: { - data: [ - { - searchQueryElement: 'search-tab', + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - fullName: null, - id: pinId, - model: ZERO, - }, - }, - ], + error: { message: '', name: '' }, }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, + }, + search: { + data: [ + { + searchQueryElement: 'search-tab', + loading: 'succeeded', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { + ...modelElementFixture, + fullName: null, + id: pinId, + model: ZERO, + }, + perfect: true, + }, + ], + }, + ], + loading: 'pending', + error: DEFAULT_ERROR, + }, }, }); diff --git a/src/constants/canvas.ts b/src/constants/canvas.ts index e5ab204a..ff6f4258 100644 --- a/src/constants/canvas.ts +++ b/src/constants/canvas.ts @@ -15,7 +15,7 @@ export const PIN_SIZE = { export const PINS_COLORS: Record<PinType, string> = { drugs: '#F48C41', chemicals: '#008325', - bioEntity: '#106AD7', + modelElement: '#106AD7', comment: '#106AD7', }; diff --git a/src/constants/index.ts b/src/constants/index.ts index 4cfb0b9b..5f890d3f 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -8,7 +8,7 @@ export const BASE_NEW_API_URL = getConfigValue('BASE_NEW_API_URL'); export const DEFAULT_PROJECT_ID = getConfigValue('DEFAULT_PROJECT_ID'); export const PROJECT_ID = getProjectIdFromUrl() || DEFAULT_PROJECT_ID; export const ZOD_SEED = parseInt(process.env.ZOD_SEED || '123', 10); -export const BIO_ENTITY = 'bioEntity'; +export const MODEL_ELEMENT = 'modelElement'; export const DRUGS_CHEMICALS = ['drugs', 'chemicals']; export const MINERVA_WEBSITE_URL = 'https://minerva.pages.uni.lu/doc/'; export const ADMIN_PANEL_URL = getConfigValue('ADMIN_PANEL_URL'); diff --git a/src/constants/pin.ts b/src/constants/pin.ts deleted file mode 100644 index 0af91625..00000000 --- a/src/constants/pin.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { PinType } from '@/types/pin'; - -export const DEFAULT_PIN_TYPE: PinType = 'bioEntity'; diff --git a/src/models/bioEntitySchema.ts b/src/models/bioEntitySchema.ts index 8a347db6..6d4d375d 100644 --- a/src/models/bioEntitySchema.ts +++ b/src/models/bioEntitySchema.ts @@ -1,17 +1,17 @@ import { ZERO } from '@/constants/common'; import { z } from 'zod'; import { reactionProduct } from '@/models/reactionProduct'; +import { modelElementModificationSchema } from '@/models/modelElementModificationSchema'; import { colorSchema } from './colorSchema'; import { glyphSchema } from './glyphSchema'; import { lineSchema } from './lineSchema'; -import { modificationResiduesSchema } from './modificationResiduesSchema'; import { operatorSchema } from './operatorSchema'; import { referenceSchema } from './referenceSchema'; import { structuralStateSchema } from './structuralStateSchema'; import { submodelSchema } from './submodelSchema'; export const bioEntitySchema = z.object({ - id: z.union([z.number().int().positive(), z.string()]), + id: z.number().int().positive(), immediateLink: z.string().nullable().optional(), name: z.string(), elementId: z.string(), @@ -21,12 +21,12 @@ export const bioEntitySchema = z.object({ notes: z.string(), symbol: z.string().nullable(), homodimer: z.number().optional(), - nameX: z.number().nullable().optional(), - nameY: z.number().nullable().optional(), - nameWidth: z.number().nullable().optional(), - nameHeight: z.number().nullable().optional(), - nameVerticalAlign: z.string().nullable().optional(), - nameHorizontalAlign: z.string().nullable().optional(), + nameX: z.number(), + nameY: z.number(), + nameWidth: z.number(), + nameHeight: z.number(), + nameVerticalAlign: z.enum(['TOP', 'MIDDLE', 'BOTTOM']), + nameHorizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER', 'END', 'START']), width: z .number() .optional() @@ -35,15 +35,15 @@ export const bioEntitySchema = z.object({ .number() .optional() .transform(height => height ?? ZERO), - visibilityLevel: z.string().nullable(), - transparencyLevel: z.string().nullable().optional(), + visibilityLevel: z.string(), + transparencyLevel: z.string(), synonyms: z.array(z.string()), - formerSymbols: z.array(z.string()).nullable().optional(), - fullName: z.string().nullable().nullable().optional(), + formerSymbols: z.array(z.string()), + fullName: z.string().nullable(), compartmentName: z.string().nullable().optional(), abbreviation: z.string().nullable(), formula: z.string().nullable(), - glyph: glyphSchema.nullable().optional(), + glyph: glyphSchema.nullable(), activity: z.boolean().optional(), structuralState: z.optional(structuralStateSchema.nullable()), hypothetical: z.boolean().nullable().optional(), @@ -54,11 +54,11 @@ export const bioEntitySchema = z.object({ charge: z.number().nullable().optional(), substanceUnits: z.boolean().nullable().optional(), onlySubstanceUnits: z.boolean().optional().nullable(), - shape: z.string().nullable().optional(), - modificationResidues: z.optional(z.array(modificationResiduesSchema)), + shape: z.enum(['SQUARE_COMPARTMENT', 'OVAL_COMPARTMENT', 'PATHWAY']).optional(), + modificationResidues: z.array(modelElementModificationSchema).optional(), complex: z.number().nullable().optional(), - compartment: z.number().nullable().optional(), - submodel: submodelSchema.nullable().optional(), + compartment: z.number().nullable(), + submodel: submodelSchema.nullable(), x: z .number() .optional() @@ -68,10 +68,10 @@ export const bioEntitySchema = z.object({ .optional() .transform(y => y ?? ZERO), lineWidth: z.number().optional(), - fontColor: colorSchema.nullable().optional(), - fontSize: z.number().nullable().optional(), - fillColor: colorSchema.nullable().optional(), - borderColor: colorSchema.nullable().optional(), + fontColor: colorSchema, + fontSize: z.number(), + fillColor: colorSchema, + borderColor: colorSchema, smiles: z.optional(z.string()).nullable(), inChI: z.optional(z.string().nullable()), inChIKey: z.optional(z.string().nullable()), diff --git a/src/models/fixtures/bioEntityFixture.ts b/src/models/fixtures/publicationElementFixture.ts similarity index 55% rename from src/models/fixtures/bioEntityFixture.ts rename to src/models/fixtures/publicationElementFixture.ts index 652ee55c..29763060 100644 --- a/src/models/fixtures/bioEntityFixture.ts +++ b/src/models/fixtures/publicationElementFixture.ts @@ -1,9 +1,9 @@ import { ZOD_SEED } from '@/constants'; // eslint-disable-next-line import/no-extraneous-dependencies import { createFixture } from 'zod-fixture'; -import { bioEntitySchema } from '@/models/bioEntitySchema'; +import { publicationElementSchema } from '@/models/publicationElementSchema'; -export const bioEntityFixture = createFixture(bioEntitySchema, { +export const publicationElementFixture = createFixture(publicationElementSchema, { seed: ZOD_SEED, array: { min: 2, max: 2 }, }); diff --git a/src/models/mocks/publicationsResponseMock.ts b/src/models/mocks/publicationsResponseMock.ts index 01240a65..45ec7d94 100644 --- a/src/models/mocks/publicationsResponseMock.ts +++ b/src/models/mocks/publicationsResponseMock.ts @@ -1,12 +1,12 @@ import { FilteredPageOf, Publication } from '@/types/models'; -import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; +import { publicationElementFixture } from '@/models/fixtures/publicationElementFixture'; export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publication> = { content: [ { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 19519, model: 52, }, @@ -24,7 +24,7 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 16167, model: 61, }, @@ -55,12 +55,12 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 17823, model: 52, }, { - ...bioEntityFixture, + ...publicationElementFixture, id: 19461, model: 52, }, @@ -79,12 +79,12 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 18189, model: 52, }, { - ...bioEntityFixture, + ...publicationElementFixture, id: 18729, model: 52, }, @@ -102,12 +102,12 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 16077, model: 58, }, { - ...bioEntityFixture, + ...publicationElementFixture, id: 16135, model: 58, }, @@ -137,7 +137,7 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 15955, model: 55, }, @@ -166,12 +166,12 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 15937, model: 55, }, { - ...bioEntityFixture, + ...publicationElementFixture, id: 15955, model: 55, }, @@ -190,7 +190,7 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 15948, model: 55, }, @@ -209,7 +209,7 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 16286, model: 62, }, @@ -236,12 +236,12 @@ export const PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK: FilteredPageOf<Publicati { elements: [ { - ...bioEntityFixture, + ...publicationElementFixture, id: 17780, model: 52, }, { - ...bioEntityFixture, + ...publicationElementFixture, id: 17937, model: 52, }, diff --git a/src/models/modelElementSchema.ts b/src/models/modelElementSchema.ts index 7f8cf7a5..60379965 100644 --- a/src/models/modelElementSchema.ts +++ b/src/models/modelElementSchema.ts @@ -6,12 +6,12 @@ import { modelElementModificationSchema } from '@/models/modelElementModificatio import { glyphSchema } from '@/models/glyphSchema'; export const modelElementSchema = z.object({ - id: z.number(), + id: z.number().int().positive(), model: z.number(), glyph: glyphSchema.nullable(), submodel: submodelSchema.nullable(), compartment: z.number().nullable(), - immediateLink: z.string().nullable(), + immediateLink: z.string().nullable().optional(), elementId: z.string(), x: z.number(), y: z.number(), diff --git a/src/models/publicationElementSchema.ts b/src/models/publicationElementSchema.ts new file mode 100644 index 00000000..9bd5e4f0 --- /dev/null +++ b/src/models/publicationElementSchema.ts @@ -0,0 +1,35 @@ +import { z } from 'zod'; +import { reactionProduct } from '@/models/reactionProduct'; +import { lineSchema } from './lineSchema'; +import { operatorSchema } from './operatorSchema'; +import { referenceSchema } from './referenceSchema'; + +export const publicationElementSchema = z.object({ + abbreviation: z.string().nullable(), + elementId: z.string(), + formula: z.string().nullable(), + geneProteinReaction: z.string().nullable().optional(), + id: z.union([z.number().int().positive(), z.string()]), + idReaction: z.string().optional(), + kinetics: z.null().optional(), + line: lineSchema.optional(), + lowerBound: z.boolean().nullable().optional(), + mechanicalConfidenceScore: z.boolean().nullable().optional(), + model: z.number(), + modifiers: z.array(reactionProduct).optional(), + name: z.string(), + notes: z.string(), + operators: z.array(operatorSchema).optional(), + processCoordinates: z.null().optional(), + products: z.array(reactionProduct).optional(), + reactants: z.array(reactionProduct).optional(), + references: z.array(referenceSchema), + reversible: z.boolean().optional(), + sboTerm: z.string(), + subsystem: z.string().nullable().optional(), + symbol: z.string().nullable(), + synonyms: z.array(z.string()), + upperBound: z.boolean().nullable().optional(), + visibilityLevel: z.string(), + z: z.number(), +}); diff --git a/src/models/publicationsSchema.ts b/src/models/publicationsSchema.ts index 14ac77ff..8fff78d7 100644 --- a/src/models/publicationsSchema.ts +++ b/src/models/publicationsSchema.ts @@ -1,8 +1,8 @@ import { z } from 'zod'; -import { bioEntitySchema } from '@/models/bioEntitySchema'; +import { publicationElementSchema } from '@/models/publicationElementSchema'; import { articleSchema } from './articleSchema'; export const publicationSchema = z.object({ - elements: z.array(bioEntitySchema), + elements: z.array(publicationElementSchema), article: articleSchema, }); diff --git a/src/models/targetSchema.ts b/src/models/targetSchema.ts index 015626e1..a9f48063 100644 --- a/src/models/targetSchema.ts +++ b/src/models/targetSchema.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { bioEntitySchema } from './bioEntitySchema'; +import { modelElementSchema } from '@/models/modelElementSchema'; import { referenceSchema } from './referenceSchema'; import { targetParticipantSchema } from './targetParticipantSchema'; @@ -9,7 +9,7 @@ export const targetSchema = z.object({ /** list of target references */ references: z.array(referenceSchema), /** list of elements on the map associated with this target */ - targetElements: z.array(bioEntitySchema), + targetElements: z.array(modelElementSchema), /** list of identifiers associated with this target */ targetParticipants: z.array(targetParticipantSchema), }); diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index 93d49308..fcb92f40 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -24,8 +24,6 @@ export const apiPath = { isPerfectMatch, }: PerfectSearchParams): string => `projects/${PROJECT_ID}/models/*/bioEntities/:search?query=${searchQuery}&size=1000&perfectMatch=${isPerfectMatch}`, - getReactionsWithIds: (ids: number[]): string => - `projects/${PROJECT_ID}/models/*/bioEntities/reactions/?id=${ids.join(',')}&size=1000`, getDrugsStringWithQuery: (searchQuery: string): string => `projects/${PROJECT_ID}/drugs:search?query=${searchQuery}`, getDrugsStringWithColumnsTarget: (columns: string, target: string): string => @@ -56,9 +54,9 @@ export const apiPath = { `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}`, addLayerImageObject: (modelId: number, layerId: number): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/images/`, - updateLayerImageObject: (modelId: number, layerId: number, imageId: number): string => + updateLayerImageObject: (modelId: number, layerId: number, imageId: number | string): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/images/${imageId}`, - removeLayerImageObject: (modelId: number, layerId: number, imageId: number): string => + removeLayerImageObject: (modelId: number, layerId: number, imageId: number | string): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/images/${imageId}`, addLayerText: (modelId: number, layerId: number): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/`, @@ -118,7 +116,6 @@ export const apiPath = { registerPluign: (): string => `plugins/`, getPlugin: (pluginId: string): string => `plugins/${pluginId}/`, getAllPlugins: (): string => `/plugins/`, - getSubmapConnections: (): string => `projects/${PROJECT_ID}/submapConnections/`, logout: (): string => `doLogout`, user: (login: string): string => `users/${login}`, updateUser: (login: string): string => `users/${login}`, diff --git a/src/redux/bioEntity/bioEntity.constants.ts b/src/redux/bioEntity/bioEntity.constants.ts index 70b92fc4..283283d5 100644 --- a/src/redux/bioEntity/bioEntity.constants.ts +++ b/src/redux/bioEntity/bioEntity.constants.ts @@ -1,24 +1,7 @@ -import { FetchDataState } from '@/types/fetchDataState'; -import { BioEntity } from '@/types/models'; import { BioEntityContentsState } from './bioEntity.types'; -export const DEFAULT_BIOENTITY_PARAMS = { - perfectMatch: false, -}; - export const BIO_ENTITY_FETCHING_ERROR_PREFIX = 'Failed to fetch bio entity'; -export const MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX = 'Failed to fetch multi bio entity'; - -export const BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE: FetchDataState<BioEntity[]> = { - data: [], - loading: 'idle', - error: { name: '', message: '' }, -}; export const BIOENTITY_INITIAL_STATE: BioEntityContentsState = { - data: [], - loading: 'idle', - error: { name: '', message: '' }, - submapConnections: BIOENTITY_SUBMAP_CONNECTIONS_INITIAL_STATE, isContentTabOpened: false, }; diff --git a/src/redux/bioEntity/bioEntity.mock.ts b/src/redux/bioEntity/bioEntity.mock.ts index 929790fa..f104198e 100644 --- a/src/redux/bioEntity/bioEntity.mock.ts +++ b/src/redux/bioEntity/bioEntity.mock.ts @@ -1,34 +1,5 @@ -import { DEFAULT_ERROR } from '@/constants/errors'; -import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { MultiSearchData } from '@/types/fetchDataState'; -import { BioEntity, BioEntityContent } from '@/types/models'; -import { HISTAMINE_MAP_ID } from '@/constants/mocks'; import { BioEntityContentsState } from './bioEntity.types'; export const BIOENTITY_INITIAL_STATE_MOCK: BioEntityContentsState = { - data: [], - loading: 'idle', - error: DEFAULT_ERROR, - submapConnections: { - data: [], - loading: 'idle', - error: DEFAULT_ERROR, - }, + isContentTabOpened: false, }; - -export const BIO_ENTITY_LINKING_TO_SUBMAP: BioEntity = { - ...bioEntityContentFixture.bioEntity, - submodel: { - mapId: HISTAMINE_MAP_ID, - type: 'DONWSTREAM_TARGETS', - }, -}; - -export const BIO_ENTITY_LINKING_TO_SUBMAP_DATA_MOCK: MultiSearchData<BioEntityContent[]>[] = [ - { - data: [{ bioEntity: BIO_ENTITY_LINKING_TO_SUBMAP, perfect: false }], - searchQueryElement: '', - loading: 'succeeded', - error: DEFAULT_ERROR, - }, -]; diff --git a/src/redux/bioEntity/bioEntity.reducers.test.ts b/src/redux/bioEntity/bioEntity.reducers.test.ts deleted file mode 100644 index 8fa2002f..00000000 --- a/src/redux/bioEntity/bioEntity.reducers.test.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { DEFAULT_ERROR } from '@/constants/errors'; -import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { apiPath } from '@/redux/apiPath'; -import { - ToolkitStoreWithSingleSlice, - createStoreInstanceUsingSliceReducer, -} from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; -import { unwrapResult } from '@reduxjs/toolkit'; -import { HttpStatusCode } from 'axios'; -import bioEntityContentsReducer from './bioEntity.slice'; -import { getBioEntity } from './bioEntity.thunks'; -import { BioEntityContentsState } from './bioEntity.types'; - -const mockedAxiosClient = mockNetworkNewAPIResponse(); -const SEARCH_QUERY = 'park7'; - -jest.mock('../../utils/error-report/errorReporting'); - -const INITIAL_STATE: BioEntityContentsState = { - data: [], - loading: 'idle', - isContentTabOpened: false, - error: { name: '', message: '' }, - submapConnections: { - data: [], - loading: 'idle', - error: { name: '', message: '' }, - }, -}; - -describe('bioEntity reducer', () => { - let store = {} as ToolkitStoreWithSingleSlice<BioEntityContentsState>; - beforeEach(() => { - store = createStoreInstanceUsingSliceReducer('bioEntity', bioEntityContentsReducer); - }); - - it('should match initial state', () => { - const action = { type: 'unknown' }; - - expect(bioEntityContentsReducer(undefined, action)).toEqual(INITIAL_STATE); - }); - - it('should update store after succesfull getBioEntity query', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - - const { type } = await store.dispatch( - getBioEntity({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ); - const { data } = store.getState().bioEntity; - const bioEnityWithSearchElement = data.find( - bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY, - ); - - expect(type).toBe('project/getBioEntityContents/fulfilled'); - expect(bioEnityWithSearchElement).toEqual({ - searchQueryElement: SEARCH_QUERY, - data: bioEntityResponseFixture.content, - loading: 'succeeded', - error: DEFAULT_ERROR, - }); - }); - - it('should update store after failed getBioEntity query', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ) - .reply(HttpStatusCode.NotFound, bioEntityResponseFixture); - - const action = await store.dispatch( - getBioEntity({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ); - const { data } = store.getState().bioEntity; - - const bioEntityWithSearchElement = data.find( - bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY, - ); - expect(action.type).toBe('project/getBioEntityContents/rejected'); - expect(() => unwrapResult(action)).toThrow( - "Failed to fetch bio entity: The page you're looking for doesn't exist. Please verify the URL and try again.", - ); - expect(bioEntityWithSearchElement).toEqual({ - searchQueryElement: SEARCH_QUERY, - data: undefined, - loading: 'failed', - error: DEFAULT_ERROR, - }); - }); - - it('should update store on loading getBioEntity query', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - - const bioEntityContentsPromise = store.dispatch( - getBioEntity({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ); - - const { data } = store.getState().bioEntity; - const bioEntityWithSearchElement = data.find( - bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY, - ); - - expect(bioEntityWithSearchElement).toEqual({ - searchQueryElement: SEARCH_QUERY, - data: undefined, - loading: 'pending', - error: DEFAULT_ERROR, - }); - - bioEntityContentsPromise.then(() => { - const { data: dataPromiseFulfilled } = store.getState().bioEntity; - - const bioEntityWithSearchElementFulfilled = dataPromiseFulfilled.find( - bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY, - ); - - expect(bioEntityWithSearchElementFulfilled).toEqual({ - searchQueryElement: SEARCH_QUERY, - data: bioEntityResponseFixture.content, - loading: 'succeeded', - error: DEFAULT_ERROR, - }); - }); - }); -}); diff --git a/src/redux/bioEntity/bioEntity.reducers.ts b/src/redux/bioEntity/bioEntity.reducers.ts index b24e17c1..f4406d50 100644 --- a/src/redux/bioEntity/bioEntity.reducers.ts +++ b/src/redux/bioEntity/bioEntity.reducers.ts @@ -1,99 +1,9 @@ -import { DEFAULT_ERROR } from '@/constants/errors'; -import { ActionReducerMapBuilder, PayloadAction } from '@reduxjs/toolkit'; -import { BioEntity, BioEntityContent } from '@/types/models'; -import { getBioEntity, getMultiBioEntity } from './bioEntity.thunks'; +import { PayloadAction } from '@reduxjs/toolkit'; import { BioEntityContentsState } from './bioEntity.types'; -export const getBioEntityContentsReducer = ( - builder: ActionReducerMapBuilder<BioEntityContentsState>, -): void => { - builder.addCase(getBioEntity.pending, (state, action) => { - state.data.push({ - searchQueryElement: action.meta.arg.searchQuery, - 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, - ); - if (bioEntities) { - bioEntities.data = action.payload; - bioEntities.loading = 'succeeded'; - } - }); - builder.addCase(getBioEntity.rejected, (state, action) => { - const bioEntities = state.data.find( - bioEntity => bioEntity.searchQueryElement === action.meta.arg.searchQuery, - ); - if (bioEntities) { - bioEntities.loading = 'failed'; - // TODO: error management to be discussed in the team - } - }); -}; - -export const getMultiBioEntityContentsReducer = ( - builder: ActionReducerMapBuilder<BioEntityContentsState>, -): void => { - builder.addCase(getMultiBioEntity.pending, state => { - state.data = []; - state.loading = 'pending'; - }); - builder.addCase(getMultiBioEntity.fulfilled, state => { - state.loading = 'succeeded'; - }); - builder.addCase(getMultiBioEntity.rejected, state => { - state.loading = 'failed'; - // TODO: error management to be discussed in the team - }); -}; - -export const clearBioEntitiesReducer = (state: BioEntityContentsState): void => { - state.data = []; - state.loading = 'idle'; -}; - export const toggleIsContentTabOpenedReducer = ( state: BioEntityContentsState, action: PayloadAction<boolean>, ): void => { state.isContentTabOpened = action.payload; }; - -export const setBioEntityContentsReducer = ( - state: BioEntityContentsState, - action: PayloadAction<BioEntityContent>, -): void => { - state.data = [ - { - data: [action.payload], - loading: 'succeeded', - error: DEFAULT_ERROR, - searchQueryElement: action.payload.bioEntity.id.toString(), - }, - ]; - state.loading = 'succeeded'; -}; - -export const setMultipleBioEntityContentsReducer = ( - state: BioEntityContentsState, - action: PayloadAction<Array<BioEntity>>, -): void => { - state.data = action.payload.map(bioEntity => { - return { - data: [ - { - bioEntity, - perfect: true, - }, - ], - searchQueryElement: bioEntity.id.toString(), - loading: 'succeeded', - error: DEFAULT_ERROR, - }; - }); - state.loading = 'succeeded'; -}; diff --git a/src/redux/bioEntity/bioEntity.selectors.ts b/src/redux/bioEntity/bioEntity.selectors.ts index d9c63a0a..1abdb89d 100644 --- a/src/redux/bioEntity/bioEntity.selectors.ts +++ b/src/redux/bioEntity/bioEntity.selectors.ts @@ -1,196 +1,58 @@ -import { ONE, SIZE_OF_EMPTY_ARRAY, ZERO } from '@/constants/common'; -import { allCommentsSelectorOfCurrentMap } from '@/redux/comment/comment.selectors'; +import { ONE, ZERO } from '@/constants/common'; import { rootSelector } from '@/redux/root/root.selectors'; -import { BioEntityWithPinType } from '@/types/bioEntity'; +import { ModelElementWithPinType } from '@/types/modelElement'; import { ElementIdTabObj } from '@/types/elements'; -import { MultiSearchData } from '@/types/fetchDataState'; -import { BioEntity, BioEntityContent, Comment, MapModel, ModelElement } from '@/types/models'; +import { ModelElement } from '@/types/models'; import { createSelector } from '@reduxjs/toolkit'; import { - currentDrawerModelElementSelector, - modelElementsWithSubmapConnectionForCurrentModelSelector, + allModelElementsSubmapConnectionsForCurrentSubmapSelector, + allSearchModelElementForCurrentModelSelector, + allSearchModelElementsIdTabForCurrentModelSelector, + searchedModelElementsForCurrentModelSelector, + searchedModelElementsSelector, } from '@/redux/modelElements/modelElements.selector'; -import { currentDrawerNewReactionSelector } from '@/redux/newReactions/newReactions.selectors'; import { - allChemicalsBioEntitesOfCurrentMapSelector, + allDrugsElementsOfCurrentMapSelector, + allDrugsIdTabSelectorOfCurrentMap, + drugsElementsForSelectedSearchElementSelector, + searchedDrugsElementsOfCurrentMapSelector, +} from '@/redux/drugs/drugs.selectors'; +import { + allChemicalsElementsOfCurrentMapSelector, allChemicalsIdTabSelectorOfCurrentMap, - chemicalsBioEntitiesForSelectedSearchElementSelector, - searchedChemicalsBioEntitesOfCurrentMapSelector, + chemicalsElementsForSelectedSearchElementSelector, + searchedChemicalsElementsOfCurrentMapSelector, } from '../chemicals/chemicals.selectors'; -import { currentSelectedBioEntityIdSelector } from '../contextMenu/contextMenu.selector'; -import { currentSelectedSearchElement } from '../drawer/drawer.selectors'; -import { - allDrugsBioEntitesOfCurrentMapSelector, - allDrugsIdTabSelectorOfCurrentMap, - drugsBioEntitiesForSelectedSearchElementSelector, - searchedDrugsBioEntitesOfCurrentMapSelector, -} from '../drugs/drugs.selectors'; -import { currentModelIdSelector, modelsDataSelector } from '../models/models.selectors'; export const bioEntitySelector = createSelector(rootSelector, state => state.bioEntity); -export const bioEntityDataSelector = createSelector(bioEntitySelector, bioEntity => bioEntity.data); - export const bioEntityIsContentTabOpenedSelector = createSelector( bioEntitySelector, bioEntity => bioEntity.isContentTabOpened, ); -export const bioEntityLoadingSelector = createSelector( - bioEntitySelector, - bioEntity => bioEntity.loading, -); - -export const bioEntityDataListSelector = createSelector(bioEntityDataSelector, bioEntityData => - bioEntityData.map(b => b.data || []).flat(), -); - -export const allSubmapConnectionsBioEntityOfCurrentSubmapSelector = createSelector( - modelElementsWithSubmapConnectionForCurrentModelSelector, - currentModelIdSelector, - (submapConnectionsBioEntity, currentModel): ModelElement[] => - submapConnectionsBioEntity.filter(({ model }) => model === currentModel), -); - -export const bioEntitiesForSelectedSearchElement = createSelector( - bioEntitySelector, - currentSelectedSearchElement, - (bioEntitiesState, currentSearchElement): MultiSearchData<BioEntityContent[]> | undefined => - bioEntitiesState.data.find( - ({ searchQueryElement }) => searchQueryElement === currentSearchElement, - ), -); - -export const searchedBioEntityElementForContextMapSelector = createSelector( - bioEntitySelector, - currentSelectedBioEntityIdSelector, - (bioEntitiesState, currentBioEntityId): BioEntity | undefined => { - return bioEntitiesState.data - .find(({ searchQueryElement }) => searchQueryElement === currentBioEntityId.toString()) - ?.data?.find(({ bioEntity }) => bioEntity.id === currentBioEntityId)?.bioEntity; - }, -); - -export const searchedBioEntityElementUniProtIdSelector = createSelector( - searchedBioEntityElementForContextMapSelector, - (bioEntitiesState): string | undefined => { - return bioEntitiesState?.references.find(({ type }) => type === 'UNIPROT')?.resource; - }, -); - -export const loadingBioEntityStatusSelector = createSelector( - bioEntitiesForSelectedSearchElement, - state => state?.loading, -); - -export const searchedBioEntitesSelectorOfCurrentMap = createSelector( - bioEntitySelector, - currentSelectedSearchElement, - currentModelIdSelector, - (bioEntities, currentSearchElement, currentModelId): BioEntity[] => { - if (!bioEntities) { - return []; - } - - return (bioEntities?.data || []) - .filter(({ searchQueryElement }) => - currentSearchElement ? searchQueryElement === currentSearchElement : true, - ) - .map(({ data }) => data || []) - .flat() - .filter(({ bioEntity }) => bioEntity.model === currentModelId) - .map(({ bioEntity }) => bioEntity); - }, -); - -export const allBioEntitesSelectorOfCurrentMap = createSelector( - bioEntitySelector, - currentModelIdSelector, - (bioEntities, currentModelId): BioEntity[] => { - if (!bioEntities) { - return []; - } - - return (bioEntities?.data || []) - .map(({ data }) => data || []) - .flat() - .filter(({ bioEntity }) => bioEntity.model === currentModelId) - .map(({ bioEntity }) => bioEntity); - }, -); - -export const allBioEntitesIdTabSelectorOfCurrentMap = createSelector( - bioEntitySelector, - currentModelIdSelector, - (bioEntities, currentModelId): ElementIdTabObj => { - if (!bioEntities) { - return {}; - } - - return Object.fromEntries( - (bioEntities?.data || []) - .map(({ data, searchQueryElement }): [typeof data, string] => [data, searchQueryElement]) - .map(([data, tab]) => - (data || []) - .flat() - .filter(({ bioEntity }) => bioEntity.model === currentModelId) - .map(d => [d.bioEntity.id, tab]), - ) - .flat(), - ); - }, -); - -export const numberOfBioEntitiesSelector = createSelector( - bioEntitiesForSelectedSearchElement, - state => (state?.data ? state.data.length : SIZE_OF_EMPTY_ARRAY), -); - -export const bioEntitiesPerModelSelector = createSelector( - bioEntitiesForSelectedSearchElement, - modelsDataSelector, - (bioEntities, models) => { - const bioEntitiesPerModelPerSearchElement = (models || []).map(model => { - const bioEntitiesInGivenModel = (bioEntities?.data || []).filter( - entity => model.id === entity.bioEntity.model, - ); - - return { - modelName: model.name, - modelId: model.id, - numberOfEntities: bioEntitiesInGivenModel.length, - bioEntities: bioEntitiesInGivenModel, - }; - }); - - return bioEntitiesPerModelPerSearchElement.filter( - model => model.numberOfEntities !== SIZE_OF_EMPTY_ARRAY, - ); - }, -); - export const allVisibleBioEntitiesSelector = createSelector( - searchedBioEntitesSelectorOfCurrentMap, - searchedChemicalsBioEntitesOfCurrentMapSelector, - searchedDrugsBioEntitesOfCurrentMapSelector, - (content, chemicals, drugs): BioEntity[] => { + searchedModelElementsForCurrentModelSelector, + searchedChemicalsElementsOfCurrentMapSelector, + searchedDrugsElementsOfCurrentMapSelector, + (content, chemicals, drugs): Array<ModelElement> => { return [content, chemicals, drugs].flat(); }, ); -export const allElementsForSearchElementSelector = createSelector( - bioEntitiesForSelectedSearchElement, - chemicalsBioEntitiesForSelectedSearchElementSelector, - drugsBioEntitiesForSelectedSearchElementSelector, - (content, chemicals, drugs): BioEntity[] => { - const contentBioEntities = (content?.data || []).map(({ bioEntity }) => bioEntity); +export const allBioEntitiesForSearchElementSelector = createSelector( + searchedModelElementsSelector, + chemicalsElementsForSelectedSearchElementSelector, + drugsElementsForSelectedSearchElementSelector, + (content, chemicals, drugs): Array<ModelElement> => { + const contentBioEntities = (content?.data || []).map(({ modelElement }) => modelElement); return [contentBioEntities, chemicals || [], drugs || []].flat(); }, ); export const allElementsForSearchElementNumberByModelId = createSelector( - allElementsForSearchElementSelector, + allBioEntitiesForSearchElementSelector, (elements): Record<number, number> => { return elements.reduce( (acc, { model }) => ({ @@ -203,7 +65,7 @@ export const allElementsForSearchElementNumberByModelId = createSelector( ); export const allBioEntitiesElementsIdsSelector = createSelector( - allBioEntitesIdTabSelectorOfCurrentMap, + allSearchModelElementsIdTabForCurrentModelSelector, allChemicalsIdTabSelectorOfCurrentMap, allDrugsIdTabSelectorOfCurrentMap, (content, chemicals, drugs): ElementIdTabObj => { @@ -215,16 +77,9 @@ export const allBioEntitiesElementsIdsSelector = createSelector( }, ); -export const currentDrawerBioEntityRelatedSubmapSelector = createSelector( - currentDrawerModelElementSelector, - modelsDataSelector, - (bioEntity, models): MapModel | undefined => - models.find(({ id }) => id === bioEntity?.submodel?.mapId), -); - export const allSubmapConnectionsBioEntityOfCurrentSubmapWithRealConnectionsSelector = createSelector( - allSubmapConnectionsBioEntityOfCurrentSubmapSelector, + allModelElementsSubmapConnectionsForCurrentSubmapSelector, allElementsForSearchElementNumberByModelId, (submapConnectionsBioEntity, modelElementsNumber): ModelElement[] => { return submapConnectionsBioEntity.filter( @@ -234,16 +89,16 @@ export const allSubmapConnectionsBioEntityOfCurrentSubmapWithRealConnectionsSele ); export const allBioEntitiesWithTypeOfCurrentMapSelector = createSelector( - allBioEntitesSelectorOfCurrentMap, - allChemicalsBioEntitesOfCurrentMapSelector, - allDrugsBioEntitesOfCurrentMapSelector, + allSearchModelElementForCurrentModelSelector, + allChemicalsElementsOfCurrentMapSelector, + allDrugsElementsOfCurrentMapSelector, allSubmapConnectionsBioEntityOfCurrentSubmapWithRealConnectionsSelector, - (content, chemicals, drugs, submapConnections): BioEntityWithPinType[] => { + (content, chemicals, drugs, submapConnections): ModelElementWithPinType[] => { return [ - content.map(v => ({ ...v, type: 'bioEntity' as const })), + content.map(v => ({ ...v, type: 'modelElement' as const })), chemicals.map(v => ({ ...v, type: 'chemicals' as const })), drugs.map(v => ({ ...v, type: 'drugs' as const })), - submapConnections.map(v => ({ ...v, type: 'bioEntity' as const })), + submapConnections.map(v => ({ ...v, type: 'modelElement' as const })), ].flat(); }, ); @@ -255,35 +110,3 @@ export const allVisibleBioEntitiesIdsSelector = createSelector( return [...elements, ...submapConnections].map(e => e.id); }, ); - -export const currentDrawerElementCommentsSelector = createSelector( - currentDrawerModelElementSelector, - allCommentsSelectorOfCurrentMap, - (element, comments): Comment[] => { - if (element) { - return comments.filter( - comment => - comment.type === 'ALIAS' && - comment.modelId === element.model && - Number(comment.elementId) === element.id, - ); - } - return []; - }, -); - -export const currentDrawerReactionCommentsSelector = createSelector( - currentDrawerNewReactionSelector, - allCommentsSelectorOfCurrentMap, - (reaction, comments): Comment[] => { - if (reaction) { - return comments.filter( - comment => - comment.type === 'REACTION' && - comment.modelId === reaction.model && - Number(comment.elementId) === reaction.id, - ); - } - return []; - }, -); diff --git a/src/redux/bioEntity/bioEntity.slice.ts b/src/redux/bioEntity/bioEntity.slice.ts index 8e40b023..45a1b7e7 100644 --- a/src/redux/bioEntity/bioEntity.slice.ts +++ b/src/redux/bioEntity/bioEntity.slice.ts @@ -1,34 +1,15 @@ import { createSlice } from '@reduxjs/toolkit'; import { BIOENTITY_INITIAL_STATE } from './bioEntity.constants'; -import { - clearBioEntitiesReducer, - getBioEntityContentsReducer, - getMultiBioEntityContentsReducer, - setBioEntityContentsReducer, - setMultipleBioEntityContentsReducer, - toggleIsContentTabOpenedReducer, -} from './bioEntity.reducers'; +import { toggleIsContentTabOpenedReducer } from './bioEntity.reducers'; export const bioEntityContentsSlice = createSlice({ name: 'bioEntityContents', initialState: BIOENTITY_INITIAL_STATE, reducers: { - clearBioEntities: clearBioEntitiesReducer, toggleIsContentTabOpened: toggleIsContentTabOpenedReducer, - setBioEntityContents: setBioEntityContentsReducer, - setMultipleBioEntityContents: setMultipleBioEntityContentsReducer, - }, - extraReducers: builder => { - getBioEntityContentsReducer(builder); - getMultiBioEntityContentsReducer(builder); }, }); -export const { - clearBioEntities, - toggleIsContentTabOpened, - setBioEntityContents, - setMultipleBioEntityContents, -} = bioEntityContentsSlice.actions; +export const { toggleIsContentTabOpened } = bioEntityContentsSlice.actions; export default bioEntityContentsSlice.reducer; diff --git a/src/redux/bioEntity/bioEntity.thunks.test.ts b/src/redux/bioEntity/bioEntity.thunks.test.ts deleted file mode 100644 index fb433fb0..00000000 --- a/src/redux/bioEntity/bioEntity.thunks.test.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture'; -import { apiPath } from '@/redux/apiPath'; -import { - ToolkitStoreWithSingleSlice, - createStoreInstanceUsingSliceReducer, -} from '@/utils/createStoreInstanceUsingSliceReducer'; -import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; -import { HttpStatusCode } from 'axios'; -import { unwrapResult } from '@reduxjs/toolkit'; -import contentsReducer from './bioEntity.slice'; -import { getBioEntity, getMultiBioEntity } from './bioEntity.thunks'; -import { BioEntityContentsState } from './bioEntity.types'; - -jest.mock('../../utils/error-report/errorReporting'); - -const mockedAxiosClient = mockNetworkNewAPIResponse(); -const SEARCH_QUERY = 'park7'; - -describe('bioEntityContents thunks', () => { - let store = {} as ToolkitStoreWithSingleSlice<BioEntityContentsState>; - beforeEach(() => { - store = createStoreInstanceUsingSliceReducer('bioEntityContents', contentsReducer); - }); - describe('getBioEntityContents', () => { - it('should return data when data response from API is valid', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - - const { payload } = await store.dispatch( - getBioEntity({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ); - expect(payload).toEqual(bioEntityResponseFixture.content); - }); - it('should return undefined when data response from API is not valid ', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ) - .reply(HttpStatusCode.Ok, { randomProperty: 'randomValue' }); - - const { payload } = await store.dispatch( - getBioEntity({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ); - expect(payload).toEqual(undefined); - }); - it('should handle error message when getBioEntityContents failed', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ) - .reply(HttpStatusCode.NotFound, null); - - const action = await store.dispatch( - getBioEntity({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ); - expect(() => unwrapResult(action)).toThrow( - "Failed to fetch bio entity: The page you're looking for doesn't exist. Please verify the URL and try again.", - ); - }); - }); - describe('getMultiBioEntity', () => { - it('should return transformed bioEntityContent array', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - - const data = await store - .dispatch( - getMultiBioEntity({ - searchQueries: [SEARCH_QUERY], - isPerfectMatch: false, - }), - ) - .unwrap(); - - expect(data).toEqual(bioEntityResponseFixture.content); - }); - it('should combine all returned bioEntityContent arrays and return array with all provided bioEntityContent elements', async () => { - mockedAxiosClient - .onGet( - apiPath.getBioEntityContentsStringWithQuery({ - searchQuery: SEARCH_QUERY, - isPerfectMatch: false, - }), - ) - .reply(HttpStatusCode.Ok, bioEntityResponseFixture); - - const data = await store - .dispatch( - getMultiBioEntity({ - searchQueries: [SEARCH_QUERY, SEARCH_QUERY], - isPerfectMatch: false, - }), - ) - .unwrap(); - - expect(data).toEqual([ - ...bioEntityResponseFixture.content, - ...bioEntityResponseFixture.content, - ]); - }); - }); -}); diff --git a/src/redux/bioEntity/bioEntity.thunks.ts b/src/redux/bioEntity/bioEntity.thunks.ts deleted file mode 100644 index 18fa812c..00000000 --- a/src/redux/bioEntity/bioEntity.thunks.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { getBioEntity } from './thunks/getBioEntity'; -import { getMultiBioEntity } from './thunks/getMultiBioEntity'; - -export { getBioEntity, getMultiBioEntity }; diff --git a/src/redux/bioEntity/bioEntity.types.ts b/src/redux/bioEntity/bioEntity.types.ts index 9540daab..07f11577 100644 --- a/src/redux/bioEntity/bioEntity.types.ts +++ b/src/redux/bioEntity/bioEntity.types.ts @@ -1,19 +1,3 @@ -import { FetchDataState, MultiFetchDataState } from '@/types/fetchDataState'; -import { BioEntity, BioEntityContent } from '@/types/models'; -import { PayloadAction } from '@reduxjs/toolkit'; - -export type BioEntityContentsState = MultiFetchDataState<BioEntityContent[]> & { - submapConnections?: FetchDataState<BioEntity[]>; +export type BioEntityContentsState = { isContentTabOpened?: boolean; }; - -export type BioEntityContentSearchQuery = { - query: string | string[]; - params: { - perfectMatch: boolean; - }; -}; - -export type SetBioEntityContentActionPayload = BioEntityContent[]; - -export type SetBioEntityContentAction = PayloadAction<SetBioEntityContentActionPayload>; diff --git a/src/redux/bioEntity/thunks/getBioEntity.ts b/src/redux/bioEntity/thunks/getBioEntity.ts deleted file mode 100644 index bf54870a..00000000 --- a/src/redux/bioEntity/thunks/getBioEntity.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema'; -import { apiPath } from '@/redux/apiPath'; -import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; -import { BioEntityContent, BioEntityResponse } from '@/types/models'; -import { PerfectSearchParams } from '@/types/search'; -import { ThunkConfig } from '@/types/store'; -import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema'; -import { createAsyncThunk } from '@reduxjs/toolkit'; -import { getError } from '@/utils/error-report/getError'; -import { addNumbersToEntityNumberData } from '../../entityNumber/entityNumber.slice'; -import { BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants'; - -type GetBioEntityProps = PerfectSearchParams; - -export const getBioEntity = createAsyncThunk< - BioEntityContent[] | undefined, - GetBioEntityProps, - ThunkConfig ->( - 'project/getBioEntityContents', - async ({ searchQuery, isPerfectMatch, addNumbersToEntityNumber = true }, { dispatch }) => { - try { - const response = await axiosInstanceNewAPI.get<BioEntityResponse>( - apiPath.getBioEntityContentsStringWithQuery({ searchQuery, isPerfectMatch }), - ); - - const isDataValidBioEnity = validateDataUsingZodSchema( - response.data, - bioEntityResponseSchema, - ); - - if (addNumbersToEntityNumber && response.data.content) { - const bioEntityIds = response.data.content.map(b => b.bioEntity.elementId); - dispatch(addNumbersToEntityNumberData(bioEntityIds)); - } - - return isDataValidBioEnity ? response.data.content : undefined; - } 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 deleted file mode 100644 index cddf3ff1..00000000 --- a/src/redux/bioEntity/thunks/getMultiBioEntity.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { ZERO } from '@/constants/common'; -import type { AppDispatch, store } from '@/redux/store'; -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 } from './getBioEntity'; -import { fetchReactionsAndGetBioEntitiesIds } from './utils/fetchReactionsAndGetBioEntitiesIds'; - -type GetMultiBioEntityProps = PerfectMultiSearchParams; -type GetMultiBioEntityActions = PayloadAction<BioEntityContent[] | undefined | string>[]; // if error thrown, string containing error message is returned - -export const getMultiBioEntity = createAsyncThunk< - BioEntityContent[], - GetMultiBioEntityProps, - ThunkConfig ->( - 'project/getMultiBioEntity', - // eslint-disable-next-line consistent-return - async ({ searchQueries, isPerfectMatch }, { dispatch, getState }) => { - try { - const asyncGetBioEntityFunctions = searchQueries.map(searchQuery => - dispatch(getBioEntity({ searchQuery, isPerfectMatch, addNumbersToEntityNumber: false })), - ); - - const bioEntityContentsActions = (await Promise.all( - asyncGetBioEntityFunctions, - )) as GetMultiBioEntityActions; - - const bioEntityContents = bioEntityContentsActions - .map(bioEntityContentsAction => bioEntityContentsAction?.payload || []) - .flat() - .filter((payload): payload is BioEntityContent => typeof payload !== 'string') - .filter(payload => 'bioEntity' in payload || {}); - - const bioEntityIds = bioEntityContents.map(b => b.bioEntity.elementId); - dispatch(addNumbersToEntityNumberData(bioEntityIds)); - - const bioEntitiesIds = await fetchReactionsAndGetBioEntitiesIds({ - bioEntityContents, - dispatch: dispatch as AppDispatch, - getState: getState as typeof store.getState, - }); - const bioEntitiesStringIds = bioEntitiesIds.map(id => String(id)); - if (bioEntitiesIds.length > ZERO) { - await dispatch( - getMultiBioEntity({ searchQueries: bioEntitiesStringIds, isPerfectMatch: true }), - ); - } - - return bioEntityContents; - } catch (error) { - return Promise.reject(getError({ error, prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX })); - } - }, -); diff --git a/src/redux/bioEntity/thunks/utils/fetchReactionsAndGetBioEntitiesIds.ts b/src/redux/bioEntity/thunks/utils/fetchReactionsAndGetBioEntitiesIds.ts deleted file mode 100644 index a29317ed..00000000 --- a/src/redux/bioEntity/thunks/utils/fetchReactionsAndGetBioEntitiesIds.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { FIRST_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; -import { openReactionDrawerById, selectTab } from '@/redux/drawer/drawer.slice'; -import { openMapAndOrSetActiveIfSelected } from '@/redux/map/map.slice'; -import { modelsNameMapSelector } from '@/redux/models/models.selectors'; -import { getReactionsByIds } from '@/redux/reactions/reactions.thunks'; -import type { AppDispatch, store } from '@/redux/store'; -import type { BioEntityContent, NewReaction } from '@/types/models'; -import getModelElementsIdsFromReaction from '@/components/Map/MapViewer/utils/listeners/mouseClick/getModelElementsIdsFromReaction'; - -interface Args { - bioEntityContents: BioEntityContent[]; - dispatch: AppDispatch; - getState: typeof store.getState; -} - -type ReactionId = { - id: number; - modelId: number; -}; - -const getReactionsIdsFromBioEntities = (bioEntites: BioEntityContent[]): ReactionId[] => { - return bioEntites - .filter(c => c?.bioEntity?.idReaction) - .filter(c => typeof c?.bioEntity?.id === 'number') - .map(c => { - let id: number; - if (typeof c.bioEntity.id === 'string') { - id = parseInt(c.bioEntity.id, 10); - } else { - id = c.bioEntity.id; - } - return { id, modelId: c.bioEntity.model }; - }); -}; - -const fetchReactions = async ( - reactionsIds: ReactionId[], - dispatch: AppDispatch, -): Promise<NewReaction[]> => { - const result = await dispatch( - getReactionsByIds({ - ids: reactionsIds, - shouldConcat: true, - }), - ); - - // if it has error (toast show should be handled by getReactionsByIds) - if (typeof result.payload === 'string') { - return []; - } - - const reactions = result.payload?.data; - if (!reactions) { - return []; - } - - return reactions; -}; - -const handleReactionShowInfoAndOpenMap = async ( - { dispatch, getState }: Args, - firstReaction: NewReaction, -): Promise<void> => { - const modelsNames = modelsNameMapSelector(getState()); - - dispatch(openReactionDrawerById(firstReaction.id)); - dispatch(selectTab('')); - dispatch( - openMapAndOrSetActiveIfSelected({ - modelId: firstReaction.model, - modelName: modelsNames[firstReaction.model], - }), - ); -}; - -export const fetchReactionsAndGetBioEntitiesIds = async (args: Args): Promise<number[]> => { - const { dispatch, bioEntityContents } = args; - - const bioEntityReactionsIds = getReactionsIdsFromBioEntities(bioEntityContents || []); - if (bioEntityReactionsIds.length === SIZE_OF_EMPTY_ARRAY) { - return []; - } - - const reactions = await fetchReactions(bioEntityReactionsIds, dispatch); - if (reactions.length === SIZE_OF_EMPTY_ARRAY) { - return []; - } - - const bioEntitiesIds = reactions - .map(reaction => getModelElementsIdsFromReaction(reaction)) - .flat(); - const firstReaction = reactions[FIRST_ARRAY_ELEMENT]; - if (firstReaction) { - handleReactionShowInfoAndOpenMap(args, firstReaction); - } - - return bioEntitiesIds; -}; diff --git a/src/redux/chemicals/chemicals.selectors.ts b/src/redux/chemicals/chemicals.selectors.ts index 7f11e09a..b9443769 100644 --- a/src/redux/chemicals/chemicals.selectors.ts +++ b/src/redux/chemicals/chemicals.selectors.ts @@ -2,7 +2,7 @@ import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; import { rootSelector } from '@/redux/root/root.selectors'; import { ElementId, ElementIdTabObj, Tab } from '@/types/elements'; import { MultiSearchData } from '@/types/fetchDataState'; -import { BioEntity, Chemical } from '@/types/models'; +import { Chemical, ModelElement } from '@/types/models'; import { createSelector } from '@reduxjs/toolkit'; import { currentSelectedSearchElement } from '../drawer/drawer.selectors'; import { currentModelIdSelector } from '../models/models.selectors'; @@ -24,10 +24,10 @@ export const chemicalsForSelectedSearchElementSelector = createSelector( ), ); -export const chemicalsBioEntitiesForSelectedSearchElementSelector = createSelector( +export const chemicalsElementsForSelectedSearchElementSelector = createSelector( chemicalsSelector, currentSelectedSearchElement, - (chemicalsState, currentSearchElement): BioEntity[] => { + (chemicalsState, currentSearchElement): ModelElement[] => { return (chemicalsState?.data || []) .filter(({ searchQueryElement }) => currentSearchElement ? searchQueryElement === currentSearchElement : true, @@ -40,25 +40,25 @@ export const chemicalsBioEntitiesForSelectedSearchElementSelector = createSelect }, ); -export const searchedChemicalsBioEntitesOfCurrentMapSelector = createSelector( - chemicalsBioEntitiesForSelectedSearchElementSelector, +export const searchedChemicalsElementsOfCurrentMapSelector = createSelector( + chemicalsElementsForSelectedSearchElementSelector, currentModelIdSelector, - (chemicalsBioEntities, currentModelId): BioEntity[] => { - return (chemicalsBioEntities || []).filter(bioEntity => bioEntity.model === currentModelId); + (chemicalsElements, currentModelId): ModelElement[] => { + return (chemicalsElements || []).filter(element => element.model === currentModelId); }, ); -export const allChemicalsBioEntitesOfCurrentMapSelector = createSelector( +export const allChemicalsElementsOfCurrentMapSelector = createSelector( chemicalsSelector, currentModelIdSelector, - (chemicalsState, currentModelId): BioEntity[] => { + (chemicalsState, currentModelId): ModelElement[] => { return (chemicalsState?.data || []) .map(({ data }) => data || []) .flat() .map(({ targets }) => targets.map(({ targetElements }) => targetElements)) .flat() .flat() - .filter(bioEntity => bioEntity.model === currentModelId); + .filter(element => element.model === currentModelId); }, ); @@ -79,8 +79,8 @@ export const allChemicalsIdTabSelectorOfCurrentMap = createSelector( .map(({ targetElements }) => targetElements) .flat() .flat() - .filter(bioEntity => bioEntity.model === currentModelId) - .map(bioEntity => [bioEntity.id, tab]), + .filter(element => element.model === currentModelId) + .map(element => [element.id, tab]), ), ) .flat() @@ -89,18 +89,6 @@ export const allChemicalsIdTabSelectorOfCurrentMap = createSelector( }, ); -export const allChemicalsBioEntitesOfAllMapsSelector = createSelector( - chemicalsSelector, - (chemicalsState): BioEntity[] => { - return (chemicalsState?.data || []) - .map(({ data }) => data || []) - .flat() - .map(({ targets }) => targets.map(({ targetElements }) => targetElements)) - .flat() - .flat(); - }, -); - export const loadingChemicalsStatusSelector = createSelector( chemicalsForSelectedSearchElementSelector, state => state?.loading, diff --git a/src/redux/comment/comment.types.ts b/src/redux/comment/comment.types.ts index 1e727562..c0e77c4e 100644 --- a/src/redux/comment/comment.types.ts +++ b/src/redux/comment/comment.types.ts @@ -1,11 +1,11 @@ import { FetchDataState } from '@/types/fetchDataState'; -import { BioEntity, Comment, NewReaction } from '@/types/models'; +import { ModelElement, Comment, NewReaction } from '@/types/models'; import { PayloadAction } from '@reduxjs/toolkit'; import { Point } from '@/types/map'; export interface CommentsState extends FetchDataState<Comment[], []> { isOpen: boolean; - commentElement: BioEntity | null; + commentElement: ModelElement | null; commentReaction: NewReaction | null; } diff --git a/src/redux/contextMenu/contextMenu.selector.ts b/src/redux/contextMenu/contextMenu.selector.ts index 9c2db16a..dc1222f8 100644 --- a/src/redux/contextMenu/contextMenu.selector.ts +++ b/src/redux/contextMenu/contextMenu.selector.ts @@ -3,8 +3,6 @@ import { rootSelector } from '../root/root.selectors'; export const contextMenuSelector = createSelector(rootSelector, state => state.contextMenu); -export const isContextMenuOpenSelector = createSelector(contextMenuSelector, state => state.isOpen); - export const currentSelectedBioEntityIdSelector = createSelector( contextMenuSelector, state => state.currentSelectedBioEntityId, diff --git a/src/redux/drawer/drawer.reducers.ts b/src/redux/drawer/drawer.reducers.ts index 88f1096c..b244295a 100644 --- a/src/redux/drawer/drawer.reducers.ts +++ b/src/redux/drawer/drawer.reducers.ts @@ -80,7 +80,7 @@ export const displayBioEntitiesListReducer = ( state.drawerName = 'search'; state.searchDrawerState.currentStep = STEP.SECOND; state.searchDrawerState.listOfBioEnitites = action.payload; - state.searchDrawerState.stepType = 'bioEntity'; + state.searchDrawerState.stepType = 'modelElement'; }; export const displayGroupedSearchResultsReducer = (state: DrawerState): void => { diff --git a/src/redux/drawer/drawer.selectors.ts b/src/redux/drawer/drawer.selectors.ts index a5f109ea..26299df5 100644 --- a/src/redux/drawer/drawer.selectors.ts +++ b/src/redux/drawer/drawer.selectors.ts @@ -100,7 +100,7 @@ export const resultListSelector = createSelector( data: chemical, })); } - case 'bioEntity': + case 'modelElement': return undefined; case 'none': return undefined; diff --git a/src/redux/drawer/drawer.types.ts b/src/redux/drawer/drawer.types.ts index 4cf1440f..4a80eea1 100644 --- a/src/redux/drawer/drawer.types.ts +++ b/src/redux/drawer/drawer.types.ts @@ -2,12 +2,13 @@ import type { DrawerName } from '@/types/drawerName'; import { KeyedFetchDataState } from '@/types/fetchDataState'; import { BioEntityContent, Chemical, Drug } from '@/types/models'; import { PayloadAction } from '@reduxjs/toolkit'; +import { SearchModelElementDataState } from '@/redux/modelElements/modelElements.types'; export type SearchDrawerState = { currentStep: number; - stepType: 'bioEntity' | 'drugs' | 'chemicals' | 'none'; + stepType: 'modelElement' | 'drugs' | 'chemicals' | 'none'; selectedValue: BioEntityContent | Drug | Chemical | undefined; - listOfBioEnitites: BioEntityContent[]; + listOfBioEnitites: Array<SearchModelElementDataState>; selectedSearchElement: string; }; @@ -49,8 +50,5 @@ export type OpenReactionDrawerByIdAction = PayloadAction<OpenReactionDrawerByIdP export type OpenBioEntityDrawerByIdPayload = number | string; export type OpenBioEntityDrawerByIdAction = PayloadAction<OpenBioEntityDrawerByIdPayload>; -export type SetSelectedSearchElementPayload = string; -export type SetSelectedSearchElementAction = PayloadAction<SetSelectedSearchElementPayload>; - export type OpenCommentDrawerByIdPayload = number; export type OpenCommentDrawerByIdAction = PayloadAction<OpenCommentDrawerByIdPayload>; diff --git a/src/redux/drugs/drugs.reducers.test.ts b/src/redux/drugs/drugs.reducers.test.ts index 69d29267..55af806f 100644 --- a/src/redux/drugs/drugs.reducers.test.ts +++ b/src/redux/drugs/drugs.reducers.test.ts @@ -40,7 +40,7 @@ describe('drugs reducer', () => { const { type } = await store.dispatch(getDrugs(SEARCH_QUERY)); const { data } = store.getState().drugs; const drugsWithSearchElement = data.find( - bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY, + searchModelElement => searchModelElement.searchQueryElement === SEARCH_QUERY, ); expect(type).toBe('project/getDrugs/fulfilled'); @@ -60,7 +60,7 @@ describe('drugs reducer', () => { const action = await store.dispatch(getDrugs(SEARCH_QUERY)); const { data } = store.getState().drugs; const drugsWithSearchElement = data.find( - bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY, + searchModelElement => searchModelElement.searchQueryElement === SEARCH_QUERY, ); expect(() => unwrapResult(action)).toThrow( @@ -84,7 +84,7 @@ describe('drugs reducer', () => { const { data } = store.getState().drugs; const drugsWithSearchElement = data.find( - bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY, + searchModelElement => searchModelElement.searchQueryElement === SEARCH_QUERY, ); expect(drugsWithSearchElement).toEqual({ @@ -98,7 +98,7 @@ describe('drugs reducer', () => { const { data: dataPromiseFulfilled } = store.getState().drugs; const drugsWithSearchElementFulfilled = dataPromiseFulfilled.find( - bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY, + searchModelElement => searchModelElement.searchQueryElement === SEARCH_QUERY, ); expect(drugsWithSearchElementFulfilled).toEqual({ searchQueryElement: SEARCH_QUERY, diff --git a/src/redux/drugs/drugs.selectors.ts b/src/redux/drugs/drugs.selectors.ts index ecaf082a..a2a616c4 100644 --- a/src/redux/drugs/drugs.selectors.ts +++ b/src/redux/drugs/drugs.selectors.ts @@ -2,7 +2,7 @@ import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; import { rootSelector } from '@/redux/root/root.selectors'; import { ElementId, ElementIdTabObj, Tab } from '@/types/elements'; import { MultiSearchData } from '@/types/fetchDataState'; -import { BioEntity, Drug } from '@/types/models'; +import { Drug, ModelElement } from '@/types/models'; import { createSelector } from '@reduxjs/toolkit'; import { currentSelectedSearchElement } from '../drawer/drawer.selectors'; import { currentModelIdSelector } from '../models/models.selectors'; @@ -38,10 +38,10 @@ export const numberOfDrugsSelector = createSelector( }, ); -export const drugsBioEntitiesForSelectedSearchElementSelector = createSelector( +export const drugsElementsForSelectedSearchElementSelector = createSelector( drugsSelector, currentSelectedSearchElement, - (drugsState, currentSearchElement): BioEntity[] => { + (drugsState, currentSearchElement): ModelElement[] => { return (drugsState?.data || []) .filter(({ searchQueryElement }) => currentSearchElement ? searchQueryElement === currentSearchElement : true, @@ -54,25 +54,25 @@ export const drugsBioEntitiesForSelectedSearchElementSelector = createSelector( }, ); -export const searchedDrugsBioEntitesOfCurrentMapSelector = createSelector( - drugsBioEntitiesForSelectedSearchElementSelector, +export const searchedDrugsElementsOfCurrentMapSelector = createSelector( + drugsElementsForSelectedSearchElementSelector, currentModelIdSelector, - (drugsBioEntities, currentModelId): BioEntity[] => { - return (drugsBioEntities || []).filter(bioEntity => bioEntity.model === currentModelId); + (drugsElements, currentModelId): ModelElement[] => { + return (drugsElements || []).filter(element => element.model === currentModelId); }, ); -export const allDrugsBioEntitesOfCurrentMapSelector = createSelector( +export const allDrugsElementsOfCurrentMapSelector = createSelector( drugsSelector, currentModelIdSelector, - (drugsState, currentModelId): BioEntity[] => { + (drugsState, currentModelId): ModelElement[] => { return (drugsState?.data || []) .map(({ data }) => data || []) .flat() .map(({ targets }) => targets.map(({ targetElements }) => targetElements)) .flat() .flat() - .filter(bioEntity => bioEntity.model === currentModelId); + .filter(element => element.model === currentModelId); }, ); @@ -93,8 +93,8 @@ export const allDrugsIdTabSelectorOfCurrentMap = createSelector( .map(({ targetElements }) => targetElements) .flat() .flat() - .filter(bioEntity => bioEntity.model === currentModelId) - .map(bioEntity => [bioEntity.id, tab]), + .filter(element => element.model === currentModelId) + .map(element => [element.id, tab]), ), ) .flat() @@ -102,15 +102,3 @@ export const allDrugsIdTabSelectorOfCurrentMap = createSelector( ); }, ); - -export const allDrugsBioEntitesOfAllMapsSelector = createSelector( - drugsSelector, - (drugsState): BioEntity[] => { - return (drugsState?.data || []) - .map(({ data }) => data || []) - .flat() - .map(({ targets }) => targets.map(({ targetElements }) => targetElements)) - .flat() - .flat(); - }, -); diff --git a/src/redux/modelElements/modelElements.constants.ts b/src/redux/modelElements/modelElements.constants.ts index 42427c11..0d017748 100644 --- a/src/redux/modelElements/modelElements.constants.ts +++ b/src/redux/modelElements/modelElements.constants.ts @@ -1,3 +1,7 @@ export const MODEL_ELEMENTS_FETCHING_ERROR_PREFIX = 'Failed to fetch model elements'; export const MODEL_ELEMENTS_DEFAULT_COMPARTMENT_NAME = 'default'; + +export const MULTI_MODEL_ELEMENTS_SEARCH_ERROR_PREFIX = 'Failed to search multi model elements'; + +export const MODEL_ELEMENT_SEARCH_ERROR_PREFIX = 'Failed to search model element'; diff --git a/src/redux/modelElements/modelElements.mock.ts b/src/redux/modelElements/modelElements.mock.ts index 583f03f3..70dc3406 100644 --- a/src/redux/modelElements/modelElements.mock.ts +++ b/src/redux/modelElements/modelElements.mock.ts @@ -1,12 +1,47 @@ import { DEFAULT_ERROR } from '@/constants/errors'; -import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; -import { FetchDataState } from '@/types/fetchDataState'; +import { + ModelElementsState, + SearchModelElementDataState, +} from '@/redux/modelElements/modelElements.types'; +import { FetchDataState, MultiFetchDataState, MultiSearchData } from '@/types/fetchDataState'; import { ModelElement } from '@/types/models'; +import { HISTAMINE_MAP_ID } from '@/constants/mocks'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; -export const MODEL_ELEMENTS_INITIAL_STATE_MOCK: ModelElementsState = {}; +export const MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK: MultiFetchDataState< + SearchModelElementDataState[] +> = { + data: [], + loading: 'idle', + error: DEFAULT_ERROR, +}; + +export const MODEL_ELEMENTS_INITIAL_STATE_MOCK: ModelElementsState = { + data: {}, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, +}; export const MODEL_ELEMENTS_STATE_INITIAL_MODEL_MOCK: FetchDataState<Array<ModelElement>> = { data: [], loading: 'idle', error: DEFAULT_ERROR, }; + +export const MODEL_ELEMENT_LINKING_TO_SUBMAP: ModelElement = { + ...modelElementFixture, + submodel: { + mapId: HISTAMINE_MAP_ID, + type: 'DONWSTREAM_TARGETS', + }, +}; + +export const MODEL_ELEMENTS_SEARCH_LINKING_TO_SUBMAP_DATA_MOCK: MultiSearchData< + SearchModelElementDataState[] +>[] = [ + { + data: [{ modelElement: MODEL_ELEMENT_LINKING_TO_SUBMAP, perfect: false }], + searchQueryElement: '', + loading: 'succeeded', + error: DEFAULT_ERROR, + }, +]; diff --git a/src/redux/modelElements/modelElements.reducers.test.ts b/src/redux/modelElements/modelElements.reducers.test.ts index 8c499a6d..9a3bc2a9 100644 --- a/src/redux/modelElements/modelElements.reducers.test.ts +++ b/src/redux/modelElements/modelElements.reducers.test.ts @@ -9,10 +9,17 @@ import { HttpStatusCode } from 'axios'; import { unwrapResult } from '@reduxjs/toolkit'; import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import modelElementsReducer from '@/redux/modelElements/modelElements.slice'; -import { getModelElementsForModel } from '@/redux/modelElements/modelElements.thunks'; +import { + getModelElementsForModel, + searchModelElement, +} from '@/redux/modelElements/modelElements.thunks'; import { modelElementsFixture } from '@/models/fixtures/modelElementsFixture'; +import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture'; +import { DEFAULT_ERROR } from '@/constants/errors'; +import { MODEL_ELEMENTS_INITIAL_STATE_MOCK } from '@/redux/modelElements/modelElements.mock'; const mockedAxiosClient = mockNetworkNewAPIResponse(); +const SEARCH_QUERY = 'park7'; describe('model elements reducer', () => { let store = {} as ToolkitStoreWithSingleSlice<ModelElementsState>; @@ -23,7 +30,7 @@ describe('model elements reducer', () => { it('should match initial state', () => { const action = { type: 'unknown' }; - expect(modelElementsReducer(undefined, action)).toEqual({}); + expect(modelElementsReducer(undefined, action)).toEqual(MODEL_ELEMENTS_INITIAL_STATE_MOCK); }); it('should update store after successful getModelElementsForModel query', async () => { @@ -32,7 +39,7 @@ describe('model elements reducer', () => { .reply(HttpStatusCode.Ok, modelElementsFixture); const { type } = await store.dispatch(getModelElementsForModel(0)); - const { data, loading, error } = store.getState().modelElements[0]; + const { data, loading, error } = store.getState().modelElements.data[0]; expect(type).toBe('modelElements/getModelElementsForModel/fulfilled'); expect(loading).toEqual('succeeded'); @@ -44,7 +51,7 @@ describe('model elements reducer', () => { mockedAxiosClient.onGet(apiPath.getModelElements(0)).reply(HttpStatusCode.NotFound, []); const action = await store.dispatch(getModelElementsForModel(0)); - const { data, loading, error } = store.getState().modelElements[0]; + const { data, loading, error } = store.getState().modelElements.data[0]; expect(action.type).toBe('modelElements/getModelElementsForModel/rejected'); expect(() => unwrapResult(action)).toThrow( @@ -62,16 +69,129 @@ describe('model elements reducer', () => { const modelElementsPromise = store.dispatch(getModelElementsForModel(0)); - const { data, loading } = store.getState().modelElements[0]; + const { data, loading } = store.getState().modelElements.data[0]; expect(data).toEqual([]); expect(loading).toEqual('pending'); modelElementsPromise.then(() => { const { data: dataPromiseFulfilled, loading: promiseFulfilled } = - store.getState().modelElements[0]; + store.getState().modelElements.data[0]; expect(dataPromiseFulfilled).toEqual(modelElementsFixture.content); expect(promiseFulfilled).toEqual('succeeded'); }); }); + + it('should update store after succesfull searchModelElement query', async () => { + mockedAxiosClient + .onGet( + apiPath.getBioEntityContentsStringWithQuery({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ) + .reply(HttpStatusCode.Ok, bioEntityResponseFixture); + + const { type } = await store.dispatch( + searchModelElement({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ); + const { search } = store.getState().modelElements; + const modelElementWithSearchQuery = search.data.find( + modelElement => modelElement.searchQueryElement === SEARCH_QUERY, + ); + + expect(type).toBe('modelElements/searchModelElement/fulfilled'); + expect(modelElementWithSearchQuery).toEqual({ + searchQueryElement: SEARCH_QUERY, + data: bioEntityResponseFixture.content.map(data => ({ + modelElement: data.bioEntity, + perfect: data.perfect, + })), + loading: 'succeeded', + error: DEFAULT_ERROR, + }); + }); + + it('should update store after failed getBioEntity query', async () => { + mockedAxiosClient + .onGet( + apiPath.getBioEntityContentsStringWithQuery({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ) + .reply(HttpStatusCode.NotFound, bioEntityResponseFixture); + + const action = await store.dispatch( + searchModelElement({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ); + const { search } = store.getState().modelElements; + + const modelElementWithSearchQuery = search.data.find( + modelElement => modelElement.searchQueryElement === SEARCH_QUERY, + ); + expect(action.type).toBe('modelElements/searchModelElement/rejected'); + expect(() => unwrapResult(action)).toThrow( + "Failed to search model element: The page you're looking for doesn't exist. Please verify the URL and try again.", + ); + expect(modelElementWithSearchQuery).toEqual({ + searchQueryElement: SEARCH_QUERY, + data: undefined, + loading: 'failed', + error: DEFAULT_ERROR, + }); + }); + + it('should update store on loading getBioEntity query', async () => { + mockedAxiosClient + .onGet( + apiPath.getBioEntityContentsStringWithQuery({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ) + .reply(HttpStatusCode.Ok, bioEntityResponseFixture); + + const searchModelElementPromise = store.dispatch( + searchModelElement({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ); + + const { search } = store.getState().modelElements; + const modelElementWithSearchQuery = search.data.find( + modelElement => modelElement.searchQueryElement === SEARCH_QUERY, + ); + + expect(modelElementWithSearchQuery).toEqual({ + searchQueryElement: SEARCH_QUERY, + data: undefined, + loading: 'pending', + error: DEFAULT_ERROR, + }); + + searchModelElementPromise.then(() => { + const { search: searchPromiseFulfilled } = store.getState().modelElements; + const modelElementWithSearchQueryFulfilled = searchPromiseFulfilled.data.find( + modelElement => modelElement.searchQueryElement === SEARCH_QUERY, + ); + + expect(modelElementWithSearchQueryFulfilled).toEqual({ + searchQueryElement: SEARCH_QUERY, + data: bioEntityResponseFixture.content.map(data => ({ + modelElement: data.bioEntity, + perfect: data.perfect, + })), + loading: 'succeeded', + error: DEFAULT_ERROR, + }); + }); + }); }); diff --git a/src/redux/modelElements/modelElements.reducers.ts b/src/redux/modelElements/modelElements.reducers.ts index 777295cf..933f2e69 100644 --- a/src/redux/modelElements/modelElements.reducers.ts +++ b/src/redux/modelElements/modelElements.reducers.ts @@ -1,36 +1,135 @@ -import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; -import { getModelElementsForModel } from '@/redux/modelElements/modelElements.thunks'; -import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; +import { ActionReducerMapBuilder, PayloadAction } from '@reduxjs/toolkit'; +import { + getModelElementsForModel, + searchModelElement, + searchMultiModelElements, +} from '@/redux/modelElements/modelElements.thunks'; +import { + ModelElementsState, + SearchModelElementDataState, +} from '@/redux/modelElements/modelElements.types'; import { MODEL_ELEMENTS_STATE_INITIAL_MODEL_MOCK } from '@/redux/modelElements/modelElements.mock'; import { DEFAULT_ERROR } from '@/constants/errors'; +import { ModelElement } from '@/types/models'; export const getModelElementsReducer = ( builder: ActionReducerMapBuilder<ModelElementsState>, ): void => { builder.addCase(getModelElementsForModel.pending, (state, action) => { const modelId = action.meta.arg; - if (state[modelId]) { - state[modelId].loading = 'pending'; + if (state.data[modelId]) { + state.data[modelId].loading = 'pending'; } else { - state[modelId] = { ...MODEL_ELEMENTS_STATE_INITIAL_MODEL_MOCK, loading: 'pending' }; + state.data[modelId] = { ...MODEL_ELEMENTS_STATE_INITIAL_MODEL_MOCK, loading: 'pending' }; } }); builder.addCase(getModelElementsForModel.fulfilled, (state, action) => { const modelId = action.meta.arg; const data = action.payload || []; - if (state[modelId]) { - state[modelId].data = data; - state[modelId].loading = 'succeeded'; + if (state.data[modelId]) { + state.data[modelId].data = data; + state.data[modelId].loading = 'succeeded'; } else { - state[modelId] = { data, loading: 'pending', error: DEFAULT_ERROR }; + state.data[modelId] = { data, loading: 'pending', error: DEFAULT_ERROR }; } }); builder.addCase(getModelElementsForModel.rejected, (state, action) => { const modelId = action.meta.arg; - if (state[modelId]) { - state[modelId].loading = 'failed'; + if (state.data[modelId]) { + state.data[modelId].loading = 'failed'; } else { - state[modelId] = { ...MODEL_ELEMENTS_STATE_INITIAL_MODEL_MOCK, loading: 'failed' }; + state.data[modelId] = { ...MODEL_ELEMENTS_STATE_INITIAL_MODEL_MOCK, loading: 'failed' }; } }); }; + +export const searchModelElementReducer = ( + builder: ActionReducerMapBuilder<ModelElementsState>, +): void => { + builder.addCase(searchModelElement.pending, (state, action) => { + state.search.data.push({ + searchQueryElement: action.meta.arg.searchQuery, + data: undefined, + loading: 'pending', + error: DEFAULT_ERROR, + }); + }); + builder.addCase(searchModelElement.fulfilled, (state, action) => { + const bioEntities = state.search.data.find( + bioEntity => bioEntity.searchQueryElement === action.meta.arg.searchQuery, + ); + if (bioEntities) { + bioEntities.data = action.payload?.map(data => ({ + modelElement: data.bioEntity, + perfect: data.perfect, + })); + bioEntities.loading = 'succeeded'; + } + }); + builder.addCase(searchModelElement.rejected, (state, action) => { + const bioEntities = state.search.data.find( + bioEntity => bioEntity.searchQueryElement === action.meta.arg.searchQuery, + ); + if (bioEntities) { + bioEntities.loading = 'failed'; + } + }); +}; + +export const searchMultiModelElementsReducer = ( + builder: ActionReducerMapBuilder<ModelElementsState>, +): void => { + builder.addCase(searchMultiModelElements.pending, state => { + state.search.data = []; + state.search.loading = 'pending'; + }); + builder.addCase(searchMultiModelElements.fulfilled, state => { + state.search.loading = 'succeeded'; + }); + builder.addCase(searchMultiModelElements.rejected, state => { + state.search.loading = 'failed'; + }); +}; + +export const setModelElementSearchReducer = ( + state: ModelElementsState, + action: PayloadAction<SearchModelElementDataState>, +): void => { + state.search = { + data: [ + { + data: [action.payload], + loading: 'succeeded', + error: DEFAULT_ERROR, + searchQueryElement: action.payload.modelElement.id.toString(), + }, + ], + loading: 'succeeded', + error: DEFAULT_ERROR, + }; +}; + +export const setMultipleModelElementSearchReducer = ( + state: ModelElementsState, + action: PayloadAction<ModelElement[]>, +): void => { + state.search.data = action.payload.map(modelElement => { + return { + data: [ + { + modelElement, + perfect: true, + }, + ], + loading: 'succeeded', + error: DEFAULT_ERROR, + searchQueryElement: modelElement.id.toString(), + }; + }); + state.search.loading = 'succeeded'; +}; + +export const clearSearchModelElementsReducer = (state: ModelElementsState): void => { + state.search.data = []; + state.search.loading = 'idle'; +}; diff --git a/src/redux/modelElements/modelElements.selector.ts b/src/redux/modelElements/modelElements.selector.ts index 55c08d7a..317aa053 100644 --- a/src/redux/modelElements/modelElements.selector.ts +++ b/src/redux/modelElements/modelElements.selector.ts @@ -1,22 +1,39 @@ 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 { currentModelIdSelector, modelsDataSelector } from '@/redux/models/models.selectors'; +import { + currentSearchedBioEntityId, + currentSelectedSearchElement, +} from '@/redux/drawer/drawer.selectors'; +import { Comment, MapModel, 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'; +import { MultiSearchData } from '@/types/fetchDataState'; +import { SearchModelElementDataState } from '@/redux/modelElements/modelElements.types'; +import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; +import { currentSelectedBioEntityIdSelector } from '@/redux/contextMenu/contextMenu.selector'; +import { ElementIdTabObj } from '@/types/elements'; +import { allCommentsSelectorOfCurrentMap } from '@/redux/comment/comment.selectors'; + +export const modelElementsStateSelector = createSelector( + rootSelector, + state => state.modelElements, +); -export const modelElementsSelector = createSelector(rootSelector, state => state.modelElements); +export const modelElementsDataSelector = createSelector( + modelElementsStateSelector, + state => state.data, +); export const modelElementsStateForCurrentModelSelector = createSelector( - modelElementsSelector, + modelElementsDataSelector, currentModelIdSelector, - (state, currentModelId) => state[currentModelId], + (data, currentModelId) => data[currentModelId], ); export const modelElementsByModelIdSelector = createSelector( - [modelElementsSelector, (_state, modelId: number): number => modelId], - (state, modelId) => state[modelId]?.data || [], + [modelElementsDataSelector, (_state, modelId: number): number => modelId], + (data, modelId) => data[modelId]?.data || [], ); export const modelElementsCurrentModelLoadingSelector = createSelector( @@ -24,8 +41,9 @@ export const modelElementsCurrentModelLoadingSelector = createSelector( state => state?.loading, ); -export const modelElementsAnyModelLoadingSelector = createSelector(modelElementsSelector, state => - Object.values(state).some(modelElementState => modelElementState.loading === 'pending'), +export const modelElementsAnyModelLoadingSelector = createSelector( + modelElementsDataSelector, + state => Object.values(state).some(modelElementState => modelElementState.loading === 'pending'), ); export const modelElementsForCurrentModelSelector = createSelector( @@ -64,7 +82,7 @@ export const currentDrawerModelElementSelector = createSelector( ); export const compartmentPathwaysSelector = createSelector( - modelElementsSelector, + modelElementsDataSelector, (state): ModelElement[] => { const pathways: ModelElement[] = []; Object.values(state).forEach(modelState => { @@ -77,3 +95,158 @@ export const compartmentPathwaysSelector = createSelector( return pathways; }, ); + +export const allModelElementsSubmapConnectionsForCurrentSubmapSelector = createSelector( + modelElementsWithSubmapConnectionForCurrentModelSelector, + currentModelIdSelector, + (submapConnectionsModelElement, currentModel): ModelElement[] => + submapConnectionsModelElement.filter(({ model }) => model === currentModel), +); + +// ------SEARCH (OLD BIO ENTITIES)------ +export const modelElementsSearchSelector = createSelector( + modelElementsStateSelector, + state => state.search, +); + +export const modelElementsSearchDataSelector = createSelector( + modelElementsSearchSelector, + state => state.data, +); + +export const searchModelElementsListSelector = createSelector( + modelElementsSearchDataSelector, + modelElementsSearchData => modelElementsSearchData.map(b => b.data || []).flat(), +); + +export const allSearchModelElementForCurrentModelSelector = createSelector( + modelElementsSearchDataSelector, + currentModelIdSelector, + (modelElementsSearchData, currentModelId): ModelElement[] => { + return modelElementsSearchData + .map(({ data }) => data || []) + .flat() + .filter(({ modelElement }) => modelElement.model === currentModelId) + .map(({ modelElement }) => modelElement); + }, +); + +export const searchedModelElementsSelector = createSelector( + modelElementsSearchDataSelector, + currentSelectedSearchElement, + ( + modelElementsSearchData, + currentSearchElement, + ): MultiSearchData<SearchModelElementDataState[]> | undefined => + modelElementsSearchData.find( + ({ searchQueryElement }) => searchQueryElement === currentSearchElement, + ), +); + +export const searchedModelElementsForCurrentModelSelector = createSelector( + modelElementsSearchDataSelector, + currentModelIdSelector, + currentSelectedSearchElement, + (modelElementsSearchData, currentModelId, currentSearchElement): ModelElement[] => { + return modelElementsSearchData + .filter(({ searchQueryElement }) => + currentSearchElement ? searchQueryElement === currentSearchElement : true, + ) + .map(({ data }) => data || []) + .flat() + .filter(({ modelElement }) => modelElement.model === currentModelId) + .map(({ modelElement }) => modelElement); + }, +); + +export const searchModelElementsLoadingSelector = createSelector( + modelElementsSearchSelector, + search => search.loading, +); + +export const searchModelElementsLoadingStatusSelector = createSelector( + searchedModelElementsSelector, + state => state?.loading, +); + +export const numberOfSearchModelElementsSelector = createSelector( + searchedModelElementsSelector, + state => (state?.data ? state.data.length : SIZE_OF_EMPTY_ARRAY), +); + +export const searchedModelElementForContextMapSelector = createSelector( + modelElementsSearchDataSelector, + currentSelectedBioEntityIdSelector, + (modelElementsSearchData, currentBioEntityId): ModelElement | undefined => { + return modelElementsSearchData + .find(({ searchQueryElement }) => searchQueryElement === currentBioEntityId.toString()) + ?.data?.find(({ modelElement }) => modelElement.id === currentBioEntityId)?.modelElement; + }, +); + +export const searchedModelElementUniProtIdSelector = createSelector( + searchedModelElementForContextMapSelector, + (modelElement): string | undefined => { + return modelElement?.references.find(({ type }) => type === 'UNIPROT')?.resource; + }, +); + +export const allSearchModelElementsIdTabForCurrentModelSelector = createSelector( + modelElementsSearchDataSelector, + currentModelIdSelector, + (modelElementsSearchData, currentModelId): ElementIdTabObj => { + const entries = modelElementsSearchData.flatMap(({ data, searchQueryElement }) => + (data || []) + .flat() + .filter(({ modelElement }) => modelElement.model === currentModelId) + .map(({ modelElement }) => [modelElement.id, searchQueryElement]), + ); + return Object.fromEntries(entries); + }, +); + +export const searchModelElementsPerModelSelector = createSelector( + searchedModelElementsSelector, + modelsDataSelector, + (modelElements, models) => { + const modelElementsPerModelPerSearchElement = (models || []).map(model => { + const modelElementsInGivenModel = (modelElements?.data || []).filter( + entity => model.id === entity.modelElement.model, + ); + + return { + modelName: model.name, + modelId: model.id, + numberOfModelElements: modelElementsInGivenModel.length, + modelElements: modelElementsInGivenModel, + }; + }); + + return modelElementsPerModelPerSearchElement.filter( + model => model.numberOfModelElements !== SIZE_OF_EMPTY_ARRAY, + ); + }, +); + +export const currentDrawerModelElementRelatedSubmapSelector = createSelector( + currentDrawerModelElementSelector, + modelsDataSelector, + (bioEntity, models): MapModel | undefined => + models.find(({ id }) => id === bioEntity?.submodel?.mapId), +); + +export const currentDrawerElementCommentsSelector = createSelector( + currentDrawerModelElementSelector, + allCommentsSelectorOfCurrentMap, + (element, comments): Comment[] => { + if (element) { + return comments.filter( + comment => + comment.type === 'ALIAS' && + comment.modelId === element.model && + Number(comment.elementId) === element.id, + ); + } + return []; + }, +); diff --git a/src/redux/modelElements/modelElements.slice.ts b/src/redux/modelElements/modelElements.slice.ts index cbf16d00..d2130dec 100644 --- a/src/redux/modelElements/modelElements.slice.ts +++ b/src/redux/modelElements/modelElements.slice.ts @@ -1,14 +1,30 @@ import { createSlice } from '@reduxjs/toolkit'; -import { getModelElementsReducer } from '@/redux/modelElements/modelElements.reducers'; +import { + clearSearchModelElementsReducer, + getModelElementsReducer, + setModelElementSearchReducer, + setMultipleModelElementSearchReducer, + searchModelElementReducer, + searchMultiModelElementsReducer, +} from '@/redux/modelElements/modelElements.reducers'; import { MODEL_ELEMENTS_INITIAL_STATE_MOCK } from '@/redux/modelElements/modelElements.mock'; export const modelElements = createSlice({ name: 'modelElements', initialState: MODEL_ELEMENTS_INITIAL_STATE_MOCK, - reducers: {}, + reducers: { + setModelElementSearch: setModelElementSearchReducer, + setMultipleModelElementSearch: setMultipleModelElementSearchReducer, + clearSearchModelElements: clearSearchModelElementsReducer, + }, extraReducers: builder => { + searchModelElementReducer(builder); + searchMultiModelElementsReducer(builder); getModelElementsReducer(builder); }, }); +export const { setModelElementSearch, setMultipleModelElementSearch, clearSearchModelElements } = + modelElements.actions; + export default modelElements.reducer; diff --git a/src/redux/modelElements/modelElements.thunks.test.ts b/src/redux/modelElements/modelElements.thunks.test.ts index cb0c5c52..7fdf47a9 100644 --- a/src/redux/modelElements/modelElements.thunks.test.ts +++ b/src/redux/modelElements/modelElements.thunks.test.ts @@ -8,9 +8,16 @@ import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { HttpStatusCode } from 'axios'; import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import modelElementsReducer from '@/redux/modelElements/modelElements.slice'; -import { getModelElementsForModel } from '@/redux/modelElements/modelElements.thunks'; +import { + getModelElementsForModel, + searchModelElement, + searchMultiModelElements, +} from '@/redux/modelElements/modelElements.thunks'; import { modelElementsFixture } from '@/models/fixtures/modelElementsFixture'; +import { bioEntityResponseFixture } from '@/models/fixtures/bioEntityContentsFixture'; +import { unwrapResult } from '@reduxjs/toolkit'; +const SEARCH_QUERY = 'park7'; const mockedAxiosClient = mockNetworkNewAPIResponse(); describe('model elements thunks', () => { @@ -38,4 +45,112 @@ describe('model elements thunks', () => { expect(payload).toEqual(undefined); }); }); + + describe('searchMultiModelElements', () => { + it('should return transformed bioEntityContent array', async () => { + mockedAxiosClient + .onGet( + apiPath.getBioEntityContentsStringWithQuery({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ) + .reply(HttpStatusCode.Ok, bioEntityResponseFixture); + + const data = await store + .dispatch( + searchMultiModelElements({ + searchQueries: [SEARCH_QUERY], + isPerfectMatch: false, + }), + ) + .unwrap(); + + expect(data).toEqual(bioEntityResponseFixture.content); + }); + + it('should combine all returned bioEntityContent arrays and return array with all provided bioEntityContent elements', async () => { + mockedAxiosClient + .onGet( + apiPath.getBioEntityContentsStringWithQuery({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ) + .reply(HttpStatusCode.Ok, bioEntityResponseFixture); + + const data = await store + .dispatch( + searchMultiModelElements({ + searchQueries: [SEARCH_QUERY, SEARCH_QUERY], + isPerfectMatch: false, + }), + ) + .unwrap(); + + expect(data).toEqual([ + ...bioEntityResponseFixture.content, + ...bioEntityResponseFixture.content, + ]); + }); + }); + + describe('searchModelElement', () => { + it('should return data when data response from API is valid', async () => { + mockedAxiosClient + .onGet( + apiPath.getBioEntityContentsStringWithQuery({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ) + .reply(HttpStatusCode.Ok, bioEntityResponseFixture); + + const { payload } = await store.dispatch( + searchModelElement({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ); + expect(payload).toEqual(bioEntityResponseFixture.content); + }); + it('should return undefined when data response from API is not valid ', async () => { + mockedAxiosClient + .onGet( + apiPath.getBioEntityContentsStringWithQuery({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ) + .reply(HttpStatusCode.Ok, { randomProperty: 'randomValue' }); + + const { payload } = await store.dispatch( + searchModelElement({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ); + expect(payload).toEqual(undefined); + }); + it('should handle error message when getBioEntityContents failed', async () => { + mockedAxiosClient + .onGet( + apiPath.getBioEntityContentsStringWithQuery({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ) + .reply(HttpStatusCode.NotFound, null); + + const action = await store.dispatch( + searchModelElement({ + searchQuery: SEARCH_QUERY, + isPerfectMatch: false, + }), + ); + expect(() => unwrapResult(action)).toThrow( + "Failed to search model element: The page you're looking for doesn't exist. Please verify the URL and try again.", + ); + }); + }); }); diff --git a/src/redux/modelElements/modelElements.thunks.ts b/src/redux/modelElements/modelElements.thunks.ts index 68f2419e..90eb0c9c 100644 --- a/src/redux/modelElements/modelElements.thunks.ts +++ b/src/redux/modelElements/modelElements.thunks.ts @@ -4,10 +4,21 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; import { ThunkConfig } from '@/types/store'; import { getError } from '@/utils/error-report/getError'; import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance'; -import { ModelElement, ModelElements } from '@/types/models'; -import { MODEL_ELEMENTS_FETCHING_ERROR_PREFIX } from '@/redux/modelElements/modelElements.constants'; +import { BioEntityContent, BioEntityResponse, ModelElement, ModelElements } from '@/types/models'; +import { + MODEL_ELEMENT_SEARCH_ERROR_PREFIX, + MODEL_ELEMENTS_FETCHING_ERROR_PREFIX, + MULTI_MODEL_ELEMENTS_SEARCH_ERROR_PREFIX, +} from '@/redux/modelElements/modelElements.constants'; import { modelElementSchema } from '@/models/modelElementSchema'; import { pageableSchema } from '@/models/pageableSchema'; +import { addNumbersToEntityNumberData } from '@/redux/entityNumber/entityNumber.slice'; +import { + SearchModelElementProps, + SearchMultiModelElementsActions, + SearchMultiModelElementsProps, +} from '@/redux/modelElements/modelElements.types'; +import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema'; export const getModelElementsForModel = createAsyncThunk< Array<ModelElement> | undefined, @@ -24,3 +35,63 @@ export const getModelElementsForModel = createAsyncThunk< return Promise.reject(getError({ error, prefix: MODEL_ELEMENTS_FETCHING_ERROR_PREFIX })); } }); + +export const searchModelElement = createAsyncThunk< + BioEntityContent[] | undefined, + SearchModelElementProps, + ThunkConfig +>( + 'modelElements/searchModelElement', + async ({ searchQuery, isPerfectMatch, addNumbersToEntityNumber = true }, { dispatch }) => { + try { + const { data } = await axiosInstanceNewAPI.get<BioEntityResponse>( + apiPath.getBioEntityContentsStringWithQuery({ searchQuery, isPerfectMatch }), + ); + + const isDataValid = validateDataUsingZodSchema(data, bioEntityResponseSchema); + const { content } = data; + if (addNumbersToEntityNumber && content) { + const modelElementsIds = content.map(b => b.bioEntity.elementId); + dispatch(addNumbersToEntityNumberData(modelElementsIds)); + } + + return isDataValid ? content : undefined; + } catch (error) { + return Promise.reject(getError({ error, prefix: MODEL_ELEMENT_SEARCH_ERROR_PREFIX })); + } + }, +); + +export const searchMultiModelElements = createAsyncThunk< + BioEntityContent[], + SearchMultiModelElementsProps, + ThunkConfig +>( + 'modelElements/searchMultiModelElements', + async ({ searchQueries, isPerfectMatch }, { dispatch }) => { + try { + const asyncGetBioEntityFunctions = searchQueries.map(searchQuery => + dispatch( + searchModelElement({ searchQuery, isPerfectMatch, addNumbersToEntityNumber: false }), + ), + ); + + const multiModelElementsActions = (await Promise.all( + asyncGetBioEntityFunctions, + )) as SearchMultiModelElementsActions; + + const multiModelElements = multiModelElementsActions + .map(multiModelElementsAction => multiModelElementsAction?.payload || []) + .flat() + .filter((payload): payload is BioEntityContent => typeof payload !== 'string') + .filter(payload => 'bioEntity' in payload || {}); + + const modelElementsIds = multiModelElements.map(b => b.bioEntity.elementId); + dispatch(addNumbersToEntityNumberData(modelElementsIds)); + + return multiModelElements; + } catch (error) { + return Promise.reject(getError({ error, prefix: MULTI_MODEL_ELEMENTS_SEARCH_ERROR_PREFIX })); + } + }, +); diff --git a/src/redux/modelElements/modelElements.types.ts b/src/redux/modelElements/modelElements.types.ts index b2d4ee68..c240d572 100644 --- a/src/redux/modelElements/modelElements.types.ts +++ b/src/redux/modelElements/modelElements.types.ts @@ -1,4 +1,22 @@ -import { KeyedFetchDataState } from '@/types/fetchDataState'; -import { ModelElement } from '@/types/models'; +import { KeyedFetchDataState, MultiFetchDataState } from '@/types/fetchDataState'; +import { BioEntityContent, ModelElement } from '@/types/models'; +import { PerfectMultiSearchParams, PerfectSearchParams } from '@/types/search'; +import { PayloadAction } from '@reduxjs/toolkit'; -export type ModelElementsState = KeyedFetchDataState<Array<ModelElement>>; +export type SearchModelElementDataState = { + perfect: boolean; + modelElement: ModelElement; +}; + +export type ModelElementsState = { + data: KeyedFetchDataState<ModelElement[]>; + search: MultiFetchDataState<SearchModelElementDataState[]>; +}; + +export type SearchMultiModelElementsProps = PerfectMultiSearchParams; + +export type SearchMultiModelElementsActions = PayloadAction< + BioEntityContent[] | undefined | string +>[]; + +export type SearchModelElementProps = PerfectSearchParams; diff --git a/src/redux/newReactions/newReactions.selectors.ts b/src/redux/newReactions/newReactions.selectors.ts index b8ba305f..a0ef6652 100644 --- a/src/redux/newReactions/newReactions.selectors.ts +++ b/src/redux/newReactions/newReactions.selectors.ts @@ -1,7 +1,8 @@ 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 { Comment, NewReaction } from '@/types/models'; +import { allCommentsSelectorOfCurrentMap } from '@/redux/comment/comment.selectors'; import { rootSelector } from '../root/root.selectors'; export const newReactionsSelector = createSelector(rootSelector, state => state.newReactions); @@ -34,3 +35,19 @@ export const currentDrawerNewReactionSelector = createSelector( return newReactions.find(newReaction => newReaction.id === currentDrawerReactionId); }, ); + +export const currentDrawerReactionCommentsSelector = createSelector( + currentDrawerNewReactionSelector, + allCommentsSelectorOfCurrentMap, + (reaction, comments): Comment[] => { + if (reaction) { + return comments.filter( + comment => + comment.type === 'REACTION' && + comment.modelId === reaction.model && + Number(comment.elementId) === reaction.id, + ); + } + return []; + }, +); diff --git a/src/redux/reactions/isReactionBioentity.ts b/src/redux/reactions/isReactionBioentity.ts deleted file mode 100644 index e4e673a2..00000000 --- a/src/redux/reactions/isReactionBioentity.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { BioEntity } from '@/types/models'; - -export const isReactionBioEntity = (bioEntity: BioEntity): boolean => { - return bioEntity.idReaction !== undefined && bioEntity.idReaction !== null; -}; diff --git a/src/redux/reactions/isReactionElement.ts b/src/redux/reactions/isReactionElement.ts new file mode 100644 index 00000000..e9a3d781 --- /dev/null +++ b/src/redux/reactions/isReactionElement.ts @@ -0,0 +1,5 @@ +import { PublicationElement } from '@/types/models'; + +export const isReactionElement = (element: PublicationElement): boolean => { + return element.idReaction !== undefined && element.idReaction !== null; +}; diff --git a/src/redux/search/search.thunks.ts b/src/redux/search/search.thunks.ts index b95730d2..ddbfc4af 100644 --- a/src/redux/search/search.thunks.ts +++ b/src/redux/search/search.thunks.ts @@ -1,10 +1,10 @@ -import { getMultiBioEntity } from '@/redux/bioEntity/bioEntity.thunks'; import { getMultiChemicals } from '@/redux/chemicals/chemicals.thunks'; import { getMultiDrugs } from '@/redux/drugs/drugs.thunks'; import { PerfectMultiSearchParams } from '@/types/search'; import { ThunkConfig } from '@/types/store'; import { createAsyncThunk } from '@reduxjs/toolkit'; import { getError } from '@/utils/error-report/getError'; +import { searchMultiModelElements } from '@/redux/modelElements/modelElements.thunks'; import { resetReactionsData } from '../reactions/reactions.slice'; import type { RootState } from '../store'; import { DATA_SEARCHING_ERROR_PREFIX } from './search.constants'; @@ -30,13 +30,13 @@ export const getSearchData = createAsyncThunk< } if (containsDisease) { await Promise.all([ - dispatch(getMultiBioEntity({ searchQueries, isPerfectMatch })), + dispatch(searchMultiModelElements({ searchQueries, isPerfectMatch })), dispatch(getMultiDrugs(searchQueries)), dispatch(getMultiChemicals(searchQueries)), ]); } else { await Promise.all([ - dispatch(getMultiBioEntity({ searchQueries, isPerfectMatch })), + dispatch(searchMultiModelElements({ searchQueries, isPerfectMatch })), dispatch(getMultiDrugs(searchQueries)), ]); } diff --git a/src/redux/search/search.thunks.utils.ts b/src/redux/search/search.thunks.utils.ts index 0744617c..43e7504a 100644 --- a/src/redux/search/search.thunks.utils.ts +++ b/src/redux/search/search.thunks.utils.ts @@ -2,8 +2,17 @@ import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import type { RootState } from '../store'; export const dispatchPluginsEvents = (searchQueries: string[], state: RootState): void => { - const bioEntities = state.bioEntity.data; - const bioEntitiesResults = bioEntities.map(bioEntity => (bioEntity.data ? bioEntity.data : [])); + const searchModelElements = state.modelElements.search.data; + const modelElementsResults = searchModelElements + .map(searchElement => (searchElement.data ? searchElement.data : [])) + .map(data => { + return data.map(result => { + return { + perfect: result.perfect, + bioEntity: result.modelElement, + }; + }); + }); const drugs = state.drugs.data; const drugsResults = drugs.map(drug => (drug.data ? drug.data : [])); @@ -14,7 +23,7 @@ export const dispatchPluginsEvents = (searchQueries: string[], state: RootState) PluginsEventBus.dispatchEvent('onSearch', { type: 'bioEntity', searchValues: searchQueries, - results: bioEntitiesResults, + results: modelElementsResults, }); PluginsEventBus.dispatchEvent('onSearch', { type: 'drugs', diff --git a/src/services/pluginsManager/bioEntities/clearAllElements.ts b/src/services/pluginsManager/bioEntities/clearAllElements.ts index ce8a4ee7..f8dfe461 100644 --- a/src/services/pluginsManager/bioEntities/clearAllElements.ts +++ b/src/services/pluginsManager/bioEntities/clearAllElements.ts @@ -1,8 +1,8 @@ -import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; import { clearChemicalsData } from '@/redux/chemicals/chemicals.slice'; import { clearDrugsData } from '@/redux/drugs/drugs.slice'; import { setMarkersData } from '@/redux/markers/markers.slice'; import { store } from '@/redux/store'; +import { clearSearchModelElements } from '@/redux/modelElements/modelElements.slice'; type ElementName = 'drugs' | 'chemicals' | 'content' | 'marker'; @@ -10,7 +10,7 @@ export const clearAllElements = (elements: ElementName[]): void => { const { dispatch } = store; if (elements.includes('content')) { - dispatch(clearBioEntities()); + dispatch(clearSearchModelElements()); } if (elements.includes('chemicals')) { diff --git a/src/services/pluginsManager/bioEntities/getAllContent.ts b/src/services/pluginsManager/bioEntities/getAllContent.ts index af8f6d11..ba999eca 100644 --- a/src/services/pluginsManager/bioEntities/getAllContent.ts +++ b/src/services/pluginsManager/bioEntities/getAllContent.ts @@ -1,10 +1,10 @@ -import { bioEntityDataListSelector } from '@/redux/bioEntity/bioEntity.selectors'; import { store } from '@/redux/store'; -import { BioEntityContent } from '@/types/models'; +import { searchModelElementsListSelector } from '@/redux/modelElements/modelElements.selector'; +import { SearchModelElementDataState } from '@/redux/modelElements/modelElements.types'; -export const getAllBioEntities = (): BioEntityContent[] => { +export const getAllBioEntities = (): SearchModelElementDataState[] => { const { getState } = store; - const bioEntities = bioEntityDataListSelector(getState()); + const bioEntities = searchModelElementsListSelector(getState()); return bioEntities || []; }; diff --git a/src/services/pluginsManager/bioEntities/getShownElements.ts b/src/services/pluginsManager/bioEntities/getShownElements.ts index 89cf67bd..be9de04a 100644 --- a/src/services/pluginsManager/bioEntities/getShownElements.ts +++ b/src/services/pluginsManager/bioEntities/getShownElements.ts @@ -1,16 +1,16 @@ -import { searchedBioEntitesSelectorOfCurrentMap } from '@/redux/bioEntity/bioEntity.selectors'; -import { searchedChemicalsBioEntitesOfCurrentMapSelector } from '@/redux/chemicals/chemicals.selectors'; -import { searchedDrugsBioEntitesOfCurrentMapSelector } from '@/redux/drugs/drugs.selectors'; +import { searchedChemicalsElementsOfCurrentMapSelector } from '@/redux/chemicals/chemicals.selectors'; +import { searchedDrugsElementsOfCurrentMapSelector } from '@/redux/drugs/drugs.selectors'; import { markersPinsOfCurrentMapDataSelector } from '@/redux/markers/markers.selectors'; import { store } from '@/redux/store'; +import { searchedModelElementsForCurrentModelSelector } from '@/redux/modelElements/modelElements.selector'; import { GetShownElementsPluginMethodResult } from './getShownElements.types'; export const getShownElements = (): GetShownElementsPluginMethodResult => { const { getState } = store; - const content = searchedBioEntitesSelectorOfCurrentMap(getState()); - const chemicals = searchedChemicalsBioEntitesOfCurrentMapSelector(getState()); - const drugs = searchedDrugsBioEntitesOfCurrentMapSelector(getState()); + const content = searchedModelElementsForCurrentModelSelector(getState()); + const chemicals = searchedChemicalsElementsOfCurrentMapSelector(getState()); + const drugs = searchedDrugsElementsOfCurrentMapSelector(getState()); const markers = markersPinsOfCurrentMapDataSelector(getState()); return { diff --git a/src/services/pluginsManager/bioEntities/getShownElements.types.ts b/src/services/pluginsManager/bioEntities/getShownElements.types.ts index 210a0e01..d0e71af0 100644 --- a/src/services/pluginsManager/bioEntities/getShownElements.types.ts +++ b/src/services/pluginsManager/bioEntities/getShownElements.types.ts @@ -1,8 +1,8 @@ -import { BioEntity, Marker } from '@/types/models'; +import { ModelElement, Marker } from '@/types/models'; export interface GetShownElementsPluginMethodResult { - content: BioEntity[]; - drugs: BioEntity[]; - chemicals: BioEntity[]; + content: ModelElement[]; + drugs: ModelElement[]; + chemicals: ModelElement[]; markers: Marker[]; } diff --git a/src/services/pluginsManager/map/triggerSearch/getVisibleBioEntitiesPolygonCoordinates.test.ts b/src/services/pluginsManager/map/triggerSearch/getVisibleBioEntitiesPolygonCoordinates.test.ts index 35661b14..fd3f7018 100644 --- a/src/services/pluginsManager/map/triggerSearch/getVisibleBioEntitiesPolygonCoordinates.test.ts +++ b/src/services/pluginsManager/map/triggerSearch/getVisibleBioEntitiesPolygonCoordinates.test.ts @@ -1,11 +1,14 @@ /* eslint-disable no-magic-numbers */ import { MAP_INITIAL_STATE } from '@/redux/map/map.constants'; import { RootState, store } from '@/redux/store'; -import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { DRAWER_INITIAL_STATE } from '@/redux/drawer/drawer.constants'; import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock'; import { HISTAMINE_MAP_ID } from '@/constants/mocks'; +import { modelElementFixture } from '@/models/fixtures/modelElementFixture'; +import { DEFAULT_ERROR } from '@/constants/errors'; +import { MODEL_ELEMENTS_INITIAL_STATE_MOCK } from '@/redux/modelElements/modelElements.mock'; +import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { getVisibleBioEntitiesPolygonCoordinates } from './getVisibleBioEntitiesPolygonCoordinates'; jest.mock('../../../../redux/store'); @@ -35,10 +38,7 @@ describe('getVisibleBioEntitiesPolygonCoordinates', () => { }, }, }, - bioEntity: { - loading: 'succeeded', - error: { message: '', name: '' }, - }, + modelElements: MODEL_ELEMENTS_INITIAL_STATE_MOCK, drugs: { loading: 'succeeded', error: { message: '', name: '' }, @@ -65,7 +65,7 @@ describe('getVisibleBioEntitiesPolygonCoordinates', () => { ...MAP_INITIAL_STATE, data: { ...MAP_INITIAL_STATE.data, - modelId: 52, + modelId: 0, size: { width: 256, height: 256, @@ -75,39 +75,36 @@ describe('getVisibleBioEntitiesPolygonCoordinates', () => { }, }, }, - bioEntity: { - data: [ - { - searchQueryElement: bioEntityContentFixture.bioEntity.name, + modelElements: { + data: { + 0: { + data: [modelElementFixture], loading: 'succeeded', - error: { name: '', message: '' }, - data: [ - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - model: 52, - x: 97, - y: 53, - z: 1, + error: { message: '', name: '' }, + }, + }, + search: { + data: [ + { + searchQueryElement: modelElementFixture.id.toString(), + loading: 'succeeded', + error: DEFAULT_ERROR, + data: [ + { + modelElement: { ...modelElementFixture, model: 0, x: 97, y: 53, z: 1 }, + perfect: true, }, - }, - { - ...bioEntityContentFixture, - bioEntity: { - ...bioEntityContentFixture.bioEntity, - model: 52, - x: 12, - y: 25, - z: 1, + { + modelElement: { ...modelElementFixture, model: 0, x: 12, y: 25, z: 1 }, + perfect: true, }, - }, - ], - }, - ], - loading: 'succeeded', - error: { message: '', name: '' }, - }, + ], + }, + ], + loading: 'succeeded', + error: DEFAULT_ERROR, + }, + } as ModelElementsState, drugs: { data: [ { @@ -141,7 +138,7 @@ describe('getVisibleBioEntitiesPolygonCoordinates', () => { }, searchDrawerState: { ...DRAWER_INITIAL_STATE.searchDrawerState, - selectedSearchElement: bioEntityContentFixture.bioEntity.name, + selectedSearchElement: modelElementFixture.id.toString(), }, }, }) as RootState, diff --git a/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts b/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts index 4a1bcd16..a813ecf9 100644 --- a/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts +++ b/src/services/pluginsManager/map/triggerSearch/searchByCoordinates.ts @@ -13,7 +13,7 @@ import { modelElementsByModelIdSelector } from '@/redux/modelElements/modelEleme import { newReactionsByModelIdSelector } from '@/redux/newReactions/newReactions.selectors'; import { closeDrawer } from '@/redux/drawer/drawer.slice'; import { resetReactionsData } from '@/redux/reactions/reactions.slice'; -import { clearBioEntities } from '@/redux/bioEntity/bioEntity.slice'; +import { clearSearchModelElements } from '@/redux/modelElements/modelElements.slice'; import { Coordinates } from './triggerSearch.types'; export const searchByCoordinates = async ( @@ -45,7 +45,7 @@ export const searchByCoordinates = async ( } dispatch(resetReactionsData()); - dispatch(clearBioEntities()); + dispatch(clearSearchModelElements()); return; } diff --git a/src/services/pluginsManager/map/triggerSearch/searchByQuery.test.ts b/src/services/pluginsManager/map/triggerSearch/searchByQuery.test.ts index 45c0e9df..b8e0c9fb 100644 --- a/src/services/pluginsManager/map/triggerSearch/searchByQuery.test.ts +++ b/src/services/pluginsManager/map/triggerSearch/searchByQuery.test.ts @@ -30,10 +30,6 @@ const MOCK_SEARCH_BY_QUERY_STORE = { }, }, }, - bioEntity: { - loading: 'succeeded', - error: { message: '', name: '' }, - }, drugs: { loading: 'succeeded', error: { message: '', name: '' }, diff --git a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts index 0b3e97df..9b591d8d 100644 --- a/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts +++ b/src/services/pluginsManager/map/triggerSearch/triggerSearch.test.ts @@ -18,6 +18,7 @@ import { MapManager } from '@/services/pluginsManager/map/mapManager'; import { ModelElementsState } from '@/redux/modelElements/modelElements.types'; import { NewReactionsState } from '@/redux/newReactions/newReactions.types'; import { LAYER_TYPE } from '@/components/Map/MapViewer/MapViewer.constants'; +import { MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK } from '@/redux/modelElements/modelElements.mock'; import { ERROR_INVALID_MODEL_ID_TYPE } from '../../errorMessages'; import { triggerSearch } from './triggerSearch'; @@ -37,11 +38,14 @@ const MOCK_STATE = { openedMaps: openedMapsThreeSubmapsFixture, }, modelElements: { - 0: { - data: [], - loading: 'succeeded', - error: { message: '', name: '' }, + data: { + 0: { + data: [], + loading: 'succeeded', + error: { message: '', name: '' }, + }, }, + search: MODEL_ELEMENTS_SEARCH_INITIAL_STATE_MOCK, } as ModelElementsState, newReactions: { 0: { diff --git a/src/services/pluginsManager/pluginContextMenu/pluginsContextMenu.types.ts b/src/services/pluginsManager/pluginContextMenu/pluginsContextMenu.types.ts index 0ea6b811..0c8231ad 100644 --- a/src/services/pluginsManager/pluginContextMenu/pluginsContextMenu.types.ts +++ b/src/services/pluginsManager/pluginContextMenu/pluginsContextMenu.types.ts @@ -1,4 +1,4 @@ -import { BioEntity, NewReaction } from '@/types/models'; +import { ModelElement, NewReaction } from '@/types/models'; export type ClickCoordinates = { modelId: number; @@ -13,7 +13,10 @@ export type PluginContextMenuItemType = { name: string; style: string; enabled: boolean; - callback: (coordinates: ClickCoordinates, element: BioEntity | NewReaction | undefined) => void; + callback: ( + coordinates: ClickCoordinates, + element: ModelElement | NewReaction | undefined, + ) => void; }; export type PluginsContextMenuType = { @@ -23,7 +26,10 @@ export type PluginsContextMenuType = { name: string, style: string, enabled: boolean, - callback: (coordinates: ClickCoordinates, element: BioEntity | NewReaction | undefined) => void, + callback: ( + coordinates: ClickCoordinates, + element: ModelElement | NewReaction | undefined, + ) => void, ) => string; removeMenu: (hash: string, id: string) => void; updateMenu: (hash: string, id: string, name: string, style: string, enabled: boolean) => void; diff --git a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts index 935487c6..c9e8f4fc 100644 --- a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts +++ b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts @@ -1,11 +1,12 @@ import { - BioEntityContent, Chemical, CreatedOverlay, Drug, ElementSearchResult, MapOverlay, + ModelElement, } from '@/types/models'; +import { SearchModelElementDataState } from '@/redux/modelElements/modelElements.types'; import { dispatchEvent } from './pluginsEventBus'; export type BackgroundEvents = 'onBackgroundOverlayChange'; @@ -56,13 +57,18 @@ export type ClickedSurfaceOverlay = { export type SearchDataReaction = { type: 'reaction'; searchValues: string[] | ElementSearchResult[]; - results: BioEntityContent[][]; + results: SearchModelElementDataState[][]; }; -export type SearchDataBioEntity = { +type SearchDataModelElementResults = { + perfect: boolean; + bioEntity: ModelElement; +}; + +export type SearchDataModelElement = { type: 'bioEntity'; searchValues: string[] | ElementSearchResult[]; - results: BioEntityContent[][]; + results: SearchDataModelElementResults[][]; }; export type SearchDataDrugs = { @@ -82,7 +88,7 @@ export type PluginUnloaded = { }; export type SearchData = - | SearchDataBioEntity + | SearchDataModelElement | SearchDataDrugs | SearchDataChemicals | SearchDataReaction; diff --git a/src/types/bioEntity.ts b/src/types/bioEntity.ts deleted file mode 100644 index 1d798469..00000000 --- a/src/types/bioEntity.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { BioEntity } from './models'; -import { PinType } from './pin'; - -export interface BioEntityWithPinType extends BioEntity { - type: PinType; -} - -export type MultiPinBioEntity = BioEntityWithPinType[]; diff --git a/src/types/modelElement.ts b/src/types/modelElement.ts new file mode 100644 index 00000000..faa3d49b --- /dev/null +++ b/src/types/modelElement.ts @@ -0,0 +1,8 @@ +import { ModelElement } from './models'; +import { PinType } from './pin'; + +export interface ModelElementWithPinType extends ModelElement { + type: PinType; +} + +export type MultiPinModelElement = ModelElementWithPinType[]; diff --git a/src/types/models.ts b/src/types/models.ts index 756f345a..5abac994 100644 --- a/src/types/models.ts +++ b/src/types/models.ts @@ -1,6 +1,5 @@ import { bioEntityContentSchema } from '@/models/bioEntityContentSchema'; import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema'; -import { bioEntitySchema } from '@/models/bioEntitySchema'; import { chemicalSchema } from '@/models/chemicalSchema'; import { colorSchema } from '@/models/colorSchema'; import { configurationOptionSchema } from '@/models/configurationOptionSchema'; @@ -70,6 +69,7 @@ import { modificationResiduesSchema } from '@/models/modificationResiduesSchema' import { segmentSchema } from '@/models/segmentSchema'; import { layerImageSchema } from '@/models/layerImageSchema'; import { glyphSchema } from '@/models/glyphSchema'; +import { publicationElementSchema } from '@/models/publicationElementSchema'; export type Project = z.infer<typeof projectSchema>; export type OverviewImageView = z.infer<typeof overviewImageView>; @@ -103,7 +103,6 @@ export type Modification = z.infer<typeof modelElementModificationSchema>; export type MapOverlay = z.infer<typeof mapOverlay>; export type Drug = z.infer<typeof drugSchema>; export type PinDetailsItem = z.infer<typeof targetSchema>; -export type BioEntity = z.infer<typeof bioEntitySchema>; export type BioEntityContent = z.infer<typeof bioEntityContentSchema>; export type BioEntityResponse = z.infer<typeof bioEntityResponseSchema>; export type Chemical = z.infer<typeof chemicalSchema>; @@ -133,6 +132,7 @@ export type CreatedOverlay = z.infer<typeof createdOverlaySchema>; export type Color = z.infer<typeof colorSchema>; export type Statistics = z.infer<typeof statisticsSchema>; export type Publication = z.infer<typeof publicationSchema>; +export type PublicationElement = z.infer<typeof publicationElementSchema>; 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 diff --git a/src/types/pin.ts b/src/types/pin.ts index 7310215f..8c0e9217 100644 --- a/src/types/pin.ts +++ b/src/types/pin.ts @@ -1 +1 @@ -export type PinType = 'chemicals' | 'drugs' | 'bioEntity' | 'comment'; +export type PinType = 'chemicals' | 'drugs' | 'modelElement' | 'comment'; diff --git a/src/utils/bioEntity/mapModelElementToBioEntity.ts b/src/utils/bioEntity/mapModelElementToBioEntity.ts deleted file mode 100644 index e8be81f2..00000000 --- a/src/utils/bioEntity/mapModelElementToBioEntity.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { BioEntity, ModelElement } from '@/types/models'; - -export function mapModelElementToBioEntity(modelElement: ModelElement): BioEntity { - return { - id: modelElement.id, - name: modelElement.name, - model: modelElement.model, - elementId: modelElement.elementId, - references: modelElement.references, - z: modelElement.z, - notes: modelElement.notes, - symbol: modelElement.symbol, - homodimer: modelElement.homodimer, - nameX: modelElement.nameX, - nameY: modelElement.nameY, - nameWidth: modelElement.nameWidth, - nameHeight: modelElement.nameHeight, - nameVerticalAlign: modelElement.nameVerticalAlign, - nameHorizontalAlign: modelElement.nameHorizontalAlign, - width: modelElement.width, - height: modelElement.height, - visibilityLevel: modelElement.visibilityLevel, - transparencyLevel: modelElement.transparencyLevel, - synonyms: modelElement.synonyms, - formerSymbols: modelElement.formerSymbols, - fullName: modelElement.fullName, - abbreviation: modelElement.abbreviation, - formula: modelElement.formula, - glyph: modelElement.glyph, - activity: modelElement.activity, - hypothetical: modelElement.hypothetical, - boundaryCondition: modelElement.boundaryCondition, - constant: modelElement.constant, - initialAmount: modelElement.initialAmount, - initialConcentration: modelElement.initialConcentration, - charge: modelElement.charge, - substanceUnits: modelElement.substanceUnits, - onlySubstanceUnits: modelElement.onlySubstanceUnits, - modificationResidues: modelElement.modificationResidues, - complex: modelElement.complex, - submodel: modelElement.submodel, - x: modelElement.x, - y: modelElement.y, - lineWidth: modelElement.lineWidth, - fontColor: modelElement.fontColor, - fontSize: modelElement.fontSize, - fillColor: modelElement.fillColor, - borderColor: modelElement.borderColor, - sboTerm: modelElement.sboTerm, - } as BioEntity; -} diff --git a/src/utils/bioEntity/mapReactionToBioEntity.ts b/src/utils/bioEntity/mapReactionToModelElement.ts similarity index 72% rename from src/utils/bioEntity/mapReactionToBioEntity.ts rename to src/utils/bioEntity/mapReactionToModelElement.ts index 0aab81b7..2f2f2dc5 100644 --- a/src/utils/bioEntity/mapReactionToBioEntity.ts +++ b/src/utils/bioEntity/mapReactionToModelElement.ts @@ -1,6 +1,6 @@ -import { BioEntity, NewReaction } from '@/types/models'; +import { ModelElement, NewReaction } from '@/types/models'; -export function mapReactionToBioEntity(reaction: NewReaction): BioEntity { +export function mapReactionToModelElement(reaction: NewReaction): ModelElement { return { id: reaction.id, name: reaction.name, @@ -15,5 +15,5 @@ export function mapReactionToBioEntity(reaction: NewReaction): BioEntity { abbreviation: reaction.abbreviation, formula: reaction.formula, sboTerm: reaction.sboTerm, - } as BioEntity; + } as ModelElement; } -- GitLab From 5305037b15cbe4b50fa444d526ef948146657fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Wed, 5 Feb 2025 12:42:44 +0100 Subject: [PATCH 06/12] fix(layers): added permission to edit layers on the map --- .../LayersDrawer/LayersDrawer.component.tsx | 14 +++++++++----- .../LayersDrawerLayerActions.component.tsx | 16 ++++++++++++---- src/components/Map/Map.component.tsx | 10 ++++++++-- src/redux/user/user.selectors.ts | 17 +++++++++++++++++ src/redux/user/user.utils.ts | 12 ++++++++++++ 5 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx index bbed3ad9..06e032bc 100644 --- a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx +++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx @@ -15,11 +15,13 @@ import { getLayersForModel, removeLayer } from '@/redux/layers/layers.thunks'; import { showToast } from '@/utils/showToast'; import { SerializedError } from '@reduxjs/toolkit'; import { LayersDrawerLayerActions } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component'; +import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'; export const LayersDrawer = (): JSX.Element => { const layersForCurrentModel = useAppSelector(layersForCurrentModelSelector); const layersVisibilityForCurrentModel = useAppSelector(layersVisibilityForCurrentModelSelector); const currentModelId = useAppSelector(currentModelIdSelector); + const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector); const dispatch = useAppDispatch(); const [isModalOpen, setIsModalOpen] = useState(false); const [layerId, setLayerId] = useState<number | null>(null); @@ -72,11 +74,13 @@ export const LayersDrawer = (): JSX.Element => { /> <DrawerHeading title="Layers" /> <div className="flex h-[calc(100%-93px)] max-h-[calc(100%-93px)] flex-col overflow-y-auto px-6"> - <div className="flex justify-start pt-2"> - <Button icon="plus" isIcon isFrontIcon onClick={addNewLayer}> - Add new layer - </Button> - </div> + {hasPrivilegeToWriteProject && ( + <div className="flex justify-start pt-2"> + <Button icon="plus" isIcon isFrontIcon onClick={addNewLayer}> + Add new layer + </Button> + </div> + )} {layersForCurrentModel.map(layer => ( <div key={layer.details.id} diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx index 02ea7ed9..b6b47396 100644 --- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx +++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx @@ -1,5 +1,7 @@ import { Button } from '@/shared/Button'; import { Switch } from '@/shared/Switch'; +import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; type LayersDrawerLayerActionsProps = { editLayer: () => void; @@ -14,13 +16,19 @@ export const LayersDrawerLayerActions = ({ isChecked, toggleVisibility, }: LayersDrawerLayerActionsProps): JSX.Element => { + const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector); + return ( <div className="flex items-center gap-2"> <Switch isChecked={isChecked} onToggle={value => toggleVisibility(value)} /> - <Button onClick={() => editLayer()}>Edit</Button> - <Button onClick={() => removeLayer()} color="error" variantStyles="remove"> - Remove - </Button> + {hasPrivilegeToWriteProject && ( + <> + <Button onClick={() => editLayer()}>Edit</Button> + <Button onClick={() => removeLayer()} color="error" variantStyles="remove"> + Remove + </Button> + </> + )} </div> ); }; diff --git a/src/components/Map/Map.component.tsx b/src/components/Map/Map.component.tsx index df0e5eac..c5636818 100644 --- a/src/components/Map/Map.component.tsx +++ b/src/components/Map/Map.component.tsx @@ -9,11 +9,13 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector'; import { MapAdditionalLogos } from '@/components/Map/MapAdditionalLogos'; import { MapDrawActions } from '@/components/Map/MapDrawActions/MapDrawActions.component'; import { layersActiveLayerSelector } from '@/redux/layers/layers.selectors'; +import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'; import { MapAdditionalActions } from './MapAdditionalActions'; import { PluginsDrawer } from './PluginsDrawer'; export const Map = (): JSX.Element => { const activeLayer = useAppSelector(layersActiveLayerSelector); + const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector); return ( <div @@ -22,8 +24,12 @@ export const Map = (): JSX.Element => { > <MapViewer /> <MapVectorBackgroundSelector /> - <MapActiveLayerSelector /> - {activeLayer && <MapDrawActions />} + {hasPrivilegeToWriteProject && ( + <> + <MapActiveLayerSelector /> + {activeLayer && <MapDrawActions />} + </> + )} <Drawer /> <PluginsDrawer /> <Legend /> diff --git a/src/redux/user/user.selectors.ts b/src/redux/user/user.selectors.ts index ed879440..2172ad73 100644 --- a/src/redux/user/user.selectors.ts +++ b/src/redux/user/user.selectors.ts @@ -1,5 +1,8 @@ import { rootSelector } from '@/redux/root/root.selectors'; import { createSelector } from '@reduxjs/toolkit'; +import { projectIdSelector } from '@/redux/project/project.selectors'; +import { hasPrivilegeToObject } from '@/redux/user/user.utils'; +import { UserPrivilege } from '@/types/models'; export const userSelector = createSelector(rootSelector, state => state.user); @@ -7,3 +10,17 @@ export const authenticatedUserSelector = createSelector(userSelector, state => s export const loadingUserSelector = createSelector(userSelector, state => state.loading); export const loginUserSelector = createSelector(userSelector, state => state.login); export const userRoleSelector = createSelector(userSelector, state => state.role); +export const userPrivilegesSelector = createSelector( + userSelector, + state => state.userData?.privileges || [], +); +export const hasPrivilegeToWriteProjectSelector = createSelector( + userPrivilegesSelector, + projectIdSelector, + (userPrivileges: UserPrivilege[], projectId: string | undefined): boolean => { + if (!projectId) { + return false; + } + return hasPrivilegeToObject(userPrivileges, 'WRITE_PROJECT', projectId); + }, +); diff --git a/src/redux/user/user.utils.ts b/src/redux/user/user.utils.ts index ecb9c623..b346b37c 100644 --- a/src/redux/user/user.utils.ts +++ b/src/redux/user/user.utils.ts @@ -3,3 +3,15 @@ import { UserPrivilege } from '@/types/models'; export const hasPrivilege = (privileges: UserPrivilege[], privilegeType: string): boolean => { return privileges.some(privilege => privilege.privilegeType === privilegeType); }; + +export const hasPrivilegeToObject = ( + privileges: UserPrivilege[], + privilegeType: string, + objectId: string, +): boolean => { + return Boolean( + privileges.find( + privilege => privilege.privilegeType === privilegeType && privilege.objectId === objectId, + ), + ); +}; -- GitLab From ef5a0e4749a8fe48ca51b092c2cc025f4928edd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Wed, 5 Feb 2025 12:56:42 +0100 Subject: [PATCH 07/12] bugfix(mouse-click): deactivated default mouse clickwhen user edits map --- .../Map/MapViewer/utils/listeners/useOlMapListeners.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts index f2952ea6..bc0e97be 100644 --- a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts +++ b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts @@ -19,6 +19,7 @@ import { useHandlePinIconClick } from '@/components/Map/MapViewer/utils/listener import { onMapPositionChange } from '@/components/Map/MapViewer/utils/listeners/onMapPositionChange'; import { onPointerMove } from '@/components/Map/MapViewer/utils/listeners/onPointerMove'; import { View } from 'ol'; +import { isMapEditToolsActiveSelector } from '@/redux/mapEditTools/mapEditTools.selectors'; interface UseOlMapListenersInput { view: View; @@ -31,6 +32,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) const isResultDrawerOpen = useSelector(resultDrawerOpen); const modelElementsForCurrentModel = useSelector(modelElementsForCurrentModelSelector); const newReactionsForCurrentModel = useSelector(newReactionsForCurrentModelSelector); + const isMapEditToolsActive = useSelector(isMapEditToolsActiveSelector); const dispatch = useAppDispatch(); const coordinate = useRef<Coordinate>([]); const pixel = useRef<Pixel>([]); @@ -90,7 +92,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) }, [mapInstance]); useEffect(() => { - if (!mapInstance) { + if (!mapInstance || isMapEditToolsActive) { return; } @@ -100,10 +102,10 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) // eslint-disable-next-line consistent-return return () => unByKey(key); - }, [mapInstance, handleMapLeftClick]); + }, [mapInstance, handleMapLeftClick, isMapEditToolsActive]); useEffect(() => { - if (!mapInstance) { + if (!mapInstance || isMapEditToolsActive) { return; } @@ -123,5 +125,5 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) // eslint-disable-next-line consistent-return return () => mapInstance.getViewport().removeEventListener('contextmenu', rightClickEvent); - }, [mapInstance, handleRightClick]); + }, [mapInstance, handleRightClick, isMapEditToolsActive]); }; -- GitLab From eea61b5eeef2a5207a2fdbb71f0fdfb5f6110298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Wed, 5 Feb 2025 15:21:06 +0100 Subject: [PATCH 08/12] feat(pathway): separation pathway from compartment --- .../processLayer/processModelElements.ts | 2 + .../utils/shapes/elements/BaseMultiPolygon.ts | 9 +++- .../utils/shapes/elements/Compartment.ts | 3 ++ .../shapes/elements/CompartmentCircle.test.ts | 1 + .../shapes/elements/CompartmentCircle.ts | 3 ++ .../elements/CompartmentPathway.test.ts | 1 + .../shapes/elements/CompartmentPathway.ts | 3 ++ .../shapes/elements/CompartmentSquare.test.ts | 1 + .../shapes/elements/CompartmentSquare.ts | 3 ++ .../utils/shapes/elements/MapElement.test.ts | 1 + .../utils/shapes/elements/MapElement.ts | 3 ++ .../elements/handleSemanticView.test.ts | 25 +++++++++++ .../shapes/elements/handleSemanticView.ts | 42 +++++++++++++++++-- .../shapes/elements/isFeatureInPathway.ts | 22 ++++++++++ src/models/bioEntitySchema.ts | 1 + src/models/modelElementSchema.ts | 1 + 16 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 src/components/Map/MapViewer/utils/shapes/elements/isFeatureInPathway.ts diff --git a/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts index b4c0b876..e558ff37 100644 --- a/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts +++ b/src/components/Map/MapViewer/utils/config/processLayer/processModelElements.ts @@ -56,6 +56,7 @@ export default function processModelElements( sboTerm: element.sboTerm, complexId: element.complex, compartmentId: element.compartment, + pathwayId: element.pathway, x: element.x, y: element.y, nameX: element.nameX, @@ -98,6 +99,7 @@ export default function processModelElements( id: element.id, complexId: element.complex, compartmentId: element.compartment, + pathwayId: element.pathway, sboTerm: element.sboTerm, shapes: elementShapes, x: element.x, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts b/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts index 59af80b8..309eba9f 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/BaseMultiPolygon.ts @@ -30,6 +30,7 @@ export interface BaseMapElementProps { id: number; complexId?: number | null; compartmentId: number | null; + pathwayId: number | null; x: number; y: number; width: number; @@ -65,6 +66,8 @@ export default abstract class BaseMultiPolygon { compartmentId: number | null; + pathwayId: number | null; + x: number; y: number; @@ -134,6 +137,7 @@ export default abstract class BaseMultiPolygon { id, complexId, compartmentId, + pathwayId, x, y, width, @@ -162,6 +166,7 @@ export default abstract class BaseMultiPolygon { this.id = id; this.complexId = complexId; this.compartmentId = compartmentId; + this.pathwayId = pathwayId; this.x = x; this.y = y; this.width = width; @@ -251,6 +256,7 @@ export default abstract class BaseMultiPolygon { id: this.id, complexId: this.complexId, compartmentId: this.compartmentId, + pathwayId: this.pathwayId, type: this.type, }); this.feature.setId(this.id); @@ -338,7 +344,8 @@ export default abstract class BaseMultiPolygon { feature, resolution, sboTerm: this.sboTerm, - compartmentId: this.compartmentId, + compartmentId: feature.get('compartmentId'), + pathwayId: this.pathwayId, complexId: this.complexId, }); const { cover } = semanticViewData; diff --git a/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts b/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts index 76770a4b..1e936900 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/Compartment.ts @@ -21,6 +21,7 @@ export interface CompartmentProps { id: number; complexId?: number | null; compartmentId: number | null; + pathwayId: number | null; sboTerm: string; x: number; y: number; @@ -66,6 +67,7 @@ export default abstract class Compartment extends BaseMultiPolygon { id, complexId, compartmentId, + pathwayId, sboTerm, x, y, @@ -98,6 +100,7 @@ export default abstract class Compartment extends BaseMultiPolygon { id, complexId, compartmentId, + pathwayId, sboTerm, x, y, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts index 1d5f41d6..130e5cad 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.test.ts @@ -43,6 +43,7 @@ describe('CompartmentCircle', () => { id: 1, complexId: null, compartmentId: null, + pathwayId: null, sboTerm: 'SBO:0000253', x: 0, y: 0, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts index 0de0037b..8684f10e 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentCircle.ts @@ -18,6 +18,7 @@ export type CompartmentCircleProps = { id: number; complexId?: number | null; compartmentId: number | null; + pathwayId: number | null; sboTerm: string; x: number; y: number; @@ -51,6 +52,7 @@ export default class CompartmentCircle extends Compartment { id, complexId, compartmentId, + pathwayId, sboTerm, x, y, @@ -82,6 +84,7 @@ export default class CompartmentCircle extends Compartment { id, complexId, compartmentId, + pathwayId, sboTerm, x, y, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts index 0b0da3b4..dc369e18 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.test.ts @@ -43,6 +43,7 @@ describe('CompartmentPathway', () => { id: 1, complexId: null, compartmentId: null, + pathwayId: null, sboTerm: 'SBO:0000253', x: 0, y: 0, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts index bf6b269e..5764212d 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentPathway.ts @@ -23,6 +23,7 @@ export type CompartmentPathwayProps = { id: number; complexId?: number | null; compartmentId: number | null; + pathwayId: number | null; sboTerm: string; x: number; y: number; @@ -58,6 +59,7 @@ export default class CompartmentPathway extends BaseMultiPolygon { id, complexId, compartmentId, + pathwayId, sboTerm, x, y, @@ -88,6 +90,7 @@ export default class CompartmentPathway extends BaseMultiPolygon { id, complexId, compartmentId, + pathwayId, sboTerm, x, y, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts index ebfdcd7a..48befabd 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.test.ts @@ -41,6 +41,7 @@ describe('CompartmentSquare', () => { id: 1, complexId: null, compartmentId: null, + pathwayId: null, sboTerm: 'SBO:0000253', x: 0, y: 0, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts index 32bb5a24..a9939228 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/CompartmentSquare.ts @@ -17,6 +17,7 @@ export type CompartmentSquareProps = { id: number; complexId?: number | null; compartmentId: number | null; + pathwayId: number | null; sboTerm: string; x: number; y: number; @@ -50,6 +51,7 @@ export default class CompartmentSquare extends Compartment { id, complexId, compartmentId, + pathwayId, sboTerm, x, y, @@ -81,6 +83,7 @@ export default class CompartmentSquare extends Compartment { id, complexId, compartmentId, + pathwayId, sboTerm, x, y, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts index 2137147c..b16cd965 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.test.ts @@ -42,6 +42,7 @@ describe('MapElement', () => { id: 1, complexId: null, compartmentId: null, + pathwayId: null, sboTerm: 'SBO:2313123', shapes: shapesFixture, x: 0, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts index 8f5f66d3..92d65a91 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/MapElement.ts @@ -34,6 +34,7 @@ export type MapElementProps = { id: number; complexId?: number | null; compartmentId: number | null; + pathwayId: number | null; sboTerm: string; shapes: Array<Shape>; x: number; @@ -99,6 +100,7 @@ export default class MapElement extends BaseMultiPolygon { id, complexId, compartmentId, + pathwayId, sboTerm, shapes, x, @@ -140,6 +142,7 @@ export default class MapElement extends BaseMultiPolygon { id, complexId, compartmentId, + pathwayId, x, y, width, diff --git a/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.test.ts b/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.test.ts index c2d9e620..aa46b777 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.test.ts @@ -58,6 +58,7 @@ describe('handleSemanticView', () => { resolution: 1, sboTerm: 'SBO:123456', compartmentId: 2, + pathwayId: null, }); expect(result).toEqual({ @@ -83,6 +84,7 @@ describe('handleSemanticView', () => { resolution: 1, sboTerm: 'SBO:123456', compartmentId: null, + pathwayId: null, complexId: 1, }); @@ -105,6 +107,29 @@ describe('handleSemanticView', () => { resolution: 1, sboTerm: 'SBO:123456', compartmentId: 2, + pathwayId: null, + }); + + expect(result).toEqual({ + cover: true, + hide: true, + largestExtent: [0, 0, 10, 5], + }); + }); + + it('should return hide = true when pathwayId points to a filled feature', () => { + const compartmentFeature = new Feature({ filled: true }); + jest + .spyOn(vectorSource, 'getFeatureById') + .mockImplementation(id => (id === 2 ? compartmentFeature : null)); + + const result = handleSemanticView({ + vectorSource, + feature, + resolution: 1, + sboTerm: 'SBO:123456', + compartmentId: null, + pathwayId: 2, }); expect(result).toEqual({ diff --git a/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.ts b/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.ts index cd5aa1f4..20c6efbb 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/handleSemanticView.ts @@ -1,7 +1,7 @@ /* eslint-disable no-magic-numbers */ import Feature from 'ol/Feature'; import VectorSource from 'ol/source/Vector'; -import { Extent } from 'ol/extent'; +import { containsExtent, Extent, getHeight, getWidth } from 'ol/extent'; import { COMPLEX_SBO_TERMS, MAP_ELEMENT_TYPES, @@ -9,6 +9,7 @@ import { import findLargestExtent from '@/components/Map/MapViewer/utils/shapes/coords/findLargestExtent'; import getDividedExtents from '@/components/Map/MapViewer/utils/shapes/coords/getDividedExtents'; import isFeatureInCompartment from '@/components/Map/MapViewer/utils/shapes/elements/isFeatureInCompartment'; +import isFeatureInPathway from '@/components/Map/MapViewer/utils/shapes/elements/isFeatureInPathway'; export default function handleSemanticView({ vectorSource, @@ -16,6 +17,7 @@ export default function handleSemanticView({ resolution, sboTerm, compartmentId, + pathwayId, complexId, }: { vectorSource: VectorSource; @@ -23,6 +25,7 @@ export default function handleSemanticView({ resolution: number; sboTerm: string; compartmentId: number | null; + pathwayId: number | null; complexId?: number | null; }): { cover: boolean; hide: boolean; largestExtent: Extent | null } { const featureId = feature.getId(); @@ -35,12 +38,15 @@ export default function handleSemanticView({ let cover = false; let hide = false; let largestExtent: Extent | null = null; + let minimalCompartmentExtent = Infinity; + let minimalCompartmentId = null; if ( getMapExtent instanceof Function && (type === MAP_ELEMENT_TYPES.COMPARTMENT || COMPLEX_SBO_TERMS.includes(sboTerm)) ) { const mapExtent = getMapExtent(resolution); const featureExtent = feature.getGeometry()?.getExtent(); + if (featureExtent && mapExtent) { const mapArea = Math.abs(mapExtent[2] - mapExtent[0]) * Math.abs(mapExtent[3] - mapExtent[1]); const compartmentArea = @@ -51,13 +57,32 @@ export default function handleSemanticView({ cover = true; let remainingExtents = [featureExtent]; vectorSource.forEachFeatureIntersectingExtent(featureExtent, intersectingFeature => { + const intersectingFeatureType = intersectingFeature.get('type'); + const intersectingFeatureExtent = intersectingFeature.getGeometry()?.getExtent(); + if ( - intersectingFeature.get('type') === MAP_ELEMENT_TYPES.COMPARTMENT && + featureId !== intersectingFeature.getId() && + !compartmentId && + intersectingFeatureType === MAP_ELEMENT_TYPES.COMPARTMENT && + intersectingFeatureExtent && + containsExtent(intersectingFeatureExtent, featureExtent) + ) { + const width = getWidth(intersectingFeatureExtent); + const height = getHeight(intersectingFeatureExtent); + const area = width * height; + if (area < minimalCompartmentExtent) { + minimalCompartmentId = intersectingFeature.getId(); + minimalCompartmentExtent = area; + } + } + + if ( + intersectingFeatureType === MAP_ELEMENT_TYPES.COMPARTMENT && intersectingFeature.get('zIndex') > feature.get('zIndex') && intersectingFeature.get('filled') && - !isFeatureInCompartment(+featureId, vectorSource, intersectingFeature) + !isFeatureInCompartment(+featureId, vectorSource, intersectingFeature) && + !isFeatureInPathway(+featureId, vectorSource, intersectingFeature) ) { - const intersectingFeatureExtent = intersectingFeature.getGeometry()?.getExtent(); if (intersectingFeatureExtent) { remainingExtents = getDividedExtents(remainingExtents, intersectingFeatureExtent); } @@ -69,6 +94,9 @@ export default function handleSemanticView({ } } + if (!compartmentId && minimalCompartmentId) { + feature.set('compartmentId', minimalCompartmentId); + } if (complexId) { const complex = vectorSource.getFeatureById(complexId); if (complex && complex.get('filled')) { @@ -81,6 +109,12 @@ export default function handleSemanticView({ hide = true; } } + if (pathwayId) { + const pathway = vectorSource.getFeatureById(pathwayId); + if (pathway && pathway.get('filled')) { + hide = true; + } + } return { cover, hide, largestExtent }; } diff --git a/src/components/Map/MapViewer/utils/shapes/elements/isFeatureInPathway.ts b/src/components/Map/MapViewer/utils/shapes/elements/isFeatureInPathway.ts new file mode 100644 index 00000000..ba726eba --- /dev/null +++ b/src/components/Map/MapViewer/utils/shapes/elements/isFeatureInPathway.ts @@ -0,0 +1,22 @@ +import VectorSource from 'ol/source/Vector'; +import Feature from 'ol/Feature'; + +export default function isFeatureInPathway( + parentPathwayId: number, + vectorSource: VectorSource, + feature: Feature, +): boolean { + const pathwayId: undefined | null | number = feature.get('pathwayId'); + + if (!pathwayId) { + return false; + } + if (pathwayId === parentPathwayId || pathwayId === feature.get('id')) { + return true; + } + const compartmentFeature = vectorSource.getFeatureById(pathwayId); + if (!compartmentFeature) { + return false; + } + return isFeatureInPathway(parentPathwayId, vectorSource, compartmentFeature); +} diff --git a/src/models/bioEntitySchema.ts b/src/models/bioEntitySchema.ts index 6d4d375d..ec78db95 100644 --- a/src/models/bioEntitySchema.ts +++ b/src/models/bioEntitySchema.ts @@ -58,6 +58,7 @@ export const bioEntitySchema = z.object({ modificationResidues: z.array(modelElementModificationSchema).optional(), complex: z.number().nullable().optional(), compartment: z.number().nullable(), + pathway: z.number().nullable(), submodel: submodelSchema.nullable(), x: z .number() diff --git a/src/models/modelElementSchema.ts b/src/models/modelElementSchema.ts index 60379965..86b82f67 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(), + pathway: z.number().nullable(), immediateLink: z.string().nullable().optional(), elementId: z.string(), x: z.number(), -- GitLab From f41bdddc52bb033f28bae36a23505caef589cfa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Thu, 6 Feb 2025 08:53:27 +0100 Subject: [PATCH 09/12] fix(overview-images): add directory to path in useOverviewImageUrl --- .../OverviewImagesModal.component.test.tsx | 6 +++++- .../utils/useOverviewImage.test.ts | 9 +++++++-- .../utils/useOverviewImageUrl.test.ts | 6 +++++- .../OverviewImagesModal/utils/useOverviewImageUrl.ts | 11 +++++++---- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/OverviewImagesModal.component.test.tsx b/src/components/FunctionalArea/Modal/OverviewImagesModal/OverviewImagesModal.component.test.tsx index c13cc7a9..af7fd742 100644 --- a/src/components/FunctionalArea/Modal/OverviewImagesModal/OverviewImagesModal.component.test.tsx +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/OverviewImagesModal.component.test.tsx @@ -18,6 +18,8 @@ jest.mock('./utils/useOverviewImageSize', () => ({ })), })); +const PROJECT_DIRECTORY = 'directory'; + const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => { const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState); @@ -42,6 +44,7 @@ describe('OverviewImagesModal - component', () => { ...projectFixture, overviewImageViews: [], topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + directory: PROJECT_DIRECTORY, }, loading: 'succeeded', error: { message: '', name: '' }, @@ -70,6 +73,7 @@ describe('OverviewImagesModal - component', () => { ...projectFixture, overviewImageViews: [PROJECT_OVERVIEW_IMAGE_MOCK], topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + directory: PROJECT_DIRECTORY, }, loading: 'succeeded', error: { message: '', name: '' }, @@ -91,7 +95,7 @@ describe('OverviewImagesModal - component', () => { it('should render image with valid src', () => { const imageElement = screen.getByAltText('overview'); - const result = `${BASE_MAP_IMAGES_URL}/map_images/${PROJECT_OVERVIEW_IMAGE_MOCK.filename}`; + const result = `${BASE_MAP_IMAGES_URL}/map_images/${PROJECT_DIRECTORY}/${PROJECT_OVERVIEW_IMAGE_MOCK.filename}`; expect(imageElement.getAttribute('src')).toBe(result); }); diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImage.test.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImage.test.ts index 702a3d48..77e90faa 100644 --- a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImage.test.ts +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImage.test.ts @@ -7,6 +7,8 @@ import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithSto import { renderHook } from '@testing-library/react'; import { useOverviewImage } from './useOverviewImage'; +const PROJECT_DIRECTORY = 'directory'; + describe('useOverviewImage - hook', () => { describe('when image data is invalid', () => { const { Wrapper } = getReduxWrapperWithStore({ @@ -15,6 +17,7 @@ describe('useOverviewImage - hook', () => { ...projectFixture, overviewImageViews: [], topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + directory: PROJECT_DIRECTORY, }, loading: 'succeeded', error: { message: '', name: '' }, @@ -48,6 +51,7 @@ describe('useOverviewImage - hook', () => { ...projectFixture, overviewImageViews: [PROJECT_OVERVIEW_IMAGE_MOCK], topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + directory: PROJECT_DIRECTORY, }, loading: 'succeeded', error: { message: '', name: '' }, @@ -66,7 +70,7 @@ describe('useOverviewImage - hook', () => { }); it('should return default size of image and valid imageUrl', () => { - const imageUrl = `${BASE_MAP_IMAGES_URL}/map_images/${PROJECT_OVERVIEW_IMAGE_MOCK.filename}`; + const imageUrl = `${BASE_MAP_IMAGES_URL}/map_images/${PROJECT_DIRECTORY}/${PROJECT_OVERVIEW_IMAGE_MOCK.filename}`; expect(result.current).toMatchObject({ imageUrl, @@ -88,6 +92,7 @@ describe('useOverviewImage - hook', () => { }, ], topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + directory: PROJECT_DIRECTORY, }, loading: 'succeeded', error: { message: '', name: '' }, @@ -109,7 +114,7 @@ describe('useOverviewImage - hook', () => { ); it('should return size of image and valid imageUrl', () => { - const imageUrl = `${BASE_MAP_IMAGES_URL}/map_images/${PROJECT_OVERVIEW_IMAGE_MOCK.filename}`; + const imageUrl = `${BASE_MAP_IMAGES_URL}/map_images/${PROJECT_DIRECTORY}/${PROJECT_OVERVIEW_IMAGE_MOCK.filename}`; expect(result.current).toMatchObject({ imageUrl, diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageUrl.test.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageUrl.test.ts index da3d6a6a..cdd9aae4 100644 --- a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageUrl.test.ts +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageUrl.test.ts @@ -6,6 +6,8 @@ import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithSto import { renderHook } from '@testing-library/react'; import { useOverviewImageUrl } from './useOverviewImageUrl'; +const PROJECT_DIRECTORY = 'directory'; + describe('useOverviewImageUrl - hook', () => { describe('when currentImage data is valid', () => { const { Wrapper } = getReduxWrapperWithStore({ @@ -14,6 +16,7 @@ describe('useOverviewImageUrl - hook', () => { ...projectFixture, overviewImageViews: [], topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + directory: PROJECT_DIRECTORY, }, loading: 'succeeded', error: { message: '', name: '' }, @@ -41,6 +44,7 @@ describe('useOverviewImageUrl - hook', () => { ...projectFixture, overviewImageViews: [PROJECT_OVERVIEW_IMAGE_MOCK], topOverviewImage: PROJECT_OVERVIEW_IMAGE_MOCK, + directory: PROJECT_DIRECTORY, }, loading: 'succeeded', error: { message: '', name: '' }, @@ -58,7 +62,7 @@ describe('useOverviewImageUrl - hook', () => { const { result } = renderHook(() => useOverviewImageUrl(), { wrapper: Wrapper }); expect(result.current).toBe( - `${BASE_MAP_IMAGES_URL}/map_images/${PROJECT_OVERVIEW_IMAGE_MOCK.filename}`, + `${BASE_MAP_IMAGES_URL}/map_images/${PROJECT_DIRECTORY}/${PROJECT_OVERVIEW_IMAGE_MOCK.filename}`, ); }); }); diff --git a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageUrl.ts b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageUrl.ts index af9e09fe..053e784c 100644 --- a/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageUrl.ts +++ b/src/components/FunctionalArea/Modal/OverviewImagesModal/utils/useOverviewImageUrl.ts @@ -1,13 +1,16 @@ import { BASE_MAP_IMAGES_URL } from '@/constants'; -import { currentOverviewImageSelector } from '@/redux/project/project.selectors'; +import { + currentOverviewImageSelector, + projectDirectorySelector, +} from '@/redux/project/project.selectors'; import { useSelector } from 'react-redux'; export const useOverviewImageUrl = (): string => { const currentImage = useSelector(currentOverviewImageSelector); - - if (!currentImage) { + const directory = useSelector(projectDirectorySelector); + if (!currentImage || !directory) { return ''; } - return `${BASE_MAP_IMAGES_URL}/map_images/${currentImage.filename}`; + return `${BASE_MAP_IMAGES_URL}/map_images/${directory}/${currentImage.filename}`; }; -- GitLab From 2da00616797202e3877ee60a1879645f05a21486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Fri, 7 Feb 2025 13:05:41 +0100 Subject: [PATCH 10/12] feat(websocket): update information from websocket connection --- package-lock.json | 23 +++-- package.json | 2 +- .../AppWrapper/AppWrapper.component.tsx | 25 +++--- .../EditOverlayModal.component.test.tsx | 4 + .../hooks/useEditOverlay.test.ts | 5 ++ .../TopBar/User/User.component.test.tsx | 1 + .../UserOverlayForm.component.test.tsx | 2 + .../UserOverlays.component.test.tsx | 3 + ...serOverlaysWithoutGroup.component.test.tsx | 8 ++ .../hooks/useUserOverlays.test.ts | 4 + .../ReactionDrawer.component.test.tsx | 1 - .../useOlMapAdditionalLayers.ts | 12 +++ .../{useOlMap.test.ts => useOlMap.test.tsx} | 0 .../utils/websocket/processLayerImage.ts | 53 +++++++++++ .../utils/websocket/processLayerText.ts | 34 +++++++ .../utils/websocket/processMessage.ts | 25 ++++++ .../utils/websocket/websocket.constants.ts | 16 ++++ src/models/sessionValidSchema.ts | 1 + src/redux/apiPath.ts | 4 + src/redux/layers/layers.reducers.ts | 34 ++++++- src/redux/layers/layers.slice.ts | 4 + src/redux/layers/layers.thunks.ts | 42 +++++++++ src/redux/user/user.mock.ts | 1 + src/redux/user/user.reducers.test.ts | 1 + src/redux/user/user.reducers.ts | 3 + src/redux/user/user.selectors.ts | 1 + src/redux/user/user.slice.ts | 1 + src/redux/user/user.thunks.ts | 10 ++- src/redux/user/user.types.ts | 1 + .../testing/getReduxWrapperWithStore.tsx | 20 ++++- .../webSocketEntityUpdates.types.ts | 17 ++++ .../webSocketEntityUpdatesProvider.tsx | 90 +++++++++++++++++++ 32 files changed, 423 insertions(+), 25 deletions(-) rename src/components/Map/MapViewer/utils/{useOlMap.test.ts => useOlMap.test.tsx} (100%) create mode 100644 src/components/Map/MapViewer/utils/websocket/processLayerImage.ts create mode 100644 src/components/Map/MapViewer/utils/websocket/processLayerText.ts create mode 100644 src/components/Map/MapViewer/utils/websocket/processMessage.ts create mode 100644 src/components/Map/MapViewer/utils/websocket/websocket.constants.ts create mode 100644 src/utils/websocket-entity-updates/webSocketEntityUpdates.types.ts create mode 100644 src/utils/websocket-entity-updates/webSocketEntityUpdatesProvider.tsx diff --git a/package-lock.json b/package-lock.json index a019d479..5c864d3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "react-dropzone": "14.2.3", "react-redux": "8.1.3", "react-select": "5.9.0", + "react-use-websocket": "4.11.1", "sonner": "1.4.3", "tailwind-merge": "1.14.0", "tailwindcss": "3.4.13", @@ -12275,6 +12276,11 @@ "react-dom": ">=16.6.0" } }, + "node_modules/react-use-websocket": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.11.1.tgz", + "integrity": "sha512-39e8mK2a2A1h8uY3ePF45b2q0vwMOmaEy7J5qEhQg4n7vYa5oDLmqutG36kZQgAQ/3KCZS0brlGRbbZJ0+zfKQ==" + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -14457,9 +14463,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "engines": { "node": ">=10.0.0" @@ -23504,6 +23510,11 @@ "prop-types": "^15.6.2" } }, + "react-use-websocket": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/react-use-websocket/-/react-use-websocket-4.11.1.tgz", + "integrity": "sha512-39e8mK2a2A1h8uY3ePF45b2q0vwMOmaEy7J5qEhQg4n7vYa5oDLmqutG36kZQgAQ/3KCZS0brlGRbbZJ0+zfKQ==" + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -25133,9 +25144,9 @@ } }, "ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "requires": {} }, diff --git a/package.json b/package.json index 0e93c457..5d0cb06b 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "react-dropzone": "14.2.3", "react-redux": "8.1.3", "react-select": "5.9.0", + "react-use-websocket": "4.11.1", "sonner": "1.4.3", "tailwind-merge": "1.14.0", "tailwindcss": "3.4.13", @@ -64,7 +65,6 @@ "zod-to-json-schema": "3.22.4" }, "devDependencies": { - "@types/ol-ext": "npm:@siedlerchr/types-ol-ext@3.6.1", "@commitlint/cli": "17.8.1", "@commitlint/config-conventional": "17.8.1", "@testing-library/jest-dom": "6.1.6", diff --git a/src/components/AppWrapper/AppWrapper.component.tsx b/src/components/AppWrapper/AppWrapper.component.tsx index 39a65352..686bd455 100644 --- a/src/components/AppWrapper/AppWrapper.component.tsx +++ b/src/components/AppWrapper/AppWrapper.component.tsx @@ -4,6 +4,7 @@ import { ReactNode } from 'react'; import { Provider } from 'react-redux'; import { Toaster } from 'sonner'; import { Modal } from '@/components/FunctionalArea/Modal'; +import { WebSocketEntityUpdatesProvider } from '@/utils/websocket-entity-updates/webSocketEntityUpdatesProvider'; interface AppWrapperProps { children: ReactNode; @@ -13,17 +14,19 @@ export const AppWrapper = ({ children }: AppWrapperProps): JSX.Element => { return ( <MapInstanceProvider> <Provider store={store}> - <> - <Modal /> - <Toaster - position="top-center" - visibleToasts={1} - style={{ - width: '700px', - }} - /> - {children} - </> + <WebSocketEntityUpdatesProvider> + <> + <Modal /> + <Toaster + position="top-center" + visibleToasts={1} + style={{ + width: '700px', + }} + /> + {children} + </> + </WebSocketEntityUpdatesProvider> </Provider> </MapInstanceProvider> ); diff --git a/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx b/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx index adacf77d..cd91fa65 100644 --- a/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx +++ b/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx @@ -94,6 +94,7 @@ describe('EditOverlayModal - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, modal: { isOpen: true, @@ -132,6 +133,7 @@ describe('EditOverlayModal - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, modal: { isOpen: true, @@ -171,6 +173,7 @@ describe('EditOverlayModal - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, modal: { isOpen: true, @@ -218,6 +221,7 @@ describe('EditOverlayModal - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, modal: { isOpen: true, diff --git a/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts b/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts index a474e15f..a086bb3e 100644 --- a/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts +++ b/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts @@ -15,6 +15,7 @@ describe('useEditOverlay', () => { login: 'test', role: 'user', userData: null, + token: null, }, modal: { isOpen: true, @@ -54,6 +55,7 @@ describe('useEditOverlay', () => { login: 'test', role: 'user', userData: null, + token: null, }, modal: { isOpen: true, @@ -96,6 +98,7 @@ describe('useEditOverlay', () => { login: null, role: 'user', userData: null, + token: null, }, modal: { isOpen: true, @@ -134,6 +137,7 @@ describe('useEditOverlay', () => { login: 'test', role: 'user', userData: null, + token: null, }, modal: { isOpen: true, @@ -173,6 +177,7 @@ describe('useEditOverlay', () => { login: null, role: 'user', userData: null, + token: null, }, modal: { isOpen: true, diff --git a/src/components/FunctionalArea/TopBar/User/User.component.test.tsx b/src/components/FunctionalArea/TopBar/User/User.component.test.tsx index 5a1ec9b5..f724d52a 100644 --- a/src/components/FunctionalArea/TopBar/User/User.component.test.tsx +++ b/src/components/FunctionalArea/TopBar/User/User.component.test.tsx @@ -126,6 +126,7 @@ describe('AuthenticatedUser component', () => { login: null, role: null, userData: null, + token: null, }); }); diff --git a/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx b/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx index 35943150..691bd20d 100644 --- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx +++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx @@ -236,6 +236,7 @@ describe('UserOverlayForm - Component', () => { loading: 'succeeded', role: 'user', userData: null, + token: null, }, project: { data: projectFixture, @@ -302,6 +303,7 @@ describe('UserOverlayForm - Component', () => { loading: 'succeeded', role: 'user', userData: null, + token: null, }, project: { data: projectFixture, diff --git a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlays.component.test.tsx b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlays.component.test.tsx index 82c38758..b8b77087 100644 --- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlays.component.test.tsx +++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlays.component.test.tsx @@ -30,6 +30,7 @@ describe('UserOverlays component', () => { login: null, role: 'user', userData: null, + token: null, }, }); @@ -45,6 +46,7 @@ describe('UserOverlays component', () => { login: 'test', role: 'user', userData: null, + token: null, }, }); @@ -59,6 +61,7 @@ describe('UserOverlays component', () => { login: 'test', role: 'user', userData: null, + token: null, }, }); diff --git a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/UserOverlaysWithoutGroup.component.test.tsx b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/UserOverlaysWithoutGroup.component.test.tsx index 6cc8c8ea..3bad7de7 100644 --- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/UserOverlaysWithoutGroup.component.test.tsx +++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/UserOverlaysWithoutGroup.component.test.tsx @@ -46,6 +46,7 @@ describe('UserOverlaysWithoutGroup - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -84,6 +85,7 @@ describe('UserOverlaysWithoutGroup - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -107,6 +109,7 @@ describe('UserOverlaysWithoutGroup - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -158,6 +161,7 @@ describe('UserOverlaysWithoutGroup - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -197,6 +201,7 @@ describe('UserOverlaysWithoutGroup - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -249,6 +254,7 @@ describe('UserOverlaysWithoutGroup - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -292,6 +298,7 @@ describe('UserOverlaysWithoutGroup - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -342,6 +349,7 @@ describe('UserOverlaysWithoutGroup - component', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, diff --git a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/hooks/useUserOverlays.test.ts b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/hooks/useUserOverlays.test.ts index f8de514a..6cb67512 100644 --- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/hooks/useUserOverlays.test.ts +++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/hooks/useUserOverlays.test.ts @@ -22,6 +22,7 @@ describe('useUserOverlays', () => { login: null, role: 'user', userData: null, + token: null, }, overlays: OVERLAYS_INITIAL_STATE_MOCK, }); @@ -58,6 +59,7 @@ describe('useUserOverlays', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -104,6 +106,7 @@ describe('useUserOverlays', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, @@ -155,6 +158,7 @@ describe('useUserOverlays', () => { login: 'test', role: 'user', userData: null, + token: null, }, overlays: { ...OVERLAYS_INITIAL_STATE_MOCK, diff --git a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx index 283dd29f..20b47479 100644 --- a/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx +++ b/src/components/Map/Drawer/ReactionDrawer/ReactionDrawer.component.test.tsx @@ -28,7 +28,6 @@ const reference = { ...referenceFixture, link: 'https://uni.lu' }; describe('ReactionDrawer - component', () => { beforeEach(() => { - jest.resetAllMocks(); jest.clearAllMocks(); }); diff --git a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts index f92c8762..6a793385 100644 --- a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts +++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts @@ -32,6 +32,8 @@ import { import { Extent } from 'ol/extent'; import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; import getTransformImageInteraction from '@/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction'; +import { useWebSocketEntityUpdatesContext } from '@/utils/websocket-entity-updates/webSocketEntityUpdatesProvider'; +import processMessage from '@/components/Map/MapViewer/utils/websocket/processMessage'; export const useOlMapAdditionalLayers = ( mapInstance: MapInstance, @@ -57,6 +59,16 @@ export const useOlMapAdditionalLayers = ( const arrowTypes = useSelector(arrowTypesSelector); const pointToProjection = usePointToProjection(); + const { lastMessage } = useWebSocketEntityUpdatesContext(); + + useEffect(() => { + if (!lastMessage) { + return; + } + + processMessage({ message: lastMessage, mapInstance }); + }, [lastMessage, mapInstance]); + const restrictionExtent: Extent = useMemo(() => { const restrictionMinPoint = pointToProjection({ x: 0, y: 0 }); const restrictionMaxPoint = pointToProjection({ x: mapSize.width, y: mapSize.height }); diff --git a/src/components/Map/MapViewer/utils/useOlMap.test.ts b/src/components/Map/MapViewer/utils/useOlMap.test.tsx similarity index 100% rename from src/components/Map/MapViewer/utils/useOlMap.test.ts rename to src/components/Map/MapViewer/utils/useOlMap.test.tsx diff --git a/src/components/Map/MapViewer/utils/websocket/processLayerImage.ts b/src/components/Map/MapViewer/utils/websocket/processLayerImage.ts new file mode 100644 index 00000000..9d4d50bc --- /dev/null +++ b/src/components/Map/MapViewer/utils/websocket/processLayerImage.ts @@ -0,0 +1,53 @@ +import { WebSocketEntityUpdateInterface } from '@/utils/websocket-entity-updates/webSocketEntityUpdates.types'; +import { store } from '@/redux/store'; +import { OPERATION_TYPES } from '@/components/Map/MapViewer/utils/websocket/websocket.constants'; +import { getLayerImage } from '@/redux/layers/layers.thunks'; +import updateGlyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph'; +import { MapInstance } from '@/types/map'; +import drawElementOnLayer from '@/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer'; +import { layerDeleteImage } from '@/redux/layers/layers.slice'; +import removeElementFromLayer from '@/components/Map/MapViewer/utils/shapes/elements/removeElementFromLayer'; + +export default async function processLayerImage({ + data, + mapInstance, +}: { + data: WebSocketEntityUpdateInterface; + mapInstance: MapInstance; +}): Promise<void> { + const { dispatch } = store; + if ( + data.type === OPERATION_TYPES.ENTITY_CREATED || + data.type === OPERATION_TYPES.ENTITY_UPDATED + ) { + const resultImage = await dispatch( + getLayerImage({ + modelId: data.mapId, + layerId: data.layerId, + imageId: data.entityId, + }), + ).unwrap(); + if (!resultImage) { + return; + } + if (data.type === OPERATION_TYPES.ENTITY_CREATED) { + drawElementOnLayer({ + mapInstance, + activeLayer: data.layerId, + object: resultImage, + drawFunctionKey: 'drawImage', + }); + } else { + updateGlyph(mapInstance, data.layerId, resultImage); + } + } else if (data.type === OPERATION_TYPES.ENTITY_DELETED) { + dispatch( + layerDeleteImage({ + modelId: data.mapId, + layerId: data.layerId, + imageId: data.entityId, + }), + ); + removeElementFromLayer({ mapInstance, layerId: data.layerId, featureId: data.entityId }); + } +} diff --git a/src/components/Map/MapViewer/utils/websocket/processLayerText.ts b/src/components/Map/MapViewer/utils/websocket/processLayerText.ts new file mode 100644 index 00000000..09b9c20f --- /dev/null +++ b/src/components/Map/MapViewer/utils/websocket/processLayerText.ts @@ -0,0 +1,34 @@ +import { WebSocketEntityUpdateInterface } from '@/utils/websocket-entity-updates/webSocketEntityUpdates.types'; +import { store } from '@/redux/store'; +import { OPERATION_TYPES } from '@/components/Map/MapViewer/utils/websocket/websocket.constants'; +import { getLayerText } from '@/redux/layers/layers.thunks'; +import { MapInstance } from '@/types/map'; +import drawElementOnLayer from '@/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer'; + +export default async function processLayerText({ + data, + mapInstance, +}: { + data: WebSocketEntityUpdateInterface; + mapInstance: MapInstance; +}): Promise<void> { + const { dispatch } = store; + if (data.type === OPERATION_TYPES.ENTITY_CREATED) { + const resultText = await dispatch( + getLayerText({ + modelId: data.mapId, + layerId: data.layerId, + textId: data.entityId, + }), + ).unwrap(); + if (!resultText) { + return; + } + drawElementOnLayer({ + mapInstance, + activeLayer: data.layerId, + object: resultText, + drawFunctionKey: 'drawText', + }); + } +} diff --git a/src/components/Map/MapViewer/utils/websocket/processMessage.ts b/src/components/Map/MapViewer/utils/websocket/processMessage.ts new file mode 100644 index 00000000..2cb63517 --- /dev/null +++ b/src/components/Map/MapViewer/utils/websocket/processMessage.ts @@ -0,0 +1,25 @@ +import { WebSocketEntityUpdateInterface } from '@/utils/websocket-entity-updates/webSocketEntityUpdates.types'; +import processLayerImage from '@/components/Map/MapViewer/utils/websocket/processLayerImage'; +import { MapInstance } from '@/types/map'; +import { ENTITY_TYPES } from '@/components/Map/MapViewer/utils/websocket/websocket.constants'; +import processLayerText from '@/components/Map/MapViewer/utils/websocket/processLayerText'; + +export default async function processMessage({ + message, + mapInstance, +}: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + message: MessageEvent<any>; + mapInstance: MapInstance; +}): Promise<void> { + try { + const data = JSON.parse(message.data) as WebSocketEntityUpdateInterface; + if (data.entityType === ENTITY_TYPES.LAYER_IMAGE) { + await processLayerImage({ data, mapInstance }); + } else if (data.entityType === ENTITY_TYPES.LAYER_TEXT) { + await processLayerText({ data, mapInstance }); + } + } catch (e) { + throw new Error(`Process websocket message error`); + } +} diff --git a/src/components/Map/MapViewer/utils/websocket/websocket.constants.ts b/src/components/Map/MapViewer/utils/websocket/websocket.constants.ts new file mode 100644 index 00000000..4f2fb742 --- /dev/null +++ b/src/components/Map/MapViewer/utils/websocket/websocket.constants.ts @@ -0,0 +1,16 @@ +export const OPERATION_TYPES = { + ENTITY_CREATED: 'ENTITY_CREATED', + ENTITY_UPDATED: 'ENTITY_UPDATED', + ENTITY_DELETED: 'ENTITY_DELETED', + MESSAGE_PROCESSED_SUCCESSFULLY: 'MESSAGE_PROCESSED_SUCCESSFULLY', +} as const; + +export const ENTITY_TYPES = { + GLYPH: 'GLYPH', + LAYER: 'LAYER', + LAYER_IMAGE: 'LAYER_IMAGE', + LAYER_LINE: 'LAYER_LINE', + LAYER_OVAL: 'LAYER_OVAL', + LAYER_RECTANGLE: 'LAYER_RECTANGLE', + LAYER_TEXT: 'LAYER_TEXT', +} as const; diff --git a/src/models/sessionValidSchema.ts b/src/models/sessionValidSchema.ts index 371cd7cd..df8a64f5 100644 --- a/src/models/sessionValidSchema.ts +++ b/src/models/sessionValidSchema.ts @@ -2,4 +2,5 @@ import { z } from 'zod'; export const sessionSchemaValid = z.object({ login: z.string(), + token: z.string(), }); diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index fcb92f40..9eb33c02 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -58,8 +58,12 @@ export const apiPath = { `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/images/${imageId}`, removeLayerImageObject: (modelId: number, layerId: number, imageId: number | string): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/images/${imageId}`, + getLayerImageObject: (modelId: number, layerId: number, imageId: number | string): string => + `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/images/${imageId}`, addLayerText: (modelId: number, layerId: number): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/`, + getLayerText: (modelId: number, layerId: number, imageId: number | string): string => + `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/${imageId}`, getLayer: (modelId: number, layerId: number): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}`, getGlyphImage: (glyphId: number): string => diff --git a/src/redux/layers/layers.reducers.ts b/src/redux/layers/layers.reducers.ts index 17c01b90..ec3c7f2f 100644 --- a/src/redux/layers/layers.reducers.ts +++ b/src/redux/layers/layers.reducers.ts @@ -1,6 +1,6 @@ /* eslint-disable no-magic-numbers */ import { ActionReducerMapBuilder, PayloadAction } from '@reduxjs/toolkit'; -import { getLayersForModel } from '@/redux/layers/layers.thunks'; +import { getLayerImage, getLayersForModel, getLayerText } from '@/redux/layers/layers.thunks'; import { LayersState } from '@/redux/layers/layers.types'; import { LAYER_STATE_DEFAULT_DATA, @@ -38,6 +38,38 @@ export const getLayersForModelReducer = (builder: ActionReducerMapBuilder<Layers }); }; +export const getLayerImageReducer = (builder: ActionReducerMapBuilder<LayersState>): void => { + builder.addCase(getLayerImage.fulfilled, (state, action) => { + const { modelId, layerId } = action.meta.arg; + const { data } = state[modelId]; + const layerImage = action.payload; + if (!data || !layerImage) { + return; + } + const layer = data.layers.find(layerState => layerState.details.id === layerId); + if (!layer) { + return; + } + layer.images[layerImage.id] = layerImage; + }); +}; + +export const getLayerTextReducer = (builder: ActionReducerMapBuilder<LayersState>): void => { + builder.addCase(getLayerText.fulfilled, (state, action) => { + const { modelId, layerId } = action.meta.arg; + const { data } = state[modelId]; + const layerText = action.payload; + if (!data || !layerText) { + return; + } + const layer = data.layers.find(layerState => layerState.details.id === layerId); + if (!layer) { + return; + } + layer.texts[layerText.id] = layerText; + }); +}; + export const setLayerVisibilityReducer = ( state: LayersState, action: PayloadAction<{ modelId: number; visible: boolean; layerId: number }>, diff --git a/src/redux/layers/layers.slice.ts b/src/redux/layers/layers.slice.ts index 82f15ba3..1f940c00 100644 --- a/src/redux/layers/layers.slice.ts +++ b/src/redux/layers/layers.slice.ts @@ -1,6 +1,8 @@ import { createSlice } from '@reduxjs/toolkit'; import { LAYERS_STATE_INITIAL_MOCK } from '@/redux/layers/layers.mock'; import { + getLayerImageReducer, + getLayerTextReducer, getLayersForModelReducer, layerAddImageReducer, layerAddTextReducer, @@ -23,6 +25,8 @@ export const layersSlice = createSlice({ }, extraReducers: builder => { getLayersForModelReducer(builder); + getLayerImageReducer(builder); + getLayerTextReducer(builder); }, }); diff --git a/src/redux/layers/layers.thunks.ts b/src/redux/layers/layers.thunks.ts index 217e407f..34c1b2d1 100644 --- a/src/redux/layers/layers.thunks.ts +++ b/src/redux/layers/layers.thunks.ts @@ -150,6 +150,27 @@ export const removeLayer = createAsyncThunk< } }); +export const getLayerImage = createAsyncThunk< + LayerImage | null, + { + modelId: number; + layerId: number; + imageId: number; + }, + ThunkConfig +>('vectorMap/getLayerImage', async ({ modelId, layerId, imageId }) => { + try { + const { data } = await axiosInstanceNewAPI.get<LayerImage>( + apiPath.getLayerImageObject(modelId, layerId, imageId), + ); + const isDataValid = validateDataUsingZodSchema(data, layerImageSchema); + + return isDataValid ? data : null; + } catch (error) { + return Promise.reject(getError({ error })); + } +}); + export const addLayerImageObject = createAsyncThunk< LayerImage | null, { @@ -266,3 +287,24 @@ export const addLayerText = createAsyncThunk< return Promise.reject(getError({ error })); } }); + +export const getLayerText = createAsyncThunk< + LayerText | null, + { + modelId: number; + layerId: number; + textId: number; + }, + ThunkConfig +>('vectorMap/getLayerText', async ({ modelId, layerId, textId }) => { + try { + const { data } = await axiosInstanceNewAPI.get<LayerText>( + apiPath.getLayerText(modelId, layerId, textId), + ); + const isDataValid = validateDataUsingZodSchema(data, layerTextSchema); + + return isDataValid ? data : null; + } catch (error) { + return Promise.reject(getError({ error })); + } +}); diff --git a/src/redux/user/user.mock.ts b/src/redux/user/user.mock.ts index ac2813cf..b469f8d5 100644 --- a/src/redux/user/user.mock.ts +++ b/src/redux/user/user.mock.ts @@ -7,4 +7,5 @@ export const USER_INITIAL_STATE_MOCK: UserState = { login: null, role: null, userData: null, + token: null, }; diff --git a/src/redux/user/user.reducers.test.ts b/src/redux/user/user.reducers.test.ts index 3033a51a..50968161 100644 --- a/src/redux/user/user.reducers.test.ts +++ b/src/redux/user/user.reducers.test.ts @@ -26,6 +26,7 @@ const INITIAL_STATE: UserState = { login: null, role: null, userData: null, + token: null, }; describe('user reducer', () => { diff --git a/src/redux/user/user.reducers.ts b/src/redux/user/user.reducers.ts index 2cb2002a..26ca31cd 100644 --- a/src/redux/user/user.reducers.ts +++ b/src/redux/user/user.reducers.ts @@ -13,6 +13,7 @@ export const loginReducer = (builder: ActionReducerMapBuilder<UserState>): void state.role = action.payload?.role || null; state.login = action.payload?.login || null; state.userData = action.payload?.userData || null; + state.token = action.payload?.token || null; }) .addCase(login.rejected, state => { state.authenticated = false; @@ -31,6 +32,7 @@ export const getSessionValidReducer = (builder: ActionReducerMapBuilder<UserStat state.login = action.payload?.login || null; state.role = action.payload?.role || null; state.userData = action.payload?.userData || null; + state.token = action.payload?.token || null; }) .addCase(getSessionValid.rejected, state => { state.authenticated = false; @@ -50,6 +52,7 @@ export const logoutReducer = (builder: ActionReducerMapBuilder<UserState>): void state.role = null; state.login = null; state.userData = null; + state.token = null; }) .addCase(logout.rejected, state => { state.loading = 'failed'; diff --git a/src/redux/user/user.selectors.ts b/src/redux/user/user.selectors.ts index 2172ad73..c760c354 100644 --- a/src/redux/user/user.selectors.ts +++ b/src/redux/user/user.selectors.ts @@ -24,3 +24,4 @@ export const hasPrivilegeToWriteProjectSelector = createSelector( return hasPrivilegeToObject(userPrivileges, 'WRITE_PROJECT', projectId); }, ); +export const userTokenSelector = createSelector(userSelector, state => state.token); diff --git a/src/redux/user/user.slice.ts b/src/redux/user/user.slice.ts index bf9f7f38..505f4e46 100644 --- a/src/redux/user/user.slice.ts +++ b/src/redux/user/user.slice.ts @@ -9,6 +9,7 @@ export const initialState: UserState = { login: null, role: null, userData: null, + token: null, }; export const userSlice = createSlice({ diff --git a/src/redux/user/user.thunks.ts b/src/redux/user/user.thunks.ts index 89e404da..ec48eb97 100644 --- a/src/redux/user/user.thunks.ts +++ b/src/redux/user/user.thunks.ts @@ -39,12 +39,12 @@ export const login = createAsyncThunk( async (credentials: { login: string; password: string }, { dispatch }) => { try { const searchParams = new URLSearchParams(credentials); - const response = await axiosInstance.post<Login>(apiPath.postLogin(), searchParams, { + const { data } = await axiosInstance.post<Login>(apiPath.postLogin(), searchParams, { withCredentials: true, }); - const isDataValid = validateDataUsingZodSchema(response.data, loginSchema); - const loginName = response.data.login; + const isDataValid = validateDataUsingZodSchema(data, loginSchema); + const loginName = data.login; if (isDataValid) { setLoginForOldMinerva(loginName); @@ -62,6 +62,7 @@ export const login = createAsyncThunk( login: loginName, role, userData, + token: data.token, }; } @@ -89,7 +90,7 @@ export const getSessionValid = createAsyncThunk('user/getSessionValid', async () const isDataValid = validateDataUsingZodSchema(response.data, sessionSchemaValid); const { - data: { login: loginName }, + data: { login: loginName, token }, } = response; const userData = await getUserData(loginName); @@ -102,6 +103,7 @@ export const getSessionValid = createAsyncThunk('user/getSessionValid', async () login: loginName, userData, role, + token, }; } diff --git a/src/redux/user/user.types.ts b/src/redux/user/user.types.ts index 08210c0a..d4e8b494 100644 --- a/src/redux/user/user.types.ts +++ b/src/redux/user/user.types.ts @@ -8,4 +8,5 @@ export type UserState = { login: null | string; role: string | null; userData: User | null; + token: string | null; }; diff --git a/src/utils/testing/getReduxWrapperWithStore.tsx b/src/utils/testing/getReduxWrapperWithStore.tsx index 18c3beb8..4b0fc7b4 100644 --- a/src/utils/testing/getReduxWrapperWithStore.tsx +++ b/src/utils/testing/getReduxWrapperWithStore.tsx @@ -1,6 +1,7 @@ import { RootState, StoreType, middlewares, reducers } from '@/redux/store'; import { configureStore } from '@reduxjs/toolkit'; import { Provider } from 'react-redux'; +import { WebSocketEntityUpdatesProvider } from '@/utils/websocket-entity-updates/webSocketEntityUpdatesProvider'; import { MapInstanceContext, MapInstanceProvider } from '../context/mapInstanceContext'; interface WrapperProps { @@ -21,6 +22,21 @@ export type GetReduxWrapperUsingSliceReducer = ( store: StoreType; }; +jest.mock('react-use-websocket', () => ({ + __esModule: true, + default: jest.fn(() => ({ + sendMessage: jest.fn(), + lastMessage: null, + readyState: 1, + })), + ReadyState: { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3, + }, +})); + export const getReduxWrapperWithStore: GetReduxWrapperUsingSliceReducer = ( preloadedState: InitialStoreState = {}, options: Options = {}, @@ -33,7 +49,9 @@ export const getReduxWrapperWithStore: GetReduxWrapperUsingSliceReducer = ( const Wrapper = ({ children }: WrapperProps): JSX.Element => ( <MapInstanceProvider initialValue={options.mapInstanceContextValue}> - <Provider store={testStore}>{children}</Provider> + <Provider store={testStore}> + <WebSocketEntityUpdatesProvider>{children}</WebSocketEntityUpdatesProvider> + </Provider> </MapInstanceProvider> ); diff --git a/src/utils/websocket-entity-updates/webSocketEntityUpdates.types.ts b/src/utils/websocket-entity-updates/webSocketEntityUpdates.types.ts new file mode 100644 index 00000000..74dee365 --- /dev/null +++ b/src/utils/websocket-entity-updates/webSocketEntityUpdates.types.ts @@ -0,0 +1,17 @@ +import { + ENTITY_TYPES, + OPERATION_TYPES, +} from '@/components/Map/MapViewer/utils/websocket/websocket.constants'; + +export type EntityType = (typeof ENTITY_TYPES)[keyof typeof ENTITY_TYPES]; +export type OperationType = (typeof OPERATION_TYPES)[keyof typeof OPERATION_TYPES]; + +export interface WebSocketEntityUpdateInterface { + entityId: number; + entityType: EntityType; + entityVersion: number; + mapId: number; + projectId: string; + layerId: number; + type: OperationType; +} diff --git a/src/utils/websocket-entity-updates/webSocketEntityUpdatesProvider.tsx b/src/utils/websocket-entity-updates/webSocketEntityUpdatesProvider.tsx new file mode 100644 index 00000000..2e9be903 --- /dev/null +++ b/src/utils/websocket-entity-updates/webSocketEntityUpdatesProvider.tsx @@ -0,0 +1,90 @@ +import React, { createContext, useContext, useEffect, useMemo, useState } from 'react'; +import useWebSocket, { ReadyState } from 'react-use-websocket'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { userTokenSelector } from '@/redux/user/user.selectors'; +import { projectIdSelector } from '@/redux/project/project.selectors'; +import { BASE_API_URL } from '@/constants'; +import { OPERATION_TYPES } from '@/components/Map/MapViewer/utils/websocket/websocket.constants'; + +export interface WebSocketEntityUpdatesContextInterface { + sendMessage: (msg: string) => void; + lastMessage: WebSocketEventMap['message'] | null; + readyState: ReadyState; +} + +const WebSocketEntityUpdatesContext = createContext< + WebSocketEntityUpdatesContextInterface | undefined +>(undefined); +const SOCKET_URL = `${BASE_API_URL.replace('https', 'wss')}/websocket/entity-updates`; +const LOGIN_COMMAND_ID = 'login'; + +export const WebSocketEntityUpdatesProvider: React.FC<{ children: React.ReactNode }> = ({ + children, +}) => { + const userToken = useAppSelector(userTokenSelector); + const projectId = useAppSelector(projectIdSelector); + const [isLogged, setIsLogged] = useState(false); + const { lastMessage, sendMessage, readyState } = useWebSocket(SOCKET_URL, { + shouldReconnect: () => true, + reconnectInterval: 5000, + share: true, + onMessage: (messageEvent: MessageEvent) => { + try { + const data = JSON.parse(messageEvent.data); + if ( + data.commandId === LOGIN_COMMAND_ID && + data.type === OPERATION_TYPES.MESSAGE_PROCESSED_SUCCESSFULLY && + data.message === 'ok' + ) { + setIsLogged(true); + } + } catch { + throw new Error('Websocket message parsing error'); + } + }, + }); + + useEffect(() => { + if (readyState !== ReadyState.OPEN) { + return; + } + if (userToken && !isLogged) { + sendMessage( + JSON.stringify({ command: 'login', token: userToken, commandId: LOGIN_COMMAND_ID }), + ); + } else if (!userToken) { + setIsLogged(false); + } + }, [isLogged, readyState, sendMessage, userToken]); + + useEffect(() => { + if (readyState !== ReadyState.OPEN) { + return; + } + + if (projectId && isLogged) { + sendMessage(JSON.stringify({ command: 'register-for-project-updates', projectId })); + } + }, [projectId, readyState, sendMessage, isLogged]); + + const contextValue = useMemo( + () => ({ sendMessage, lastMessage, readyState }), + [sendMessage, lastMessage, readyState], + ); + + return ( + <WebSocketEntityUpdatesContext.Provider value={contextValue}> + {children} + </WebSocketEntityUpdatesContext.Provider> + ); +}; + +export const useWebSocketEntityUpdatesContext = (): WebSocketEntityUpdatesContextInterface => { + const context = useContext(WebSocketEntityUpdatesContext); + if (!context) { + throw new Error( + 'useWebSocketEntityUpdatesContext must be used inside a WebSocketEntityUpdatesProvider', + ); + } + return context; +}; -- GitLab From 9490b91f5bf6267d84147b89f62b800759a7e211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Fri, 7 Feb 2025 13:44:51 +0100 Subject: [PATCH 11/12] feat(layer-image): correct z index on bring to front/back --- .../MapDrawEditActions.component.tsx | 18 ++++++++++++------ src/redux/layers/layers.selectors.ts | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/components/Map/MapDrawActions/MapDrawEditActions.component.tsx b/src/components/Map/MapDrawActions/MapDrawEditActions.component.tsx index 01ebfff1..2e21cc62 100644 --- a/src/components/Map/MapDrawActions/MapDrawEditActions.component.tsx +++ b/src/components/Map/MapDrawActions/MapDrawEditActions.component.tsx @@ -6,7 +6,11 @@ import { MapDrawActionsButton } from '@/components/Map/MapDrawActions/MapDrawAct import { openLayerImageObjectEditFactoryModal } from '@/redux/modal/modal.slice'; import { removeLayerImage, updateLayerImageObject } from '@/redux/layers/layers.thunks'; import { mapModelIdSelector } from '@/redux/map/map.selectors'; -import { layersActiveLayerSelector } from '@/redux/layers/layers.selectors'; +import { + highestZIndexSelector, + layersActiveLayerSelector, + lowestZIndexSelector, +} from '@/redux/layers/layers.selectors'; import { layerDeleteImage, layerUpdateImage } from '@/redux/layers/layers.slice'; import { useMapInstance } from '@/utils/context/mapInstanceContext'; import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; @@ -28,6 +32,8 @@ export const MapDrawEditActionsComponent = ({ }: MapDrawEditActionsComponentProps): React.JSX.Element => { const currentModelId = useAppSelector(mapModelIdSelector); const activeLayer = useAppSelector(layersActiveLayerSelector); + const highestZIndex = useAppSelector(highestZIndexSelector); + const lowestZIndex = useAppSelector(lowestZIndexSelector); const layerImageObject = useAppSelector(mapEditToolsLayerImageObjectSelector); const dispatch = useAppDispatch(); const { mapInstance } = useMapInstance(); @@ -51,7 +57,7 @@ export const MapDrawEditActionsComponent = ({ modelId: currentModelId, layerId: activeLayer, ...layerImageObject, - z: layerImageObject.z + value, + z: value, }), ).unwrap(); if (layerImage) { @@ -129,15 +135,15 @@ export const MapDrawEditActionsComponent = ({ /> <MapDrawActionsButton isActive={false} - toggleMapEditAction={() => updateZIndex(1)} + toggleMapEditAction={() => updateZIndex(highestZIndex + 1)} icon="arrow-double-up" - title="Remove image" + title="Bring to front" /> <MapDrawActionsButton isActive={false} - toggleMapEditAction={() => updateZIndex(-1)} + toggleMapEditAction={() => updateZIndex(lowestZIndex - 1)} icon="arrow-double-down" - title="Remove image" + title="Bring to back" /> </> )} diff --git a/src/redux/layers/layers.selectors.ts b/src/redux/layers/layers.selectors.ts index 8f0c8664..67e2dfae 100644 --- a/src/redux/layers/layers.selectors.ts +++ b/src/redux/layers/layers.selectors.ts @@ -49,3 +49,22 @@ export const highestZIndexSelector = createSelector(layersForCurrentModelSelecto return Math.max(maxZ, layerMaxZ); }, 0); }); + +export const lowestZIndexSelector = createSelector(layersForCurrentModelSelector, layers => { + if (!layers || layers.length === 0) return 0; + + const getMinZFromItems = <T extends { z?: number }>(items: T[] = []): number => + items.length > 0 ? Math.min(...items.map(item => item.z || 0)) : 0; + + return layers.reduce((minZ, layer) => { + const textsMinZ = getMinZFromItems(Object.values(layer.texts)); + const rectsMinZ = getMinZFromItems(layer.rects); + const ovalsMinZ = getMinZFromItems(layer.ovals); + const linesMinZ = getMinZFromItems(layer.lines); + const imagesMinZ = getMinZFromItems(Object.values(layer.images)); + + const layerMinZ = Math.min(textsMinZ, rectsMinZ, ovalsMinZ, linesMinZ, imagesMinZ); + + return Math.min(minZ, layerMinZ); + }, 0); +}); -- GitLab From e3c0a5dd4b5701ee3bd8aa00bf8850a89a817e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Fri, 7 Feb 2025 15:01:36 +0100 Subject: [PATCH 12/12] fix(layer-text): correct color model in ColorTilePicker --- .../LayerTextFactoryModal.component.tsx | 8 +-- .../LayerTextForm.component.tsx | 6 ++- .../Map/MapViewer/utils/shapes/layer/Layer.ts | 2 + .../MapViewer/utils/shapes/text/Text.test.ts | 3 +- .../Map/MapViewer/utils/shapes/text/Text.ts | 50 ++++++++++++++++--- .../ColorTilePicker.component.test.tsx | 8 +-- .../ColorPicker/ColorTilePicker.component.tsx | 14 ++++-- 7 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx index e715c093..98809597 100644 --- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx @@ -23,7 +23,7 @@ import { addLayerText } from '@/redux/layers/layers.thunks'; import { layerAddText } from '@/redux/layers/layers.slice'; import drawElementOnLayer from '@/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer'; import { useMapInstance } from '@/utils/context/mapInstanceContext'; -import { BLACK_COLOR, WHITE_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; +import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants'; export const LayerTextFactoryModal: React.FC = () => { const activeLayer = useAppSelector(layersActiveLayerSelector); @@ -40,7 +40,7 @@ export const LayerTextFactoryModal: React.FC = () => { horizontalAlign: DEFAULT_HORIZONTAL_ALIGNMENT, verticalAlign: DEFAULT_VERTICAL_ALIGNMENT, color: BLACK_COLOR, - borderColor: { ...WHITE_COLOR, alpha: 0 }, + borderColor: BLACK_COLOR, }); const handleSubmit = async (): Promise<void> => { @@ -87,10 +87,6 @@ export const LayerTextFactoryModal: React.FC = () => { } finally { setIsSending(false); } - setIsSending(true); - setTimeout(() => { - setIsSending(false); - }, 5000); }; const changeValues = (value: string | number | Color, key: string): void => { diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component.tsx index b2b7bb45..22bcde3c 100644 --- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component.tsx @@ -58,11 +58,15 @@ export const LayerTextForm = ({ data, onChange }: LayerTextFormProps): React.JSX </div> <div> <span>Color:</span> - <ColorTilePicker colorChange={color => onChange(hexToRgbIntAlpha(color), 'color')} /> + <ColorTilePicker + initialColor={data.color} + colorChange={color => onChange(hexToRgbIntAlpha(color), 'color')} + /> </div> <div> <span>Border color:</span> <ColorTilePicker + initialColor={data.borderColor} colorChange={color => onChange(hexToRgbIntAlpha(color), 'borderColor')} /> </div> diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts index b9070811..e4541a1f 100644 --- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts @@ -134,6 +134,7 @@ export default class Layer { width: text.width, height: text.height, fontColor: text.color, + borderColor: text.borderColor, fontSize: text.fontSize, text: text.notes, verticalAlign: text.verticalAlign as VerticalAlign, @@ -158,6 +159,7 @@ export default class Layer { width: text.width, height: text.height, fontColor: text.color, + borderColor: text.borderColor, fontSize: text.fontSize, text: text.notes, verticalAlign: text.verticalAlign as VerticalAlign, diff --git a/src/components/Map/MapViewer/utils/shapes/text/Text.test.ts b/src/components/Map/MapViewer/utils/shapes/text/Text.test.ts index d40cf459..4a12cf8c 100644 --- a/src/components/Map/MapViewer/utils/shapes/text/Text.test.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/Text.test.ts @@ -34,9 +34,10 @@ describe('Text', () => { text: 'Test', fontSize: 12, fontColor: BLACK_COLOR, + borderColor: BLACK_COLOR, verticalAlign: 'MIDDLE', horizontalAlign: 'CENTER', - pointToProjection: jest.fn(), + pointToProjection: jest.fn(({ x, y }) => [x, y]), mapInstance, }; diff --git a/src/components/Map/MapViewer/utils/shapes/text/Text.ts b/src/components/Map/MapViewer/utils/shapes/text/Text.ts index c853b369..a965d030 100644 --- a/src/components/Map/MapViewer/utils/shapes/text/Text.ts +++ b/src/components/Map/MapViewer/utils/shapes/text/Text.ts @@ -11,6 +11,11 @@ import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapVi import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords'; import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle'; import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; +import Polygon from 'ol/geom/Polygon'; +import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke'; +import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; +import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle'; +import { Stroke } from 'ol/style'; export interface TextProps { x: number; @@ -21,6 +26,7 @@ export interface TextProps { text: string; fontSize: number; fontColor: Color; + borderColor: Color; verticalAlign: VerticalAlign; horizontalAlign: HorizontalAlign; pointToProjection: UsePointToProjectionResult; @@ -34,6 +40,10 @@ export default class Text { style: Style; + polygonStyle: Style; + + strokeStyle: Stroke; + point: Point; feature: Feature<Point>; @@ -47,6 +57,7 @@ export default class Text { text, fontSize, fontColor, + borderColor, verticalAlign, horizontalAlign, pointToProjection, @@ -65,6 +76,27 @@ export default class Text { horizontalAlign, pointToProjection, }); + const borderPolygon = new Polygon([ + [ + pointToProjection({ x, y }), + pointToProjection({ x: x + width, y }), + pointToProjection({ x: x + width, y: y + height }), + pointToProjection({ x, y: y + height }), + pointToProjection({ x, y }), + ], + ]); + this.strokeStyle = getStroke({ + color: rgbToHex(borderColor), + width: 1, + }); + this.polygonStyle = getStyle({ + geometry: borderPolygon, + borderColor, + fillColor: { rgb: 0, alpha: 0 }, + lineWidth: 1, + zIndex, + }); + const textStyle = getTextStyle({ text, fontSize, @@ -78,7 +110,7 @@ export default class Text { this.feature = new Feature({ geometry: this.point, - getTextScale: (resolution: number): number => { + getScale: (resolution: number): number => { const maxZoom = mapInstance?.getView().get('originalMaxZoom'); if (maxZoom) { const minResolution = mapInstance?.getView().getResolutionForZoom(maxZoom); @@ -94,15 +126,17 @@ export default class Text { } protected getStyle(feature: FeatureLike, resolution: number): Style | Array<Style> | void { - const getTextScale = feature.get('getTextScale'); - let textScale = 1; - if (getTextScale instanceof Function) { - textScale = getTextScale(resolution); + const getScale = feature.get('getScale'); + let scale = 1; + if (getScale instanceof Function) { + scale = getScale(resolution); } - if (textScale < TEXT_CUTOFF_SCALE) { + if (scale < TEXT_CUTOFF_SCALE) { return undefined; } - this.style.getText()?.setScale(textScale); - return this.style; + return [ + getScaledElementStyle(this.polygonStyle, this.strokeStyle, scale), + getScaledElementStyle(this.style, undefined, scale), + ]; } } diff --git a/src/shared/ColorPicker/ColorTilePicker.component.test.tsx b/src/shared/ColorPicker/ColorTilePicker.component.test.tsx index bab787c0..e9c12958 100644 --- a/src/shared/ColorPicker/ColorTilePicker.component.test.tsx +++ b/src/shared/ColorPicker/ColorTilePicker.component.test.tsx @@ -4,13 +4,13 @@ import { ColorTilePicker } from './ColorTilePicker.component'; describe('ColorTilePicker', () => { it('renders with the initial color', () => { - render(<ColorTilePicker initialColor="#00ff00" colorChange={jest.fn()} />); + render(<ColorTilePicker initialColor={{ rgb: 65280, alpha: 255 }} colorChange={jest.fn()} />); const colorTile = screen.getByRole('button'); expect(colorTile).toHaveStyle({ backgroundColor: '#00ff00' }); }); it('toggles color picker visibility on click', () => { - render(<ColorTilePicker initialColor="#000000" colorChange={jest.fn()} />); + render(<ColorTilePicker initialColor={{ rgb: 0, alpha: 255 }} colorChange={jest.fn()} />); const colorTile = screen.getByRole('button'); expect(screen.queryByTestId('color-picker')).not.toBeInTheDocument(); @@ -23,7 +23,7 @@ describe('ColorTilePicker', () => { }); it('closes color picker when clicking outside', () => { - render(<ColorTilePicker initialColor="#000000" colorChange={jest.fn()} />); + render(<ColorTilePicker initialColor={{ rgb: 0, alpha: 255 }} colorChange={jest.fn()} />); const colorTile = screen.getByRole('button'); fireEvent.click(colorTile); @@ -34,7 +34,7 @@ describe('ColorTilePicker', () => { }); it('handles keyboard interaction (Enter key)', () => { - render(<ColorTilePicker initialColor="#000000" colorChange={jest.fn()} />); + render(<ColorTilePicker initialColor={{ rgb: 0, alpha: 255 }} colorChange={jest.fn()} />); const colorTile = screen.getByRole('button'); expect(screen.queryByTestId('color-picker')).not.toBeInTheDocument(); diff --git a/src/shared/ColorPicker/ColorTilePicker.component.tsx b/src/shared/ColorPicker/ColorTilePicker.component.tsx index 044ae2c1..ce47fc4d 100644 --- a/src/shared/ColorPicker/ColorTilePicker.component.tsx +++ b/src/shared/ColorPicker/ColorTilePicker.component.tsx @@ -1,9 +1,11 @@ import React, { useState, useEffect, useRef } from 'react'; import ColorPicker, { Color, ColorPickerProps } from '@rc-component/color-picker'; +import { Color as RgbIntAlphaColor } from '@/types/models'; import '@rc-component/color-picker/assets/index.css'; +import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex'; type ColorTilePickerProps = { - initialColor?: string; + initialColor?: RgbIntAlphaColor; colorChange: (color: string) => void; height?: string; testId?: string; @@ -15,14 +17,16 @@ export const ColorTilePicker: React.FC<ColorTilePickerProps> = ({ height = '40px', testId = 'color-tile-picker', }) => { - const [color, setColor] = useState<string>(initialColor || '#000000'); + const [color, setColor] = useState<Color>( + () => new Color(initialColor ? rgbToHex(initialColor) : '#000000'), + ); const [visible, setVisible] = useState<boolean>(false); const pickerRef = useRef<HTMLDivElement>(null); // Referencja do elementu pickera const handleChange: ColorPickerProps['onChange'] = (newColor: Color) => { - setColor(newColor.toHexString()); - colorChange(color); + setColor(newColor); + colorChange(newColor.toHexString()); }; const handleKeyPress = (event: React.KeyboardEvent<HTMLDivElement>): void => { @@ -54,7 +58,7 @@ export const ColorTilePicker: React.FC<ColorTilePickerProps> = ({ onKeyDown={handleKeyPress} style={{ height, - backgroundColor: color, + backgroundColor: color.toHexString(), }} /> {visible && ( -- GitLab