Tuesday, 18 February 2020

Announcing: mapguide-react-layout 0.13

Here it is. The last release of mapguide-react-layout in its current form. There will be bugfix releases as required but from this release onwards, mapguide-react-layout will be re-branded as something else, and when I figure out what that will be called, you will find out here first!

Here's the highlights of what's new and changed in this release.

Revamped External Layer Manager

Already showcased in previous dev diary entries, the 0.13 release features a revamped external layer manager allowing you to add external layers from file-based or remote WFS/WMS data sources.

The External Layer Manager also has the following new changes since my dev diary posts.

We've tweaked the WMS select tool to now also display the feature in our client-side selection overlay if the WMS GetFeatureInfo response contains geometry data.

You'll also notice that the WMS feature tooltip is styled differently (to distinguish it from the regular feature tooltip) and is also now also close-able (indicated by the clickable [x])

This WMS Query tool is a separate widget, which you can add to your application by including the following widget definition in your Application Definintion and referencing that widget from a toolbar or menu.

<Widget xsi:type="UiWidgetType">
      <Location />
      <Extension />
      <Label>WMS Query</Label>
      <Tooltip>Click to query for features in WMS layers at the point you click</Tooltip>
      <StatusText />

Also for vector layers, you can now style points with image icons through the style editor.

Storybook-based demo

This release is the first one to be showcased in storybook.

Legend Search Filtering

The legend now includes a search box to easily drill down big layer/group structures if you need to rapidly locate a specific layer for toggling. Useful for maps with very large layer/group structures.

Template Changes - Aqua

Thanks to the use of react-rnd, we now finally have resizable dialogs in the Aqua Template!

Template Changes - Other

For all templates, making a map selection will now automatically give focus to the selection panel.

The only exception to this behavior is the sidebar template in mobile view, where rather than automatically flying out a full screen selection panel, we just flash a red indicator over the selection panel toggle to let you know there are selected features to look at.

Removed "Invalid Task Pane" warning

If you work with multi-map configurations, you may have noticed this warning on Task Pane content when switching between maps.

This warning is shown when the passed MAPNAME and SESSION parameters for any loaded URL in the Task Pane does not match the mapname/session of the map you're currently looking at.

Upon further reflection, this warning is overzealous as any Task Pane content that needs to know the actual map name and session id can simply request this information from the viewer APIs in javascript. So this warning has been removed in this release.

SVG icon replacements

Some of the image based icons used by the viewer have been replaced with SVG icon equivalents from the blueprint icon set. This is to enable the possibility of scalable versions of these user interfaces in future releases.


Other Changes

There is a whole load of other fixes and minor improvements which you can find in the full 0.13 release notes in the download link below.


Friday, 7 February 2020

mapguide-react-layout dev diary part 25: There is a general purpose map viewer in there.

As I am tidying up the remaining loose ends for the upcoming 0.13 release, I am going to be giving the project a slight re-branding and revised mission statement after this release.

Because although I've touted the mapguide-react-layout project as a "modern map viewer for MapGuide", the fact of the matter is that only a small portion of the viewer codebase concerns integration with the services provided by MapGuide. The rest of the codebase builds on top of the already solid foundations provided OpenLayers, React and TypeScript that can also work with other web mapping servers and services.

I haven't come up with the specifics yet, but my current thoughts so far are:
  • This project will be renamed to something else (name TBD)
  • The npm package will have a different name. The mapguide-react-layout packages up to 0.13 will still remain on npm, but when the time is right I'll put a deprecation warning on mapguide-react-layout to let you all know about the new package and that you should migrate over to it.
  • MapGuide-specific functionality and features of the viewer will be extracted and separated out. How this separation will be done TBD.
With this move, there is potential for some nice cross-pollination:

  • I could pivot the vscode-map-preview extension to be based on this viewer (and its kitchen sink of built-in functionality) instead of raw OpenLayers strung together with other libraries and re-creating functionality I already take for granted in mapguide-react-layout.
  • I'm parking my static map publishing idea for Maestro because the prospect of having a mapguide-react-layout viewer that need not necessarily have MapGuide Server dependencies is a more attractive proposition to build this idea on top of.
  • There's opportunities for adoption of this viewer in other projects where the hard MapGuide Server dependency would've nixed such opportunities.
