changeset 3488:aa264021e2bf zpg-ldc

merged default into zpg-ldc branch.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 27 May 2019 16:38:07 +0200
parents fdb0439850d5 (current diff) 1fbb6dc7d362 (diff)
children 76d63f18f55f
files
diffstat 8 files changed, 83 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/fairway/AvailableFairwayDepth.vue	Mon May 27 16:37:19 2019 +0200
+++ b/client/src/components/fairway/AvailableFairwayDepth.vue	Mon May 27 16:38:07 2019 +0200
@@ -147,7 +147,7 @@
     };
   },
   created() {
-    window.addEventListener("resize", debounce(this.drawDiagram), 100);
+    window.addEventListener("resize", debounce(this.drawDiagram), 200);
   },
   mounted() {
     this.drawDiagram();
@@ -206,7 +206,7 @@
     },
     csvFileName() {
       return `${this.$gettext("fairwayavailability")}-${
-        this.selectedFairwayAvailabilityFeature.properties.name
+        this.featureName
       }-${filters.surveyDate(this.fromDate)}-${filters.surveyDate(
         this.toDate
       )}-${this.$gettext(this.frequency)}-.csv`;
@@ -236,6 +236,7 @@
       )}) ${this.$gettext(this.frequency)}`;
     },
     featureName() {
+      if (this.selectedFairwayAvailabilityFeature == null) return "";
       return this.selectedFairwayAvailabilityFeature.properties.name;
     }
   },
--- a/client/src/components/fairway/AvailableFairwayDepthDialogue.vue	Mon May 27 16:37:19 2019 +0200
+++ b/client/src/components/fairway/AvailableFairwayDepthDialogue.vue	Mon May 27 16:38:07 2019 +0200
@@ -11,26 +11,26 @@
         <UISpinnerOverlay v-if="loading" />
         <div class="mb-2 d-flex justify-content-between align-items-center">
           <div>
-            <input :value="$options.BOTTLENECKS" type="radio" v-model="type" />
+            <input :value="$options.BOTTLENECK" type="radio" v-model="type" />
             <small class="ml-1 text-muted">
               <translate>Bottlenecks</translate>
             </small>
           </div>
           <div>
-            <input :value="$options.STRETCHES" type="radio" v-model="type" />
+            <input :value="$options.STRETCH" type="radio" v-model="type" />
             <small class="ml-1 text-muted">
               <translate>Stretches</translate>
             </small>
           </div>
           <div>
-            <input :value="$options.SECTIONS" type="radio" v-model="type" />
+            <input :value="$options.SECTION" type="radio" v-model="type" />
             <small class="ml-1 text-muted">
               <translate>Sections</translate>
             </small>
           </div>
         </div>
         <select
-          v-if="type === $options.BOTTLENECKS"
+          v-if="type === $options.BOTTLENECK"
           @change="entrySelected"
           class="form-control font-weight-bold"
           v-model="selectedEntry"
@@ -51,7 +51,7 @@
           </optgroup>
         </select>
         <select
-          v-else-if="type === $options.STRETCHES"
+          v-else-if="type === $options.STRETCH"
           @change="entrySelected"
           class="form-control font-weight-bold"
           v-model="selectedEntry"
@@ -66,7 +66,7 @@
           </option>
         </select>
         <select
-          v-else-if="type === $options.SECTIONS"
+          v-else-if="type === $options.SECTION"
           @change="entrySelected"
           class="form-control font-weight-bold"
           v-model="selectedEntry"
@@ -278,7 +278,7 @@
       "limitingFactorsPerBottleneck"
     ]),
     depthLimitVisible() {
-      if (this.type !== this.$options.BOTTLENECKS) return true;
+      if (this.type !== this.$options.BOTTLENECK) return true;
       if (
         this.selectedEntry &&
         this.limitingFactorsPerBottleneck[this.selectedEntry.properties.name] ==
@@ -288,7 +288,7 @@
       return false;
     },
     widthLimitVisible() {
-      if (this.type !== this.$options.BOTTLENECKS) return true;
+      if (this.type !== this.$options.BOTTLENECK) return true;
       if (
         this.selectedEntry &&
         this.limitingFactorsPerBottleneck[this.selectedEntry.properties.name] ==
@@ -297,7 +297,7 @@
         return true;
     },
     limitingFactor() {
-      if (this.type !== this.$options.BOTTLENECKS) return;
+      if (this.type !== this.$options.BOTTLENECK) return;
       if (this.selectedEntry)
         return this.limitingFactorsPerBottleneck[
           this.selectedEntry.properties.name
@@ -399,38 +399,38 @@
       return this.$gettext("Available fairway depth");
     },
     placeholder() {
-      if (this.type === this.$options.BOTTLENECKS)
+      if (this.type === this.$options.BOTTLENECK)
         return this.$gettext("Select bottleneck");
-      if (this.type === this.$options.STRETCHES)
+      if (this.type === this.$options.STRETCH)
         return this.$gettext("Select stretch");
       return this.$gettext("Select section");
     }
   },
   watch: {
     selectedBottleneck() {
-      this.type = this.$options.BOTTLENECKS;
+      this.type = this.$options.BOTTLENECK;
       this.setSelectedBottleneck();
     },
     selectedStretchId() {
-      this.type = this.$options.STRETCHES;
+      this.type = this.$options.STRETCH;
       this.setSelectedStretch();
     },
     selectedSectionId() {
-      this.type = this.$options.SECTIONS;
+      this.type = this.$options.SECTION;
       this.setSelectedSection();
     },
     type(type) {
-      if (type === this.$options.BOTTLENECKS && this.selectedBottleneck) {
+      if (type === this.$options.BOTTLENECK && this.selectedBottleneck) {
         this.openLayersMap()
           .getLayer("BOTTLENECKS")
           .setVisible(true);
         this.setSelectedBottleneck();
-      } else if (type === this.$options.STRETCHES && this.selectedStretchId) {
+      } else if (type === this.$options.STRETCH && this.selectedStretchId) {
         this.openLayersMap()
           .getLayer("STRETCHES")
           .setVisible(true);
         this.setSelectedStretch();
-      } else if (type === this.$options.SECTIONS && this.selectedSectionId) {
+      } else if (type === this.$options.SECTION && this.selectedSectionId) {
         this.openLayersMap()
           .getLayer("SECTIONS")
           .setVisible(true);
@@ -528,7 +528,7 @@
       this.$store.commit("application/showFairwayDepthLNWL", false);
     },
     entrySelected() {
-      if (this.type === this.$options.BOTTLENECKS) {
+      if (this.type === this.$options.BOTTLENECK) {
         this.openLayersMap()
           .getLayer("BOTTLENECKS")
           .setVisible(true);
@@ -539,12 +539,12 @@
           );
         }
       }
-      if (this.type === this.$options.STRETCHES) {
+      if (this.type === this.$options.STRETCH) {
         this.openLayersMap()
           .getLayer("STRETCHES")
           .setVisible(true);
       }
-      if (this.type === this.$options.SECTIONS) {
+      if (this.type === this.$options.SECTION) {
         this.openLayersMap()
           .getLayer("SECTIONS")
           .setVisible(true);
@@ -581,9 +581,9 @@
       );
     }
   },
-  BOTTLENECKS: "bottlenecks",
-  SECTIONS: "sections",
-  STRETCHES: "stretches",
+  BOTTLENECK: "bottleneck",
+  SECTION: "section",
+  STRETCH: "stretch",
   AVAILABLEFAIRWAYDEPTH: app.$gettext("Available Fairway Depth"),
   FREQUENCIES: FREQUENCIES,
   LIMITINGFACTORS: LIMITINGFACTORS
--- a/client/src/components/fairway/AvailableFairwayDepthLNWL.vue	Mon May 27 16:37:19 2019 +0200
+++ b/client/src/components/fairway/AvailableFairwayDepthLNWL.vue	Mon May 27 16:38:07 2019 +0200
@@ -138,7 +138,7 @@
     };
   },
   created() {
-    window.addEventListener("resize", debounce(this.drawDiagram), 100);
+    window.addEventListener("resize", debounce(this.drawDiagram), 200);
   },
   mounted() {
     this.drawDiagram();
@@ -197,7 +197,7 @@
     },
     csvFileName() {
       return `${this.$gettext("fairwayavailabilityLNWL")}-${
-        this.selectedFairwayAvailabilityFeature.properties.name
+        this.featureName
       }-${filters.surveyDate(this.fromDate)}-${filters.surveyDate(
         this.toDate
       )}-${this.$gettext(this.frequency)}-.csv`;
@@ -219,6 +219,7 @@
       )}) ${this.$gettext(this.frequency)}`;
     },
     featureName() {
+      if (this.selectedFairwayAvailabilityFeature == null) return "";
       return this.selectedFairwayAvailabilityFeature.properties.name;
     },
     widthPerItem() {
--- a/client/src/components/identify/formatter.js	Mon May 27 16:37:19 2019 +0200
+++ b/client/src/components/identify/formatter.js	Mon May 27 16:38:07 2019 +0200
@@ -4,7 +4,11 @@
     if (p.key === "objname") p.key = "Name";
     if (p.key === "staging_done" || p.key === "fa_critical")
       p.val = p.val ? "yes" : "no";
-    if (p.key === "date_info" || p.key === "fa_date_info") {
+    if (
+      p.key === "date_info" ||
+      p.key === "fa_date_info" ||
+      p.key === "gm_measuredate"
+    ) {
       p.val = new Date(p.val).toLocaleString();
     }
 
@@ -23,7 +27,9 @@
       if (p.key === "fa_critical") p.key = "Fairway Critical";
       if (p.key === "gauge_objname") p.key = "Reference Gauge";
       if (p.key === "source_organization") p.key = "Source Organization";
+      if (p.key === "gm_measuredate") p.key = "Gauge Waterlevel Date";
       if (p.key === "gm_waterlevel") p.key = "Gauge Waterlevel";
+      if (p.key === "gm_n_14d") p.key = "G.W. Count in Last 14 Days";
 
       // remove certain props
       let propsToRemove = ["nobjnm", "reference_water_levels"];
@@ -59,7 +65,9 @@
   gauges_geoserver: {
     label: "Gauge",
     props: p => {
+      if (p.key === "gm_measuredate") p.key = "Latest Waterlevel Date";
       if (p.key === "gm_waterlevel") p.key = "Latest Waterlevel";
+      if (p.key === "gm_n_14d") p.key = "Measurement Count in Last 14 Days";
 
       return p;
     }
--- a/client/src/components/map/styles.js	Mon May 27 16:37:19 2019 +0200
+++ b/client/src/components/map/styles.js	Mon May 27 16:38:07 2019 +0200
@@ -238,7 +238,7 @@
       );
     } else {
       // TODO: Get information from feature and check the ranges according to #423, #424, #425
-      let colorWaterlevel = "lime";
+      let colorWaterlevel = classifications.gmAvailability(feature);
       let colorUniformTriangle = "lime";
       let colorComparison = "white";
       let colorAccuracy = classifications.forecastAccuracy(feature);
--- a/client/src/lib/classifications.js	Mon May 27 16:37:19 2019 +0200
+++ b/client/src/lib/classifications.js	Mon May 27 16:38:07 2019 +0200
@@ -34,6 +34,25 @@
       return "red";
     }
   },
