From 5367327e4bc71e6c05fd5e5199c4e5af1d82cd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl> Date: Fri, 8 Nov 2024 10:21:27 +0100 Subject: [PATCH] feat(vector-map): implement pin interactions --- .../mapLeftClick/leftClickHandleAlias.test.ts | 5 +++-- .../listeners/mapLeftClick/leftClickHandleAlias.ts | 5 +++-- .../mapLeftClick/leftClickHandleReaction.test.ts | 3 ++- .../mapLeftClick/leftClickHandleReaction.ts | 5 +++-- .../listeners/mapLeftClick/onMapLeftClick.test.ts | 5 +++-- .../listeners/mapLeftClick/onMapLeftClick.ts | 13 ++++++++----- .../utils/shapes/elements/MapElement.ts | 3 ++- .../utils/shapes/reaction/Reaction.ts | 7 ++++--- .../listeners/mapSingleClick/onMapSingleClick.ts | 1 + .../MapViewer/utils/listeners/useOlMapListeners.ts | 8 ++++---- src/constants/features.ts | 3 +++ 11 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleAlias.test.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleAlias.test.ts index 9d86665c..82b8dfc2 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleAlias.test.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleAlias.test.ts @@ -4,6 +4,7 @@ import { openBioEntityDrawerById, selectTab } from '@/redux/drawer/drawer.slice' import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; import { Feature } from 'ol'; +import { FEATURE_TYPE } from '@/constants/features'; jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); const eventBusDispatchEventSpy = jest.spyOn(PluginsEventBus, 'dispatchEvent'); @@ -12,7 +13,7 @@ describe('leftClickHandleAlias', () => { let dispatch: jest.Mock; const modelId = 1; const hasFitBounds = true; - const feature = new Feature({ type: 'ALIAS', id: 1 }); + const feature = new Feature({ type: FEATURE_TYPE.ALIAS, id: 1 }); beforeEach(() => { jest.clearAllMocks(); @@ -33,7 +34,7 @@ describe('leftClickHandleAlias', () => { expect(eventBusDispatchEventSpy).toHaveBeenCalledWith('onSearch', { type: 'bioEntity', - searchValues: [{ id: 1, modelId, type: 'ALIAS' }], + searchValues: [{ id: 1, modelId, type: FEATURE_TYPE.ALIAS }], results: [ mockBioEntities.map(bioEntity => ({ perfect: true, diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleAlias.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleAlias.ts index 1657e825..f5d678d9 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleAlias.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleAlias.ts @@ -4,6 +4,7 @@ import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEnti 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'; /* prettier-ignore */ export const leftClickHandleAlias = @@ -12,7 +13,7 @@ export const leftClickHandleAlias = const id = feature.get('id'); const bioEntities = await dispatch( getMultiBioEntityByIds({ - elementsToFetch: [{ elementId: id, type: 'ALIAS', modelId, addNumbersToEntityNumber: true }], + elementsToFetch: [{ elementId: id, type: FEATURE_TYPE.ALIAS, modelId, addNumbersToEntityNumber: true }], }), ).unwrap(); dispatch(selectTab(`${id}`)); @@ -20,7 +21,7 @@ export const leftClickHandleAlias = PluginsEventBus.dispatchEvent('onSearch', { type: 'bioEntity', - searchValues: [{ id, modelId, type: 'ALIAS' }], + searchValues: [{ id, modelId, type: FEATURE_TYPE.ALIAS }], results: [ bioEntities.map(bioEntity => { return { perfect: true, bioEntity }; diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction.test.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction.test.ts index 372bc9a7..1bca3522 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction.test.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction.test.ts @@ -9,6 +9,7 @@ import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; import { apiPath } from '@/redux/apiPath'; import { HttpStatusCode } from 'axios'; import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; +import { FEATURE_TYPE } from '@/constants/features'; const mockedAxiosClient = mockNetworkNewAPIResponse(); jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); @@ -19,7 +20,7 @@ describe('leftClickHandleReaction', () => { let modelId = 1; let reactionId = 1; const hasFitBounds = true; - const feature = new Feature({ type: 'REACTION', id: 1 }); + const feature = new Feature({ type: FEATURE_TYPE.REACTION, id: 1 }); beforeEach(() => { jest.clearAllMocks(); diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction.ts index 34996f35..1481cee4 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction.ts @@ -12,6 +12,7 @@ import { bioEntitySchema } from '@/models/bioEntitySchema'; import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEntity'; import { FeatureLike } from 'ol/Feature'; import { getBioEntitiesIdsFromReaction } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/getBioEntitiesIdsFromReaction'; +import { FEATURE_TYPE } from '@/constants/features'; /* prettier-ignore */ export const leftClickHandleReaction = @@ -44,7 +45,7 @@ export const leftClickHandleReaction = return { elementId: parseInt(bioEntityId, 10), modelId, - type: 'ALIAS' + type: FEATURE_TYPE.ALIAS }; }) }) @@ -55,7 +56,7 @@ export const leftClickHandleReaction = result.push({ bioEntity: reactionNewApi, perfect: true }); PluginsEventBus.dispatchEvent('onSearch', { type: 'reaction', - searchValues: [{ id, modelId, type: 'REACTION' }], + searchValues: [{ id, modelId, type: FEATURE_TYPE.REACTION }], results: [result] }); diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/onMapLeftClick.test.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/onMapLeftClick.test.ts index 0065208e..e7fa9bc7 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/onMapLeftClick.test.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/onMapLeftClick.test.ts @@ -10,6 +10,7 @@ import { Comment } from '@/types/models'; import { Layer } from 'ol/layer'; import SimpleGeometry from 'ol/geom/SimpleGeometry'; import { Feature } from 'ol'; +import { FEATURE_TYPE } from '@/constants/features'; import * as leftClickHandleAlias from './leftClickHandleAlias'; import * as leftClickHandleReaction from './leftClickHandleReaction'; @@ -71,7 +72,7 @@ describe('onMapLeftClick', () => { const dispatch = jest.fn(() => ({ unwrap: jest.fn().mockResolvedValue(mockBioEntities), })); - const feature = new Feature({ id: 1, type: 'ALIAS' }); + const feature = new Feature({ id: 1, type: FEATURE_TYPE.ALIAS }); jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { callback(feature, null as unknown as Layer, null as unknown as SimpleGeometry); }); @@ -93,7 +94,7 @@ describe('onMapLeftClick', () => { const dispatch = jest.fn(() => ({ unwrap: jest.fn().mockResolvedValue(mockBioEntities), })); - const feature = new Feature({ id: 1, type: 'REACTION' }); + const feature = new Feature({ id: 1, type: FEATURE_TYPE.REACTION }); jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { callback(feature, null as unknown as Layer, null as unknown as SimpleGeometry); }); diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/onMapLeftClick.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/onMapLeftClick.ts index 035d1a5b..aa481cd3 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/onMapLeftClick.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/onMapLeftClick.ts @@ -13,6 +13,7 @@ import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/ import { resetReactionsData } from '@/redux/reactions/reactions.slice'; import { leftClickHandleReaction } from '@/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction'; import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset'; +import { FEATURE_TYPE } from '@/constants/features'; /* prettier-ignore */ export const onMapLeftClick = @@ -24,13 +25,14 @@ export const onMapLeftClick = dispatch(updateLastClick({ coordinates: point, modelId })); let featureAtPixel: FeatureLike | undefined; - mapInstance.forEachFeatureAtPixel(pixel, feature => { - if(feature.get('id') && ['ALIAS', 'REACTION'].includes(feature.get('type'))) { + mapInstance.forEachFeatureAtPixel(pixel, (feature) => { + if(feature.get('id') && [...Object.values(FEATURE_TYPE)].includes(feature.get('type'))) { featureAtPixel = feature; return true; } return false; - }, {hitTolerance: 20}); + }, {hitTolerance: 10}); + if(!featureAtPixel) { if (isResultDrawerOpen) { dispatch(closeDrawer()); @@ -42,6 +44,7 @@ export const onMapLeftClick = } const { shouldBlockCoordSearch } = handleFeaturesClick([featureAtPixel], dispatch, comments); + if (shouldBlockCoordSearch) { return; } @@ -49,9 +52,9 @@ export const onMapLeftClick = dispatch(handleDataReset); const type = featureAtPixel.get('type'); - if(type === 'ALIAS') { + if(type === FEATURE_TYPE.ALIAS) { await leftClickHandleAlias(dispatch)(featureAtPixel, modelId); - } else if (type === 'REACTION') { + } else if (type === FEATURE_TYPE.REACTION) { await leftClickHandleReaction(dispatch)(featureAtPixel, modelId); } }; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts index 92798f3b..dae35c65 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts @@ -21,6 +21,7 @@ import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shap import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; import { BioShapesDict, LineTypeDict } from '@/redux/shapes/shapes.types'; +import { FEATURE_TYPE } from '@/constants/features'; export type MapElementProps = { id: number; @@ -101,7 +102,7 @@ export default class MapElement extends BaseMultiPolygon { modifications = [], }: MapElementProps) { super({ - type: 'ALIAS', + type: FEATURE_TYPE.ALIAS, id, x, y, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts index 67c061ec..9bd713ce 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts @@ -15,6 +15,7 @@ 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 { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types'; +import { FEATURE_TYPE } from '@/constants/features'; export interface ReactionProps { id: number; @@ -204,7 +205,7 @@ export default class Reaction { style: lineStyle, lineWidth: line.width, id: this.id, - type: 'REACTION', + type: FEATURE_TYPE.REACTION, }); lineFeature.setStyle(this.getStyle.bind(this)); @@ -252,7 +253,7 @@ export default class Reaction { style: styles, lineWidth: this.line.width, id: this.id, - type: 'REACTION', + type: FEATURE_TYPE.REACTION, }); squareFeature.setStyle(this.getStyle.bind(this)); return squareFeature; @@ -306,7 +307,7 @@ export default class Reaction { style: circleStyle, lineWidth: 1, id: this.id, - type: 'REACTION', + type: FEATURE_TYPE.REACTION, }); circleFeature.setStyle(this.getStyle.bind(this)); return circleFeature; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts index 04908fba..44e9d10b 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts @@ -26,6 +26,7 @@ export const onMapSingleClick = const featuresAtPixel: FeatureLike[] = []; mapInstance.forEachFeatureAtPixel(pixel, (feature) => featuresAtPixel.push(feature)); + const { shouldBlockCoordSearch } = handleFeaturesClick(featuresAtPixel, dispatch, comments); if (shouldBlockCoordSearch) { diff --git a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts index 7b1888d5..d10e31d5 100644 --- a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts +++ b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts @@ -102,7 +102,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) }, [view, handleChangeCenter]); useEffect(() => { - if (!mapInstance || vectorRendering) { + if (!mapInstance) { return; } @@ -110,7 +110,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) // eslint-disable-next-line consistent-return return () => unByKey(key); - }, [mapInstance, vectorRendering]); + }, [mapInstance]); useEffect(() => { if (!mapInstance || vectorRendering) { @@ -126,7 +126,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) }, [mapInstance, handleMapSingleClick, vectorRendering]); useEffect(() => { - if (!mapInstance || vectorRendering) { + if (!mapInstance) { return; } @@ -143,5 +143,5 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) // eslint-disable-next-line consistent-return return () => mapInstance.getViewport().removeEventListener('contextmenu', rightClickEvent); - }, [mapInstance, handleRightClick, vectorRendering]); + }, [mapInstance, handleRightClick]); }; diff --git a/src/constants/features.ts b/src/constants/features.ts index 6edbb352..036bfd09 100644 --- a/src/constants/features.ts +++ b/src/constants/features.ts @@ -4,6 +4,8 @@ export const FEATURE_TYPE = { SURFACE_OVERLAY: 'SURFACE_OVERLAY', SURFACE_MARKER: 'SURFACE_MARKER', PIN_ICON_COMMENT: 'PIN_ICON_COMMENT', + ALIAS: 'ALIAS', + REACTION: 'REACTION', } as const; export const PIN_ICON_ANY = [ @@ -11,4 +13,5 @@ export const PIN_ICON_ANY = [ FEATURE_TYPE.PIN_ICON_MARKER, FEATURE_TYPE.PIN_ICON_COMMENT, ]; + export const SURFACE_ANY = [FEATURE_TYPE.SURFACE_OVERLAY, FEATURE_TYPE.SURFACE_MARKER]; -- GitLab