changeset 3240:5240f5440b62

client: implemnt pdf-template for fairwayprofile diagram
author Fadi Abbud <fadi.abbud@intevation.de>
date Fri, 10 May 2019 12:09:24 +0200
parents a7d44d1ae57d
children ecfa09241437
files client/src/components/fairway/Fairwayprofile.vue
diffstat 1 files changed, 211 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/fairway/Fairwayprofile.vue	Fri May 10 11:56:57 2019 +0200
+++ b/client/src/components/fairway/Fairwayprofile.vue	Fri May 10 12:09:24 2019 +0200
@@ -14,6 +14,19 @@
           Ground
         </div>
         <div>
+          <select
+            v-model="form.template"
+            @change="applyChange"
+            class="form-control d-block custom-select-sm w-100"
+          >
+            <option
+              v-for="template in templates"
+              :value="template"
+              :key="template.name"
+            >
+              {{ template.name }}
+            </option>
+          </select>
           <button
             @click="downloadPDF"
             type="button"
@@ -55,11 +68,15 @@
 import debounce from "debounce";
 import jsPDF from "jspdf";
 import canvg from "canvg";
+import { pdfgen } from "@/lib/mixins";
+import { HTTP } from "@/lib/http";
+import { displayError } from "@/lib/errors";
 
 const GROUND_COLOR = "#4A2F06";
 const WATER_COLOR = "#005DFF";
 
 export default {
+  mixins: [pdfgen],
   name: "fairwayprofile",
   components: {
     DiagramLegend: () => import("@/components/DiagramLegend")
@@ -73,7 +90,46 @@
         right: 40,
         bottom: 30,
         left: 40
-      }
+      },
+      form: {
+        template: null
+      },
+      templates: [],
+      defaultTemplate: {
+        name: "default",
+        properties: {
+          paperSize: "a4",
+          format: "lanscape"
+        },
+        elements: [
+          {
+            type: "diagram",
+            position: "topleft",
+            offset: { x: 20, y: 60 },
+            width: 290,
+            height: 100
+          },
+          {
+            type: "diagramtitle",
+            position: "topleft",
+            offset: { x: 90, y: 30 },
+            fontsize: 22,
+            color: "steelblue"
+          },
+          {
+            type: "diagramlegend",
+            position: "topleft",
+            offset: { x: 30, y: 160 },
+            color: "black"
+          }
+        ]
+      },
+      pdf: {
+        doc: null,
+        width: 32,
+        height: 297
+      },
+      templateData: null
     };
   },
   computed: {
@@ -175,12 +231,92 @@
       );
       this.$store.dispatch("fairwayprofile/clearCurrentProfile");
     },
+    applyChange() {
+      if (this.form.template.hasOwnProperty("properties")) {
+        this.templateData = this.defaultTemplate;
+        return;
+      }
+      if (this.form.template) {
+        HTTP.get("/templates/diagram/" + this.form.template.name, {
+          headers: {
+            "X-Gemma-Auth": localStorage.getItem("token"),
+            "Content-type": "text/xml; charset=UTF-8"
+          }
+        })
+          .then(response => {
+            this.templateData = response.data.template_data;
+          })
+          .catch(e => {
+            const { status, data } = e.response;
+            displayError({
+              title: this.$gettext("Backend Error"),
+              message: `${status}: ${data.message || data}`
+            });
+          });
+      }
+    },
     downloadPDF() {
+      if (this.templateData) {
+        this.pdf.doc = new jsPDF(
+          "l",
+          "mm",
+          this.templateData.properties.paperSize
+        );
+        // pdf width and height in millimeter (landscape)
+        this.pdf.width =
+          this.templateData.properties.paperSize === "a3" ? 420 : 297;
+        this.pdf.height =
+          this.templateData.properties.paperSize === "a3" ? 297 : 210;
+        let defaultOffset = { x: 0, Y: 0 },
+          defaultColor = "black";
+        this.templateData.elements.forEach(e => {
+          switch (e.type) {
+            case "diagram": {
+              this.addDiagram(
+                e.position,
+                e.offset || defaultOffset,
+                e.width,
+                e.height
+              );
+              break;
+            }
+            case "diagramlegend": {
+              this.addDiagramLegend(
+                e.position,
+                e.offset || defaultOffset,
+                e.color || defaultColor
+              );
+              break;
+            }
+            case "diagramtitle": {
+              this.addDiagramTitle(e.position, e.offset, e.fontsize, e.color);
+              break;
+            }
+          }
+        });
+      }
+      this.pdf.doc.save("Fairwayprofile diagram");
+    },
+    addDiagram(position, offset, width, height) {
+      let x = offset.x,
+        y = offset.y;
       var svg = this.$refs.diagramContainer.innerHTML;
       if (svg) {
         svg = svg.replace(/\r?\n|\r/g, "").trim();
       }
-      var pdf = new jsPDF("l", "mm", "a3");
+      // landscape format is used for both a3,a4 papersize
+      if (!width) {
+        width = this.form.paperSize === "a3" ? 380 : 290;
+      }
+      if (!height) {
+        height = this.form.paperSize === "a3" ? 130 : 100;
+      }
+      if (["topright", "bottomright"].indexOf(position) !== -1) {
+        x = this.pdf.width - offset.x - width;
+      }
+      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
+        y = this.pdf.height - offset.y - height;
+      }
       var canvas = document.createElement("canvas");
       canvas.width = window.innerWidth;
       canvas.height = window.innerHeight / 2;
