Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions jest.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default {
projects: [{
displayName: 'unit-tests',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
setupFilesAfterEnv: ['jest-expect-message', '<rootDir>/jest.setup.js'],
testMatch: [
'<rootDir>/src/**/*.test.[jt]s?(x)',
'<rootDir>/plugins/**/*.test.[jt]s?(x)',
Expand All @@ -18,9 +18,15 @@ export default {
testPathIgnorePatterns: ['<rootDir>/src/test-utils.js'],
coveragePathIgnorePatterns: [
'<rootDir>/src/test-utils.js',
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this - so I could see what isn't covered in draw-es. and then added it back in

But I left it as a list of specific folders, so it's easier to comment one out while the tests are being added

'<rootDir>/plugins/beta/',
'<rootDir>/providers/beta/'
'<rootDir>/plugins/beta/datasets/',
'<rootDir>/providers/beta/',
'<rootDir>/plugins/beta/draw-es',
'<rootDir>/plugins/beta/draw-ml',
'<rootDir>/plugins/beta/frame',
'<rootDir>/plugins/beta/map-styles',
'<rootDir>/plugins/beta/scale-bar',
'<rootDir>/plugins/beta/use-location'
],
transformIgnorePatterns: []
}]
}
}
8 changes: 8 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
"geodesy": "^2.4.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^30.0.4",
"jest-expect-message": "^1.1.3",
"likec4": "^1.50.0",
"mapbox-gl-snap": "^1.1.9",
"mini-css-extract-plugin": "^2.9.2",
Expand Down
72 changes: 52 additions & 20 deletions plugins/beta/draw-es/src/events.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as simplifyOperator from "@arcgis/core/geometry/operators/simplifyOperator.js"
import * as simplifyOperator from '@arcgis/core/geometry/operators/simplifyOperator.js'
import { createGraphic, createSymbol, graphicToGeoJSON } from './graphic.js'

const MODE_CHANGE_DELAY = 50

export function attachEvents({ pluginState, mapProvider, events, eventBus, buttonConfig, mapColorScheme }) {
export function attachEvents ({ pluginState, mapProvider, events, eventBus, buttonConfig, mapColorScheme }) {
const { view, sketchViewModel, sketchLayer, emptySketchLayer } = mapProvider

if (!sketchViewModel) {
Expand All @@ -12,36 +12,36 @@ export function attachEvents({ pluginState, mapProvider, events, eventBus, butto

const { drawDone, drawCancel } = buttonConfig
const { dispatch, mode, feature } = pluginState

// Re-colour graphics when map style changes
const reColour = async () => {
const activeGraphicId = pluginState.feature?.properties?.id
let activeGraphic = null
const isCreating = sketchViewModel.state === 'active' && !activeGraphicId

// Cancel and wait, but only if we're in update mode (not create mode)
if (sketchViewModel.state === 'active' && activeGraphicId) {
sketchViewModel.cancel()
await new Promise(resolve => setTimeout(resolve, MODE_CHANGE_DELAY))
}

// Update the default symbol for new polygons
sketchViewModel.polygonSymbol = createSymbol(mapColorScheme)

// Update existing graphics
sketchLayer?.graphics.items.forEach(graphic => {
const newGraphic = createGraphic(
graphic.attributes.id,
graphic.geometry.rings,
graphic.attributes.id,
graphic.geometry.rings,
mapColorScheme
)
graphic.symbol = newGraphic.symbol

if (activeGraphicId === graphic.attributes.id) {
activeGraphic = graphic
}
})

// Re-enter update mode only if we were editing (not creating)
if (activeGraphic && !isCreating && sketchViewModel.layer === sketchLayer) {
try {
Expand All @@ -68,10 +68,19 @@ export function attachEvents({ pluginState, mapProvider, events, eventBus, butto
// Event handlers
const handleMapStyleChange = () => reColour()

const onGraphicChanged = (graphic) => {
if (!graphic) {
return
}
const tempFeature = graphicToGeoJSON(graphic)
eventBus.emit('draw:updated', tempFeature)
dispatch({ type: 'SET_FEATURE', payload: { tempFeature } })
}

const handleSketchUpdate = (e) => {
const toolInfoType = e.toolEventInfo?.type
const graphic = e.graphics[0]

// Prevent polygon move
if (toolInfoType === 'move-start') {
sketchViewModel.cancel()
Expand All @@ -87,10 +96,8 @@ export function attachEvents({ pluginState, mapProvider, events, eventBus, butto
}

// Emit event on update
if (toolInfoType === 'reshape-stop') {
const tempFeature = graphicToGeoJSON(graphic)
eventBus.emit('draw:updated', tempFeature)
dispatch({ type: 'SET_FEATURE', payload: { tempFeature }})
if (toolInfoType === 'reshape-stop' || toolInfoType === 'vertex-remove') {
onGraphicChanged(graphic)
}
}

Expand All @@ -108,17 +115,38 @@ export function attachEvents({ pluginState, mapProvider, events, eventBus, butto
updateGraphic()
}

const handleCreate = async (event) => {
const { toolEventInfo } = event
const graphic = event?.graphic
if (graphic && toolEventInfo?.type === 'vertex-add') {
const rings = graphic.geometry?.rings
// rings.length is > 1 occurs when the shape becomes complex (ie self intersects)
// setTimeout is required to cause the undo to be called after handleCreate completes
// otherwise the previous change, rather than this one, is undone
if (rings?.length > 1) {
setTimeout(() => sketchViewModel.undo(), 0)
} else if (rings?.[0]?.length > 3) {
onGraphicChanged(graphic) // emit a graphic update on draw, once the graphic is 2D
}
}
}

const handleUndo = async (event) => {
const graphic = event?.graphics?.[0]
onGraphicChanged(graphic)
}

const handleDone = () => {
sketchViewModel.cancel()
sketchViewModel.layer = emptySketchLayer
dispatch({ type: 'SET_MODE', payload: null })
dispatch({ type: 'SET_FEATURE', payload: { feature: null, tempFeature: null }})
dispatch({ type: 'SET_FEATURE', payload: { feature: null, tempFeature: null } })
eventBus.emit('draw:done', { newFeature: pluginState.tempFeature })
}

const handleCancel = () => {
sketchViewModel.cancel()

// Clear all graphics
sketchLayer.removeAll()

Expand All @@ -143,10 +171,12 @@ export function attachEvents({ pluginState, mapProvider, events, eventBus, butto
eventBus.on(events.MAP_STYLE_CHANGE, handleMapStyleChange)
const sketchUpdateHandler = sketchViewModel.on('update', handleSketchUpdate)
const viewClickHandler = view.on('click', handleViewClick)

const createHandler = sketchViewModel.on('create', handleCreate)
const undoHandler = sketchViewModel.on('undo', handleUndo)

const prevDoneClick = drawDone.onClick
const prevCancelClick = drawCancel.onClick

drawDone.onClick = handleDone
drawCancel.onClick = handleCancel

Expand All @@ -155,7 +185,9 @@ export function attachEvents({ pluginState, mapProvider, events, eventBus, butto
eventBus.off(events.MAP_STYLE_CHANGE, handleMapStyleChange)
sketchUpdateHandler.remove()
viewClickHandler.remove()
createHandler.remove()
undoHandler.remove()
drawDone.onClick = prevDoneClick
drawCancel.onClick = prevCancelClick
}
}
}
Loading
Loading