Skip to content

Feat/mapcontrol plugin#115

Open
BhattaraiSijan wants to merge 23 commits into
developmentfrom
feat/mapcontrol-plugin
Open

Feat/mapcontrol plugin#115
BhattaraiSijan wants to merge 23 commits into
developmentfrom
feat/mapcontrol-plugin

Conversation

@BhattaraiSijan

Copy link
Copy Markdown
Collaborator

Description

Adds MapControl, a floating toolbar over the map with four features. Each can be
enabled/disabled per-mission from the Configure page.

The plugin is bus-only: the React component is MMGIS-independent and a thin wrapper
translates its callbacks into mmgisAPI calls. Map operations that didn't exist yet are
added in core (Map_.js) and exposed over the event bus so any future plugin can reuse them.

Geocode search

On each keystroke we hit the Nominatim API with the URL-encoded query — debounced 300ms,
only firing for queries ≥2 chars, limit=5. No API key or backend (public endpoint). On
selecting a result we reorder Nominatim's bbox ([min_lat,max_lat,min_lon,max_lon]) into
Leaflet order ([[S,W],[N,E]]), fly to it via map:fitBounds, and drop a pin via
map:createLayer.

Basemap switching

Styles come from msv.basemap.styles[] in the mission config (configurable per mission);
if none are defined we fall back to provider defaults, which differ by engine (Leaflet →
raster XYZ tiles, deck.gl → vector style JSON). The active style is matched against
msv.basemap.style. On select we call map:setBasemap, which calls the engine's
setBasemapStyle() — deck.gl swaps the vector style in place; Leaflet rebuilds the tile
layer (handling mapbox://, raw {z}/{x}/{y} templates, and an OSM fallback).

Measure

We subscribe to map:click / map:mousemove, collect two points, and draw the line +
endpoints as a vector layer via map:createLayer. Distance is computed with Turf; the
label is positioned by projecting the segment midpoint via map:latLngToContainerPoint.

Zoom

map:zoomIn / map:zoomOut, clamped to the engine's min/max zoom.

Core changes (beyond the plugin)

New map:* handlers in Map_.js, also exposed as documented methods on mmgisAPI:
setBasemap / getBasemap / getBasemapStyles, zoomIn / zoomOut,
latLngToContainerPoint, and the map:click / map:mousemove event streams.

Two supporting changes were required:

  • Engine adaptersLeafletAdapter gained runtime basemap tile rendering (it had
    none before); DeckGLAdapter gained setStyle and normalized {lat,lng} pointer-event
    emission.
  • Configure page — basemap config now applies to any engine (was deck.gl-only), and
    new missions get a default view.

Dependency on #90 (imapengine-drawing)

Vector overlays (the measure line and the search pin) are drawn via map:createLayer /
map:removeLayer, which are provided by #90. We deliberately do not define our own
overlay channels — an earlier version added map:addOverlay/map:removeOverlay, which
collided by name with #90's (their addOverlay is a different operation: an HTML element
anchored at a point). Using map:createLayer is the operation we actually need and removes
the duplication. Until #90 merges these two features no-op (guarded, no crash); the rest of
the plugin is self-contained.

Known limitation / future work

MapControl is a floating overlay, not a docked panel, so it bypasses the normal panel-mount
path: it self-mounts at bundle load by polling for the map container and rendering into a
position:fixed layer on document.body. This works but should be replaced by a proper
"floating tool" mount path in the Modern layout so overlays don't have to self-mount.

Testing

Manual only:

  • Toggle each of the four features from the Configure page; confirm each appears/hides.
  • Test on both a Leaflet and a deck.gl mission.
  • Basemap switcher: confirm the list populates (it retries until the map registers its
    handlers) and switching restyles the map on both engines.
  • Search: type a place, confirm results, select one, confirm fly-to + pin.
  • Measure: click two points, confirm line + distance label. (Requires feat(core): drawing primitives + overlay + bus surface on IMapEngine #90 for the overlay.)
  • Zoom: confirm in/out and that it stops at min/max.

@BhattaraiSijan BhattaraiSijan requested a review from slesaad June 8, 2026 16:03

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can you use the skill i shared to make this component align with the reusable components pattern?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Refractored to monorepo pattern in this

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

some of the files in this folder can be shared between tools, see current development branch for pattern

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants