Thursday, 27 July 2017

Announcing: mapguide-react-layout 0.9.5

This was originally going to be versioned 0.9.2, but the volume of changes was too big to be a bugfix-level single patch version bump, but at the same time, it was also not enough to warrant a minor version bump, so I decided to go half way with 0.9.5.

Here's what's new in this release.

Toggle-able Layer Transparency

The viewer options UI is now fleshed out to allow you to toggle transparency of:

  • The MapGuide map (and any tiled layer groups)
  • The MapGuide selection overlay
  • External Base Layers
To illustrate this, here's a self-explanatory GIF



This allows one to easily compare the MapGuide map against its base layer backdrops without requiring actual visibility toggling.

And yes, this works even on IE (11, the only version I care to support)

Sprite Icon Support

This release now supports the standard Fusion icon sprite. This will no longer load the individual icons for commands and widgets if it is clear they are referencing the standard icon sprite.


Targeted Command Support

If a command or widget requires execution in a New Window or a specific frame, the viewer will now support it. Note that if a command or widget is set to execute in a New Window, we won't actually spawn a new physical browser window, we'll run it in an iframe inside a BlueprintJS dialog component instead.

Other Changes/Fixes
  • Added support for extension properties for Buffer, FeatureInfo, Query, Search, SelectWithin, Theme.
  • Fixed Fusion MapMessage bar emulation
  • Fixed tooltip queries not being sent with pixel-buffered polygon geometries
  • Fixed zoom requests not snapping the scale to the closest finite list if viewing a tiled map
  • Legend now properly renders layers with multiple geometry styles
  • Fix excessive BlueprintJS toaster components being created and not cleaned up
  • Fix flyout menus requiring double-click to re-open (after clicking a menu item inside the first time)

Friday, 21 July 2017

So ... where's MapGuide Open Source 3.2?

Here's the story, since I gather not everyone reads the mapguide-users mailing list where I mentioned this subject many months ago.

I've decided (many months ago) to skip on making this release.

The differences between 3.1 and (a 3.2 release if I had decided to make one) is so small that it isn't worth investing the build resources on a 3.2 release cycle.

Since I'm skipping on a 3.2 release, it means that we have a good year-long window of solid development time to get some compelling features into the release after it (currently set as 3.3). Some of this development work is already starting to bear fruit.

Now that's not to say there isn't going to be a MapGuide release sometime between now and when 3.3 is out. I still do hope to put out the (hinted previously) patch releases for MGOS 2.6, 3.0 and 3.1 in between, but that requires me rebuilding my build infrastructure first and that is currently taking a back seat to landing some solid features into 3.3 first, so that's where things are at.

And as always. As these features land, you can expect this blog to talk about it.

Sunday, 9 July 2017

React-ing to the need for a modern MapGuide viewer (Part 17): Reason number 5537485 why react was the right choice

An issue cropped up where the legend was not properly rendering a given layer that has multiple geometry styles. This issue was easily reproducible with the Redline widget.

We were expecting to see this after creating a redline layer and drawing some objects.


But we got this instead


Because this legend is a react component, we can inspect it (and the problem layer node) with the React developer tools


Remember the important React motto: The UI is a function of props and state. The HTML content of the LayerNode should be reflective of the props and state given to it. We should've seen something that resembled 3 style icons. But nothing's there.

So let's just check that the layer model for this LayerNode component is indeed a layer with multiple geometry styles


Indeed it is, so that means that the LayerNode component is the culprit. It is not handling the case of multiple geometry styles properly.

As we've already set up our test infrastructure to make it easy to write and run tests, it should be easy to write up an enzyme unit test that shows what we were actually expecting to see when a LayerNode renders a layer that has multiple geometry styles

component.legend.spec.tsx


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import * as React from "react";
import { shallow, mount, render } from "enzyme";
import { MapLayer } from "../src/api/contracts/runtime-map";
import { LayerNode } from "../src/components/legend";
import { ILegendContext } from "../src/components/context";

// Mocks the ILegendContext needed by LayerNode and other legend sub-components
function mockContext(): ILegendContext {
    return {
        getIconMimeType: () => "image/png",
        getStdIcon: (path: string) => path,
        getChildren: (id) => [],
        getCurrentScale: () => this.props.currentScale,
        getTree: () => {},
        getGroupVisibility: (group) => group.ActuallyVisible,
        getLayerVisibility: (layer) => layer.ActuallyVisible,
        setGroupVisibility: () => {},
        setLayerVisibility: () => {},
        getLayerSelectability: (layer) => true,
        setLayerSelectability: () => {},
        getGroupExpanded: (group) => true,
        setGroupExpanded: () => {},
        getLayerExpanded: (layer) => true,
        setLayerExpanded: () => {}
    };
}

