Skip to content
Merged
Show file tree
Hide file tree
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
87 changes: 75 additions & 12 deletions src/components/layerlist/LayerLegendImage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
import LayerLegend from '@/util/LayerLegend';

/**
* Module for one legend element.
* Component rendering a legend image for a layer.
* It reacts to:
* - map view resolution changes
* - layer source changes (e.g. WMS params updates)
*/
export default {
name: 'wgu-layerlegendimage',
Expand All @@ -21,33 +24,77 @@ export default {
data () {
return {
resolution: this.mapView.getResolution(),
viewResolutionChanged: undefined
viewResolutionChanged: undefined,
sourceRevision: 0,
sourceChanged: undefined
}
},
/**
* Register for an event to update the legend on resolution change.
* Register event listeners.
*/
created () {
const viewResolutionChanged = function (event) {
this.resolution = event.target.getResolution();
}.bind(this);

this.mapView.on('change:resolution', viewResolutionChanged);
this.viewResolutionChanged = viewResolutionChanged;
this.registerViewResolutionChanged(this.mapView);
this.registerSourceChanged(this.layer?.getSource());
},
/**
* Unregister the event fired on resolution change.
* Unregister event listeners.
*/
unmounted () {
if (this.viewResolutionChanged) {
this.mapView.un('change:resolution', this.viewResolutionChanged);
this.unregisterViewResolutionChanged(this.mapView);
this.unregisterSourceChanged(this.layer?.getSource());
},
methods: {
/**
* Registers a listener for map view resolution changes.
*/
registerViewResolutionChanged (view) {
if (!view) return;

this.viewResolutionChanged = (event) => {
this.resolution = event.target.getResolution();
};

view.on('change:resolution', this.viewResolutionChanged);
},
/**
* Unregisters the resolution change listener.
*/
unregisterViewResolutionChanged (view) {
if (view && this.viewResolutionChanged) {
view.un('change:resolution', this.viewResolutionChanged);
}
},
/**
* Registers a listener for source changes.
*/
registerSourceChanged (source) {
if (!source) return;

this.sourceChanged = () => {
this.sourceRevision++;
};

source.on('change', this.sourceChanged)
},
/**
* Unregisters the source change listener.
*/
unregisterSourceChanged (source) {
if (source && this.sourceChanged) {
source.un('change', this.sourceChanged);
}
}
},
computed: {
/**
* Returns a URL to the layers legend image.
*/
legendURL () {
// Remarks: No-op to force dependency tracking on the sourceRevision
// counter to recompute the legendURL whenever the source changes.
const trackRevision = () => { return this.sourceRevision };
trackRevision();

const legendUtil = new LayerLegend(this.$appConfig?.legend);
const options = {
language: this.$i18n.locale,
Expand All @@ -56,6 +103,22 @@ export default {
return legendUtil.getUrl(
this.layer, this.resolution, options, this.layer.get('legendUrl'));
}
},
watch: {
/**
* Reacts to layer replacement and rebinds source listeners.
*/
layer: {
handler (newLayer, oldLayer) {
const newSource = newLayer?.getSource?.();
const oldSource = oldLayer?.getSource?.();

if (newSource !== oldSource) {
this.unregisterSourceChanged(oldSource);
this.registerSourceChanged(newSource);
}
}
}
}
};
</script>
17 changes: 13 additions & 4 deletions src/util/LayerLegend.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,23 @@ const WMSSourceLegend = {
* @returns {String} The legend URL.
*/
getUrl (source, resolution, options) {
const legendOptions = { ...options };

const wmsParams = source.getParams();
const wmsVersion = ObjectUtil.getValueIgnoreCase(wmsParams, 'VERSION') || '1.3.0';
// apply mandatory SLD_VERSION param for WMS 1.3.0 GetLegendGraphic request
if (wmsVersion === '1.3.0' && !ObjectUtil.getValueIgnoreCase(options, 'SLD_VERSION')) {
options.SLD_VERSION = '1.1.0';

// Apply mandatory SLD_VERSION param for WMS 1.3.0 GetLegendGraphic request.
if (wmsVersion === '1.3.0' && !ObjectUtil.getValueIgnoreCase(legendOptions, 'SLD_VERSION')) {
legendOptions.SLD_VERSION = '1.1.0';
}

// Forward STYLES param, which may affect the legends appearance.
const wmsStyle = ObjectUtil.getValueIgnoreCase(wmsParams, 'STYLES');
if (wmsStyle && !ObjectUtil.getValueIgnoreCase(legendOptions, 'STYLE')) {
legendOptions.STYLE = wmsStyle;
}

return source.getLegendUrl(resolution, options);
return source.getLegendUrl(resolution, legendOptions);
}
}

Expand Down
19 changes: 19 additions & 0 deletions tests/unit/specs/components/layerlist/LayerLegendImage.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,25 @@ describe('layerlist/LayerLegendImage.vue', () => {
'SCALE=3571428.571428572&language=de&SLD_VERSION=1.1.0');
});

it('legendURL supports WMS style parameter', async () => {
await comp.setProps({ layer: wmsLayer });

expect(vm.legendURL).to.equal('https://ahocevar.com/geoserver/wms?' +
'SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&FORMAT=image%2Fpng&LAYER=topp%3Astates&' +
'SCALE=3571428.571428572&language=en&SLD_VERSION=1.1.0');

const source = wmsLayer.getSource();
const params = source.getParams();
source.updateParams({
...params,
STYLES: 'foo'
});

expect(vm.legendURL).to.equal('https://ahocevar.com/geoserver/wms?' +
'SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&FORMAT=image%2Fpng&LAYER=topp%3Astates&' +
'SCALE=3571428.571428572&language=en&SLD_VERSION=1.1.0&STYLE=foo');
})

afterEach(() => {
vm.$i18n.locale = 'en';
comp.unmount();
Expand Down
Loading