diff --git a/src/controls/print/print-legend.js b/src/controls/print/print-legend.js index 19c38bc6d..23c45a26b 100644 --- a/src/controls/print/print-legend.js +++ b/src/controls/print/print-legend.js @@ -1,6 +1,7 @@ import { ImageArcGISRest, ImageWMS } from 'ol/source'; import { Component } from '../../ui'; import { isHidden, renderSvgIcon } from '../../utils/legendmaker'; +import ImageLayerLegendRules from '../../utils/jsonlegends'; /** * More information: https://developers.arcgis.com/rest/services-reference/enterprise/legend-map-service-.htm @@ -56,7 +57,7 @@ const LayerRow = function LayerRow(options) { * @param {"image/png"|"application/json"} format * @returns {string|null} */ - const getWMSLegendUrl = (aLayer, format) => { + /* const getWMSLegendUrl = (aLayer, format) => { const url = getOneUrl(aLayer); const layerName = aLayer.get('name'); const style = viewer.getStyle(aLayer.get('styleName')); @@ -67,7 +68,7 @@ const LayerRow = function LayerRow(options) { 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 @@ -78,7 +79,7 @@ const LayerRow = function LayerRow(options) { * @param {number} dpi * @returns {Promise} */ - const getAGSLegendJSON = async (aLayer, dpi = 150) => { + /* 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}`; @@ -89,13 +90,13 @@ const LayerRow = function LayerRow(options) { console.warn(e); return null; } - }; + }; */ /** * @param {string|null} url * @returns {Promise} */ - const getLegendGraphicJSON = async (url) => { + /* const getLegendGraphicJSON = async (url) => { try { if (!url) { return null; @@ -106,7 +107,7 @@ const LayerRow = function LayerRow(options) { console.warn(e); return null; } - }; + }; */ /** * @param {string} title @@ -188,10 +189,18 @@ const LayerRow = function LayerRow(options) { * @returns {Promise} */ const getWMSJSONContent = async (title) => { - const getLegendGraphicUrl = getWMSLegendUrl(layer, 'image/png'); - const json = await getLegendGraphicJSON(getWMSLegendUrl(layer, 'application/json')); + // onst getLegendGraphicUrl = getWMSLegendUrl(layer, 'image/png'); + const maxResolution = viewer.getResolutions()[viewer.getResolutions().length - 1]; + const getLegendGraphicUrl = layer.getSource().getLegendUrl(maxResolution, { + legend_options: 'dpi:300' + }); + // const json = await getLegendGraphicJSON(getWMSLegendUrl(layer, 'application/json')); + const rules = await ImageLayerLegendRules({ + layer, + viewer + }); - if (!json) { + if (!rules) { return `
${title}
@@ -200,17 +209,17 @@ const LayerRow = function LayerRow(options) { ${title}
`; } - if (json.Legend[0].rules.length <= 1) { + if (rules.length <= 1) { const icon = `${title}`; return getTitleWithIcon(title, icon); } - const rules = json.Legend[0].rules.map((rule, index) => { + const listItems = rules.map((rule, index) => { const ruleImageUrl = `${getLegendGraphicUrl}&rule=${rule.name}`; const rowTitle = rule.title ? rule.title : index + 1; return getListItem(rowTitle, ruleImageUrl, true); }); - return getTitleWithChildren(title, rules); + return getTitleWithChildren(title, listItems); }; /** @@ -221,11 +230,20 @@ const LayerRow = function LayerRow(options) { * @returns {Promise} */ const getAGSJSONContent = async (title, id) => { - const json = await getAGSLegendJSON(layer); - if (!json) { + // const json = await getAGSLegendJSON(layer); + // const layersDetails = json.layers; + const layersDetails = await ImageLayerLegendRules({ + layer, + viewer, + legendOpts: { + dpi: 200 + } + }); + + if (layersDetails.length === 0) { return getTitleWithIcon(title, ''); } - const legendLayer = json.layers.find((l) => +l.layerId === +id || l.layerName === id); + const legendLayer = layersDetails.find((l) => +l.layerId === +id || l.layerName === id); if (!legendLayer) { return getTitleWithIcon(title, ''); } diff --git a/src/utils/jsonlegends.js b/src/utils/jsonlegends.js new file mode 100644 index 000000000..677da3611 --- /dev/null +++ b/src/utils/jsonlegends.js @@ -0,0 +1,55 @@ +import { ImageArcGISRest, ImageWMS } from 'ol/source'; + +function 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; +} + +async function fetchJsonLegend({ + url, + serverVendor +}) { + const reply = await fetch(url); + const json = await reply.json(); + if (serverVendor === 'arcgis') return json?.layers; + else if (serverVendor === 'geoserver') return json.Legend[0]?.rules; + return []; +} +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 + let url; + + if (serverVendor === 'arcgis') { + let mapServerUrlString = getOneUrl(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') { + const maxResolution = viewer.getResolutions()[viewer.getResolutions().length - 1]; + url = layer.getSource().getLegendUrl(maxResolution, { + FORMAT: 'application/json', + ...legendOpts + }); + } + if (url) { + return fetchJsonLegend({ + url, + serverVendor + }); + } return []; +} + +export default getJsonLegendDetails;