Skip to content

Commit 2f68d12

Browse files
authored
Merge pull request #118 from Dataport/fix/marker-draggability-after-map-size-change
fix marker draggability after map size change
2 parents 89690ad + 588efe2 commit 2f68d12

File tree

5 files changed

+77
-83
lines changed

5 files changed

+77
-83
lines changed

packages/plugins/Pins/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## 1.3.1
4+
5+
- Fix: The map dragged along with the pin in some situations, rendering the pin effectively immovable. This has been fixed.
6+
37
## 1.3.0
48

59
- Feature: Pins can now be re-initialized with the `setupInitial` action. This is an advanced feature currently only available when coding clients.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { PolarGetterTree } from '@polar/lib-custom-types'
2+
import { generateSimpleGetters } from '@repositoryname/vuex-generators'
3+
import { PinsGetters, PinsState } from '../types'
4+
import { getInitialState } from './state'
5+
6+
const getters: PolarGetterTree<PinsState, PinsGetters> = {
7+
...generateSimpleGetters(getInitialState()),
8+
toZoomLevel(_, __, ___, rootGetters) {
9+
return (rootGetters.configuration.pins || {}).toZoomLevel || 0
10+
},
11+
atZoomLevel(_, __, ___, rootGetters) {
12+
return (
13+
(rootGetters.configuration.pins || {}).appearOnClick?.atZoomLevel || 0
14+
)
15+
},
16+
}
17+
18+
export default getters

packages/plugins/Pins/src/store/index.ts

Lines changed: 43 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import {
2-
generateSimpleGetters,
3-
generateSimpleMutations,
4-
} from '@repositoryname/vuex-generators'
1+
import { generateSimpleMutations } from '@repositoryname/vuex-generators'
52
import { passesBoundaryCheck } from '@polar/lib-passes-boundary-check'
63
import VectorLayer from 'ol/layer/Vector'
74
import Point from 'ol/geom/Point'
@@ -13,56 +10,52 @@ import { toLonLat, transform } from 'ol/proj'
1310
import { pointerMove } from 'ol/events/condition'
1411
import { Geometry } from 'ol/geom'
1512
import { Coordinate } from 'ol/coordinate'
16-
import { PinsState } from '../types'
13+
import { PinsState, PinsGetters } from '../types'
1714
import getPointCoordinate from '../util/getPointCoordinate'
1815
import { getPinStyle } from '../util/getPinStyle'
19-
20-
const getInitialState = (): PinsState => ({
21-
isActive: false,
22-
transformedCoordinate: [],
23-
latLon: [],
24-
coordinatesAfterDrag: [],
25-
getsDragged: false,
26-
toZoomLevel: 0,
27-
atZoomLevel: 0,
28-
})
16+
import { getInitialState } from './state'
17+
import getters from './getters'
2918

