Skip to content

Commit

Permalink
Print support for relative URLs (#1797)
Browse files Browse the repository at this point in the history
Actually print plugin fails when you have a WMS like "/geoserver".
This fixes this behavior using the origin of the browser.
  • Loading branch information
offtherailz authored May 9, 2017
1 parent e34ad2a commit eb9b6e9
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 4 deletions.
1 change: 1 addition & 0 deletions docma-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
"web/client/utils/index.jsdoc",
"web/client/utils/CoordinatesUtils.js",
"web/client/utils/PluginsUtils.js",
"web/client/utils/PrintUtils.js",
"web/client/utils/ShareUtils.js"
],
"jsapi": "web/client/jsapi/MapStore2.js",
Expand Down
76 changes: 73 additions & 3 deletions web/client/utils/PrintUtils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* Copyright 2016, GeoSolutions Sas.
* All rights reserved.
*
Expand All @@ -21,15 +21,55 @@ const assign = require('object-assign');
const getGeomType = function(layer) {
return (layer.features && layer.features[0]) ? layer.features[0].geometry.type : undefined;
};

/**
* Utilities for Print
* @memberof utils
*/
const PrintUtils = {
/**
* Given a static resource, returns the resource's absolute
* URL. Supports file paths with or without origin/protocol.
* @param {string} uri the uri to transform
* @param {string} [origin=window.location.origin] the origin to use
*/
toAbsoluteURL: (uri, origin) => {
// Handle absolute URLs (with protocol-relative prefix)
// Example: //domain.com/file.png
if (uri.search(/^\/\//) !== -1) {
return window.location.protocol + uri;
}

// Handle absolute URLs (with explicit origin)
// Example: http://domain.com/file.png
if (uri.search(/:\/\//) !== -1) {
return uri;
}

// Handle absolute URLs (without explicit origin)
// Example: /file.png
if (uri.search(/^\//) !== -1) {
return (origin || window.location.origin) + uri;
}
},
/**
* Tranform the original URL configuration of the layer into a URL
* usable for the print service.
* @param {string|array} input Original URL
* @return {string} the URL modified as GeoServer requires
*/
normalizeUrl: (input) => {
let result = isArray(input) ? input[0] : input;
if (result.indexOf('?') !== -1) {
result = result.substring(0, result.indexOf('?'));
}
return result;
return PrintUtils.toAbsoluteURL(result);
},
/**
* Find the layout name for the given options.
* The convention is: `PAGE_FORMAT + ("_2_pages_legend"|"_2_pages_legend"|"") + ("_landscape"|"")``
* @param {object} spec the spec with the options
* @return {string} the layout name.
*/
getLayoutName: (spec) => {
let layoutName = [spec.sheet];
if (spec.includeLegend) {
Expand All @@ -44,15 +84,33 @@ const PrintUtils = {
}
return layoutName.join('_');
},
/**
* Gets the print scales allowed from the capabilities of the print service.
* @param {capabilities} capabilities the capabilities of the print service
* @return {array} the scales array
*/
getPrintScales: (capabilities) => {
return capabilities.scales.slice(0).reverse().map((scale) => parseFloat(scale.value)) || [];
},
/**
* Guest the nearest zoom level in the allowed scales
* @param {number} zoom the zoom level
* @param {array} scales the allowed scales
* @param {array} [mapScales=defaultScales] the map scales
* @return {number} the index that best approximates the current map scale
*/
getNearestZoom: (zoom, scales, mapScales = defaultScales) => {
const mapScale = mapScales[zoom];
return scales.reduce((previous, current, index) => {
return current < mapScale ? previous : index;
}, 0);
},
/**
* Get the mapSize for print preview, parsing the layout and limiting the width.
* @param {object} layout the layout object
* @param {number} maxWidth the max width for the mapSize
* @return {object} width and height of a map limited by the maxWidth and with the same ratio of the layout
*/
getMapSize: (layout, maxWidth) => {
if (layout) {
const width = layout.rotation ? layout.map.height : layout.map.width;
Expand All @@ -67,6 +125,11 @@ const PrintUtils = {
height: 100
};
},
/**
* Creates the mapfish print specification from the current configuration
* @param {object} spec the current configuration
* @return {object} the mapfish print configuration to send to the server
*/
getMapfishPrintSpecification: (spec) => {
const projectedCenter = CoordinatesUtils.reproject(spec.center, 'EPSG:4326', spec.projection);
return {
Expand All @@ -92,6 +155,13 @@ const PrintUtils = {
"legends": PrintUtils.getMapfishLayersSpecification(spec.layers, spec, 'legend')
};
},
/**
* Generate the layers (or legend) specification for print.
* @param {array} layers the layers configurations
* @param {spec} spec the print configurations
* @param {string} purpose allowed values: `map|legend`. Tells which spec to generate.
* @return {array} the configuration array for layers (or legend) to send to the print service.
*/
getMapfishLayersSpecification: (layers, spec, purpose) => {
return layers.filter((layer) => PrintUtils.specCreators[layer.type] && PrintUtils.specCreators[layer.type][purpose])
.map((layer) => PrintUtils.specCreators[layer.type][purpose](layer, spec));
Expand Down
72 changes: 71 additions & 1 deletion web/client/utils/__tests__/PrintUtils-test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* Copyright 2016, GeoSolutions Sas.
* All rights reserved.
*
Expand Down Expand Up @@ -83,6 +83,50 @@ const mapFishVectorLayer = {
]
}
};

const testSpec = {
"antiAliasing": true,
"iconSize": 24,
"legendDpi": 96,
"fontFamily": "Verdana",
"fontSize": 8,
"bold": false,
"italic": false,
"resolution": "96",
"name": "",
"description": "",
"sheet": "A2",
"includeLegend": true,
"twoPages": true,
"center": {
"x": 8.930511,
"y": 44.417107,
"crs": "EPSG:4326"
},
"zoom": 11,
"scaleZoom": 3,
"scale": 50000,
"layers": [
{
"group": "background",
"source": "osm",
"name": "mapnik",
"title": "Open Street Map",
"type": "osm",
"visibility": true,
"singleTile": false,
"dimensions": [],
"id": "mapnik__0",
"loading": false,
"loadingError": false
}
],
"projection": "EPSG:900913",
"size": {
"height": 462,
"width": 368
}
};
describe('PrintUtils', () => {

it('custom params are applied to wms layers', () => {
Expand All @@ -99,6 +143,11 @@ describe('PrintUtils', () => {
expect(specs.length).toBe(1);
expect(specs[0].geoJson.features[0].geometry.coordinates[0], mapFishVectorLayer).toBe(mapFishVectorLayer.geoJson.features[0].geometry.coordinates[0]);
});
it('vector layer generation for legend', () => {
const specs = PrintUtils.getMapfishLayersSpecification([layer], {projection: "EPSG:3857"}, 'legend');
expect(specs).toExist();
expect(specs.length).toBe(1);
});
it('vector layer default point style', () => {
const style = PrintUtils.getOlDefaultStyle({features: [{geometry: {type: "Point"}}]});
expect(style).toExist();
Expand All @@ -120,4 +169,25 @@ describe('PrintUtils', () => {
expect(style).toExist();
expect(style.strokeWidth).toBe(3);
});
it('toAbsoluteUrl', () => {
const url = PrintUtils.toAbsoluteURL("/geoserver", "http://localhost:8080");
expect(url).toExist();
expect(url).toBe("http://localhost:8080/geoserver");
expect(PrintUtils.toAbsoluteURL("//someurl/geoserver").indexOf("http")).toBe(0);
});
it('getMapSize', () => {
expect(PrintUtils.getMapSize()).toExist(); // check defaults
expect(PrintUtils.getMapSize({map: {width: 200, height: 200}}, 150).height).toBe(150);
expect(PrintUtils.getMapSize({rotation: true, map: {width: 200, height: 100}}, 200).height).toBe(400);
});
it('getNearestZoom', () => {
const scales = [1000, 1000, 1000000, 10000000];
expect(PrintUtils.getNearestZoom(0, scales)).toBe(0);
});
it('getMapfishPrintSpecification', () => {
const printSpec = PrintUtils.getMapfishPrintSpecification(testSpec);
expect(printSpec).toExist();
expect(printSpec.dpi).toBe(96);
expect(printSpec.layers.length).toBe(1);
});
});

0 comments on commit eb9b6e9

Please sign in to comment.