@@ -190,34 +326,60 @@
         ignoreDimensions: true
       });
       var imgData = canvas.toDataURL("image/png");
-      pdf.addImage(imgData, "PNG", 40, 60, 380, 130);
-      // Fairway profile info for the pdf title
-      this.addDiagramTitle(pdf, 140, 30, 22, "steelblue");
-      this.addDiagramLegend(pdf, 60, 190, "black");
-      pdf.save("Fairwayprofile diagram");
+      this.pdf.doc.addImage(imgData, "PNG", x, y, width, height);
     },
-    addDiagramTitle(pdf, x, y, size, color) {
+    addDiagramTitle(position, offset, size, color) {
+      let x = offset.x,
+        y = offset.y;
       let fairwayInfo =
         this.selectedBottleneck + " (" + this.selectedSurvey.date_info + ")";
-      pdf.setTextColor(color);
-      pdf.setFontSize(22);
-      pdf.setFontStyle("bold");
-      pdf.text(fairwayInfo, x, y);
+      let width =
+        (this.pdf.doc.getStringUnitWidth(fairwayInfo) * size) / (72 / 25.6) +
+        size / 2;
+      // if position is on the right, x needs to be calculate with pdf width and
+      // the size of the element
+      if (["topright", "bottomright"].indexOf(position) !== -1) {
+        x = this.pdf.width - offset.x - width;
+      }
+      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
+        y = this.pdf.height - offset.y - this.getTextHeight(1);
+      }
+      this.pdf.doc.setTextColor(color);
+      this.pdf.doc.setFontSize(size);
+      this.pdf.doc.setFontStyle("bold");
+      this.pdf.doc.text(fairwayInfo, x, y, { baseline: "hanging" });
     },
     // Diagram legend
-    addDiagramLegend(pdf, x, y, color) {
-      pdf.setFontSize(10);
-      pdf.setTextColor(color);
-      pdf.setDrawColor("white");
-      pdf.setFillColor("#5995ff");
-      pdf.circle(x, y, 2, "FD");
-      pdf.text(x + 3, y + 1, "Water");
-      pdf.setFillColor("#1f4fff");
-      pdf.circle(x, y + 5, 2, "FD");
-      pdf.text(x + 3, y + 6, "Fairway");
-      pdf.setFillColor("#4a2f06");
-      pdf.circle(x, y + 10, 2, "FD");
-      pdf.text(x + 3, y + 11, "Ground");
+    addDiagramLegend(position, offset, color) {
+      let x = offset.x,
+        y = offset.y;
+      let width =
+        (this.pdf.doc.getStringUnitWidth("Ground") * 10) / (72 / 25.6) + 5;
+      if (["topright", "bottomright"].indexOf(position) !== -1) {
+        x = this.pdf.width - offset.x - width;
+      }
+      if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
+        y = this.pdf.height - offset.y - this.getTextHeight(3);
+      }
+      this.pdf.doc.setFontSize(10);
+      this.pdf.doc.setTextColor(color);
+      this.pdf.doc.setDrawColor("white");
+      this.pdf.doc.setFillColor("#5995ff");
+      this.pdf.doc.circle(x, y, 2, "FD");
+      this.pdf.doc.text(x + 3, y + 1, "Water");
+      this.pdf.doc.setFillColor("#1f4fff");
+      this.pdf.doc.circle(x, y + 5, 2, "FD");
+      this.pdf.doc.text(x + 3, y + 6, "Fairway");
+      this.pdf.doc.setFillColor("#4a2f06");
+      this.pdf.doc.circle(x, y + 10, 2, "FD");
+      this.pdf.doc.text(x + 3, y + 11, "Ground");
+    },
+    getTextHeight(numberOfLines) {
+      return (
+        numberOfLines *
+        ((this.pdf.doc.getFontSize() * 25.4) / 80) *
+        this.pdf.doc.getLineHeightFactor()
+      );
     },
     calcRelativeDepth(depth) {
       /* takes a depth value and substracts the delta of the relative waterlevel
@@ -460,6 +622,30 @@
   },
   mounted() {
     this.drawDiagram();
+    this.templates[0] = this.defaultTemplate;
+    this.form.template = this.templates[0];
+    this.templateData = this.form.template;
+    HTTP.get("/templates/diagram", {
+      headers: {
+        "X-Gemma-Auth": localStorage.getItem("token"),
+        "Content-type": "text/xml; charset=UTF-8"
+      }
+    })
+      .then(response => {
+        if (response.data.length) {
+          this.templates = response.data;
+          this.form.template = this.templates[0];
+          this.templates[this.templates.length] = this.defaultTemplate;
+          this.applyChange();
+        }
+      })
+      .catch(e => {
+        const { status, data } = e.response;
+        displayError({
+          title: this.$gettext("Backend Error"),
+          message: `${status}: ${data.message || data}`
+        });
+      });
   },
   updated() {
     this.drawDiagram();