3019
// OK for module creation
3120
// eslint-disable-next-line max-lines-per-function
3221
export const makeStoreModule = () => {
3322
let pinsLayer: VectorLayer<Vector<Geometry>>
34-
3523
const move = new Select({
3624
layers: (l) => l === pinsLayer,
3725
style: null,
3826
condition: pointerMove,
3927
})
4028

41-
const storeModule: PolarModule<PinsState, PinsState> = {
29+
const storeModule: PolarModule<PinsState, PinsGetters> = {
4230
namespaced: true,
4331
state: getInitialState(),
4432
actions: {
45-
/**
46-
* Responsible for setting up the module by adding a watcher. This watcher
47-
* calls removeMarker and showMarker if the store for addressSearch changes
48-
* its value for the chosenAddress.
49-
*/
50-
setupModule({ getters, rootGetters, dispatch, commit }): void {
51-
const { appearOnClick, coordinateSource, movable, toZoomLevel } =
52-
rootGetters.configuration.pins || {}
53-
const interactions = rootGetters.map.getInteractions()
54-
if (toZoomLevel) {
55-
commit('setToZoomLevel', toZoomLevel)
56-
}
57-
if (appearOnClick?.atZoomLevel) {
58-
commit('setAtZoomLevel', appearOnClick.atZoomLevel)
59-
}
60-
const showPin = appearOnClick === undefined ? true : appearOnClick.show
33+
setupModule({ rootGetters, dispatch }): void {
34+
dispatch('setupClickInteraction')
35+
dispatch('setupCoordinateSource')
36+
rootGetters.map.addInteraction(move)
37+
move.on('select', ({ selected }) => {
38+
const { movable } = rootGetters.configuration.pins || {}
39+
if (!movable || movable === 'none') {
40+
document.body.style.cursor = selected.length ? 'not-allowed' : ''
41+
}
42+
})
43+
dispatch('setupInitial')
44+
// without update, map will pan during drag
45+
this.watch(
46+
() => rootGetters.hasSmallWidth || rootGetters.hasSmallHeight,
47+
() => dispatch('updateMarkerDraggability')
48+
)
49+
},
50+
setupClickInteraction({ rootGetters, getters, commit, dispatch }): void {
51+
const { appearOnClick, movable } = rootGetters.configuration.pins || {}
6152
if (typeof movable === 'boolean') {
6253
console.warn(
6354
"@polar/plugin-pins: Using a boolean for the configuration parameter 'movable' has been deprecated and will be removed in the next major release."
6455
)
6556
}
57+
const interactions = rootGetters.map.getInteractions()
58+
const showPin = appearOnClick === undefined ? true : appearOnClick.show
6659
rootGetters.map.on('singleclick', async ({ coordinate }) => {
6760
const isDrawing = interactions.getArray().some(
6861
(interaction) =>
@@ -72,7 +65,6 @@ export const makeStoreModule = () => {
7265
// @ts-expect-error | internal hack to detect it from Draw plugin
7366
interaction._isDeleteSelect
7467
)
75-
7668
if (
7769
((typeof movable === 'boolean' && movable) ||
7870
movable === 'drag' ||
@@ -85,15 +77,17 @@ export const makeStoreModule = () => {
8577
(await dispatch('isCoordinateInBoundaryLayer', coordinate))
8678
) {
8779
const payload = { coordinates: coordinate, clicked: true }
88-
8980
dispatch('removeMarker')
9081
dispatch('showMarker', payload)
9182
commit('setCoordinatesAfterDrag', coordinate)
9283
dispatch('updateCoordinates', coordinate)
9384
}
9485
})
95-
86+
},
87+
setupCoordinateSource({ rootGetters, dispatch }): void {
88+
const { coordinateSource } = rootGetters.configuration.pins || {}
9689
if (coordinateSource) {
90+
// redo marker if source (e.g. from addressSearch) changes
9791
this.watch(
9892
() => rootGetters[coordinateSource],
9993
(feature) => {
@@ -113,16 +107,6 @@ export const makeStoreModule = () => {
113107
{ deep: true }
114108
)
115109
}
116-
117-
rootGetters.map.addInteraction(move)
118-
move.on('select', ({ selected }) => {
119-
const { movable } = rootGetters.configuration.pins || {}
120-
if (!movable || movable === 'none') {
121-
document.body.style.cursor = selected.length ? 'not-allowed' : ''
122-
}
123-
})
124-
125-
dispatch('setupInitial')
126110
},
127111
setupInitial({ rootGetters, getters, dispatch, commit }): void {
128112
const { initial } = rootGetters.configuration.pins as PinsConfiguration
@@ -132,7 +116,6 @@ export const makeStoreModule = () => {
132116
typeof epsg === 'string'
133117
? transform(coordinates, epsg, rootGetters.configuration.epsg)
134118
: coordinates
135-
136119
dispatch('removeMarker')
137120
dispatch('showMarker', {
138121
coordinates: transformedCoordinates,
@@ -190,23 +173,20 @@ export const makeStoreModule = () => {
190173
map.addLayer(pinsLayer)
191174
pinsLayer.setZIndex(100)
192175
commit('setIsActive', true)
193-
const movable = configuration.pins?.movable
194-
if (typeof movable === 'boolean' && movable) {
195-
dispatch('makeMarkerDraggable')
196-
} else if (movable === 'drag') {
197-
dispatch('makeMarkerDraggable')
198-
}
176+
dispatch('updateMarkerDraggability')
199177
}
200178
},
201-
/**
202-
* Makes the mapMarker draggable
203-
*/
204-
makeMarkerDraggable({
205-
rootGetters: { map },
179+
// Decides whether to make the mapMarker draggable and, if so, does so.
180+
updateMarkerDraggability({
181+
rootGetters: { map, configuration },
206182
getters,
207183
commit,
208184
dispatch,
209185
}): void {
186+
const movable = configuration.pins?.movable
187+
if (movable !== 'drag' && movable !== true) {
188+
return
189+
}
210190
const { atZoomLevel } = getters
211191
const previousTranslate = map
212192
.getInteractions()
@@ -221,7 +201,6 @@ export const makeStoreModule = () => {
221201
map.removeInteraction(previousTranslate)
222202
}
223203
map.addInteraction(translate)
224-
225204
translate.on('translatestart', () => {
226205
commit('setGetsDragged', true)
227206
})
@@ -231,7 +210,6 @@ export const makeStoreModule = () => {
231210
const geometry = feat.getGeometry()
232211
// @ts-expect-error | abstract method missing on type, exists in all implementations
233212
let coordinates = geometry?.getCoordinates()
234-
235213
if (!(await dispatch('isCoordinateInBoundaryLayer', coordinates))) {
236214
coordinates = getters.transformedCoordinate
237215
dispatch('removeMarker')
@@ -245,15 +223,10 @@ export const makeStoreModule = () => {
245223
})
246224
})
247225
},
248-
/**
249-
* Removes the mapMarker from the map by removing its vectorLayer
250-
*/
226+
// Removes the mapMarker from the map by removing its vectorLayer
251227
removeMarker({ rootGetters: { map }, commit }): void {
252228
map.getLayers().forEach(function (layer) {
253-
if (
254-
layer !== undefined &&
255-
layer.get('polarInternalId') === 'mapMarkerVectorLayer'
256-
) {
229+
if (layer?.get?.('polarInternalId') === 'mapMarkerVectorLayer') {
257230
map.removeLayer(layer)
258231
}
259232
})
@@ -266,7 +239,6 @@ export const makeStoreModule = () => {
266239
updateCoordinates({ commit, rootGetters }, coordinates: Coordinate) {
267240
const lonLat = toLonLat(coordinates, rootGetters.configuration.epsg)
268241
const latLon = [lonLat[1], lonLat[0]]
269-
270242
commit('setTransformedCoordinate', coordinates)
271243
commit('setLatLon', latLon)
272244
},
@@ -281,13 +253,11 @@ export const makeStoreModule = () => {
281253
): Promise<boolean> {
282254
const { boundaryLayerId, toastAction, boundaryOnError } =
283255
rootGetters.configuration?.pins || {}
284-
285256
const boundaryCheckResult = await passesBoundaryCheck(
286257
rootGetters.map,
287258
boundaryLayerId,
288259
coordinates
289260
)
290-
291261
if (
292262
!boundaryLayerId ||
293263
// if a setup error occurred, client will act as if no boundaryLayerId specified
@@ -297,15 +267,10 @@ export const makeStoreModule = () => {
297267
) {
298268
return true
299269
}
300-
301270
const errorOccurred = typeof boundaryCheckResult === 'symbol'
302-
303271
if (toastAction) {
304272
const toast = errorOccurred
305-
? {
306-
type: 'error',
307-
text: 'plugins.pins.toast.boundaryError',
308-
}
273+
? { type: 'error', text: 'plugins.pins.toast.boundaryError' }
309274
: {
310275
type: 'info',
311276
text: 'plugins.pins.toast.notInBoundary',
@@ -320,16 +285,11 @@ export const makeStoreModule = () => {
320285
: ['Pin position outside of boundary layer:', coordinates]
321286
)
322287
}
323-
324288
return false
325289
},
326290
},
327-
mutations: {
328-
...generateSimpleMutations(getInitialState()),
329-
},
330-
getters: {
331-
...generateSimpleGetters(getInitialState()),
332-
},
291+
mutations: { ...generateSimpleMutations(getInitialState()) },
292+
getters,
333293
}
334294
return storeModule
335295
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { PinsState } from '../types'
2+
3+
export const getInitialState = (): PinsState => ({
4+
isActive: false,
5+
transformedCoordinate: [],
6+
latLon: [],
7+
coordinatesAfterDrag: [],
8+
getsDragged: false,
9+
})

packages/plugins/Pins/src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ export interface PinsState {
44
latLon: number[]
55
coordinatesAfterDrag: number[]
66
getsDragged: boolean
7+
}
8+
9+
export interface PinsGetters extends PinsState {
710
toZoomLevel: number
811
atZoomLevel: number
912
}

0 commit comments

Comments
 (0)