describe("components/legend", () => {
    it("renders a multi-geom-style layer with a rule for each geom style", () => {
        const layer: MapLayer = {
            Type: 1,
            Selectable: true,
            LayerDefinition: "Session:841258e8-63f9-11e7-8000-0a002700000f_en_MTI3LjAuMC4x0AFC0AFB0AFA//testing.LayerDefinition",
            Name: "_testing",
            LegendLabel: "testing",
            ObjectId: "abcd12345",
            DisplayInLegend: true,
            ExpandInLegend: true,
            Visible: true,
            ActuallyVisible: true,
            ScaleRange: [
                {
                    MinScale: 0,
                    MaxScale: 10000,
                    FeatureStyle: [
                        {
                            Type: 4,
                            Rule: [
                                {
                                    Icon: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAB1JREFUOI1j/M/A8J+BAsBEieZRA0YNGDVgMBkAAFhtAh6Zl924AAAAAElFTkSuQmCC"
                                }
                            ]
                        },
                        {
                            Type: 4,
                            Rule: [
                                {
                                    Icon: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAACVJREFUOI1jYBgFwwAwMjD8bcAjL8rAwKCNR56LibruGQVDFAAACkEBy4yPOpAAAAAASUVORK5CYII="
                                }
                            ]
                        },
                        {
                            Type: 4,
                            Rule: [
                                {
                                    Icon: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAFhJREFUOI3t0D0OQFAUROHPIwoNS7ZJe5BoKJR+OpVH4jUkTjv3TDI3w6Z2zooNeSSfKNQYIwd3NISH6sFfQLCkFmQJdkVIGlG+44mfLyjMaCPpgO7C7tkBAXgKXzBhmUQAAAAASUVORK5CYII="
                                }
                            ]
                        }
                    ]
                }
            ]
        };
        const wrapper = shallow(<LayerNode layer={layer} />, {
            context: mockContext()
        });
        const rules = wrapper.find("RuleNode");
        expect(rules.length).toBe(3); //One for each geom style
    });
});

Running this in jest confirms our expectations were not met:

Summary of all failing tests
 FAIL  test\component.legend.spec.tsx (6.75s)
  ● components/legend › renders a multi-geom-style layer with a rule for each geom style

    expect(received).toBe(expected)

    Expected value to be (using ===):
      3
    Received:
      0

      at Object. (test/component.legend.spec.tsx:149:30)
      at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
      at process._tickCallback (internal/process/next_tick.js:103:7)


Test Suites: 1 failed, 22 passed, 23 total
Tests:       1 failed, 94 passed, 95 total
Snapshots:   0 total
Time:        14.532s
Ran all test suites.

We expected 3 RuleNode components (one for each geometry style) to have been rendered, but we only got nothing.

A look at the LayerNode rendering shows why. It only considered the first feature style of any layer's scale range.

So once that was fixed, not only does our test pass, but we have visual confirmation that multi-geometry-style layers now render like they did in the Fusion and AJAX viewers.


So the reason for writing this post was just a re-affirmation of my choice for using React to build this viewer.

  • The top-quality developer/debugging experience.
  • The react way of thinking about UIs that allowed me to easily identify the culprit (the LayerNode component)
  • The top-quality testing ecosystem around React (Jest, enzyme) that allowed me to easily write a unit test on this component to confirm and verify my expectations

Friday, 30 June 2017

Announcing: MapGuide Maestro 6.0m7

So you've downloaded the new build of Fusion for your respective version of MapGuide Open Source so you can use the current iteration of Bing Maps as the v6/v7 versions of Bing Maps that Fusion was using will be shut down hours after this post is published.

But this iteration of Bing Maps now requires an API key to use it. So you sign up for an API key in the bing maps portal. Now where you do put this thing?

Well, here's a new release of MapGuide Maestro to help you with this very task among some new features and fixes.

Updated Fusion editor for Bing Maps

The fusion editor has been updated to work against the current iteration of Bing Maps. It has a new field for you to put your Bing Maps API key


When you put in the key and clicked Set API key it will write the API key into the top-level BingMapKey extension element of the Application Definition XML.


Also the available bing layer list has been updated to match what the current iteration provides.


The only difference is that the base layer formerly known as the "Hybrid" base layer has been renamed to "AerialsWithLabels". So if you use the bing hybrid layer you need to replace it with AerialsWithLabels.

This release of Maestro also includes new validation rules for Application Definitions to catch these new Bing Maps issues.


Auto-Configured Spatial Contexts in WMS Configuration Documents

In my adventures of consuming WMS services in MapGuide and building the initial WMS configuration document, I've been consistently observing a pattern like this:


