changeset 3875:30083005f13e improve-fwa-diagrams

merged default into improve-fwa-diagrams
author Markus Kottlaender <markus@intevation.de>
date Fri, 21 Jun 2019 08:34:07 +0200
parents 7b6a74919051 (current diff) 9fa108794e21 (diff)
children 0c6ef9e655fc
files
diffstat 9 files changed, 109 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Jun 20 15:34:25 2019 +0200
+++ b/.hgtags	Fri Jun 21 08:34:07 2019 +0200
@@ -6,3 +6,4 @@
 83f9a131dfb69f3ea1f430728a0831ccf96316d7 v2.1.0
 4d69b79e9df6e2b646ac60f75f6655bb3c64f6c6 v2.1.0
 4d7b481e1d392cd68c48a4ad19fc2865110e724e v3-uat2
+d4a5d11e23a043026a747c626d133b45047d17df v3
--- a/client/package.json	Thu Jun 20 15:34:25 2019 +0200
+++ b/client/package.json	Fri Jun 21 08:34:07 2019 +0200
@@ -1,6 +1,6 @@
 {
   "name": "gemmajs",
-  "version": "3.0.0-dev",
+  "version": "3.0.1-dev",
   "license": "AGPL-3.0-or-later",
   "repository": {
     "type": "hg",
--- a/client/src/components/gauge/HydrologicalConditions.vue	Thu Jun 20 15:34:25 2019 +0200
+++ b/client/src/components/gauge/HydrologicalConditions.vue	Fri Jun 21 08:34:07 2019 +0200
@@ -543,7 +543,10 @@
       updaters.push(this.drawWaterlevelLineChart("q75"));
       updaters.push(this.drawWaterlevelLineChart("mean", this.yearWaterlevels));
       updaters.push(this.drawNowLines());
-      this.drawRefLines(refWaterLevels); // static, doesn't need an updater
+
+      if (refWaterLevels) {
+        this.drawRefLines(refWaterLevels); // static, doesn't need an updater
+      }
 
       // INTERACTIONS
 
@@ -673,23 +676,31 @@
       return { width, mainHeight, navHeight, mainMargin, navMargin };
     },
     getExtent(refWaterLevels) {
-      const waterlevelsRelevantForExtent = [];
+      const waterlevelValues = [];
       this.longtermWaterlevels.forEach(wl => {
-        waterlevelsRelevantForExtent.push(wl.min, wl.max);
+        waterlevelValues.push(wl.min, wl.max);
       });
-      waterlevelsRelevantForExtent.push(
-        refWaterLevels.HDC + (refWaterLevels.HDC - refWaterLevels.LDC) / 8,
-        Math.max(
-          refWaterLevels.LDC - (refWaterLevels.HDC - refWaterLevels.LDC) / 4,
-          0
-        )
-      );
+      if (refWaterLevels) {
+        waterlevelValues.push(
+          refWaterLevels.HDC + (refWaterLevels.HDC - refWaterLevels.LDC) / 8,
+          Math.max(
+            refWaterLevels.LDC - (refWaterLevels.HDC - refWaterLevels.LDC) / 4,
+            0
+          )
+        );
+      } else {
+        let delta = d3.max(waterlevelValues) - d3.min(waterlevelValues);
+        waterlevelValues.push(
+          d3.max(waterlevelValues) + delta * 0.1,
+          d3.min(waterlevelValues) - delta * 0.1
+        );
+      }
       return {
         // set min/max values for the date axis
         date: [startOfYear(new Date()), endOfYear(new Date())],
         // set min/max values for the waterlevel axis
         // including HDC (+ 1/8 HDC-LDC) and LDC (- 1/4 HDC-LDC)
-        waterlevel: d3.extent(waterlevelsRelevantForExtent)
+        waterlevel: d3.extent(waterlevelValues)
       };
     },
     getScale() {
@@ -740,16 +751,20 @@
       };
     },
     drawNowLines() {
+      const now = new Date();
+      const nowCoords = [
+        { x: now, y: this.extent.waterlevel[0] },
+        { x: now, y: this.extent.waterlevel[1] }
+      ];
       const nowLine = d3
         .line()
         .x(d => this.scale.x(d.x))
         .y(d => this.scale.y(d.y));
-
       const nowLabel = selection => {
         selection.attr(
           "transform",
-          `translate(${this.scale.x(new Date())}, ${this.scale.y(
-            this.extent.waterlevel[1] - 16
+          `translate(${this.scale.x(now)}, ${this.scale.y(
+            this.extent.waterlevel[1]
           )})`
         );
       };
@@ -757,10 +772,7 @@
       // draw in main
       this.diagram
         .append("path")
-        .datum([
-          { x: new Date(), y: this.extent.waterlevel[0] },
-          { x: new Date(), y: this.extent.waterlevel[1] - 20 }
-        ])
+        .datum(nowCoords)
         .attr("class", "now-line")
         .attr("d", nowLine);
       this.diagram // label
@@ -773,10 +785,7 @@
       // draw in nav
       this.navigation
         .append("path")
-        .datum([
-          { x: new Date(), y: this.extent.waterlevel[0] },
-          { x: new Date(), y: this.extent.waterlevel[1] - 20 }
-        ])
+        .datum(nowCoords)
         .attr("class", "now-line")
         .attr(
           "d",
--- a/client/src/components/gauge/Waterlevel.vue	Thu Jun 20 15:34:25 2019 +0200
+++ b/client/src/components/gauge/Waterlevel.vue	Fri Jun 21 08:34:07 2019 +0200
@@ -565,7 +565,9 @@
 
       // static, don't need updater
       this.drawNavigationChart();
-      this.drawRefLines(refWaterLevels);
+      if (refWaterLevels) {
+        this.drawRefLines(refWaterLevels);
+      }
 
       updaters.push(this.drawNashSutcliffe(72));
       updaters.push(this.drawNashSutcliffe(48));
@@ -730,6 +732,23 @@
       return { width, mainHeight, navHeight, mainMargin, navMargin };
     },
     getExtent(refWaterLevels) {
+      let waterlevelValues = [...this.waterlevels.map(wl => wl.waterlevel)];
+      if (refWaterLevels) {
+        waterlevelValues.push(
+          refWaterLevels.HDC + (refWaterLevels.HDC - refWaterLevels.LDC) / 8,
+          Math.max(
+            refWaterLevels.LDC - (refWaterLevels.HDC - refWaterLevels.LDC) / 4,
+            0
+          )
+        );
+      } else {
+        let delta = d3.max(waterlevelValues) - d3.min(waterlevelValues);
+        waterlevelValues.push(
+          d3.max(waterlevelValues) + delta * 0.1,
+          d3.min(waterlevelValues) - delta * 0.1
+        );
+      }
+
       return {
         // set min/max values for the date axis
         date: [
@@ -738,24 +757,8 @@
         ],
         // set min/max values for the waterlevel axis
         // including HDC (+ 1/8 HDC-LDC) and LDC (- 1/4 HDC-LDC)
-        waterlevel: d3.extent(
-          [
-            ...this.waterlevels,
-            {
-              waterlevel:
-                refWaterLevels.HDC +
-                (refWaterLevels.HDC - refWaterLevels.LDC) / 8
-            },
-            {
-              waterlevel: Math.max(
-                refWaterLevels.LDC -
-                  (refWaterLevels.HDC - refWaterLevels.LDC) / 4,
-                0
-              )
-            }
-          ],
-          d => d.waterlevel
-        )
+        // or, if no refWaterlevels exist, +-10% of delta between min and max wl
+        waterlevel: d3.extent(waterlevelValues)
       };
     },
     getScale() {
@@ -859,16 +862,20 @@
         );
     },
     drawNowLines() {
+      const now = new Date();
+      const nowCoords = [
+        { x: now, y: this.extent.waterlevel[0] },
+        { x: now, y: this.extent.waterlevel[1] }
+      ];
       const nowLine = d3
         .line()
         .x(d => this.scale.x(d.x))
         .y(d => this.scale.y(d.y));
-
       const nowLabel = selection => {
         selection.attr(
           "transform",
-          `translate(${this.scale.x(new Date())}, ${this.scale.y(
-            this.extent.waterlevel[1] - 16
+          `translate(${this.scale.x(now)}, ${this.scale.y(
+            this.extent.waterlevel[1]
           )})`
         );
       };
@@ -876,10 +883,7 @@
       // draw in main
       this.diagram
         .append("path")
-        .datum([
-          { x: new Date(), y: this.extent.waterlevel[0] },
-          { x: new Date(), y: this.extent.waterlevel[1] - 20 }
-        ])
+        .datum(nowCoords)
         .attr("class", "now-line")
         .attr("d", nowLine);
       this.diagram // label
@@ -892,10 +896,7 @@
       // draw in nav
       this.navigation
         .append("path")
-        .datum([
-          { x: new Date(), y: this.extent.waterlevel[0] },
-          { x: new Date(), y: this.extent.waterlevel[1] - 20 }
-        ])
+        .datum(nowCoords)
         .attr("class", "now-line")
         .attr(
           "d",
--- a/client/src/components/map/styles.js	Thu Jun 20 15:34:25 2019 +0200
+++ b/client/src/components/map/styles.js	Fri Jun 21 08:34:07 2019 +0200
@@ -319,10 +319,15 @@
       if (waterlevel) {
         text += "\n(" + waterlevel + " cm)";
         let refWaterlevels = JSON.parse(feature.get("reference_water_levels"));
-        if (waterlevel < refWaterlevels.LDC) iconColor = "brown";
-        if (waterlevel > refWaterlevels.LDC && waterlevel < refWaterlevels.HDC)
-          iconColor = "blue";
-        if (waterlevel > refWaterlevels.HDC) iconColor = "red";
+        if (refWaterlevels) {
+          if (waterlevel < refWaterlevels.LDC) iconColor = "brown";
+          if (
+            waterlevel > refWaterlevels.LDC &&
+            waterlevel < refWaterlevels.HDC
+          )
+            iconColor = "blue";
+          if (waterlevel > refWaterlevels.HDC) iconColor = "red";
+        }
       }
 
       return [
--- a/pkg/controllers/gauges.go	Thu Jun 20 15:34:25 2019 +0200
+++ b/pkg/controllers/gauges.go	Fri Jun 21 08:34:07 2019 +0200
@@ -663,6 +663,7 @@
 		return
 	}
 
+	// TODO: FIXME The filter is not correct for predictions!?
 	filters := filterAnd{
 		buildFilterTerm(
 			"location = ($%d::char(2), $%d::char(3), $%d::char(5), $%d::char(5), $%d::int)",
@@ -677,7 +678,7 @@
 			buildFilterTerm(
 				`date_issue = (
                  SELECT max(date_issue)
-                 FROM waterway.gauge_measurements gm
+                 FROM waterway.gauge_predictions gm
                  WHERE location = ($%d::char(2), $%d::char(3), $%d::char(5), $%d::char(5), $%d::int))`,
 				isrs.CountryCode,
 				isrs.LoCode,
--- a/pkg/controllers/pwreset.go	Thu Jun 20 15:34:25 2019 +0200
+++ b/pkg/controllers/pwreset.go	Fri Jun 21 08:34:07 2019 +0200
@@ -288,15 +288,11 @@
 	return
 }
 
-func passwordReset(
-	_ interface{},
-	req *http.Request,
-	_ *sql.Conn,
-) (jr JSONResult, err error) {
+func passwordReset(rw http.ResponseWriter, req *http.Request) {
 
 	hash := mux.Vars(req)["hash"]
-	if _, err = hex.DecodeString(hash); err != nil {
-		err = JSONError{http.StatusBadRequest, "Invalid hash"}
+	if _, err := hex.DecodeString(hash); err != nil {
+		http.Error(rw, "invalid hash", http.StatusBadRequest)
 		return
 	}
 
@@ -304,7 +300,7 @@
 
 	ctx := req.Context()
 
-	if err = auth.RunAs(
+	if err := auth.RunAs(
 		ctx, pwResetRole, func(conn *sql.Conn) error {
 			err := conn.QueryRowContext(ctx, findRequestSQL, hash).Scan(&email, &user)
 			switch {
@@ -324,12 +320,18 @@
 			_, err = conn.ExecContext(ctx, deleteRequestSQL, hash)
 			return err
 		}); err == nil {
-		body := changedMessageBody(useHTTPS(req), user, password, host(req))
-		if err = misc.SendMail(email, "Password Reset Done", body); err == nil {
-			jr.Result = &struct {
-				SendTo string `json:"send-to"`
-			}{email}
+		https := useHTTPS(req)
+		server := host(req)
+		body := changedMessageBody(https, user, password, server)
+		if err = misc.SendMail(email, "Password Reset Done", body); err != nil {
+			log.Printf("error: %v\n", err)
+			http.Error(
+				rw,
+				http.StatusText(http.StatusInternalServerError),
+				http.StatusInternalServerError)
+			return
 		}
+		var url = https + "://" + server
+		http.Redirect(rw, req, url, http.StatusSeeOther)
 	}
-	return
 }
--- a/pkg/controllers/routes.go	Thu Jun 20 15:34:25 2019 +0200
+++ b/pkg/controllers/routes.go	Fri Jun 21 08:34:07 2019 +0200
@@ -104,10 +104,8 @@
 		NoConn: true,
 	}).Methods(http.MethodPost)
 
-	api.Handle("/users/passwordreset/{hash}", &JSONHandler{
-		Handle: passwordReset,
-		NoConn: true,
-	}).Methods(http.MethodGet)
+	api.HandleFunc("/users/passwordreset/{hash}", passwordReset).
+		Methods(http.MethodGet)
 
 	// Print templates
 	api.Handle("/templates", any(&JSONHandler{
--- a/pkg/imports/gm.go	Thu Jun 20 15:34:25 2019 +0200
+++ b/pkg/imports/gm.go	Fri Jun 21 08:34:07 2019 +0200
@@ -363,6 +363,7 @@
 	for _, msg := range result {
 		for _, wrm := range msg.Wrm {
 			curr := string(*wrm.Geo_object.Id)
+			curr = strings.TrimSpace(curr)
 			currIsrs, err := models.IsrsFromString(curr)
 			if err != nil {
 				feedback.Warn("Invalid ISRS code %v", err)
@@ -370,7 +371,7 @@
 			}
 			feedback.Info("Found measurements/predictions for %s", curr)
 			if !isKnown(curr) {
-				feedback.Warn("Cannot import data for %s", curr)
+				feedback.Warn("Cannot find gauge %q for import", curr)
 				continue
 			}
 
@@ -385,6 +386,11 @@
 			newM, newP := 0, 0
 			for _, measure := range wrm.Measure {
 				var unit string
+				if *measure.Measure_code != nts.Measure_code_enumWAL {
+					feedback.Warn("Ignored message with measure_code %s",
+						*measure.Measure_code)
+					continue
+				}
 				if measure.Unit == nil {
 					feedback.Info("'Unit' not specified. Assuming 'cm'")
 					unit = "cm"
@@ -399,17 +405,18 @@
 				convert(measure.Value_min)
 				convert(measure.Value_max)
 
-				if *measure.Measure_code != nts.Measure_code_enumWAL {
-					feedback.Warn("Ignored message with measure_code %s",
-						*measure.Measure_code)
-					continue
-				}
-
 				var dummy int
 				if measure.Predicted {
-					var confInterval pgtype.Numrange
+					confInterval := pgtype.Numrange{
+						Lower:     pgtype.Numeric{Status: pgtype.Null},
+						Upper:     pgtype.Numeric{Status: pgtype.Null},
+						LowerType: pgtype.Inclusive,
+						UpperType: pgtype.Inclusive,
+						Status:    pgtype.Null,
+					}
 					if measure.Value_min != nil && measure.Value_max != nil {
-						var valueMin, valueMax pgtype.Numeric
+						valueMin := pgtype.Numeric{Status: pgtype.Null}
+						valueMax := pgtype.Numeric{Status: pgtype.Null}
 						valueMin.Set(measure.Value_min)
 						valueMax.Set(measure.Value_max)
 						confInterval = pgtype.Numrange{