+  gmAvailability(gauge) {
+    let gmDate = gauge.get("gm_measuredate");
+    let gmN = gauge.get("gm_n_14d");
+    if (
+      gmDate !== undefined &&
+      gmDate !== null &&
+      Date.parse(gmDate) > Date.now() - 86400000 // latest value within 24 h
+    ) {
+      if (
+        gmN !== undefined &&
+        gmN !== null &&
+        gmN >= 1344 // one value every 15 min in 14 days
+      ) {
+        return "lime";
+      }
+      return "yellow";
+    }
+    return "red";
+  },
   forecastAccuracy(gauge) {
     let fa3d = gauge.get("forecast_accuracy_3d");
     let fa1d = gauge.get("forecast_accuracy_1d");
--- a/client/src/store/fairwayavailability.js	Mon May 27 16:37:19 2019 +0200
+++ b/client/src/store/fairwayavailability.js	Mon May 27 16:38:07 2019 +0200
@@ -32,9 +32,9 @@
 };
 
 const TYPES = {
-  BOTTLENECKS: "bottlenecks",
-  SECTIONS: "sections",
-  STRETCHES: "stretches"
+  BOTTLENECK: "bottleneck",
+  SECTION: "section",
+  STRETCH: "stretch"
 };
 
 const FREQUENCIES = {
@@ -67,7 +67,7 @@
 
 const init = () => {
   return {
-    type: "bottlenecks",
+    type: TYPES.BOTTLENECK,
     selectedFairwayAvailabilityFeature: null,
     to: format(new Date(), "YYYY-MM-DD"),
     from: format(subYears(new Date(), 1), "YYYY-MM-DD"),
@@ -222,18 +222,18 @@
         let additionalParams = "";
         let endpoint = "";
         switch (type) {
-          case TYPES.BOTTLENECKS:
+          case TYPES.BOTTLENECK:
             endpoint = "bottleneck";
             if (limitingFactor === LIMITINGFACTORS.DEPTH)
               additionalParams = `&breaks=${depthLimit1},${depthLimit2}`;
             if (limitingFactor === LIMITINGFACTORS.WIDTH)
               additionalParams = `&breaks=${widthLimit1},${widthLimit2}`;
             break;
-          case TYPES.SECTIONS:
+          case TYPES.SECTION:
             endpoint = "section";
             additionalParams = `&depthbreaks=${depthLimit1},${depthLimit2}&widthbreaks=${widthLimit1},${widthLimit2}`;
             break;
-          case TYPES.STRETCHES:
+          case TYPES.STRETCH:
             endpoint = "stretch";
             additionalParams = `&depthbreaks=${depthLimit1},${depthLimit2}&widthbreaks=${widthLimit1},${widthLimit2}`;
             break;
@@ -285,18 +285,18 @@
         let additionalParams = "";
         let endpoint = "";
         switch (type) {
-          case TYPES.BOTTLENECKS:
+          case TYPES.BOTTLENECK:
             endpoint = "bottleneck";
             if (limitingFactor === LIMITINGFACTORS.DEPTH)
               additionalParams = `&breaks=${depthLimit1},${depthLimit2}`;
             if (limitingFactor === LIMITINGFACTORS.WIDTH)
               additionalParams = `&breaks=${widthLimit1},${widthLimit2}`;
             break;
-          case TYPES.SECTIONS:
+          case TYPES.SECTION:
             endpoint = "section";
             additionalParams = `&depthbreaks=${depthLimit1},${depthLimit2}&widthbreaks=${widthLimit1},${widthLimit2}`;
             break;
-          case TYPES.STRETCHES:
+          case TYPES.STRETCH:
             endpoint = "stretch";
             additionalParams = `&depthbreaks=${depthLimit1},${depthLimit2}&widthbreaks=${widthLimit1},${widthLimit2}`;
             break;
--- a/schema/geoserver_views.sql	Mon May 27 16:37:19 2019 +0200
+++ b/schema/geoserver_views.sql	Mon May 27 16:38:07 2019 +0200
@@ -12,7 +12,9 @@
         g.date_info,
         g.source_organization,
         r.rwls AS reference_water_levels,
+        wl.measure_date AS gm_measuredate,
         wl.water_level AS gm_waterlevel,
+        wl_14d.n AS gm_n_14d,
         fca.forecast_accuracy_3d,
         fca.forecast_accuracy_1d
     FROM waterway.gauges g
@@ -22,10 +24,20 @@
                 FROM waterway.gauges_reference_water_levels
                 GROUP BY location, validity) AS r
             USING (location, validity)
-        LEFT JOIN (SELECT DISTINCT ON (location) location, water_level
+        LEFT JOIN (SELECT DISTINCT ON (location)
+                    location,
+                    measure_date,
+                    water_level
                 FROM waterway.gauge_measurements
                 ORDER BY location, measure_date DESC) AS wl
             USING (location)
+        LEFT JOIN (SELECT location, count(water_level) AS n
+                FROM waterway.gauge_measurements
+                -- consider all measurements within 14 days plus a tolerance
+                WHERE measure_date
+                    >= current_timestamp - '14 days 00:15'::interval
+                GROUP BY location) AS wl_14d
+            USING (location)
         LEFT JOIN (SELECT location,
                     max(acc) FILTER (WHERE
                         measure_date <= current_timestamp + '1 day'::interval)
@@ -89,7 +101,9 @@
         g.reference_water_levels,
         fal.date_info AS fa_date_info,
         fal.critical AS fa_critical,
+        g.gm_measuredate,
         g.gm_waterlevel,
+        g.gm_n_14d,
         srl.date_max,
         g.forecast_accuracy_3d,
         g.forecast_accuracy_1d