From 4bec84a3a4c9d02f7379be9866bfad8811480491 Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@nibio.no>
Date: Wed, 25 Oct 2023 16:25:19 +0200
Subject: [PATCH] Show popup with location values for model

---
 spatial/static/spatial/js/slidingMap.js   | 82 ++++++++++++++++++++++-
 spatial/templates/spatial/slidingMap.html |  1 +
 2 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/spatial/static/spatial/js/slidingMap.js b/spatial/static/spatial/js/slidingMap.js
index 67f0eced..4fd425f1 100644
--- a/spatial/static/spatial/js/slidingMap.js
+++ b/spatial/static/spatial/js/slidingMap.js
@@ -1,3 +1,4 @@
+// TODO: Handle most/all EPSG codes 
 proj4.defs(
     'EPSG:25833',
     '+proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs'
@@ -13,6 +14,8 @@ let timestamps = undefined;
 let currentParameter = "WARNING_STATUS";
 let parameters = [currentParameter];
 let WMSLayersDateBucket = {};
+let map = undefined;
+let popup = undefined;
 
 function switchLayer(dayIndex)
 {
@@ -32,10 +35,16 @@ function setCurrentDate(layerIndex)
     document.getElementById("currentDate").innerHTML=moment(parseInt(timestamps[layerIndex])).format("YYYY-MM-DD");
 }
 
+function getCurrentVisibleOLLayer()
+{
+    // The WMS layer returned from mapserver is found
+    let currentWMSLayer = WMSLayersDateBucket[currentTimestamp][currentParameter];
+    // We have the ordering in the openlayers Map as a property, use that to return the OpenLayers layer
+    return layers[currentLayer["ordering"]];
+}
 
 
 async function initSlidingMap(lonLat, zoomLevel, mapAttribution) {
-	var map;
 
     var backgroundLayer = new ol.layer.Tile({
 		source: new ol.source.OSM({
@@ -52,6 +61,7 @@ async function initSlidingMap(lonLat, zoomLevel, mapAttribution) {
     let response = await fetch(mapserverURL + modelId + "?service=WMS&version=1.3.0&request=GetCapabilities");
     let result = parser.read(await response.text());
     let WMSLayers = result.Capability.Layer.Layer;
+    //console.info(WMSLayers[0]);
 
     // Analyze and organize layers
     // First dimension: Time
@@ -101,7 +111,7 @@ async function initSlidingMap(lonLat, zoomLevel, mapAttribution) {
                         params: { "LAYERS": modelId + "." + currentLayerParam + "." + dateStr, "TRANSPARENT": "TRUE" },
                         serverType: "mapserver",
                         ratio: 1,
-                        projection: ol.proj.get("EPSG:25833")
+                        projection: ol.proj.get(currentLayer.CRS[0])
                     }),
                     visible: false,
                     opacity: 0.5
@@ -139,6 +149,13 @@ async function initSlidingMap(lonLat, zoomLevel, mapAttribution) {
 	});
 	map.setView(view);
 
+    popup = new ol.Overlay({
+    element: document.getElementById('popup')
+    });
+    map.addOverlay(popup);
+
+    map.on('singleclick', displayQueryResult);
+
     // Add the parameter selector
     let radioHTML = "";
     for(let i=0;i<parameters.length;i++)
@@ -154,4 +171,65 @@ function switchParameter(selectedParameter)
 {
     currentParameter = selectedParameter;
     switchLayer(document.getElementById("layerDateRange").value);
+}
+
+async function displayQueryResult(evt)
+{
+    let coordinate = proj4(map.getView().getProjection().getCode(), 'EPSG:25833', evt.coordinate)
+    let currentWMSLayer = WMSLayersDateBucket[currentTimestamp][currentParameter];
+    let currentLayer = getCurrentVisibleOLLayer();
+    //console.info(currentLayer);
+    const url = currentLayer.getSource().getGetFeatureInfoUrl(
+        coordinate,
+        map.getView().getResolution(),
+        currentWMSLayer.CRS[0],
+        { 'INFO_FORMAT': 'text/xml' }
+    );
+    
+    //console.info(url);
+    let response = await fetch(url);
+    let responseXML = await response.text();
+
+    const parser = new DOMParser();
+    const xmlDOM = parser.parseFromString(responseXML,"text/xml");
+    const result = xmlDOM.getElementsByTagName("vipsResult")[0]
+    if(result) {
+        // We may or may not have warning status included
+        let warningStatus = xmlDOM.getElementsByTagName("warningStatus").length == 1 ? xmlDOM.getElementsByTagName("warningStatus")[0].getAttribute("value") : null;
+        let parameters = {};
+        let parameterElements = xmlDOM.getElementsByTagName("parameter");
+        for(let i=0;i<parameterElements.length;i++)
+        {
+            parameters[parameterElements[i].getAttribute("name")] = parameterElements[i].getAttribute("value");
+        }
+        //console.info("warningStatus = " + warningStatus);
+        //console.info(parameters);
+
+        let warningStatusTitle =  warningStatus == 0 ? "N/A"
+                                : warningStatus == 1 ? "Missing data"
+                                : warningStatus == 2 ? "No risk"
+                                : warningStatus == 3 ? "Possible risk"
+                                : warningStatus == 4 ? "High risk" : "";
+        
+        let paramHTML = "<ul>";
+        paramCodes = Object.keys(parameters);
+        for(let i=0;i<paramCodes.length;i++)
+        {
+            paramHTML += "<li>" + paramCodes[i] + " = " + parameters[paramCodes[i]] + "</li>"
+        }
+        paramHTML += "</ul>";
+
+        // Render results
+        // TODO: Handle click outside layer
+        let popupElement = popup.getElement();
+        $(popupElement).popover('destroy');
+        popup.setPosition(evt.coordinate);
+        $(popupElement).popover({
+            'placement': 'top',
+            'animation': false,
+            'html': true,
+            'content': '<h4>' + warningStatusTitle + '</h4>' + paramHTML
+          });
+          $(popupElement).popover('show');
+    }
 }
\ No newline at end of file
diff --git a/spatial/templates/spatial/slidingMap.html b/spatial/templates/spatial/slidingMap.html
index b1773872..3b2b777d 100644
--- a/spatial/templates/spatial/slidingMap.html
+++ b/spatial/templates/spatial/slidingMap.html
@@ -33,5 +33,6 @@
 			<div class="form-group" id="paramselector" style="position: absolute; right: 20px; bottom: 20px; background-color: white; z-index: 1000;padding: 15px; border-radius: 15px;">
 			</div>
         </div>
+		<div id="popup" title="Location details"></div>
        
 {% endblock %}
\ No newline at end of file
-- 
GitLab