Skip to content

Commit

Permalink
fix: revise print-legend and new utility file, adapt legendmaker
Browse files Browse the repository at this point in the history
  • Loading branch information
Grammostola committed Feb 26, 2024
1 parent d7078db commit 944dc10
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 155 deletions.
102 changes: 16 additions & 86 deletions src/controls/print/print-legend.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ImageArcGISRest, ImageWMS } from 'ol/source';
import { Component } from '../../ui';
import { isHidden, renderSvgIcon } from '../../utils/legendmaker';
import ImageLayerLegendRules from '../../utils/jsonlegends';
import ImageLayerLegendRules, { getSourceUrl } from '../../utils/imagelayerlegendutils';

/**
* More information: https://developers.arcgis.com/rest/services-reference/enterprise/legend-map-service-.htm
Expand Down Expand Up @@ -36,79 +35,6 @@ const LayerRow = function LayerRow(options) {
viewer
} = options;

/**
* @param {Layer} aLayer
* @returns {string|null}
*/
const getOneUrl = (aLayer) => {
const source = aLayer.getSource();
if ((source instanceof ImageWMS || source instanceof ImageArcGISRest) && typeof source.getUrl === 'function') {
return source.getUrl();
} else if (typeof source.getUrls === 'function') {
return source.getUrls()[0];
}
return null;
};

/**
* Returns the URL to the WMS legend in the specified format
*
* @param {Layer} aLayer
* @param {"image/png"|"application/json"} format
* @returns {string|null}
*/
/* const getWMSLegendUrl = (aLayer, format) => {
const url = getOneUrl(aLayer);
const layerName = aLayer.get('name');
const style = viewer.getStyle(aLayer.get('styleName'));
if (style && style[0] && style[0][0] && style[0][0].icon) {
if (style[0][0].icon.src.includes('?')) {
return `${style[0][0].icon.src}&format=${format}`;
}
return `${style[0][0].icon.src}?format=${format}`;
}
return `${url}?SERVICE=WMS&layer=${layerName}&format=${format}&version=1.1.1&request=getLegendGraphic&scale=401&legend_options=dpi:300`;
}; */

/**
* Returns the JSON-encoded legend from the ArcGIS Legend Map Service
*
* More information: https://developers.arcgis.com/rest/services-reference/enterprise/legend-map-service-.htm
*
* @param {Layer} aLayer
* @param {number} dpi
* @returns {Promise<ArcGISLegendResponse>}
*/
/* const getAGSLegendJSON = async (aLayer, dpi = 150) => {
// rewrite the URL if needed
const mapServerUrl = getOneUrl(aLayer).replace(/\/arcgis(\/rest)?\/services\/([^/]+\/[^/]+)\/MapServer\/WMSServer/, '/arcgis/rest/services/$2/MapServer');
const url = `${mapServerUrl}/legend?f=json&dpi=${dpi}`;
try {
const response = await fetch(url);
return await response.json();
} catch (e) {
console.warn(e);
return null;
}
}; */

/**
* @param {string|null} url
* @returns {Promise<null|any>}
*/
/* const getLegendGraphicJSON = async (url) => {
try {
if (!url) {
return null;
}
const response = await fetch(url);
return await response.json();
} catch (e) {
console.warn(e);
return null;
}
}; */

