Thursday, 10 May 2018

Announcing: MapGuide Maestro 6.0m9

Here's a new milestone release of MapGuide Maestro. Here's what's new in this release.

mapguide-react-layout support

One of the design goals of mapguide-react-layout viewer was to be highly compatible with existing Web and Flexible layout documents ensuring for the same authoring experience as the existing AJAX and Fusion viewer offerings.

However, the authoring experience in Maestro knows nothing about mapguide-react-layout, so any authoring experience still assumes the use of AJAX or Fusion viewers.

With this release, we have a new preference for specifying the base URL of a mapguide-react-layout installation.


Once this is set, the Web and Flexible Layout editors light up with additional viewer URLs allowing you to load the Web/Flexible Layout with a mapguide-react-layout template of your choice. 



Since the UI for this has changed from a read-only text box to a combo box, once cannot easily select the URL to copy/paste. To workaround this, a convenience "Copy to Clipboard" button is included to easily copy the current viewer URL for pasting elsewhere.

The other authoring experience change is that a new Flexible Layout will no longer include Fusion widgets that are not supported by mapguide-react-layout. These widgets are really esoteric ones, so most authors won't probably notice any differences.

MgTileSeeder improvements

The new MgTileSeeder tool has been improved with the following changes:
  • A new --failed-requests parameter for specifying a log file to log failed requests to
  • A new --max-parallelism parameter for controlling the max degreee of parallelism when sending tile requests
  • New xyz_replay and mapguide_replay commands for re-requesting failed requests from a log file previously logged via the new --failed-requests parameter
Improved OGR Feature Source support

The OGR provider has been the primary recipient of my continued developer attention since the release of MapGuide Open Source 3.1.1 as there are many things in the provider with room for improvement. Given this, it was time to also give the OGR provider equivalent treatment in Maestro, so with this release, feature sources using the OGR provider now has its own specialized editor.



Most of the UI here should be self-explanatory, but the Other Properties section deserves some explanation. This is a future-proof data grid for editing connection properties that may be introduced in future builds/releases of the OGR provider.

Another case where the OGR provider gets better treatment is the support in the SHP feature source editor to convert it across to use the OGR provider. 



This feature was added to improve the SHP story for MapGuide on 64-bit Linux where the current dedicated SHP provider has unresolved 64-bit portability problems making it unusable. However, the OGR provider has no such issues making it a viable alternative FDO provider for SHP files on 64-bit Linux. This conversion feature helps facilitate this transition in an easy manner. However, there's still some glaring problems with the converted OGR feature source, such as the FDO provider using a hard-coded schema name of "OGRSchema". Nothing some python scripting elbow grease can't fix afterwards. Or you can watch this space :)

Other fixes/changes
  • Fix: Rename resource with "update references" checked will disregard overwrite flag
  • Fix: NullReferenceException when ticking a new geometry type and adding a rule to the grid for the first time in Layer Definition editor
  • Fix: MgInvalidRepositoryTypeException when validating layers. Previous workaround was to disable validation on save. With this release you can safely re-enable this if you so choose.
  • Fix: Editing default path in line usage context in Symbol Definition editor does nothing
  • Fix: Cannot browse symbol definiton parameters in any field of the Path editor dialog 
Download 
Project Web Site

Tuesday, 10 April 2018

Some patches and fixes of MapGuide Open Source 3.1.1

Barely a week after releasing MapGuide Open Source 3.1.1, I've added some patches that may be of use for some of you out there.

Firstly, I've uploaded a newer release of Fusion that includes a fix for an issue with Google Maps support discovered after the 3.1.1 release. If you downloaded Fusion with the updated Bing Maps support in the past, this release is packaged in the same fashion: Download, extract and overwrite the existing Fusion installation.

Secondly, for those that use Oracle and have been clamoring for 12c support. I've uploaded experimental King Oracle FDO provider dlls that have been built against the Oracle 12c instant client SDK. These providers have not yet been fully tested against Oracle 12c and has been made available for you to provide any feedback or report any issues regarding 12c support.

If either one of these patches is of interest to you, grab them from the updated 3.1.1 release notes page.

Wednesday, 4 April 2018

Announcing: mg-desktop and MapGuide nuget packages for 3.1.1

It's been so long since putting out the last release of MapGuide that you sometimes forget that there are also supplemental build artifacts that tail off of the main MapGuide build process that need to be released as well!

In our case, that would be new nuget packages for the MapGuide .net API and mg-desktop.

The new mg-desktop binaries are also available as plain zip packages, should the NuGet way of acquiring not work out for you.

Tuesday, 3 April 2018

Announcing: MapGuide Open Source 3.1.1

I am pleased to announce the final release of MapGuide Open Source 3.1.1

The only changes from the Release Candidate are:
  • A fix in the AJAX viewer to prevent clicks in interactive tooltip content from falling through (possibly accidentally triggering map selections as a result).
  • Permission fixes for the windows installer and linux install scripts so that the Fusion QuickPlot widget can work out of the box.
Download/Release Notes

Wednesday, 28 March 2018

Making Immutable.JS objects easier to work with in TypeScript: TypeScript 2.8 edition

TypeScript 2.8 was released today and one of the new touted features is conditional types.

With the introduction of condition types, it was worth revisiting an older post of mine about making immutable.js easier to use in TypeScript and see how one would solve this problem with TypeScript 2.8.

For reference, consider these interfaces:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
interface IGeographicCoordinate {
    lat: number;
    lng: number;
}

interface IPlacemark {
    id: number;
    coordinate: IGeographicCoordinate;
    name: string;
}

At the time of that post (this was before the revolutionary TypeScript 2.0 release), this was the best I could do to work with the immutable.js versions objects that adhered to the shape of the above interfaces.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
type GeographicCoordinateProperties = "lat" | "lng";
type PlacemarkProperties = "id" | "coordinate" | "name";

interface IGeographicCoordinateImmutable {
    get(key: GeographicCoordinateProperties): any;
    get(key: "lat"): number;
    get(key: "lng"): number;
}

interface IPlacemarkImmutable {
    get(key: PlacemarkProperties): any;
    get(key: "id"): number;
    get(key: "coordinate"): IGeographicCoordinateImmutable;
    get(key: "name"): string;
}

Notice we had to manually write "immutable" equivalents of every interface and we didn't have constructs like keyof to auto-deduce all the allowed property names. We also had to manually spell out all the specific return types for each property name due to mapped types not existing yet at that point in time.

With TypeScript 2.8, we can leverage conditional types and features from earlier versions of TypeScript to create this majestic piece of generic and type-safe beauty:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
interface ImmutableObject<T> {
    get<P extends keyof T>(key: P): T[P] extends Array<infer U> ? ImmutableList<U> : T[P] extends object ? ImmutableObject<T[P]> : T[P]; 
}

interface ImmutableList<T> {
    count(): number;
    get(index: number): T extends object ? ImmutableObject<T> : T;
}

// The immutable.js fromJS() API
declare function fromJS<T>(obj: T): ImmutableObject<T>;

So how does this work? To illustrate, lets update our example interfaces to include a 3rd interface


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
interface IGeographicCoordinate {
    lat: number;
    lng: number;
}

interface IPlacemark {
    id: number;
    coordinate: IGeographicCoordinate;
    name: string;
}

interface ISearchResult {
    query: string;
    results: IPlacemark[];
}

Then let's start with the get method of ImmutableObject<T>

The fragment P extends keyof T describes the type placeholder P on this method that is any variable that is a valid member name of type T. Using our above interfaces as an example, keyof IPlacemark is the type equivalent of:

 "id" | "coordinate" | "name"

The type of key parameter of the get method is constrained to any of the member names in T (auto-deduced via the keyof operator), thus you cannot plug in names of members that are not part of T.

The return type T[P] is a mapped type that gives the corresponding type based on the value you put in for the key parameter. If we use IPlacemark as an example:
  • Calling get with "id" will deduce T[P] to the type: number
  • Calling get with "coordinate" will deduce T[P] to the type: IGeographicCoordinate
  • Calling get with "name" will deduce T[P] to the type: string
We then leverage the new conditional types feature to conditionally deduce the appropriate return type based on properties of T[P] that we can ask of through the conditional types feature:
  • If the mapped type is an array (T[P] extends Array) resolve the return type to ImmutableList of the inferred type U. The infer U fragment defines an ad-hoc type placeholder U that will resolve to the item type of the array.
  • Otherwise, if it is an object (T[P] extends object) resolve the return type to ImmutableObject of the mapped type
  • Otherwise, it will resolve the return type to the mapped type.
To illustrate with ISearchResult as an example:
  • Calling get with "query" will deduce a return type of: string
  • Calling get with "results" will deduce a return type of: ImmutableList<IPlacemark>
Now on to the get method of ImmutableList<T>

ImmutableList<T> is a immutable collection wrapper. The get method here simply returns the item of type T at the specified index. Once again we leverage conditional types to ask some questions of the type T to deduce the correct return type.
  • If T is an object (T extends object), resolve the return type to: ImmutableObject<T>, making this mapped type fully recursive all the way down however many levels it needs to go
  • Otherwise T must only be a primitive type, so resolve the return type as-is.
Now how do we know this actually works and is not some abstract piece of theory?

See for yourself on the TypeScript playground (NOTE: If the code fragment doesn't load in the playground, you can copy/paste the code from this gist I've prepared earlier)

No red squiggles! Also, put your mouse over every variable, you will see the type matches the type specified in the respective end-of-line comment.

Hopefully this post has shed some light on how powerful this new conditional types feature of TypeScript 2.8 really is

Tuesday, 27 March 2018

Announcing: MapGuide Open Source 3.1.1 Release Candidate

I am pleased to announce the release candidate of MapGuide Open Source 3.1.1 is now available.

Of the ton of bug fixes and minor enhancements since the 3.1 release, the key changes of note in 3.1.1 are:

Have a gander at the full list of changes for more information.

This is a release candidate, and not the final release as it's been so long since the 3.1 release that I want to make sure our release process is still sound after such a long break between releases. Barring anything of a show-stopping nature, the final release of 3.1.1 will drop one week from now.