diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts index 212465ce35f150f5631ed8db563f50b4cbe34f7d..fb720a2799702c4a049aa1ca3ed4ba0c6db8d41b 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.test.ts @@ -51,7 +51,11 @@ describe('onMapLeftClick', () => { it('dispatches updateLastClick and resets data if no feature at pixel', async () => { const dispatch = jest.fn(); jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { - callback(new Feature({}), null as unknown as Layer, null as unknown as SimpleGeometry); + callback( + new Feature({ zIndex: 1 }), + null as unknown as Layer, + null as unknown as SimpleGeometry, + ); }); await onMapLeftClick( mapSize, @@ -74,7 +78,7 @@ describe('onMapLeftClick', () => { const dispatch = jest.fn(() => ({ unwrap: jest.fn().mockResolvedValue(mockBioEntities), })); - const feature = new Feature({ id: 1, type: FEATURE_TYPE.ALIAS }); + const feature = new Feature({ id: 1, type: FEATURE_TYPE.ALIAS, zIndex: 1 }); jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => { callback(feature, null as unknown as Layer, null as unknown as SimpleGeometry); }); @@ -98,7 +102,7 @@ describe('onMapLeftClick', () => { const dispatch = jest.fn(() => ({ unwrap: jest.fn().mockResolvedValue(mockBioEntities), })); - const feature = new Feature({ id: 1, type: FEATURE_TYPE.REACTION }); + const feature = new Feature({ id: 1, type: FEATURE_TYPE.REACTION, zIndex: 1 }); 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/mouseClick/mouseLeftClick/onMapLeftClick.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts index 839ef138cb6e80ebce57c311ccff3f02673ae10a..be79fe07dfc43ed838dfff4ce47ff2003f411e44 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseLeftClick/onMapLeftClick.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-magic-numbers */ import { MapSize } from '@/redux/map/map.types'; import { AppDispatch } from '@/redux/store'; import { Map, MapBrowserEvent } from 'ol'; @@ -26,13 +27,12 @@ export const onMapLeftClick = let featureAtPixel: FeatureLike | undefined; mapInstance.forEachFeatureAtPixel(pixel, (feature, ) => { - if(feature.get('id') && [...Object.values(FEATURE_TYPE)].includes(feature.get('type'))) { + if(feature.get('id') && [...Object.values(FEATURE_TYPE)].includes(feature.get('type')) && feature.get('zIndex') >= 0) { featureAtPixel = feature; return true; } return false; }, {hitTolerance: 10}); - if(!featureAtPixel) { if (isResultDrawerOpen) { dispatch(closeDrawer()); @@ -53,7 +53,7 @@ export const onMapLeftClick = const type = featureAtPixel.get('type'); const id = featureAtPixel.get('id'); - if(type === FEATURE_TYPE.ALIAS) { + if([FEATURE_TYPE.ALIAS, FEATURE_TYPE.GLYPH].includes(type)) { await leftClickHandleAlias(dispatch)(featureAtPixel, modelId); } else if (type === FEATURE_TYPE.REACTION) { clickHandleReaction(dispatch)(modelElements, reactions, id, modelId); diff --git a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.ts b/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.ts index 902f7d52763fbb88f768c0e854aa55919800ef6c..38a214a58252060d254fa77845db4cc670771ed7 100644 --- a/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.ts +++ b/src/components/Map/MapViewer/MapViewerVector/listeners/mouseClick/mouseRightClick/onMapRightClick.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-magic-numbers */ import { MapSize } from '@/redux/map/map.types'; import { AppDispatch } from '@/redux/store'; import { Feature, Map, MapBrowserEvent } from 'ol'; @@ -30,7 +31,11 @@ export const onMapRightClick = const source = layer.getSource(); if (source instanceof VectorSource) { foundFeature = source.getClosestFeatureToCoordinate(coordinate, (feature) => { - return [FEATURE_TYPE.ALIAS, FEATURE_TYPE.REACTION].includes(feature.get('type')); + return [ + FEATURE_TYPE.ALIAS, + FEATURE_TYPE.REACTION, + FEATURE_TYPE.GLYPH + ].includes(feature.get('type')) && feature.get('zIndex') >= 0; }); } } @@ -44,7 +49,7 @@ export const onMapRightClick = const type = foundFeature.get('type'); const id = foundFeature.get('id'); - if(type === FEATURE_TYPE.ALIAS) { + if([FEATURE_TYPE.ALIAS, FEATURE_TYPE.GLYPH].includes(type)) { const modelElement = modelElements.find(element => element.id === id); if(!modelElement) { return; diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/processModelElements.ts b/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/processModelElements.ts index 066712d01a07dfc03dc7d8ab86ebf0b9b9c3d158..dc49f6fd2e09f6770c32a5b1a529661dac3cd3c0 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/processModelElements.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/processModelElements.ts @@ -31,7 +31,8 @@ export default function processModelElements( modelElements.content.forEach((element: ModelElement) => { if (element.glyph) { const glyph = new Glyph({ - id: element.glyph.id, + elementId: element.id, + glyphId: element.glyph.id, x: element.x, y: element.y, width: element.width, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts index 5997a743aa0b5c5c1151d4a2cfd6dcd75d96302e..135bd83963af228325449c4b9d97ac18b924a29e 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts @@ -178,6 +178,7 @@ export default abstract class BaseMultiPolygon { }, id: this.id, type: this.type, + zIndex: this.zIndex, }); this.feature.setStyle(this.getStyle.bind(this)); diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph.test.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph.test.ts index e0235269d1d38a2002ceca0cfd41b4a951528dd2..2f8d4777750896b50556e628bd1ec50b30df3bca 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph.test.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph.test.ts @@ -29,7 +29,8 @@ describe('Glyph', () => { pointToProjectionMock = jest.fn().mockReturnValue([10, 20]); props = { - id: 1, + elementId: 1, + glyphId: 1, x: 10, y: 20, width: 32, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph.ts index 963a69c4c788ae050d866d4eee54ed5c176e8ce8..603184469b16dda895e68718027da2f231509019 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Glyph.ts @@ -10,9 +10,13 @@ import { BASE_NEW_API_URL } from '@/constants'; 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'; export type GlyphProps = { - id: number; + elementId: number; + glyphId: number; x: number; y: number; width: number; @@ -27,6 +31,8 @@ export default class Glyph { style: Style; + polygonStyle: Style; + width: number; height: number; @@ -43,7 +49,17 @@ export default class Glyph { pointToProjection: UsePointToProjectionResult; - constructor({ id, x, y, width, height, zIndex, pointToProjection, mapInstance }: GlyphProps) { + constructor({ + elementId, + glyphId, + x, + y, + width, + height, + zIndex, + pointToProjection, + mapInstance, + }: GlyphProps) { this.width = width; this.height = height; this.x = x; @@ -66,8 +82,17 @@ export default class Glyph { pointToProjection({ x, y }), ], ]); + this.polygonStyle = getStyle({ + geometry: polygon, + zIndex, + borderColor: { ...WHITE_COLOR, alpha: 0 }, + fillColor: { ...WHITE_COLOR, alpha: 0 }, + }); const iconFeature = new Feature({ geometry: polygon, + id: elementId, + type: FEATURE_TYPE.GLYPH, + zIndex, getImageScale: (resolution: number): number => { if (mapInstance) { return mapInstance.getView().getMinResolution() / resolution; @@ -90,7 +115,7 @@ export default class Glyph { this.style = new Style({ image: new Icon({ anchor: [0, 0], - src: `${BASE_NEW_API_URL}${apiPath.getGlyphImage(id)}`, + src: `${BASE_NEW_API_URL}${apiPath.getGlyphImage(glyphId)}`, size: [width, height], }), zIndex, @@ -118,6 +143,6 @@ export default class Glyph { (this.style.getImage() as Icon).setAnchor(anchor); this.style.setGeometry(new Point(coords)); } - return this.style; + return [this.style, this.polygonStyle]; } } diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.ts index 97168e2d6b9b65dcfda1f258e4b3b61f44953101..02e0ab19de5d93cb2c793d89631e86370370dcd0 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getArrowFeature.ts @@ -60,6 +60,7 @@ export default function getArrowFeature({ const arrowFeature = new Feature({ geometry: new MultiPolygon(arrowPolygons), style: arrowStyles, + zIndex, }); arrowFeature.setStyle(arrowStyles); return arrowFeature; 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 f81407649044d907650be43c9c1908023f2cd7da..a3878b53137e971c06719a8d6537cbd1685c2e5f 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts @@ -213,6 +213,7 @@ export default class Reaction { id: this.id, type: FEATURE_TYPE.REACTION, elementType: REACTION_ELEMENT_TYPES.LINE, + zIndex: this.zIndex, }); lineFeature.setStyle(this.getStyle.bind(this)); @@ -262,6 +263,7 @@ export default class Reaction { id: this.id, type: FEATURE_TYPE.REACTION, elementType: REACTION_ELEMENT_TYPES.SQUARE, + zIndex: this.zIndex, }); squareFeature.setStyle(this.getStyle.bind(this)); return squareFeature; @@ -318,6 +320,7 @@ export default class Reaction { type: FEATURE_TYPE.REACTION, elementType: REACTION_ELEMENT_TYPES.OPERATOR, fontSize: 10, + zIndex: this.zIndex, }); circleFeature.setStyle(this.getStyle.bind(this)); return circleFeature; diff --git a/src/constants/features.ts b/src/constants/features.ts index 036bfd09e4ae6ad2cf9cbf1ee6172ccc896a5234..7faacd6d9d218caa63921eb66fb1e306ca611d9a 100644 --- a/src/constants/features.ts +++ b/src/constants/features.ts @@ -6,6 +6,7 @@ export const FEATURE_TYPE = { PIN_ICON_COMMENT: 'PIN_ICON_COMMENT', ALIAS: 'ALIAS', REACTION: 'REACTION', + GLYPH: 'GLYPH', } as const; export const PIN_ICON_ANY = [