Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix print composite layer legend #2116

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 58 additions & 10 deletions src/controls/print/print-legend.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ const LayerRow = function LayerRow(options) {
return null;
};

/**
* Helper that creates a WMS getLegendGraphics request url string
* @param {any} url base url
* @param {any} layerName name of layer to create legend for
* @param {any} format valid mime type
* @returns {string} A WMS getLegendGraphics request url string
*/
const createGetlegendGrapicUrl = (url, layerName, format) => `${url}?SERVICE=WMS&layer=${layerName}&format=${format}&version=1.1.1&request=getLegendGraphic&scale=401&legend_options=dpi:300`;

/**
* Returns the URL to the WMS legend in the specified format
*
Expand All @@ -66,7 +75,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`;
return createGetlegendGrapicUrl(url, layerName, format);
};

/**
Expand Down Expand Up @@ -203,20 +212,59 @@ const LayerRow = function LayerRow(options) {
<img src="${getLegendGraphicUrl}" alt="${title}" />
</div>`;
}
if (json.Legend[0].rules.length <= 1) {
// Handle the simple one first. One layer, one rule
if (json.Legend.length === 1 && json.Legend[0].rules.length <= 1) {
const icon = `<img class="cover" src="${getLegendGraphicUrl}" alt="${title}"/>`;
return getTitleWithIcon(title, icon);
}

const thematicStyle = (layer.get('thematicStyling') === true) ? viewer.getStyle(layer.get('styleName')) : undefined;
const rules = json.Legend[0].rules.reduce((okRules, rule, index) => {
if (!(layer.get('thematicStyling')) || thematicStyle[0]?.thematic[index]?.visible) {
const ruleImageUrl = `${getLegendGraphicUrl}&rule=${rule.name}`;
const rowTitle = rule.title ? rule.title : index + 1;
okRules.push(getListItem(rowTitle, ruleImageUrl, true));
}
return okRules;
}, []);
const rules = [];
let index = 0;
const layerName = layer.get('id');
const isLayerGroup = json.Legend.length > 1;
// Loop all layers in json response. Usually there is only one, but Layer Groups have several.
json.Legend.forEach(currLayer => {
let currLayerName = currLayer.layerName;
currLayer.rules.forEach(currRule => {
if (!(layer.get('thematicStyling')) || thematicStyle[0]?.thematic[index]?.visible) {
let layerImageUrl;
if (isLayerGroup) {
// This is layer group and the contained layer is most likely not known to us,
// so we can't treat is as an Origo layer.
// Generate a request and hope that the server has a layer by that name.
const baseUrl = getOneUrl(layer);
const layerWs = layerName.split(':');
if (layerWs.length > 1) {
currLayerName = `${layerWs[0]}:${currLayer.layerName}`;
}
// This is a little bit shaky, if Layer Group name constains workspace, contained layers must come from
// the same workspace, but if layer group is a top level layer group (no workspace), contained layers can
// come from any workspace but the json response NEVER contains info about workspace.
// So for Layer Groups with a workspace prefix we can assume that the actual layers should have the same workspace prefix,
// but for top level Layer Groups we have absolutely no idea which workspace the layer is in.
// But not all is lost as Geoserver tries its best to get the legend for any workspace with that layer name.
// Problem is when the same layer name appears in several workspaces. In that case you get from what is configured as default.
// One more tricky thing is that layer groups can configure different symbols than the actual layer.
// Querying the layer Group for png will return the group layer style, but the getLegendGrapich for each layer
// will return the symbol for the actual layer, so legend and print legend will differ.
layerImageUrl = createGetlegendGrapicUrl(baseUrl, currLayerName, 'image/png');
} else {
layerImageUrl = getLegendGraphicUrl;
}
let ruleImageUrl = `${layerImageUrl}`;
// Add specific rule if necessary. If there is only one rule there is no need (in fact it will probably break as most
// styles using only one rule will not have a named rule). This is to handle Layer Groups without rules in some of the contained
// layer's style
if (currLayer.rules.length > 1) {
ruleImageUrl += `&rule=${currRule.name}`;
}
const rowTitle = currRule.title ? currRule.title : index + 1;
rules.push(getListItem(rowTitle, ruleImageUrl, true));
}
index += 1;
});
});

return getTitleWithChildren(title, rules);
};
Expand Down
Loading