Friday, 22 July 2016

React-ing to the need for a modern MapGuide viewer (Part 2): The baseline

I've decided that cataloging my adventure in developing this viewer is enough to warrant its own blog mini-series. So here's part 2 of my adventure. I have no idea how many parts this will take :)

So to continue where we left off, we had a basic map viewer component built on the main pillars of
And it is all written in glorious TypeScript. I've mentioned once on a previous post that writing web frontend code in a language with static typing and a compilation phase (gasp!), with a clean and simple-to-understand component model offered by React is just heavenly! If I could go back in time, I'd have written the Fusion framework in TypeScript, but sadly it didn't exist around 2008 (when Fusion made its debut in MapGuide) and my involvement in the MapGuide project was nowhere near the level it is now.

So before I continue, I should also probably mention what I aim to achieve with this viewer:
  • It will be built on modern, best-of-breed web front-end technologies (React, OpenLayers 3, etc)
  • I will not be shackled with the burden of supporting legacy browsers. This viewer will demand a modern web browser. If one has to use Internet Explorer, it must be IE11
  • It will require MapGuide Open Source 3.0 as the minimal version as this viewer will leverage capabilities present in this particular version onwards.
  • It will at least have some level of feature parity with the AJAX/Fusion viewer offerings, that is to say:
    • It will have a Legend component for toggling layer visibility and comprehending layer symbology/thematics.
    • It will have a Task Pane component that functions as a generic container for content and/or contextual UI
    • It will have a Map Selection component for easy viewing of selected features
    • It will include a stock set of commands, with extension points for developers to add their own.
    • It will have opt-in integration with external base layers (OpenStreetMap, etc), provided your Map Definition meets the requirements (ie. It is in EPSG:3857/WGS84.PseudoMercator).
    • I will not at this time consider any kind of integration with Google Maps as their APIs are not only a constantly moving target, but a TOS minefield I just do not want to wander in at this point in time.
    • I do hope to allow for some level of free-form component layout (ala. templates) so one is not tied to a layout I choose by default.
So with that being said, for this post I want to focus on the last major bullet point: Getting to parity with our current viewer offerings.

So let's introduce our new Legend component.

Implementing this component wasn't difficult, I mainly copypasta'd most of the presentation logic from the existing feature-complete legend used in my various mapguide-rest sample applications.

The difference here is that because this is now a React component, there is zero jQuery or DOM manipulation. Instead, we are just render Group/Layer child components for each layer and group we encounter in our runtime map. It is all pure UI as a function of props and state, and letting React's virtual DOM figure out how to actually update the DOM in the most efficient manner. What this means is that our component model cleanly matches how our layers and groups are conceptually structured.

As for the other components, I'm still working on them (currently focused on the Task Pane) so we'll leave that for another post. But visually speaking, when you put these 3 items together:

It's already starting to look like our existing AJAX viewer!

And before I close out this post, In terms of our current JS bundle size, here's the results of the current weigh-in (using our current Fusion production bundle for comparison).

We've got plenty of breathing room.

Saturday, 16 July 2016

React-ing to the need for a modern MapGuide viewer

A few months ago, I mused about a hypothetical future map viewer for MapGuide.

Having a good solid 6 months of working with React and TypeScript (and dealing with Webpack in anger) under my belt, I felt confident enough to give this idea a crack.

This is what the consumption story looks like so far:

The HTML is just:
  • One script tag (to the webpack bundle, containing the map viewer component and all of its dependencies
  • Making an instance of the entry point class (currently called MapGuide.Application)
  • Mounting the class (using React terminology here) at the desired DOM element with properties to pass into the root React component
And voila! Instant OpenLayers3-powered map viewer. Pretty simple stuff.

When we look at the current React component composition:

It's one root component (I'm intending for this to be something conceptually similar to the ApplicationDefinition/WebLayout for our existing viewers), and a child component that is wrapped by a react-dimensions higher-order component to automatically resize the map viewer according to parent element/window size changes (so we can hook in and call updateSize on the internal ol.Map to prevent image distortion)

The major deviation from my original thoughts is that in the above HTML code, there is no references to React or having to mount the viewer component using the React APIs. I've come to realize that this would be cumbersome as your ultimate entry point will always be HTML/JavaScript, way outside the zone of React/TypeScript/(T|J)SX, and although this is a "component", our final bundle is ultimately more an application instead of a library. So having a wrapper (which is what MapGuide.Application does) to do all of this leg work simplifies the whole setup process.

That's not to say we can't componentize this map viewer (as a library/package you can npm install), but my primary goal is to have an experience similar to our existing viewer offerings, which are applications whose features and behaviour is driven by configuration files. So in that respect, including a script tag and writing some JavaScript to point to your configuration and kickstart the application is much more easier to comprehend than installing node, npm, Webpack and messing with frontend development stacks.

So far so good. We're just beginning to scratch the surface.

Friday, 24 June 2016

Let's introduce the other major player

My plans for the VSCode map extension now extend beyond just OpenLayers

At this point there are some small oddities:

  • The timeline button SVG has broken hrefs. You can see it from the missing play/pause/rewind graphics.
  • The Cesium InfoBox doesn't work.
This is probably due to a combination of:
  • Running cesium from the local file system
  • The VSCode/Electron webview or Cesium itself imposing sandboxing restrictions that breaks the InfoBox
Still, for the purposes of being able to quick and easily preview CZML content, this is a very nice starting point.

Friday, 17 June 2016

Announcing: vscode-map-preview 0.4.0

Today I pushed out a new version (0.4.0) of the vscode-map-preview extension. You might have already gotten a prompt from Visual Studio Code to auto-update to this version.

