Skip to content
Snippets Groups Projects
Commit 5367327e authored by Miłosz Grocholewski's avatar Miłosz Grocholewski
Browse files

feat(vector-map): implement pin interactions

parent 9484fc3a
No related branches found
No related tags found
1 merge request!301feat(vector-map): implement pin interactions
Pipeline #97758 passed
Showing
with 36 additions and 22 deletions
...@@ -4,6 +4,7 @@ import { openBioEntityDrawerById, selectTab } from '@/redux/drawer/drawer.slice' ...@@ -4,6 +4,7 @@ import { openBioEntityDrawerById, selectTab } from '@/redux/drawer/drawer.slice'
import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds';
import { Feature } from 'ol'; import { Feature } from 'ol';
import { FEATURE_TYPE } from '@/constants/features';
jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds');
const eventBusDispatchEventSpy = jest.spyOn(PluginsEventBus, 'dispatchEvent'); const eventBusDispatchEventSpy = jest.spyOn(PluginsEventBus, 'dispatchEvent');
...@@ -12,7 +13,7 @@ describe('leftClickHandleAlias', () => { ...@@ -12,7 +13,7 @@ describe('leftClickHandleAlias', () => {
let dispatch: jest.Mock; let dispatch: jest.Mock;
const modelId = 1; const modelId = 1;
const hasFitBounds = true; const hasFitBounds = true;
const feature = new Feature({ type: 'ALIAS', id: 1 }); const feature = new Feature({ type: FEATURE_TYPE.ALIAS, id: 1 });
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
...@@ -33,7 +34,7 @@ describe('leftClickHandleAlias', () => { ...@@ -33,7 +34,7 @@ describe('leftClickHandleAlias', () => {
expect(eventBusDispatchEventSpy).toHaveBeenCalledWith('onSearch', { expect(eventBusDispatchEventSpy).toHaveBeenCalledWith('onSearch', {
type: 'bioEntity', type: 'bioEntity',
searchValues: [{ id: 1, modelId, type: 'ALIAS' }], searchValues: [{ id: 1, modelId, type: FEATURE_TYPE.ALIAS }],
results: [ results: [
mockBioEntities.map(bioEntity => ({ mockBioEntities.map(bioEntity => ({
perfect: true, perfect: true,
......
...@@ -4,6 +4,7 @@ import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEnti ...@@ -4,6 +4,7 @@ import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEnti
import { FeatureLike } from 'ol/Feature'; import { FeatureLike } from 'ol/Feature';
import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus'; import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds'; import { searchFitBounds } from '@/services/pluginsManager/map/triggerSearch/searchFitBounds';
import { FEATURE_TYPE } from '@/constants/features';
/* prettier-ignore */ /* prettier-ignore */
export const leftClickHandleAlias = export const leftClickHandleAlias =
...@@ -12,7 +13,7 @@ export const leftClickHandleAlias = ...@@ -12,7 +13,7 @@ export const leftClickHandleAlias =
const id = feature.get('id'); const id = feature.get('id');
const bioEntities = await dispatch( const bioEntities = await dispatch(
getMultiBioEntityByIds({ getMultiBioEntityByIds({
elementsToFetch: [{ elementId: id, type: 'ALIAS', modelId, addNumbersToEntityNumber: true }], elementsToFetch: [{ elementId: id, type: FEATURE_TYPE.ALIAS, modelId, addNumbersToEntityNumber: true }],
}), }),
).unwrap(); ).unwrap();
dispatch(selectTab(`${id}`)); dispatch(selectTab(`${id}`));
...@@ -20,7 +21,7 @@ export const leftClickHandleAlias = ...@@ -20,7 +21,7 @@ export const leftClickHandleAlias =
PluginsEventBus.dispatchEvent('onSearch', { PluginsEventBus.dispatchEvent('onSearch', {
type: 'bioEntity', type: 'bioEntity',
searchValues: [{ id, modelId, type: 'ALIAS' }], searchValues: [{ id, modelId, type: FEATURE_TYPE.ALIAS }],
results: [ results: [
bioEntities.map(bioEntity => { bioEntities.map(bioEntity => {
return { perfect: true, bioEntity }; return { perfect: true, bioEntity };
......
...@@ -9,6 +9,7 @@ import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse'; ...@@ -9,6 +9,7 @@ import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
import { apiPath } from '@/redux/apiPath'; import { apiPath } from '@/redux/apiPath';
import { HttpStatusCode } from 'axios'; import { HttpStatusCode } from 'axios';
import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture'; import { bioEntityFixture } from '@/models/fixtures/bioEntityFixture';
import { FEATURE_TYPE } from '@/constants/features';
const mockedAxiosClient = mockNetworkNewAPIResponse(); const mockedAxiosClient = mockNetworkNewAPIResponse();
jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds'); jest.mock('../../../../../../services/pluginsManager/map/triggerSearch/searchFitBounds');
...@@ -19,7 +20,7 @@ describe('leftClickHandleReaction', () => { ...@@ -19,7 +20,7 @@ describe('leftClickHandleReaction', () => {
let modelId = 1; let modelId = 1;
let reactionId = 1; let reactionId = 1;
const hasFitBounds = true; const hasFitBounds = true;
const feature = new Feature({ type: 'REACTION', id: 1 }); const feature = new Feature({ type: FEATURE_TYPE.REACTION, id: 1 });
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
......
...@@ -12,6 +12,7 @@ import { bioEntitySchema } from '@/models/bioEntitySchema'; ...@@ -12,6 +12,7 @@ import { bioEntitySchema } from '@/models/bioEntitySchema';
import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEntity'; import { getMultiBioEntityByIds } from '@/redux/bioEntity/thunks/getMultiBioEntity';
import { FeatureLike } from 'ol/Feature'; import { FeatureLike } from 'ol/Feature';
import { getBioEntitiesIdsFromReaction } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/getBioEntitiesIdsFromReaction'; import { getBioEntitiesIdsFromReaction } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/getBioEntitiesIdsFromReaction';
import { FEATURE_TYPE } from '@/constants/features';
/* prettier-ignore */ /* prettier-ignore */
export const leftClickHandleReaction = export const leftClickHandleReaction =
...@@ -44,7 +45,7 @@ export const leftClickHandleReaction = ...@@ -44,7 +45,7 @@ export const leftClickHandleReaction =
return { return {
elementId: parseInt(bioEntityId, 10), elementId: parseInt(bioEntityId, 10),
modelId, modelId,
type: 'ALIAS' type: FEATURE_TYPE.ALIAS
}; };
}) })
}) })
...@@ -55,7 +56,7 @@ export const leftClickHandleReaction = ...@@ -55,7 +56,7 @@ export const leftClickHandleReaction =
result.push({ bioEntity: reactionNewApi, perfect: true }); result.push({ bioEntity: reactionNewApi, perfect: true });
PluginsEventBus.dispatchEvent('onSearch', { PluginsEventBus.dispatchEvent('onSearch', {
type: 'reaction', type: 'reaction',
searchValues: [{ id, modelId, type: 'REACTION' }], searchValues: [{ id, modelId, type: FEATURE_TYPE.REACTION }],
results: [result] results: [result]
}); });
......
...@@ -10,6 +10,7 @@ import { Comment } from '@/types/models'; ...@@ -10,6 +10,7 @@ import { Comment } from '@/types/models';
import { Layer } from 'ol/layer'; import { Layer } from 'ol/layer';
import SimpleGeometry from 'ol/geom/SimpleGeometry'; import SimpleGeometry from 'ol/geom/SimpleGeometry';
import { Feature } from 'ol'; import { Feature } from 'ol';
import { FEATURE_TYPE } from '@/constants/features';
import * as leftClickHandleAlias from './leftClickHandleAlias'; import * as leftClickHandleAlias from './leftClickHandleAlias';
import * as leftClickHandleReaction from './leftClickHandleReaction'; import * as leftClickHandleReaction from './leftClickHandleReaction';
...@@ -71,7 +72,7 @@ describe('onMapLeftClick', () => { ...@@ -71,7 +72,7 @@ describe('onMapLeftClick', () => {
const dispatch = jest.fn(() => ({ const dispatch = jest.fn(() => ({
unwrap: jest.fn().mockResolvedValue(mockBioEntities), 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) => { jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => {
callback(feature, null as unknown as Layer, null as unknown as SimpleGeometry); callback(feature, null as unknown as Layer, null as unknown as SimpleGeometry);
}); });
...@@ -93,7 +94,7 @@ describe('onMapLeftClick', () => { ...@@ -93,7 +94,7 @@ describe('onMapLeftClick', () => {
const dispatch = jest.fn(() => ({ const dispatch = jest.fn(() => ({
unwrap: jest.fn().mockResolvedValue(mockBioEntities), 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) => { jest.spyOn(mapInstance, 'forEachFeatureAtPixel').mockImplementation((_, callback) => {
callback(feature, null as unknown as Layer, null as unknown as SimpleGeometry); callback(feature, null as unknown as Layer, null as unknown as SimpleGeometry);
}); });
......
...@@ -13,6 +13,7 @@ import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/ ...@@ -13,6 +13,7 @@ import { handleFeaturesClick } from '@/components/Map/MapViewer/utils/listeners/
import { resetReactionsData } from '@/redux/reactions/reactions.slice'; import { resetReactionsData } from '@/redux/reactions/reactions.slice';
import { leftClickHandleReaction } from '@/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction'; import { leftClickHandleReaction } from '@/components/Map/MapViewer/MapViewerVector/listeners/mapLeftClick/leftClickHandleReaction';
import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset'; import { handleDataReset } from '@/components/Map/MapViewer/utils/listeners/mapSingleClick/handleDataReset';
import { FEATURE_TYPE } from '@/constants/features';
/* prettier-ignore */ /* prettier-ignore */
export const onMapLeftClick = export const onMapLeftClick =
...@@ -24,13 +25,14 @@ export const onMapLeftClick = ...@@ -24,13 +25,14 @@ export const onMapLeftClick =
dispatch(updateLastClick({ coordinates: point, modelId })); dispatch(updateLastClick({ coordinates: point, modelId }));
let featureAtPixel: FeatureLike | undefined; let featureAtPixel: FeatureLike | undefined;
mapInstance.forEachFeatureAtPixel(pixel, feature => { mapInstance.forEachFeatureAtPixel(pixel, (feature) => {
if(feature.get('id') && ['ALIAS', 'REACTION'].includes(feature.get('type'))) { if(feature.get('id') && [...Object.values(FEATURE_TYPE)].includes(feature.get('type'))) {
featureAtPixel = feature; featureAtPixel = feature;
return true; return true;
} }
return false; return false;
}, {hitTolerance: 20}); }, {hitTolerance: 10});
if(!featureAtPixel) { if(!featureAtPixel) {
if (isResultDrawerOpen) { if (isResultDrawerOpen) {
dispatch(closeDrawer()); dispatch(closeDrawer());
...@@ -42,6 +44,7 @@ export const onMapLeftClick = ...@@ -42,6 +44,7 @@ export const onMapLeftClick =
} }
const { shouldBlockCoordSearch } = handleFeaturesClick([featureAtPixel], dispatch, comments); const { shouldBlockCoordSearch } = handleFeaturesClick([featureAtPixel], dispatch, comments);
if (shouldBlockCoordSearch) { if (shouldBlockCoordSearch) {
return; return;
} }
...@@ -49,9 +52,9 @@ export const onMapLeftClick = ...@@ -49,9 +52,9 @@ export const onMapLeftClick =
dispatch(handleDataReset); dispatch(handleDataReset);
const type = featureAtPixel.get('type'); const type = featureAtPixel.get('type');
if(type === 'ALIAS') { if(type === FEATURE_TYPE.ALIAS) {
await leftClickHandleAlias(dispatch)(featureAtPixel, modelId); await leftClickHandleAlias(dispatch)(featureAtPixel, modelId);
} else if (type === 'REACTION') { } else if (type === FEATURE_TYPE.REACTION) {
await leftClickHandleReaction(dispatch)(featureAtPixel, modelId); await leftClickHandleReaction(dispatch)(featureAtPixel, modelId);
} }
}; };
...@@ -21,6 +21,7 @@ import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shap ...@@ -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 getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle';
import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon'; import getShapePolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getShapePolygon';
import { BioShapesDict, LineTypeDict } from '@/redux/shapes/shapes.types'; import { BioShapesDict, LineTypeDict } from '@/redux/shapes/shapes.types';
import { FEATURE_TYPE } from '@/constants/features';
export type MapElementProps = { export type MapElementProps = {
id: number; id: number;
...@@ -101,7 +102,7 @@ export default class MapElement extends BaseMultiPolygon { ...@@ -101,7 +102,7 @@ export default class MapElement extends BaseMultiPolygon {
modifications = [], modifications = [],
}: MapElementProps) { }: MapElementProps) {
super({ super({
type: 'ALIAS', type: FEATURE_TYPE.ALIAS,
id, id,
x, x,
y, y,
......
...@@ -15,6 +15,7 @@ import { MapInstance } from '@/types/map'; ...@@ -15,6 +15,7 @@ import { MapInstance } from '@/types/map';
import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle'; import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle';
import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex'; import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex';
import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types'; import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types';
import { FEATURE_TYPE } from '@/constants/features';
export interface ReactionProps { export interface ReactionProps {
id: number; id: number;
...@@ -204,7 +205,7 @@ export default class Reaction { ...@@ -204,7 +205,7 @@ export default class Reaction {
style: lineStyle, style: lineStyle,
lineWidth: line.width, lineWidth: line.width,
id: this.id, id: this.id,
type: 'REACTION', type: FEATURE_TYPE.REACTION,
}); });
lineFeature.setStyle(this.getStyle.bind(this)); lineFeature.setStyle(this.getStyle.bind(this));
...@@ -252,7 +253,7 @@ export default class Reaction { ...@@ -252,7 +253,7 @@ export default class Reaction {
style: styles, style: styles,
lineWidth: this.line.width, lineWidth: this.line.width,
id: this.id, id: this.id,
type: 'REACTION', type: FEATURE_TYPE.REACTION,
}); });
squareFeature.setStyle(this.getStyle.bind(this)); squareFeature.setStyle(this.getStyle.bind(this));
return squareFeature; return squareFeature;
...@@ -306,7 +307,7 @@ export default class Reaction { ...@@ -306,7 +307,7 @@ export default class Reaction {
style: circleStyle, style: circleStyle,
lineWidth: 1, lineWidth: 1,
id: this.id, id: this.id,
type: 'REACTION', type: FEATURE_TYPE.REACTION,
}); });
circleFeature.setStyle(this.getStyle.bind(this)); circleFeature.setStyle(this.getStyle.bind(this));
return circleFeature; return circleFeature;
......
...@@ -26,6 +26,7 @@ export const onMapSingleClick = ...@@ -26,6 +26,7 @@ export const onMapSingleClick =
const featuresAtPixel: FeatureLike[] = []; const featuresAtPixel: FeatureLike[] = [];
mapInstance.forEachFeatureAtPixel(pixel, (feature) => featuresAtPixel.push(feature)); mapInstance.forEachFeatureAtPixel(pixel, (feature) => featuresAtPixel.push(feature));
const { shouldBlockCoordSearch } = handleFeaturesClick(featuresAtPixel, dispatch, comments); const { shouldBlockCoordSearch } = handleFeaturesClick(featuresAtPixel, dispatch, comments);
if (shouldBlockCoordSearch) { if (shouldBlockCoordSearch) {
......
...@@ -102,7 +102,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) ...@@ -102,7 +102,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput)
}, [view, handleChangeCenter]); }, [view, handleChangeCenter]);
useEffect(() => { useEffect(() => {
if (!mapInstance || vectorRendering) { if (!mapInstance) {
return; return;
} }
...@@ -110,7 +110,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) ...@@ -110,7 +110,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput)
// eslint-disable-next-line consistent-return // eslint-disable-next-line consistent-return
return () => unByKey(key); return () => unByKey(key);
}, [mapInstance, vectorRendering]); }, [mapInstance]);
useEffect(() => { useEffect(() => {
if (!mapInstance || vectorRendering) { if (!mapInstance || vectorRendering) {
...@@ -126,7 +126,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) ...@@ -126,7 +126,7 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput)
}, [mapInstance, handleMapSingleClick, vectorRendering]); }, [mapInstance, handleMapSingleClick, vectorRendering]);
useEffect(() => { useEffect(() => {
if (!mapInstance || vectorRendering) { if (!mapInstance) {
return; return;
} }
...@@ -143,5 +143,5 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput) ...@@ -143,5 +143,5 @@ export const useOlMapListeners = ({ view, mapInstance }: UseOlMapListenersInput)
// eslint-disable-next-line consistent-return // eslint-disable-next-line consistent-return
return () => mapInstance.getViewport().removeEventListener('contextmenu', rightClickEvent); return () => mapInstance.getViewport().removeEventListener('contextmenu', rightClickEvent);
}, [mapInstance, handleRightClick, vectorRendering]); }, [mapInstance, handleRightClick]);
}; };
...@@ -4,6 +4,8 @@ export const FEATURE_TYPE = { ...@@ -4,6 +4,8 @@ export const FEATURE_TYPE = {
SURFACE_OVERLAY: 'SURFACE_OVERLAY', SURFACE_OVERLAY: 'SURFACE_OVERLAY',
SURFACE_MARKER: 'SURFACE_MARKER', SURFACE_MARKER: 'SURFACE_MARKER',
PIN_ICON_COMMENT: 'PIN_ICON_COMMENT', PIN_ICON_COMMENT: 'PIN_ICON_COMMENT',
ALIAS: 'ALIAS',
REACTION: 'REACTION',
} as const; } as const;
export const PIN_ICON_ANY = [ export const PIN_ICON_ANY = [
...@@ -11,4 +13,5 @@ export const PIN_ICON_ANY = [ ...@@ -11,4 +13,5 @@ export const PIN_ICON_ANY = [
FEATURE_TYPE.PIN_ICON_MARKER, FEATURE_TYPE.PIN_ICON_MARKER,
FEATURE_TYPE.PIN_ICON_COMMENT, FEATURE_TYPE.PIN_ICON_COMMENT,
]; ];
export const SURFACE_ANY = [FEATURE_TYPE.SURFACE_OVERLAY, FEATURE_TYPE.SURFACE_MARKER]; export const SURFACE_ANY = [FEATURE_TYPE.SURFACE_OVERLAY, FEATURE_TYPE.SURFACE_MARKER];
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment