Skip to content
Open
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
25 changes: 25 additions & 0 deletions assets/src/modules/WMS.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,29 @@ export default class WMS {
body: params,
});
}

/**
* Get legend graphic as PNG image URL from WMS
* @param {object} options - optional parameters which can override this._defaultGetLegendGraphicsParameters
* @returns {string} PNG image URL
* @memberof WMS
*/
getLegendGraphicPNG(options) {
const layers = options['LAYERS'] ?? options['LAYER'];
// Check if layer is specified
if (!layers) {
throw new RequestError(
'LAYERS or LAYER parameter is required for getLegendGraphic request',
options,
);
}

const params = new URLSearchParams({
...this._defaultGetLegendGraphicParameters,
...options,
FORMAT: 'image/png' // Force PNG format for external WMS layers
});

return `${globalThis['lizUrls'].wms}?${params}`;
}
}
65 changes: 52 additions & 13 deletions assets/src/modules/action/Symbology.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,60 @@ export async function updateLayerTreeLayersSymbology(treeLayers, method=HttpRequ

if (method.toUpperCase() == HttpRequestMethods.GET) {
for (const treeLayer of treeLayers) {
const wmsParams = {
LAYER: treeLayer.wmsName,
STYLES: treeLayer.wmsSelectedStyleName,
};
// Check if this is an external WMS layer using the backend flag
const layerCfg = treeLayer._mapItemState?._layerItemState?._layerTreeItemCfg?._layerCfg;
const isExternalWMS = layerCfg?._externalWmsToggle === true
|| layerCfg?._externalWmsToggle === 'True';
Comment on lines +36 to +38
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const layerCfg = treeLayer._mapItemState?._layerItemState?._layerTreeItemCfg?._layerCfg;
const isExternalWMS = layerCfg?._externalWmsToggle === true
|| layerCfg?._externalWmsToggle === 'True';
const isExternalWMS = treeLayer.layerConfig.externalWmsToggle;


await wms.getLegendGraphic(wmsParams).then((response) => {
for (const node of response.nodes) {
// If the layer has no symbology, there is no type property
if (node.hasOwnProperty('type')) {
treeLayer.symbology = node;
}
if (isExternalWMS) {
// For external WMS layers, get PNG legend directly
const wmsParams = {
LAYER: treeLayer.wmsName,
STYLES: treeLayer.wmsSelectedStyleName,
LAYERTITLE: 'FALSE',
};
try {
const pngUrl = wms.getLegendGraphicPNG(wmsParams);
// Fetch the PNG and convert to base64
const response = await fetch(pngUrl);
const blob = await response.blob();
const reader = new FileReader();

await new Promise((resolve, reject) => {
reader.onloadend = () => {
const base64data = reader.result.split(',')[1]; // Remove data:image/png;base64, prefix
treeLayer.symbology = {
type: 'layer',
name: treeLayer.wmsName,
title: treeLayer.name,
icon: base64data
};
resolve();
};
reader.onerror = reject;
reader.readAsDataURL(blob);
});
} catch (error) {
console.error('Error loading external WMS legend:', error);
// Fallback to default icon will be handled by symbology state
Comment on lines +40 to +70
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (isExternalWMS) {
// For external WMS layers, get PNG legend directly
const wmsParams = {
LAYER: treeLayer.wmsName,
STYLES: treeLayer.wmsSelectedStyleName,
LAYERTITLE: 'FALSE',
};
try {
const pngUrl = wms.getLegendGraphicPNG(wmsParams);
// Fetch the PNG and convert to base64
const response = await fetch(pngUrl);
const blob = await response.blob();
const reader = new FileReader();
await new Promise((resolve, reject) => {
reader.onloadend = () => {
const base64data = reader.result.split(',')[1]; // Remove data:image/png;base64, prefix
treeLayer.symbology = {
type: 'layer',
name: treeLayer.wmsName,
title: treeLayer.name,
icon: base64data
};
resolve();
};
reader.onerror = reject;
reader.readAsDataURL(blob);
});
} catch (error) {
console.error('Error loading external WMS legend:', error);
// Fallback to default icon will be handled by symbology state

Do not request the image and simulate a child icon. I prefer to enhance the treeview component to display the legend image has a child.

}
}).catch((error) => {
console.error(error);
});
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} else {
if (!isExternalWMS) {

Request JSON only for non external WMS

// For normal layers, use JSON format
const wmsParams = {
LAYER: treeLayer.wmsName,
STYLES: treeLayer.wmsSelectedStyleName,
};
await wms.getLegendGraphic(wmsParams).then((response) => {
for (const node of response.nodes) {
// If the layer has no symbology, there is no type property
if (node.hasOwnProperty('type')) {
treeLayer.symbology = node;
}
}
}).catch((error) => {
console.error(error);
});
}
}
return treeLayers;
}
Expand Down
9 changes: 6 additions & 3 deletions lizmap/modules/lizmap/lib/Project/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -2045,12 +2045,15 @@ public function getUpdatedConfig()
&& !array_key_exists('crs', $layerDatasource)) {
$layerDatasource['crs'] = 'EPSG:3857';
}
// Set externalWmsToggle for ALL external WMS layers (not just EPSG:3857)
$obj->externalWmsToggle = 'True';
$obj->externalAccess = $layerDatasource;
Comment on lines +2048 to +2050
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Set externalWmsToggle for ALL external WMS layers (not just EPSG:3857)
$obj->externalWmsToggle = 'True';
$obj->externalAccess = $layerDatasource;
if (array_key_exists('type', $layerDatasource)
&& $layerDatasource['type'] == 'wms') {
// Set externalWmsToggle for ALL external WMS layers (not just EPSG:3857)
$obj->externalWmsToggle = 'True';
$obj->externalAccess = $layerDatasource;
}

Activate external only for WMS layers.

We should verify that the project's projection is recognized by the source service or that the OpenLayers layer created reuses the CRS of the source layer.


// if the layer datasource contains type and crs EPSG:3857
// external access can be provided
// additional external access configuration can be provided
if (array_key_exists('type', $layerDatasource)
&& $layerDatasource['crs'] == 'EPSG:3857') {
$obj->externalWmsToggle = 'True';
$obj->externalAccess = $layerDatasource;
// Additional external access for EPSG:3857 layers
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keeps it for other $layerDatasource by using an else if or an || in the previous if

}
}
}
Expand Down
Loading