diff --git a/docs/plugins/events.md b/docs/plugins/events.md index 957b28a29c0bbde50cd8fc105001e55976bbe822..7ad4cf647dc7cab321177ea49654401480f61fcd 100644 --- a/docs/plugins/events.md +++ b/docs/plugins/events.md @@ -201,6 +201,34 @@ To listen for specific events, plugins can use the `addListener` method in `even } ``` +- onPinIconClick - triggered when someone clicks on a pin icon; the element to which the pin is attached is passed as an argument. Example argument: + +```javascript +{ + "id": 40072, +} +``` + +```javascript +{ + "id": "b0a478ad-7e7a-47f5-8130-e96cbeaa0cfe", // marker pin +} +``` + +- onSurfaceOverlayClick - triggered when someone clicks on a overlay surface; the element to which the pin is attached is passed as an argument. Example argument: + +```javascript +{ + "id": 18, +} +``` + +```javascript +{ + "id": "a3a5305f-acfa-47ff-bf77-a26d017c6eb3", // surface marker overlay +} +``` + - onSubmapOpen - triggered when submap opens; the submap identifier is passed as an argument. Example argument: ``` diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/createFeatureFromExtent.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/createFeatureFromExtent.ts index 121bfe2bb2b3c25f79ecb2f0dd7809a4378ace40..f79764b2ab2d992e9ad3ca2cdd8aa5feb9ec9d5c 100644 --- a/src/components/Map/MapViewer/utils/config/overlaysLayer/createFeatureFromExtent.ts +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/createFeatureFromExtent.ts @@ -1,5 +1,5 @@ -import Polygon, { fromExtent } from 'ol/geom/Polygon'; import Feature from 'ol/Feature'; +import Polygon, { fromExtent } from 'ol/geom/Polygon'; export const createFeatureFromExtent = ([xMin, yMin, xMax, yMax]: number[]): Feature<Polygon> => - new Feature({ geometry: fromExtent([xMin, yMin, xMax, yMax]) }); + new Feature({ geometry: fromExtent([xMin, yMin, xMax, yMax]), type: 'surface' }); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts index ff7bfb00b7af92fa23a3d9be3ae2e4d826320252..31d33f86365ee5667a43a2a9d6af7489fc06f1f2 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts @@ -15,8 +15,11 @@ export const getPinFeature = ( y: y + (height || ZERO) / HALF, }; - return new Feature({ + const feature = new Feature({ geometry: new Point(pointToProjection(point)), - name: id, + id, + type: 'pin', }); + + return feature; }; diff --git a/src/components/Map/MapViewer/utils/config/useOlMapLayers.ts b/src/components/Map/MapViewer/utils/config/useOlMapLayers.ts index ff40ba9134e054c7dd1cb444337071f2a7aef2ed..a42e967759c12b43c1ce2da7158b4a2641a2620d 100644 --- a/src/components/Map/MapViewer/utils/config/useOlMapLayers.ts +++ b/src/components/Map/MapViewer/utils/config/useOlMapLayers.ts @@ -22,7 +22,7 @@ export const useOlMapLayers = ({ mapInstance }: UseOlMapLayersInput): MapConfig[ return; } - mapInstance.setLayers([tileLayer, reactionsLayer, pinsLayer, overlaysLayer]); + mapInstance.setLayers([tileLayer, reactionsLayer, overlaysLayer, pinsLayer]); }, [reactionsLayer, tileLayer, pinsLayer, mapInstance, overlaysLayer]); return [tileLayer, pinsLayer, reactionsLayer, overlaysLayer]; diff --git a/src/components/Map/MapViewer/utils/listeners/mapFeatureClick/useMapFeatureClick.ts b/src/components/Map/MapViewer/utils/listeners/mapFeatureClick/useMapFeatureClick.ts new file mode 100644 index 0000000000000000000000000000000000000000..2ab3ea05ef07487fb13dfa07e88ccb4f728ee1fb --- /dev/null +++ b/src/components/Map/MapViewer/utils/listeners/mapFeatureClick/useMapFeatureClick.ts @@ -0,0 +1,15 @@ +import { FeatureLike } from 'ol/Feature'; + +interface UseMapFeatureClickResult { + handleFeatureClick(feature: FeatureLike): void; +} + +export const useMapFeatureClick = (): UseMapFeatureClickResult => { + const handleFeatureClick = (feature: FeatureLike): void => { + console.log(feature.get('type')); + }; + + return { + handleFeatureClick, + }; +}; diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts index 6940b226047f357dbbcb9f900c32d78ffafd5934..4661b41ae55f019c422500a163b33213bfb5ba58 100644 --- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts +++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts @@ -1,6 +1,7 @@ import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common'; import { MapSize } from '@/redux/map/map.types'; import { AppDispatch } from '@/redux/store'; +import { MapInstance } from '@/types/map'; import { MapBrowserEvent } from 'ol'; import { getSearchResults } from './getSearchResults'; import { handleDataReset } from './handleDataReset'; @@ -9,7 +10,7 @@ import { handleSearchResultAction } from './handleSearchResultAction'; /* prettier-ignore */ export const onMapSingleClick = (mapSize: MapSize, modelId: number, dispatch: AppDispatch) => - async ({ coordinate }: MapBrowserEvent<UIEvent>): Promise<void> => { + async ({ coordinate }: Pick<MapBrowserEvent<UIEvent>, 'coordinate'>, mapInstance: MapInstance): Promise<void> => { // 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); diff --git a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts index 1742d6fa7304541ec8f13ba93f5811b7be0b8bde..1c0b9fcf413876cbff92bcd408a9564b0756b3ea 100644 --- a/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts +++ b/src/components/Map/MapViewer/utils/listeners/useOlMapListeners.ts @@ -10,6 +10,7 @@ import { Pixel } from 'ol/pixel'; import { useEffect, useRef } from 'react'; import { useSelector } from 'react-redux'; import { useDebouncedCallback } from 'use-debounce'; +import { useMapFeatureClick } from './mapFeatureClick/useMapFeatureClick'; import { onMapRightClick } from './mapRightClick/onMapRightClick'; import { onMapSingleClick } from './mapSingleClick/onMapSingleClick'; import { onMapPositionChange } from './onMapPositionChange'; @@ -23,6 +24,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) const mapSize = useSelector(mapDataSizeSelector); const modelId = useSelector(currentModelIdSelector); const mapLastZoomValue = useSelector(mapDataLastZoomValue); + const { handleFeatureClick } = useMapFeatureClick(); const coordinate = useRef<Coordinate>([]); const pixel = useRef<Pixel>([]); const dispatch = useAppDispatch(); @@ -58,7 +60,22 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) return; } - const key = mapInstance.on('singleclick', handleMapSingleClick); + const key = mapInstance.on('click', e => { + mapInstance.forEachFeatureAtPixel(e.pixel, handleFeatureClick); + }); + + // eslint-disable-next-line consistent-return + return () => unByKey(key); + }, [mapInstance, handleFeatureClick]); + + useEffect(() => { + if (!mapInstance) { + return; + } + + const key = mapInstance.on('singleclick', ({ coordinate: ciird }) => + handleMapSingleClick({ coordinate }, mapInstance), + ); // eslint-disable-next-line consistent-return return () => unByKey(key); diff --git a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.constants.ts b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.constants.ts index 5fd9ea0a98a72dbfe3eacd96d8d708f81c3058bd..5a5eb6520a5ff713805d90e82fa4c997b5710629 100644 --- a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.constants.ts +++ b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.constants.ts @@ -14,6 +14,8 @@ const PLUGINS_EVENTS = { onZoomChanged: 'onZoomChanged', onCenterChanged: 'onCenterChanged', onBioEntityClick: 'onBioEntityClick', + onPinIconClick: 'onPinIconClick', + onSurfaceOverlayClick: 'onSurfaceOverlayClick', }, search: { onSearch: 'onSearch', diff --git a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.ts b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.ts index 5227eabbdc6e6ea1f43b84d809fe6718af2fcc4c..aa7221ab01b36e9a3455c2e65f34631aaf423098 100644 --- a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.ts +++ b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.ts @@ -4,6 +4,8 @@ import { ALLOWED_PLUGINS_EVENTS, LISTENER_NOT_FOUND } from './pluginsEventBus.co import type { CenteredCoordinates, ClickedBioEntity, + ClickedPinIcon, + ClickedSurfaceOverlay, Events, EventsData, PluginsEventBusType, @@ -21,6 +23,8 @@ export function dispatchEvent(type: 'onSubmapClose', submapId: number): void; export function dispatchEvent(type: 'onZoomChanged', data: ZoomChanged): void; export function dispatchEvent(type: 'onCenterChanged', data: CenteredCoordinates): void; export function dispatchEvent(type: 'onBioEntityClick', data: ClickedBioEntity): void; +export function dispatchEvent(type: 'onPinIconClick', data: ClickedPinIcon): void; +export function dispatchEvent(type: 'onSurfaceOverlayClick', data: ClickedSurfaceOverlay): void; export function dispatchEvent(type: 'onSearch', data: SearchData): void; export function dispatchEvent(type: Events, data: EventsData): void { if (!ALLOWED_PLUGINS_EVENTS.includes(type)) throw new Error(`Invalid event type: ${type}`); diff --git a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts index 7679bb0af514be8208c15a0a23c55c3de096aafe..4260f3994f3b0fdbb8c44fb81c8e749429db409a 100644 --- a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts +++ b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts @@ -6,13 +6,15 @@ export type OverlayEvents = | 'onAddDataOverlay' | 'onRemoveDataOverlay' | 'onShowOverlay' - | 'onHideOverlay'; + | 'onHideOverlay' + | 'onSurfaceOverlayClick'; export type SubmapEvents = | 'onSubmapOpen' | 'onSubmapClose' | 'onZoomChanged' | 'onCenterChanged' - | 'onBioEntityClick'; + | 'onBioEntityClick' + | 'onPinIconClick'; export type SearchEvents = 'onSearch'; export type Events = OverlayEvents | BackgroundEvents | SubmapEvents | SearchEvents; @@ -34,6 +36,14 @@ export type ClickedBioEntity = { modelId: number; }; +export type ClickedPinIcon = { + id: number | string; +}; + +export type ClickedSurfaceOverlay = { + id: number | string; +}; + export type SearchDataBioEntity = { type: 'bioEntity'; searchValues: string[]; @@ -61,6 +71,8 @@ export type EventsData = | ZoomChanged | CenteredCoordinates | ClickedBioEntity + | ClickedPinIcon + | ClickedSurfaceOverlay | SearchData; export type PluginsEventBusType = {