changeset 2215:82867a69e10e pdf-export

merged default in pdf-export
author Markus Kottlaender <markus@intevation.de>
date Thu, 07 Feb 2019 11:27:07 +0100
parents 5a4b0c85e7a8 (current diff) 55bedb39295a (diff)
children 585373d33f8f
files client/src/components/Pdftool.vue client/src/store/map.js
diffstat 10 files changed, 220 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/ImportStretches.vue	Thu Feb 07 10:38:17 2019 +0100
+++ b/client/src/components/ImportStretches.vue	Thu Feb 07 11:27:07 2019 +0100
@@ -263,6 +263,7 @@
 import { mapState, mapGetters } from "vuex";
 import { displayError, displayInfo } from "@/lib/errors.js";
 import { formatSurveyDate } from "@/lib/date.js";
+import { LAYERS } from "@/store/map.js";
 
 export default {
   name: "importstretches",
@@ -356,6 +357,7 @@
       });
     },
     moveMapToStretch(index) {
+      this.$store.commit("map/setLayerVisible", LAYERS.STRETCHES);
       this.$store.commit("map/moveToExtent", {
         feature: this.stretches[index],
         zoom: 17,
@@ -406,6 +408,7 @@
       this.edit = true;
     },
     togglePipette(t) {
+      this.$store.commit("map/setLayerVisible", LAYERS.DISTANCEMARKSAXIS);
       if (t === "start") {
         this.pipetteStart = !this.pipetteStart;
         this.pipetteEnd = false;
--- a/client/src/components/Maplayer.vue	Thu Feb 07 10:38:17 2019 +0100
+++ b/client/src/components/Maplayer.vue	Thu Feb 07 11:27:07 2019 +0100
@@ -36,6 +36,7 @@
 import "ol/ol.css";
 import { Map, View } from "ol";
 import { WFS, GeoJSON } from "ol/format.js";
+import { equalTo } from "ol/format/filter.js";
 import { Stroke, Style, Fill } from "ol/style.js";
 
 /* for the sake of debugging */
@@ -163,6 +164,7 @@
       controls: [],
       view: new View({
         center: [this.extent.lon, this.extent.lat],
+        minZoom: 5, // restrict zooming out to ~size of Europe for width 1000px
         zoom: this.extent.zoom,
         projection: this.projection
       })
@@ -179,33 +181,37 @@
 
     // TODO make display of layers more dynamic, e.g. from a list
 
-    // loading the full WFS layer, by not setting the loader function
-    // and without bboxStrategy
-    var featureRequest = new WFS().writeGetFeature({
-      srsName: "EPSG:3857",
-      featureNS: "gemma",
-      featurePrefix: "gemma",
-      featureTypes: ["fairway_dimensions"],
-      outputFormat: "application/json"
-    });
+    // load different fairway dimension layers (level of service)
+    ["1", "2", "3"].forEach(los => {
+      // loading the full WFS layer, by not setting the loader function
+      // and without bboxStrategy
+      var featureRequest = new WFS().writeGetFeature({
+        srsName: "EPSG:3857",
+        featureNS: "gemma",
+        featurePrefix: "gemma",
+        featureTypes: ["fairway_dimensions"],
+        outputFormat: "application/json",
+        filter: equalTo("level_of_service", los)
+      });
 
-    // NOTE: loading the full fairway_dimensions makes sure
-    //       that all are available for the intersection with the profile
-    HTTP.post(
-      "/internal/wfs",
-      new XMLSerializer().serializeToString(featureRequest),
-      {
-        headers: {
-          "X-Gemma-Auth": localStorage.getItem("token"),
-          "Content-type": "text/xml; charset=UTF-8"
+      // NOTE: loading the full fairway_dimensions makes sure
+      //       that all are available for the intersection with the profile
+      HTTP.post(
+        "/internal/wfs",
+        new XMLSerializer().serializeToString(featureRequest),
+        {
+          headers: {
+            "X-Gemma-Auth": localStorage.getItem("token"),
+            "Content-type": "text/xml; charset=UTF-8"
+          }
         }
-      }
-    ).then(response => {
-      this.getVSourceByName("Fairway Dimensions").addFeatures(
-        new GeoJSON().readFeatures(JSON.stringify(response.data))
-      );
-      // would scale to the extend of all resulting features
-      // this.openLayersMap.getView().fit(vectorSrc.getExtent());
+      ).then(response => {
+        this.getVSourceByName("Fairway Dimensions LOS " + los).addFeatures(
+          new GeoJSON().readFeatures(JSON.stringify(response.data))
+        );
+        // would scale to the extend of all resulting features
+        // this.openLayersMap.getView().fit(vectorSrc.getExtent());
+      });
     });
 
     // load following layers with bboxStrategy (using our request builder)
--- a/client/src/components/Pdftool.vue	Thu Feb 07 10:38:17 2019 +0100
+++ b/client/src/components/Pdftool.vue	Thu Feb 07 11:27:07 2019 +0100
@@ -144,7 +144,7 @@
   },
   computed: {
     ...mapState("application", ["showPdfTool", "logoForPDF", "pdfTemplates"]),
-    ...mapState("bottlenecks", ["selectedSurvey"]),
+    ...mapState("bottlenecks", ["selectedBottleneck", "selectedSurvey"]),
     ...mapState("map", ["openLayersMap", "isolinesLegendImgDataURL"]),
     ...mapGetters("map", ["getLayerByName"]),
     ...mapState("user", ["user"])
@@ -254,7 +254,8 @@
         //self.addAboutBox(pdf, width, height);
 
         if (self.getLayerByName("Bottleneck isolines").isVisible) {
-          self.addLegend(pdf, width, height);
+          self.addBottleneckInfo(pdf, 13, width, height);
+          self.addLegend(pdf, 14, width, height);
         }
         if (template) {
           template.elements.forEach(t => {
@@ -406,7 +407,7 @@
         unit = "km";
         unitConversionFactor = 1e6;
       } else if (maxLength >= 1e4) {
-        // >= 10 m)
+        // >= 10 m
         unit = "m";
         unitConversionFactor = 1e3;
       }
@@ -519,7 +520,7 @@
         "Dislaimer: Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua.";
       this.addText(doc, 5, docHeight - 6, 8, "black", 115, str);
     },
-    addLegend(doc, docWidth) {
+    addLegend(doc, fromTop, docWidth) {
       // transforming into an HTMLImageElement only to find out
       // the width x height of the legend image
       // FUTURE: find a better way to get the width and height
@@ -527,8 +528,46 @@
       legendImage.src = this.isolinesLegendImgDataURL;
       let aspectRatio = legendImage.width / legendImage.height;
 
-      this.addRoundedBox(doc, docWidth - 54, 0, 54, 50 / aspectRatio + 4);
-      doc.addImage(legendImage, docWidth - 52, 2, 50, 50 / aspectRatio);
+      this.addRoundedBox(doc, docWidth - 54, fromTop, 54, 50 / aspectRatio + 4);
+      doc.addImage(
+        legendImage,
+        docWidth - 52,
+        fromTop + 2,
+        50,
+        50 / aspectRatio
+      );
+    },
+    addBottleneckInfo(doc, height, docWidth) {
+      this.addRoundedBox(doc, docWidth - 54, 0, 54, height);
+
+      console.log("Fontlist =", doc.getFontList());
+      doc.setFont("times", "normal");
+
+      let name, w, str;
+
+      doc.setFontStyle("italic");
+      name = this.$gettext("Bottleneck") + ": ";
+      w = doc.getTextWidth(name);
+      this.addText(doc, docWidth - 51, 4, 8, "black", 46, name);
+      doc.setFontStyle("bold");
+      str = this.selectedBottleneck;
+      this.addText(doc, docWidth - 51 + w, 4, 8, "black", 46, str);
+
+      doc.setFontStyle("italic");
+      name = this.$gettext("Survey date") + ": ";
+      w = doc.getTextWidth(name);
+      this.addText(doc, docWidth - 51, 7.5, 8, "black", 46, name);
+      doc.setFontStyle("normal");
+      str = this.selectedSurvey.date_info;
+      this.addText(doc, docWidth - 51 + w, 7.5, 8, "black", 46, str);
+
+      doc.setFontStyle("italic");
+      name = this.$gettext("Ref gauge") + ": ";
+      w = doc.getTextWidth(name);
+      this.addText(doc, docWidth - 51, 11, 8, "black", 46, name);
+      doc.setFontStyle("normal");
+      str = this.selectedSurvey.gauge_objname;
+      this.addText(doc, docWidth - 51 + w, 11, 8, "black", 46, str);
     }
   },
   mounted() {
--- a/client/src/components/staging/StagingDetail.vue	Thu Feb 07 10:38:17 2019 +0100
+++ b/client/src/components/staging/StagingDetail.vue	Thu Feb 07 11:27:07 2019 +0100
@@ -162,6 +162,7 @@
 import { or as orFilter, equalTo as equalToFilter } from "ol/format/filter.js";
 import { displayError } from "@/lib/errors.js";
 import { mapState } from "vuex";
+import { LAYERS } from "@/store/map.js";
 
 export default {
   name: "stagingdetail",
@@ -206,6 +207,7 @@
   },
   methods: {
     zoomToStretch(name) {
+      this.$store.commit("map/setLayerVisible", LAYERS.STRETCHES);
       this.$store
         .dispatch("imports/loadStretch", name)
         .then(response => {
@@ -301,6 +303,7 @@
       return item.status === STATES.APPROVED;
     },
     moveToBottleneck(index) {
+      this.$store.commit("map/setLayerVisible", LAYERS.BOTTLENECKS);
       this.moveToExtent(this.bottlenecks[index]);
     },
     moveToExtent(feature) {
--- a/client/src/store/fairway.js	Thu Feb 07 10:38:17 2019 +0100
+++ b/client/src/store/fairway.js	Thu Feb 07 11:27:07 2019 +0100
@@ -201,7 +201,7 @@
             .then(() => {
               rootState.map.cutTool.setActive(false);
               rootGetters["map/getVSourceByName"](
-                "Fairway Dimensions"
+                "Fairway Dimensions LOS 3"
               ).forEachFeatureIntersectingExtent(
                 // need to use EPSG:3857 which is the proj of vectorSource
                 profileLine
--- a/client/src/store/map.js	Thu Feb 07 10:38:17 2019 +0100
+++ b/client/src/store/map.js	Thu Feb 07 11:27:07 2019 +0100
@@ -33,6 +33,23 @@
 import bbox from "@turf/bbox";
 import app from "../main";
 
+const LAYERS = {
+  OPENSTREETMAP: "Open Streetmap",
+  INLANDECDIS: "Inland ECDIS chart Danube",
+  WATERWAYAREA: "Waterway Area",
+  STRETCHES: "Stretches",
+  FAIRWAYDIMENSIONSLOS1: "Fairway Dimensions LOS 1",
+  FAIRWAYDIMENSIONSLOS2: "Fairway Dimensions LOS 2",
+  FAIRWAYDIMENSIONSLOS3: "Fairway Dimensions LOS 3",
+  WATERWAYAXIS: "Waterway Axis",
+  BOTTLENECKS: "Bottlenecks",
+  BOTTLENECKISOLINE: "Bottleneck isolines",
+  DISTANCEMARKS: "Distance marks",
+  DISTANCEMARKSAXIS: "Distance marks, Axis",
+  DRAWTOOL: "Draw Tool",
+  CUTTOOL: "Cut Tool"
+};
+
 // initial state
 const init = () => {
   return {
@@ -51,7 +68,7 @@
     isolinesLegendImgDataURL: "",
     layers: [
       {
-        name: "Open Streetmap",
+        name: LAYERS.OPENSTREETMAP,
         data: new TileLayer({
           source: new OSM()
         }),
@@ -59,7 +76,7 @@
         showInLegend: true
       },
       {
-        name: "Inland ECDIS chart Danube",
+        name: LAYERS.INLANDECDIS,
         data: new TileLayer({
           source: new TileWMS({
             preload: 1,
@@ -72,7 +89,7 @@
         showInLegend: true
       },
       {
-        name: "Waterway Area",
+        name: LAYERS.WATERWAYAREA,
         data: new VectorLayer({
           source: new VectorSource({
             strategy: bboxStrategy
@@ -88,7 +105,7 @@
         showInLegend: true
       },
       {
-        name: "Stretches",
+        name: LAYERS.STRETCHES,
         data: new VectorLayer({
           source: new VectorSource({
             strategy: bboxStrategy
@@ -107,18 +124,14 @@
         showInLegend: true
       },
       {
-        name: "Fairway Dimensions",
+        name: LAYERS.FAIRWAYDIMENSIONSLOS1,
         data: new VectorLayer({
           source: new VectorSource(),
-          style: function(feature) {
-            let strokeColor =
-              feature.get("level_of_service").toString() === "3"
-                ? "rgba(0, 0, 255, 1.0)"
-                : "rgba(0, 100, 150, 1.0)";
+          style: function() {
             return [
               new Style({
                 stroke: new Stroke({
-                  color: strokeColor,
+                  color: "rgba(76, 76, 255, 1.0)",
                   width: 2
                 })
               }),
@@ -129,7 +142,7 @@
                   fill: new Fill({
                     color: "black"
                   }),
-                  text: "LOS: " + feature.get("level_of_service").toString()
+                  text: "LOS: 1"
                   //, zIndex: 10
                 })
               })
@@ -140,7 +153,65 @@
         showInLegend: true
       },
       {
-        name: "Waterway Axis",
+        name: LAYERS.FAIRWAYDIMENSIONSLOS2,
+        data: new VectorLayer({
+          source: new VectorSource(),
+          style: function() {
+            return [
+              new Style({
+                stroke: new Stroke({
+                  color: "rgba(38, 38, 127, 1.0)",
+                  width: 2
+                })
+              }),
+              new Style({
+                text: new Text({
+                  font: 'bold 12px "Open Sans", "sans-serif"',
+                  placement: "line",
+                  fill: new Fill({
+                    color: "black"
+                  }),
+                  text: "LOS: 2"
+                  //, zIndex: 10
+                })
+              })
+            ];
+          }
+        }),
+        isVisible: true,
+        showInLegend: true
+      },
+      {
+        name: LAYERS.FAIRWAYDIMENSIONSLOS3,
+        data: new VectorLayer({
+          source: new VectorSource(),
+          style: function() {
+            return [
+              new Style({
+                stroke: new Stroke({
+                  color: "rgba(0, 0, 255, 1.0)",
+                  width: 2
+                })
+              }),
+              new Style({
+                text: new Text({
+                  font: 'bold 12px "Open Sans", "sans-serif"',
+                  placement: "line",
+                  fill: new Fill({
+                    color: "black"
+                  }),
+                  text: "LOS: 3"
+                  //, zIndex: 10
+                })
+              })
+            ];
+          }
+        }),
+        isVisible: true,
+        showInLegend: true
+      },
+      {
+        name: LAYERS.WATERWAYAXIS,
         data: new VectorLayer({
           source: new VectorSource({
             strategy: bboxStrategy
@@ -157,7 +228,7 @@
         showInLegend: true
       },
       {
-        name: "Bottlenecks",
+        name: LAYERS.BOTTLENECKS,
         data: new VectorLayer({
           source: new VectorSource({
             strategy: bboxStrategy
@@ -176,7 +247,7 @@
         showInLegend: true
       },
       {
-        name: "Bottleneck isolines",
+        name: LAYERS.BOTTLENECKISOLINE,
         data: new TileLayer({
           source: new TileWMS({
             preload: 0,
@@ -204,7 +275,7 @@
         showInLegend: true
       },
       {
-        name: "Distance marks",
+        name: LAYERS.DISTANCEMARKS,
         forLegendStyle: { point: true, resolution: 8 },
         data: new VectorLayer({
           source: new VectorSource({
@@ -215,7 +286,7 @@
         showInLegend: true
       },
       {
-        name: "Distance marks, Axis",
+        name: LAYERS.DISTANCEMARKSAXIS,
         forLegendStyle: { point: true, resolution: 8 },
         data: new VectorLayer({
           source: new VectorSource({
@@ -252,7 +323,7 @@
         showInLegend: true
       },
       {
-        name: "Draw Tool",
+        name: LAYERS.DRAWTOOL,
         data: new VectorLayer({
           source: new VectorSource({ wrapX: false }),
           style: function(feature) {
@@ -300,7 +371,7 @@
         showInLegend: false
       },
       {
-        name: "Cut Tool",
+        name: LAYERS.CUTTOOL,
         data: new VectorLayer({
           source: new VectorSource({ wrapX: false }),
           style: function(feature) {
@@ -371,6 +442,21 @@
     extent: (state, extent) => {
       state.extent = extent;
     },
+    setLayerVisible: (state, name) => {
+      const layer = state.layers.findIndex(l => l.name === name);
+      state.layers[layer].isVisible = true;
+      state.layers[layer].data.setVisible(true);
+    },
+    setLayerInvisible: (state, name) => {
+      const layer = state.layers.findIndex(l => l.name === name);
+      state.layers[layer].isVisible = false;
+      state.layers[layer].data.setVisible(false);
+    },
+    toggleVisibilityByName: (state, name) => {
+      const layer = state.layers.findIndex(l => l.name === name);
+      state.layers[layer].isVisible = !state.layers[layer].isVisible;
+      state.layers[layer].data.setVisible(state.layers[layer].isVisible);
+    },
     toggleVisibility: (state, layer) => {
       state.layers[layer].isVisible = !state.layers[layer].isVisible;
       state.layers[layer].data.setVisible(state.layers[layer].isVisible);
@@ -591,3 +677,5 @@
     }
   }
 };
+
+export { LAYERS };
--- a/pkg/controllers/surveys.go	Thu Feb 07 10:38:17 2019 +0100
+++ b/pkg/controllers/surveys.go	Thu Feb 07 11:27:07 2019 +0100
@@ -4,13 +4,14 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later
 // License-Filename: LICENSES/AGPL-3.0.txt
 //
-// Copyright (C) 2018 by via donau
+// Copyright (C) 2018, 2019 by via donau
 //   – Österreichische Wasserstraßen-Gesellschaft mbH
 // Software engineering by Intevation GmbH
 //
 // Author(s):
 //  * Sascha Wilde <sascha.wilde@intevation.de>
 //  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
+//  * Bernhard Reiter <bernhard.reiter@intevation.de>
 
 package controllers
 
@@ -26,10 +27,15 @@
 	listSurveysSQL = `
 SELECT
   s.bottleneck_id,
-  s.date_info::text
-FROM waterway.bottlenecks b JOIN waterway.sounding_results s
-ON b.id = s.bottleneck_id
-WHERE b.objnam=$1`
+  s.date_info::text,
+  bg.objname AS gauge_objname
+FROM
+  ( SELECT * FROM waterway.bottlenecks AS b, waterway.gauges AS g
+    WHERE b.fk_g_fid = g.location
+  ) AS bg
+  JOIN waterway.sounding_results AS s
+ON bg.id = s.bottleneck_id
+WHERE bg.objnam=$1`
 )
 
 func listSurveys(
@@ -55,6 +61,7 @@
 		if err = rows.Scan(
 			&survey.BottleneckID,
 			&survey.DateInfo,
+			&survey.ReferenceGauge,
 		); err != nil {
 			return
 		}
--- a/pkg/imports/wp.go	Thu Feb 07 10:38:17 2019 +0100
+++ b/pkg/imports/wp.go	Thu Feb 07 11:27:07 2019 +0100
@@ -98,14 +98,6 @@
 )`
 
 	insertWaterwayProfileSQL = `
-WITH point AS (
-  SELECT
-	ST_Buffer(geom, $14::float) AS geom,
-    geom                AS point
-  FROM waterway.distance_marks_virtual
-  WHERE location_code =
-    ($1::char(2), $2::char(3), $3::char(5), $4::char(5), $5::int)
-)
 INSERT INTO waterway.waterway_profiles (
   location,
   geom,
@@ -120,9 +112,11 @@
 ) VALUES (
   ($1, $2, $3, $4, $5),
   ( SELECT wp_geoms.geom
-    FROM wp_geoms, point
-    WHERE wp_geoms.geom && point.geom
-    ORDER BY ST_Distance(point.point, wp_geoms.geom, true)
+    FROM wp_geoms, waterway.distance_marks_virtual AS dmv
+    WHERE dmv.location_code =
+        ($1::char(2), $2::char(3), $3::char(5), $4::char(5), $5::int)
+      AND ST_DWithin(dmv.geom, wp_geoms.geom, $14::float)
+    ORDER BY ST_Distance(dmv.geom, wp_geoms.geom, true)
     LIMIT 1
   ),
   $6,
@@ -236,6 +230,10 @@
 		return err
 	}
 
+	if _, err := tx.ExecContext(ctx, createTempIndexSQL); err != nil {
+		return err
+	}
+
 	insertStmt, err := tx.PrepareContext(ctx, insertGeomTmpTableSQL)
 	if err != nil {
 		return err
--- a/pkg/models/surveys.go	Thu Feb 07 10:38:17 2019 +0100
+++ b/pkg/models/surveys.go	Thu Feb 07 11:27:07 2019 +0100
@@ -4,7 +4,7 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later
 // License-Filename: LICENSES/AGPL-3.0.txt
 //
-// Copyright (C) 2018 by via donau
+// Copyright (C) 2018, 2019 by via donau
 //   – Österreichische Wasserstraßen-Gesellschaft mbH
 // Software engineering by Intevation GmbH
 //
@@ -15,7 +15,8 @@
 
 type (
 	Survey struct {
-		BottleneckID string `json:"bottleneck_id"`
-		DateInfo     string `json:"date_info"`
+		BottleneckID   string `json:"bottleneck_id"`
+		DateInfo       string `json:"date_info"`
+		ReferenceGauge string `json:"gauge_objname"`
 	}
 )
--- a/schema/gemma.sql	Thu Feb 07 10:38:17 2019 +0100
+++ b/schema/gemma.sql	Thu Feb 07 11:27:07 2019 +0100
@@ -329,7 +329,7 @@
     -- At least geoserver-2.13.2 does not serve type geography correctly
     -- and does not serve the location_code as isrs type
     CREATE VIEW distance_marks_geoserver AS
-        SELECT location_code::VARCHAR,
+        SELECT isrs_asText(location_code),
                geom::Geometry(POINT, 4326),
                related_enc,
                (location_code).hectometre
@@ -400,7 +400,6 @@
         location isrs NOT NULL,
         geom geography(linestring, 4326), -- TODO: NOT NIL
         validity tstzrange,
-        EXCLUDE USING GIST (isrs_asText(location) WITH =, validity WITH &&),
         lnwl double precision,
         mwl double precision,
         hnwl double precision,
@@ -412,7 +411,10 @@
         date_info timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
         source_organization varchar NOT NULL,
         staging_done boolean NOT NULL DEFAULT false,
-        UNIQUE (location, validity, staging_done)
+        EXCLUDE USING GIST (
+            isrs_asText(location) WITH =,
+            validity WITH &&,
+            CAST(staging_done AS int) WITH =)
     )
     CREATE TRIGGER waterway_profiles_date_info
         BEFORE UPDATE ON waterway_profiles