The pattern being, that the names of the discovered spatial contexts usually follow the pattern of "EPSG:XXXX", yet we had to then go and manually fill in the correct coordinate systems one by one, even though the EPSG code is right there in the name!

With this release, we now automatically infer and fill in such coordinate systems for you



Other Changes

  • Fixed inability to preview maps using the local viewer if the map uses a transparent background color
  • Refine the error message when attempting to calculate meters-per-unit in MgCooker and you have no map or tile set selected. Selected is a misnomer, you have to actually check the respective tree node, and the error message has been updated to reflect that.
  • Package updates to DockPanelSuite and Newtonsoft.Json


Download

Using Bing Maps? Here's some new builds of Fusion.

I gave out the warning last month, and just in time before Microsoft pulls the plug on the Bing Maps legacy controls and services on June 30th 2017, here's some new builds of Fusion with support for the current iteration of Bing Maps.

The current iteration of Bing Maps now requires an API key, so if you don't have one you can signup for one at the bing maps portal.

I don't normally put out releases of Fusion like this. I'd normally would just roll it into a new point release of MapGuide Open Source, but I'm currently not in a suitable position at the moment to put out new builds of MapGuide, so this will have to suffice.

Download Fusion for your particular version of MapGuide here:

Fusion for MGOS 2.6

Fusion for MGOS 3.0

Fusion for MGOS 3.1

To install, just extract the zip file contents to the www directory of your MapGuide installation. Be sure to back up or remove the existing fusion directory before doing this.

Now, having not put out a new release of MapGuide for a while, there are also plenty of fixes and minor enhancements made to these respective branches of Fusion since the version bundled with their respective released version of MapGuide. You can check out the changelogs for these respective branches here:

Fusion for MGOS 2.6 Changelog

Fusion for MGOS 3.0 Changelog

Fusion for MGOS 3.1 Changelog

So you've got your Bing Maps API key, where in the Application Definition do you put this key in?

Maybe you want to check out the next post.

Monday, 26 June 2017

Announcing: mapguide-react-layout 0.9.1

This is a small bug fix release that brings updates to key libraries we use:

And includes the following fixes:
This release also has one small enhancement, the viewer now supports a mount option for specifying initial visibility of template elements (Legend, Task Pane, Selection Panel). Currently this will have the most impact when used with the Aqua and Sidebar viewer templates.

For other viewer templates, this new feature won't have much effect yet. For example, take the Slate template.


The very design of this template means that if you wanted all Legend/TaskPane/SelectionPanel to be hidden initially, you just cannot do it. Because they all reside in an accordion, one of these elements has to be visible. The original Fusion templates (at least slate from my memory) could conceivably have Legend/TaskPane/SelectionPanel all hidden because its sidebar was collapsible. That is not the case in this iteration of Slate (and the other ported templates with a sidebar). Having collapsible sidebars in these viewer templates will be a problem a future release will be fixing.

Finally, one thing that was actually possible in the 0.9 release, but I didn't really mention because I wanted to make sure this feature was working before actually announcing it is that Script Commands which is the InvokeScript replacement in mapguide-react-layout can be used with the standard viewer bundle. You no longer need to exclusively use the npm module to have support for Script Commands.

You can see an example of script command registration using the standard viewer bundle here.

Saturday, 3 June 2017

Look ma, no tooltip requests!

So what does tiles of ascii-like content give us?

UTFGrid tiles allows us to pre-render tooltip interaction data. Because we're pre-rendering such data, no mapagent requests are ever made, we can fetch for such tiles just like other map image tiles.

If you remember my previous notes about MapGuide scalability, session repositories add memory and administrative burden/bookkeeping to the running MapGuide Server. If you can get away with not having to create a session repository and keeping it alive, you should. Currently, tooltip requests sadly, require a runtime map (thus, requiring a session be created first and the initial runtime map state to be saved to its session repository).

Because this is pre-rendered tiles of interaction data, paired with map image tiles, it's a very scalable map viewing solution. No CREATERUNTIMEMAP operation was needed to demonstrate this example, nor did we have to create or hit any session-based resources.

Also, because UTFGrids are accessed using the same XYZ tile access scheme, we can re-use the XYZ tile provider in the Tile Set Definition and just specify the new TileFormat of UTFGRID


Accessing UTFGrid tiles is just like accessing XYZ tiles, via the GETTILEIMAGE mapagent operation, but using the UTFGrid Tile Set Definition as the resource id.

The usual mapping suspects of OpenLayers and Leaflet already support UTFGrids, so you can easily take advantage of UTFGrids when it finally lands in MapGuide proper.

Now to make sure UTFGrid support also works on our Linux builds before I draft up that RFC.