So when 0.13 finally drops, that will be the end of mapguide-react-layout in its current form. Not because I'm done with the project, but because it's time for this project to evolve.

Saturday, 1 February 2020

Announcing: vscode-map-preview 0.5.1

This release restricts the display of the new preview UI buttons to only files whose extension we know to be preview-able

The preview buttons now only display for the following file extensions:

  • .geosjon
  • .csv
  • .kml
  • .gml
  • .gpx
  • .igc

Although preview-able content may exist within .txt, .xml and .json files, these formats are too generic to reliably determine ahead of time if this is actually the case (before the preview command is run).

The preview commands can still be run the "old fashioned" way for all other cases.

Wednesday, 29 January 2020

Announcing: vscode-map-preview 0.5.0

Having figured out the technique for seamlessly loading CSV data in mapguide-react-layout, it was clear that there was another OpenLayers-based tool of mine that could benefit as well, hence a new release of the VSCode Map Preview extension.

Here's what's new in this release.

CSV Support


Rather than bombard you with excessive UI prompts for what column is the X coordinate and what column is the Y coordinate, we just check for a list of common column pairs:
  • X/Y
  • Lon/Lat
  • Lng/Lat
  • Long/Lat
  • Longitude/Latitude
  • Easting/Northing
If you want to add more column pairs to search for, there is a new configuration setting to define these pairs.

Preview buttons

Having learned about VSCode menu contribution points, we now finally have buttons in the editor UI to invoke the preview commands!

Custom Projection Support

The extension now supports custom projections allowing you to preview data from projections other than 4326 or 3857. A new configuration property is available to let you define additional custom projections:

To find/register your custom projection, visit epsg.io and get the proj.4 or proj4js definition for your particular EPSG code and add a new entry with this EPSG code and definition as per the above fragment.

Because of this support, the Map Preview (with projection) command now presents a list of known projections instead of requiring you to enter the EPSG code manually

Other Changes

Vertex styling for line/polygon features can now be toggled on/off through a new configuration property.

OpenLayers has also been updated to the latest release (6.1.1) and the extension fixes some corner cases when previewing certain types of KML and GeoJSON content.

mapguide-react-layout dev diary part 24: Adding *even* more than just WMS layers

Since I introduced the revamped external layer manager, the creativity floodgates have opened as I have realised that there are many other things that we could implement on top. So for this post, I'm going to cover even more cool things you can do with the revamped external layer manager.

Revised file-loading process

The UI for loading file-based layers has been tweaked a bit. This means that the first step is picking your file as usual. Note that we've changed the "uploader" UI back to a plain blueprint-styled file input due to bundle size budget constraints that required us to drop react-dropzone

After picking the file, we now give you the ability to specify the projection of this file you just picked, which is now a number picker instead of a dropdown. If you enter an EPSG code not known to the viewer, it will now do an epsg.io lookup and register the found projection on-the-fly before adding the vector layer. The design that drives this UI has been refactored to be more modular and flexible, meaning we now can identify the "type" of the file based on the first successful driver to properly parse the file content.

This refactored design also finally allows us to add ...

CSV Support!

When looking at what types of files to support for external vector layers, CSV seemed like a no-brainer to support. Point data is after-all, commonly defined in CSV files.

The problem with CSV files is that there is no established standard as to how point coordinates are defined. The ideal solution would involve having to attempt peek and introspect the file and build the UI to allow picking the correct point coordinate columns. But this UI would complicate our 2-step UI for file-based layers. How would we know the file we're about to add is indeed a CSV file to then be able to present a UI for the user to pick the columns for point coordinate data?

In the interest of pragmatism and avoid having to answer that hard question altogether, our approach is to look for the most common column labels for point coordinates on the first line of the file we encounter:

  • X/Y
  • Lon/Lat
  • Lng/Lat
  • Longitude/Latitude
  • Easting/Northing