/**
* @param {string} title
* @param {string[]} children
Expand Down Expand Up @@ -188,13 +114,11 @@ const LayerRow = function LayerRow(options) {
* @param {string} title
* @returns {Promise<string>}
*/
const getWMSJSONContent = async (title) => {
// onst getLegendGraphicUrl = getWMSLegendUrl(layer, 'image/png');
const getWMSJSONContent = async (title, serverVendor) => {
const maxResolution = viewer.getResolutions()[viewer.getResolutions().length - 1];
const getLegendGraphicUrl = layer.getSource().getLegendUrl(maxResolution, {
legend_options: 'dpi:300'
legend_options: 'dpi:150'
});
// const json = await getLegendGraphicJSON(getWMSLegendUrl(layer, 'application/json'));
const rules = await ImageLayerLegendRules({
layer,
viewer
Expand All @@ -215,9 +139,14 @@ const LayerRow = function LayerRow(options) {
}

const listItems = rules.map((rule, index) => {
const ruleImageUrl = `${getLegendGraphicUrl}&rule=${rule.name}`;
let ruleImageSource;
if (serverVendor === 'qgis') {
ruleImageSource = `data:image/png;base64,${rule.icon}`;
} else {
ruleImageSource = `${getLegendGraphicUrl}&rule=${rule.name}`;
}
const rowTitle = rule.title ? rule.title : index + 1;
return getListItem(rowTitle, ruleImageUrl, true);
return getListItem(rowTitle, ruleImageSource, true);
});
return getTitleWithChildren(title, listItems);
};
Expand All @@ -230,13 +159,11 @@ const LayerRow = function LayerRow(options) {
* @returns {Promise<string>}
*/
const getAGSJSONContent = async (title, id) => {
// const json = await getAGSLegendJSON(layer);
// const layersDetails = json.layers;
const layersDetails = await ImageLayerLegendRules({
layer,
viewer,
legendOpts: {
dpi: 200
dpi: 150
}
});

Expand All @@ -261,10 +188,13 @@ const LayerRow = function LayerRow(options) {
} else {
content = getTitleWithIcon(title, '');
const lType = layer.get('type');
if ((lType && lType.includes('AGS')) || /\/arcgis\/services\/[^/]+\/[^/]+\/MapServer\/WMSServer/.test(getOneUrl(layer))) {
const mapSource = viewer.getMapSource();
const sourceName = layer.get('sourceName');
const serverVendor = mapSource[sourceName].type?.toLowerCase();
if ((lType?.includes('AGS')) || ((lType?.includes('WMS')) && (getSourceUrl(layer).includes('/arcgis/'))) || (serverVendor === 'arcgis')) {
content = await getAGSJSONContent(title, layer.get('id'));
} else if (lType && lType.includes('WMS')) {
content = await getWMSJSONContent(title);
content = await getWMSJSONContent(title, serverVendor);
}
}
return `
Expand Down
8 changes: 3 additions & 5 deletions src/layer/wms.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,28 +81,26 @@ function createWmsStyle({ wmsOptions, source, viewer, initialStyle = false }) {
}

let getLegendString;
let getLegendJson;
let styleName;

if (newStyle.defaultWMSServerStyle) {
getLegendString = source.getLegendUrl(maxResolution, legendParams);
getLegendJson = source.getLegendUrl(maxResolution, Object.assign({}, legendParams, { FORMAT: 'application/json' }));
// getLegendJson = source.getLegendUrl(maxResolution, Object.assign({}, legendParams, { FORMAT: 'application/json' }));
styleName = `${wmsOptions.name}_WMSServerDefault`;
} else {
getLegendString = source.getLegendUrl(maxResolution, {
STYLE: newStyle.style,
...legendParams
});
getLegendJson = source.getLegendUrl(maxResolution, Object.assign({}, legendParams, { FORMAT: 'application/json' }));
// getLegendJson = source.getLegendUrl(maxResolution, Object.assign({}, legendParams, { FORMAT: 'application/json' }));
styleName = newStyle.style;
}

const hasThemeLegend = newStyle.hasThemeLegend || false;
const thematicStyling = newStyle.thematicStyling || false;
const style = [[{
icon: {
src: `${getLegendString}`,
json: `${getLegendJson}`
src: `${getLegendString}`
},
extendedLegend: hasThemeLegend,
thematicStyling
Expand Down
69 changes: 69 additions & 0 deletions src/utils/imagelayerlegendutils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
export function getSourceUrl(layer) {
let sourceUrl;
const source = layer.getSource();
if (source && typeof source.getUrl === 'function') {
sourceUrl = source.getUrl();
} else if (source && Array.isArray(source.getUrls()) && source.getUrls().length > 0) {
sourceUrl = source.getUrls()[0];
}
return sourceUrl;
}

async function fetchJsonLegend({
url,
serverVendor
}) {
const reply = await fetch(url);
let json;
let rules;
try {
json = await reply.json();
} catch (e) {
json = undefined;
}
if (json) {
if (serverVendor === 'arcgis') rules = json?.layers;
else if (serverVendor === 'geoserver') rules = json?.Legend[0]?.rules;
else if (serverVendor === 'qgis') rules = json?.nodes[0]?.symbols;
} else rules = [];

if (rules === undefined) rules = [];
return rules;
}
export default async function getJsonLegendDetails({ layer, viewer, legendOpts }) {
const mapSource = viewer.getMapSource();
const sourceName = layer.get('sourceName');
let serverVendor = mapSource[sourceName].type?.toLowerCase();
if (!serverVendor) serverVendor = 'geoserver'; // make similar assumption as before
const maxResolution = viewer.getResolutions()[viewer.getResolutions().length - 1];
let url;

if (serverVendor === 'arcgis') {
let mapServerUrlString = getSourceUrl(layer);
if (layer.get('type') === 'WMS') {
const urlParts = mapServerUrlString.split('services');
mapServerUrlString = `${urlParts[0]}rest/services${urlParts[1].split('/WMSServer')[0]}`;
}
mapServerUrlString += '/legend';
url = new URL(mapServerUrlString);
url.searchParams.append('f', 'json');
url.searchParams.append('dpi', legendOpts?.dpi || 150);
} else if (serverVendor === 'geoserver') {
url = layer.getSource().getLegendUrl(maxResolution, {
FORMAT: 'application/json',
...legendOpts
});
} else if (serverVendor === 'qgis') {
url = layer.getSource().getLegendUrl(maxResolution, {
FORMAT: 'application/json',
SHOWRULEDETAILS: true,
...legendOpts
});
}
if (url) {
return fetchJsonLegend({
url,
serverVendor
});
} return [];
}
55 changes: 0 additions & 55 deletions src/utils/jsonlegends.js

This file was deleted.

22 changes: 13 additions & 9 deletions src/utils/legendmaker.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { renderIcon, renderSvg } from './legendrender';
import { Button, Element as El } from '../ui';
import ImageLayerLegendRules from './imagelayerlegendutils';

const size = 24;
const checkIcon = '#ic_check_circle_24px';
Expand Down Expand Up @@ -166,17 +167,20 @@ async function setIcon(src, cmp, styleRules, layer, viewer, clickable) {
const hasThemeLegend = layer.get('hasThemeLegend');
if (!style[0].thematic) {
style[0].thematic = [];
const paramsString = src.icon.json;
const searchParams = new URLSearchParams(paramsString);
const response = await fetch(src.icon.json);
const jsonData = await response.json();
jsonData.Legend[0].rules.forEach(row => {
searchParams.set('FORMAT', 'image/png');
searchParams.set('RULE', row.name);
const imgUrl = decodeURIComponent(searchParams.toString());
const maxResolution = viewer.getResolutions()[viewer.getResolutions().length - 1];
const getLegendGraphicUrl = new URL(layer.getSource().getLegendUrl(maxResolution, {
legend_options: 'dpi:150',
SCALE: 100
}));
const rules = await ImageLayerLegendRules({
layer,
viewer
});
rules.forEach(row => {
getLegendGraphicUrl.searchParams.set('RULE', row.name);
if (typeof row.filter !== 'undefined') {
style[0].thematic.push({
image: { src: imgUrl },
image: { src: getLegendGraphicUrl.href },
filter: row.filter,
name: row.name,
label: row.title || row.name,
Expand Down

0 comments on commit 944dc10

Please sign in to comment.