Here's some new features in this version.

Configuration Options

This version adds a bucket-load of configuration options around:
  • Controlling the style of vector features in your preview layer
  • Controlling the style of selected features in your preview layer
  • Controlling the display of the mouse coordinate tracker
  • Controlling the default base layer to use
Once saved to your user settings, these updated settings take effect on the next preview

Preview (with specific projection)

When previewing a file format, the source project can generally be inferred. For example, KML will always be EPSG:4326, for GeoJSON it should figure it out if you have a crs property on there.

But then you have formats like Well-Known Text (WKT), which we can render a preview of, but without proper contextual information such as projection, the data may not be placed where you expect it to be.

For example if we preview WKT as-is:

Because there is no projection context in the data itself, the coordinates are assumed to already be in EPSG:3857, and means the point lies just off the shores of Null Island, which in actuality, the above coordinates are actually supposed to be EPSG:4326 and is supposed to be the central business district of Melbourne, Australia.

To fix this, we need a way to declare that the data we're previewing is actually of a specific projection, which is what the new Map Preview (with projection) command gives us. It's just like the regular Map Preview command, but provides an input prompt for entering the proper EPSG code for this data.

Which will then be used as the projection of the data about to be previewed, ensuring the data is placed at the right location.

As an aside, you can put away that SQL Server Management Studio. VSCode with this extension is way more quicker and lightweight way for easy WKT visualization.

One caveat is that for this new command the only supported projections are:

  • EPSG:4326
  • EPSG:3857
I'll need to add custom projection support in order to be able to add support for more projections beyond the above two projections.

Other Changes

This version includes fixes to allow for subsequent map previews to work better and fixes various CSS issue with the map preview.

If you haven't already, check out and install the extension on the Visual Studio marketplace.

Wednesday, 8 June 2016

Introducing: Map Preview extension for Visual Studio Code

From an idea, to an MVP, to now a published extension on the Visual Studio Marketplace

I am proud to announce the availability of the Map Preview extension for Visual Studio Code

Just to recap for those who don't know, this extension allows you to view any plain-text based geospatial data file or content as vector features on an interactive map (powered by OpenLayers), allowing for quick and easy visualization of plain-text geographic content without firing up a dedicated GIS application to view it or pasting the content into a GitHub gist.

All rendered features are selectable on the map and any useful attribute information is displayed as a popup. The map also provides plenty of available base layers for giving your preview data a real-world contextual backdrop.

The initial release supports formats that are supported by OpenLayers, which is currently:
If your document content checks out as any of the above formats, it can be previewed on a map with this extension.

You can install this extension with the following command:

ext install vscode-map-preview

The source code for this extension is available on my GitHub repo

Feel free to send feedback, pull requests, etc, etc.

Thursday, 2 June 2016

Because sometimes making a gist on github is just too tedious

It started from a conversation today at work.

"You know how you can preview markdown files as HTML in Visual Studio Code?"
"What if there was an extension that could do this previewing as well, but with non-binary geospatial data files like GeoJSON? So you don't have to ... you know ... go to github, make a gist, paste your GeoJSON and preview?"
"That would be awesome!"

So once I got home, I did some research to answer some questions that will test whether this idea is feasible:

That confidence boosting set of findings gave me enough motivation to fire up VSCode, yo generate a new TypeScript VSCode extension project, wait for npm to install 50 bajillion packages and set out to hack out an MVP extension for VSCode.

2 and a half hours later ...

I love it when you have an idea, the idea shows feasibility after some encouraging results from research and after some hacking around, you reach a point like the above gif that tells you ... yes this idea definitely has some legs and you should keep on going!

Friday, 27 May 2016

Announcing: MapGuide Open Source 3.1 Beta 1

After several months of messing with vagrant for a more streamlined build pipeline and clearing some last-minute roadblocks, I am happy to finally announce the availability of the 1st beta release of MapGuide Open Source 3.1.

In terms of new features, well ... 3.1 can mostly be considered a "bugfix" release. The major features I had hoped to get implemented before this release cycle did not materialize in time, so I'll spare you the usual showcase series of blog posts every time we do a new major release, because you can fit it all in this one post.

New Layer Definition Cache

When MapGuide renders maps, we have to fetch Layer Definition documents from the repository to know how to render and style feature data. Until now, those documents aren't being cached, so we have to fetch the same Layer Definition documents over and over every time MapGuide renders a map image.

3.1 introduces a new server-side Layer Definition cache so we can avoid repeated fetching of Layer Definitions from the repository (and converting the XML to its object-oriented form) every time we render maps. For maps with a very large layer count, some noticeable gains in rendering performance should be noticeable.

Updated Web Tier Components

MapGuide Open Source 3.1 Beta 1 includes the following updated Web Tier components.

  • Apache HTTPD 2.4.18
  • PHP 5.5.33
  • Tomcat 7.0.68

Linux support

The Ubuntu build of MapGuide Open Source 3.1 Beta 1 now supports Ubuntu 14.04 LTS.

The Linux builds in general have a new and improved service control script for:

  • Restarting the mgserver daemon
  • Checking the running status of the mgserver daemon
  • Extra warnings when attempting to start an already started mgserver daemon or stopping an already stopped mgserver daemon
Many thanks to Gabriele Monfardini for providing this new service control script.

Like 3.0, the 64-bit Linux builds should still be considered experimental/preview for 3.1 and should still only be used for testing and feedback. Use in production at your own risk.


Fusion has some important and long overdue fixes for Google Maps support and various widgets

For more information, consult the release notes in the link below.