If the file you add has a CSV header and it contains one of the above pairs of columns and the row data referenced by these columns checks out as numbers, it will be accepted as a CSV file.

Added Layers UI Changes

The UI for added layers has been compressed to maximize screen real estate

The opacity slider took up a lot of space (relatively speaking) and toggles a setting I deem to be non-essential to overall functionality, so that slider is now hidden behind a layer options panel (toggled by the new cog icon)

Finally for WMS layers, we now register their source load events so they can contribute to the viewer busy state, meaning that we can properly communicate busy loading state for any added WMS layers.

WMS UI changes

After loading the WMS capabilities URL, for each layer we find you now have the ability to add the WMS layer in as a single-tile or tiled WMS layer.

WFS Support

It seems strange that this external layer manager supports WMS services but does not support the other major W*S service. This was a glaring omission the viewer now addresses. WFS is available as a new layer type:

Added WFS layers are vector layers and assumes the UI of added file-based layers.

Due to viewer bundle size budget constraints the WFS layer UI will only care about layers in the loaded capabilities document that offer GeoJSON output. We could add support for GML2 and GML3 (the formats commonly associated with WFS), but it is not worth blowing up our bundle size to add format drivers for such an esoteric and verbose format.

Select tool support for external layers

So now our revamped external layer manager can add data from a whole assortment of file formats and remote WFS/WMS services. But these data sources are not just for show. They generally have intelligence attached in the form of attribute data for vector data or in the case of WMS layers, APIs to get at such data (WMS GetFeatureInfo), so to put the cherry on top of this revamped external layer manager, the viewer should provide some means of interacting with these layers after adding them.

To this end, our default select tool can now select vector features from external layers and display their attributes in an overlay tooltip.

Vector features take precedence over MapGuide layers. That is to say, the select tool will now try to select vector features first (and display its attributes if found). Only when no vector feature are selected does the viewer proceed with the normal MapGuide layer selection logic.

For WMS layers, we introduce a new active tool dedicated for sending GetFeatureInfo requests against any WMS layers on the current map. The effect is still the same, click on a WMS layer and if we get data back from a WMS GetFeatureInfo response, we'll show the data in a overlay tooltip.

The choice to do WMS "selection" is done through a separate active tool instead of adding on to the default select tool behavior was because adding WMS layer selection logic to the existing select tool would complicate the control flow significantly given that WMS GetFeatureInfo requests are asynchronous and it is hard to maintain a selection priority when dealing with a map that has vector, WMS and MapGuide layers together.

In Closing

The revamped external layer manager is the last major feature for the upcoming 0.13 release. Remaining work before release will primarily be knocking off any remaining bugs and loose ends and also tidying up documentation.

Friday, 10 January 2020

mapguide-react-layout dev diary part 23: Adding more than just WMS layers

In the tail end of part 21, I did say that the next release (0.13) will have some actual new features besides some important under-the-hood updates and for this post we'll be talking about one such feature.

Way back in the 0.11 release, a new component was introduced to allow adding external WMS layers to your current map.

I knew at that point in time that this component had much more room for improvement as the wide array of formats that OpenLayers can support means we can add more than just WMS layers.

For the upcoming 0.13 release we've re-designed and re-built this component to allow adding a wider array of external layers to your map. When you bring up the external layer manager, you are now greeted with a choice of what kind of layer to add:
  1. A local file-based layer
  2. A remote URL-based layer
With a local file-based layer, simply drag a supported file type into the specified drop-zone or click the drop-zone itself to be prompted for a file to load. Once loaded, specify the projection of the data source (default will be EPSG:4326) and the layer will be added to the map.

Several things to note with local file-based layers.

Firstly, the files you pick are not uploaded to any server. The "upload" UI is merely a means to obtain a HTML5 FileReader so we can load the vector features client-side into the map directly.

Secondly, the following file formats are supported in this mode:
  • GeoJSON/TopoJSON
  • KML
  • GPX
  • IGC
Finally, the available projection list in the following dropdown:

Are built-in projections provided by the proj4js library we're using along with any additional projections registered while discovering map definitions or projections registered up-front.

The other mode is remote URL-based layers, which is how you add WMS and WFS layers through this re-designed UI.

UI for adding WFS layers is near identical, so it is not shown here.

Loaded layers can be viewed and managed through the Manage Layers tab, which itself has been re-designed as well.

Every layer in this list:
  • Can have their visibility toggled via the switch
  • Can have their opacity changed via the slider
  • Can have their draw-order (relative to the MapGuide map) changed through the up/down arrow buttons
  • Can be removed later on via the button with the trash icon
For WMS layers that support the LegendURL sub-capability, you can click the info button to show the WMS legend inline.

For added vector layers, you can zoom to the extents of that layer.

And for vector layers that aren't KML files, you can edit the style for these features. For KML files, the style is intrinsically part of the file itself, so the style is effectively "locked in" for such layers and is not editable as a result.

So in closing, the revised external layer manager now supports adding the following external data sources to your current map:
  • Local files: GeoJSON/TopoJSON, KML, GPX, IGC
  • Remote sources: WMS, WFS
We could actually add many more formats, but this revised external layer manager took a significant toll on our production bundle size and adding more formats would've blown up the bundle size to unacceptable levels. This list of formats I have determined to be a "good enough" list given our bundle size constraints.

Thanks to the storybook support, you can also see a live demo of this external layer manager here.

Tuesday, 17 December 2019

mapguide-react-layout dev diary part 22: It's story time!

With the major under-the-hood updates out of the way, it was time to tackle another long-standing item on my todo list. The ability to showcase the key components of mapguide-react-layout in storybook.

From storybook's home page introduction:
Storybook is a user interface development environment and playground for UI components. The tool enables developers to create components independently and showcase components interactively in an isolated development environment.
In the case of mapguide-react-layout, the motivation was to be able to leverage our existing gh-pages branch that currently hosts the project landing page and API docs to also host storybook to showcase the various react components that make up mapguide-react-layout as an [interactive playground / component documentation / pseudo-demo site] on GitHub Pages.

The major challenge to storybook adoption

Storybook has existed for quite some time now, so what was the major blocker to adopting storybook in mapguide-react-layout?

Namely, mapguide-react-layout would require a running MapGuide Server in order to properly showcase the viewer components. While I have no problems pointing storybook to a demo MapGuide Server if there was no other options, it shouldn't need to be a hard requirement. If we can intercept and where possible, mock the expected responses from the MapGuide Server, then it means it would simplify our ability to host storybook on GitHub Pages.

It turns out that it is indeed possible to "mock out" the MapGuide Server dependency:
  • The requests to the mapagent are done through a dedicated class. We just needed a mechanism to register an alternate implementation that can just return canned response data for certain requests.
  • The API for OpenLayers image sources allows us to register a custom "image load function". We can register our own image load function that intercepts the mapagent rendering request URL and using the HTML5 Canvas API, render out an alternate image that simply dumps out the key request parameters of note and export the rendered image out to a data URI to be assigned to the image element that OpenLayer provides.
The end result of this, is that it means we can showcase our map viewer components, but with the MapGuide Server communication bits mocked out and canned response data returned where needed.

We can showcase the map viewer component without dependency to a running MapGuide Server with the canned replacement image still providing useful information about what would happen on a real MapGuide Server.

Our test app def is set up with Stamen and OSM maps so that even though we're rendering a textual placeholder in place of the actual MapGuide-rendered map image, you still have some "real world context" that the Stamen/OSM base layer provides.

We can showcase the legend component by providing a canned CREATERUNTIMEMAP response of the Sheboygan map.

We can showcase our selection panel by providing a canned QUERYMAPFEATURES response.

And so on, and so on.

In closing ...

Storybook for mapguide-react-layout is now live on GitHub Pages. If you ever wanted to see or explore the components that make up this mapguide-react-layout and how they work without the need to spin up your own dev environment and/or a running MapGuide Server, we now have storybook for that.

It will be periodically kept up to date I'm guessing, with each new release in the future.