Skip to content

Layer Manager: add "Share layer to external services" to the layer menu #159

Description

@CarsonDavis

Layer Manager: add "Share layer to external services" to the layer menu

Motivation

Today there's no way to take a layer you're looking at in MMGIS and view it in another GIS tool (QGIS, ArcGIS, or any standards-friendly client). If a science team has tuned a layer — picked a colormap, set the color scale min/max, chosen a time — that styled view lives only inside MMGIS. To reproduce it elsewhere, someone has to hunt down the underlying service URL by hand and manually reconstruct the colormap, rescale, and time parameters, which is tedious and error-prone. The result is that MMGIS layers are effectively trapped in MMGIS.

We want a one-click way to copy a layer's URL out of MMGIS and paste it straight into another GIS tool, reproducing the same layer — same styling, same moment in time — that you see on the map right now.

How it should work

  • Each layer in the Layer Manager has a three-dots (overflow) menu. Add a "Share to external services" option to that menu.
  • Clicking it surfaces a ready-to-copy URL for that layer, with a copy-to-clipboard affordance. The user copies it and pastes it into QGIS, ArcGIS, or another GIS client, and the layer shows up looking the way it did in MMGIS.
  • The URL form adapts to the layer's underlying service type:
    • XYZ tile layers → an XYZ tile-template URL. The {z}/{x}/{y} tile placeholders stay intact (GIS clients need those), but everything else is resolved — the active colormap, the current color-scale min/max, the selected time, and the full service/base URL are all baked in.
    • WMTS layers → a WMTS link.
    • WMS layers → a WMS link.
  • Styling is captured from the current on-screen state, not just the layer's saved defaults: if the user has changed the colormap or color-scale min/max, the shared URL reflects what they're currently looking at.
  • Time is baked in as a snapshot. For time-enabled layers, the currently-selected time is resolved into a fixed value in the URL so the external tool shows that exact moment. (No live/dynamic time parameter — most desktop GIS clients wouldn't fill it in anyway.)
  • The pasted URL should "just work" — it's the fully-resolved address MMGIS itself uses to render the layer, not a template full of unfilled variables the user has to fix by hand.

Done when

  • The Layer Manager three-dots menu shows a "Share to external services" option for tile-based layers.
  • Choosing it presents a copyable URL with a clear copy action.
  • For an XYZ tile layer, the copied URL keeps {z}/{x}/{y} but has the colormap, color-scale min/max, time, and base/service URL all resolved into it.
  • For a WMTS layer the URL is a usable WMTS link; for a WMS layer, a usable WMS link.
  • If the user changes the colormap or rescale min/max in MMGIS and then shares, the new values appear in the URL.
  • For a time-enabled layer, the currently-selected time is present in the URL as a fixed value (snapshot), not an unresolved placeholder.
  • Pasting the resulting URL into QGIS (and verified against at least one other generic GIS client / ArcGIS) renders the layer matching what's shown in MMGIS.
  • A layer type that can't be meaningfully shared this way doesn't offer a broken/empty URL (the option is hidden or clearly unavailable).

Out of scope

  • Vector / GeoJSON (geodatasets) layers — sharing those as a data download or feature URL is a separate concern; this issue is tile-based layers only.
  • Offering a live/dynamic time parameter, or a UI toggle between snapshot and dynamic time.
  • Any server-side proxy, short-link service, or authentication/token handling for external access — this shares the URL as-is.
  • Building a general "share whole map / share view" feature; this is per-layer.
Draft implementation plan — written as of 42b9e0a on 2026-06-18. Rough guide; re-verify against latest code.

Current behavior

  • The three-dots menu lives in the modern Layer Manager, not the legacy Layers tool. The kebab button is rendered in src/essence/Tools/LayerManager/lib/geo/LayerLegend/LayerLegend.tsx (~lines 176–181) and is currently a placeholder with no click handler and no menu items — a clean insertion point. Menu/handler wiring conventions for this component are in src/essence/Tools/LayerManager/adapters/handlers.ts.
  • Layer config is read via the MMGIS API (L_.layers.data[layerName]); the raw configured url carries scheme prefixes (COG:, stac-collection:, titiler-url:, geodatasets:) and template variables.
  • URL resolution already exists and is the thing to surface:
    • Tile/COG layers resolve per-tile in src/essence/Basics/Layers_/leaflet-tilelayer-middleware.js (getTileUrl(), ~21–105): time placeholders replaced (~67–82), STAC/COG datetime injected (~29–40), COG render params applied (~48).
    • COG/TiTiler params merged in src/essence/Basics/Layers_/cogUrlUtils.ts (applyCogFieldsToUrl(), ~33–60): colormap_name (~47), rescale=<min>,<max> (~52), expression, resampling. Uses currentCogMin/Max (runtime) over cogMin/Max (config).
    • Vector layers resolve in src/essence/Basics/Layers_/LayerCapturer.js (~15–72) — out of scope here but shares the time-substitution logic.
  • Current vs default styling state for the panel is built in src/essence/Tools/LayerManager/adapters/buildLayerLegendData.ts (~67–92): currentCogColormap, currentCogMin/Max, titilerUrl. Runtime updates flow through handlers.ts setColormap() / setRescale().
  • Time substitution: per-layer time config (enabled, type, format, start/end); tags {starttime}/{endtime}/{time}/{customtime.N} substituted in both the tile middleware (~67–82) and LayerCapturer; global state in src/essence/Basics/TimeControl_/TimeControl.js (~270–300).
  • Existing export precedent (legacy tool, different component) for reference only: src/essence/Tools/Layers/LayersTool.js (~570–651) — GeoJSON/KML/SHP export and raster downloadURL links. There is no existing "copy URL"/"share link" anywhere; this is greenfield.

Where the change lands & rough plan

  1. Add a "Share to external services" item to the kebab menu in LayerLegend.tsx; gate visibility to tile-based layer types.
  2. Add a builder that, given a layer + current panel state, produces the external URL by layer type:
    • XYZ: take the resolved tile URL but preserve {z}/{x}/{y} while substituting in colormap (colormap_name), rescale (currentCogMin/Max), resolved current time, and the full base/service URL. Reuse applyCogFieldsToUrl() and the time-substitution logic rather than re-deriving them.
    • WMTS / WMS: emit the appropriate service link form for those layer types.
  3. Pull styling from the current/runtime values (currentCogColormap, currentCogMin/Max) so on-screen changes are reflected, falling back to config defaults.
  4. Resolve the current time to a fixed value (snapshot) using the same formatting the middleware uses, instead of leaving {starttime}/{endtime} tags.
  5. Present the URL in a small dialog/popover with a copy-to-clipboard button.

⚠️ Gotcha: the tile-fetch path resolves {z}/{x}/{y} and the styling/time tags together at request time. For sharing you must resolve everything except {z}/{x}/{y}. Don't just grab a fetched tile URL (those have concrete tile coords) and don't reuse the raw config URL (those have unresolved colormap/rescale/time). The share URL is a third form: tile placeholders in, everything else out.

References

  • src/essence/Tools/LayerManager/lib/geo/LayerLegend/LayerLegend.tsx (~176–181) — kebab menu
  • src/essence/Tools/LayerManager/adapters/handlers.ts — menu/handler wiring conventions
  • src/essence/Basics/Layers_/cogUrlUtils.ts (applyCogFieldsToUrl, ~33–60) — colormap/rescale params
  • src/essence/Basics/Layers_/leaflet-tilelayer-middleware.js (getTileUrl, ~21–105) — URL + time resolution
  • src/essence/Tools/LayerManager/adapters/buildLayerLegendData.ts (~67–92) — current vs default styling state
  • src/essence/Basics/TimeControl_/TimeControl.js (~270–300) — global time state

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions