changeset 2247:e6fba449aa3c

merged pdf-export in default
author Markus Kottlaender <markus@intevation.de>
date Wed, 13 Feb 2019 16:41:00 +0100
parents 2cba13653a58
children cce158db02b0
files client/src/assets/application.scss client/src/components/Pdftool.vue client/src/components/systemconfiguration/PDFTemplates.vue client/src/components/systemconfiguration/Systemconfiguration.vue client/src/store/application.js pkg/controllers/printtemplates.go
diffstat 6 files changed, 160 insertions(+), 193 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/assets/application.scss	Wed Feb 13 16:13:44 2019 +0100
+++ b/client/src/assets/application.scss	Wed Feb 13 16:41:00 2019 +0100
@@ -131,11 +131,10 @@
 }
 
 .list-fade-enter-active, .list-fade-leave-active {
-  transition: transform .3s;
+  transition: opacity .3s;
 }
 .list-fade-enter, .list-fade-leave-to {
   opacity: 0;
-  transform: translateY(20px);
 }
 
 .pointer {
--- a/client/src/components/Pdftool.vue	Wed Feb 13 16:13:44 2019 +0100
+++ b/client/src/components/Pdftool.vue	Wed Feb 13 16:41:00 2019 +0100
@@ -57,35 +57,18 @@
             </select>
           </div>
         </div>
-        <!--
-        <small class="d-block my-2">
-          <input
-            type="radio"
-            id="pdfexport-downloadtype-download"
-            value="download"
-            v-model="form.downloadType"
-            selected
-          />
-          <label for="pdfexport-downloadtype-download" class="ml-1 mr-2">
-            <translate>Download</translate>
-          </label>
-          <input
-            type="radio"
-            id="pdfexport-downloadtype-open"
-            value="open"
-            v-model="form.downloadType"
-          />
-          <label for="pdfexport-downloadtype-open" class="ml-1">
-            <translate>Open in new window</translate>
-          </label>
-        </small>
-        -->
         <button
           @click="download"
           type="button"
           :disabled="!readyToGenerate"
           class="btn btn-sm btn-info d-block w-100 mt-2"
         >
+          <font-awesome-icon
+            v-if="!readyToGenerate"
+            class="mr-1"
+            icon="spinner"
+            spin
+          />
           <translate>Generate PDF</translate>
         </button>
       </div>
@@ -114,6 +97,8 @@
 import "@/lib/font-linbiolinum.js";
 import { getPointResolution } from "ol/proj.js";
 import locale2 from "locale2";
+import { HTTP } from "../lib/http";
+import { displayError } from "@/lib/errors.js";
 
 var paperSizes = {
   // in millimeter, landscape [width, height]
@@ -132,6 +117,7 @@
         downloadType: "download",
         resolution: "80"
       },
+      templateData: null,
       pdf: {
         doc: null,
         width: null,
@@ -153,14 +139,28 @@
     // applied to the rest of the form.
     applyTemplateToForm() {
       if (this.form.template) {
-        this.form.format = this.form.template.properties.format;
-        this.form.paperSize = this.form.template.properties.paperSize;
-        this.form.resolution = this.form.template.properties.resolution;
+        HTTP.get("/templates/print/" + 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;
+            this.form.format = this.templateData.properties.format;
+            this.form.paperSize = this.templateData.properties.paperSize;
+            this.form.resolution = this.templateData.properties.resolution;
+          })
+          .catch(e => {
+            const { status, data } = e.response;
+            displayError({
+              title: "Backend Error",
+              message: `${status}: ${data.message || data}`
+            });
+          });
       }
     },
     download() {
-      let template = this.form.template;
-
       // disable button while working on it
       this.readyToGenerate = false;
 
@@ -237,15 +237,15 @@
           this.pdf.height
         );
 
-        if (template) {
+        if (this.templateData) {
           this.pdf.doc.setFont("linbiolinum", "normal");
           let defaultFontSize = 11,
-            defaultRounding = 0,
+            defaultRounding = 2,
             defaultTextColor = "black",
             defaultBgColor = "white",
             defaultPadding = 3,
             defaultOffset = { x: 0, y: 0 };
-          template.elements.forEach(e => {
+          this.templateData.elements.forEach(e => {
             switch (e.type) {
               case "text": {
                 this.addText(
@@ -673,7 +673,7 @@
         this.getLayerByName("Bottleneck isolines").isVisible
       ) {
         let width = 54;
-        let height = 13;
+        let height = 17;
         let padding = 3;
 
         // x/y defaults to offset for topleft corner (normal x/y coordinates)
@@ -704,11 +704,13 @@
         this.pdf.doc.setFontStyle("bold");
         this.pdf.doc.text(x + padding + w, y + padding, str);
 
+        let survey = this.selectedSurvey;
+
         str = this.$gettext("Survey date") + ": ";
         w = this.pdf.doc.getTextWidth(str);
         this.pdf.doc.setFontStyle("italic");
         this.pdf.doc.text(x + padding, y + padding + 3, str);
-        str = this.selectedSurvey.date_info;
+        str = survey.date_info;
         this.pdf.doc.setFontStyle("normal");
         this.pdf.doc.text(x + padding + w, y + padding + 3, str);
 
@@ -716,9 +718,22 @@
         w = this.pdf.doc.getTextWidth(str);
         this.pdf.doc.setFontStyle("italic");
         this.pdf.doc.text(x + padding, y + padding + 6, str);
-        str = this.selectedSurvey.gauge_objname;
+        str = survey.gauge_objname;
         this.pdf.doc.setFontStyle("normal");
         this.pdf.doc.text(x + padding + w, y + padding + 6, str);
+
+        str = this.$gettext("Depth relativ to") + ": ";
+        w = this.pdf.doc.getTextWidth(str);
+        this.pdf.doc.setFontStyle("italic");
+        this.pdf.doc.text(x + padding, y + padding + 9, str);
+        this.pdf.doc.setFontStyle("normal");
+        str = survey.depth_reference + " = ";
+        if (survey.hasOwnProperty("waterlevel_value")) {
+          str += survey.waterlevel_value + " cm";
+        } else {
+          str += "?";
+        }
+        this.pdf.doc.text(x + padding + w, y + padding + 9, str);
       }
     },
     replacePlaceholders(text) {
@@ -741,6 +756,7 @@
   mounted() {
     this.$store.dispatch("application/loadPdfTemplates").then(() => {
       this.form.template = this.pdfTemplates[0];
+      this.applyTemplateToForm();
     });
   }
 };
--- a/client/src/components/systemconfiguration/PDFTemplates.vue	Wed Feb 13 16:13:44 2019 +0100
+++ b/client/src/components/systemconfiguration/PDFTemplates.vue	Wed Feb 13 16:41:00 2019 +0100
@@ -4,36 +4,25 @@
       <h5><translate>PDF-Templates</translate></h5>
       <input
         @change="upload"
-        id="uploadPDFTemplates"
-        ref="uploadPDFTemplates"
+        id="uploadPDFTemplate"
+        ref="uploadPDFTemplate"
         type="file"
         style="visibility:hidden"
       />
-      <button
-        class="btn btn-sm btn-info"
-        @click="$refs.uploadPDFTemplates.click()"
-      >
-        <font-awesome-icon icon="spinner" class="fa-spin" v-if="uploading" />
-        <font-awesome-icon icon="plus" v-else />
-      </button>
     </div>
-    <div class="d-flex mt-1">
+    <div class="mt-1">
       <table class="table table-sm">
         <thead>
           <tr>
             <th>Name</th>
-            <th>Description</th>
             <th>Date</th>
-            <th>Country</th>
             <th></th>
           </tr>
         </thead>
         <transition-group name="list-fade" tag="tbody">
           <tr v-for="template in pdfTemplates" :key="template.name">
             <td>{{ template.name }}</td>
-            <td>{{ template.description }}</td>
-            <td>{{ template.date }}</td>
-            <td></td>
+            <td>{{ template.time }}</td>
             <td class="text-right">
               <button class="btn btn-sm btn-info mr-2">
                 <font-awesome-icon icon="download" />
@@ -51,6 +40,18 @@
           </tr>
         </transition-group>
       </table>
+      <button
+        class="btn btn-sm btn-info"
+        @click="$refs.uploadPDFTemplate.click()"
+      >
+        <font-awesome-icon
+          icon="spinner"
+          class="fa-spin fa-fw"
+          v-if="uploading"
+        />
+        <font-awesome-icon icon="upload" class="fa-fw" v-else />
+        <translate>Upload new template</translate>
+      </button>
     </div>
 
     <div
@@ -126,10 +127,10 @@
       this.uploading = true;
       this.$store
         .dispatch(
-          "application/uploadPDFTemplates",
-          this.$refs.uploadPDFTemplates.files
+          "application/uploadPDFTemplate",
+          this.$refs.uploadPDFTemplate.files
         )
-        .then(() => {
+        .finally(() => {
           this.uploading = false;
         });
     },
@@ -137,6 +138,9 @@
       this.showDeleteTemplatePrompt = false;
       this.$store.dispatch("application/removePDFTemplate", template);
     }
+  },
+  mounted() {
+    this.$store.dispatch("application/loadPdfTemplates");
   }
 };
 </script>
--- a/client/src/components/systemconfiguration/Systemconfiguration.vue	Wed Feb 13 16:13:44 2019 +0100
+++ b/client/src/components/systemconfiguration/Systemconfiguration.vue	Wed Feb 13 16:41:00 2019 +0100
@@ -31,7 +31,7 @@
             <translate>Send</translate>
           </a>
         </div>
-        <!-- <PDFTemplates /> -->
+        <PDFTemplates />
       </div>
       <!-- card-body -->
     </div>
--- a/client/src/store/application.js	Wed Feb 13 16:13:44 2019 +0100
+++ b/client/src/store/application.js	Wed Feb 13 16:41:00 2019 +0100
@@ -15,7 +15,8 @@
  */
 
 import { version } from "../../package.json";
-// import { HTTP } from "../lib/http";
+import { HTTP } from "../lib/http";
+import { displayError } from "@/lib/errors.js";
 
 // initial state
 const init = () => {
@@ -112,146 +113,93 @@
   },
   actions: {
     loadPdfTemplates({ commit }) {
-      return new Promise(resolve => {
-        // pretend we do something async
-        setTimeout(function() {
-          commit("pdfTemplates", [
-            {
-              name: "Default Template",
-              properties: {
-                format: "landscape",
-                resolution: "120",
-                paperSize: "a4"
-              },
-              elements: [
-                {
-                  type: "textbox",
-                  position: "bottomleft",
-                  offset: { x: 2, y: 2 },
-                  width: 100,
-                  fontSize: 8,
-                  text: "Date of publication: {date} - generated by: {user}"
-                },
-                {
-                  type: "bottleneck",
-                  position: "topleft",
-                  offset: { x: 2, y: 2 }
-                },
-                {
-                  type: "legend",
-                  position: "topleft",
-                  offset: { x: 2, y: 18 }
-                },
-                {
-                  type: "scalebar",
-                  position: "bottomright",
-                  offset: { x: 2, y: 2 }
-                },
-                {
-                  type: "northarrow",
-                  position: "topright",
-                  offset: { x: 10, y: 5 },
-                  size: 2
-                }
-              ]
-            },
-            {
-              name: "Full Template",
-              properties: {
-                format: "landscape",
-                resolution: "120",
-                paperSize: "a4"
-              },
-              elements: [
-                {
-                  type: "box",
-                  position: "topleft",
-                  offset: { x: 20, y: 2 },
-                  width: 60,
-                  height: 25,
-                  color: "green"
-                },
-                {
-                  type: "text",
-                  position: "topleft",
-                  offset: { x: 23, y: 5 },
-                  width: 56,
-                  fontSize: 10,
-                  color: "greenyellow",
-                  text:
-                    "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
-                },
-                {
-                  type: "textbox",
-                  position: "bottomleft",
-                  offset: { x: 2, y: 2 },
-                  width: 90,
-                  padding: 3,
-                  fontSize: 7,
-                  color: "gray",
-                  background: "white",
-                  text: "Date of publication: {date} - generated by: {user}"
-                },
-                {
-                  type: "image",
-                  format: "PNG",
-                  position: "bottomleft",
-                  offset: { x: 2, y: 10 },
-                  width: 90,
-                  height: 12,
-                  border: 2
-                },
-                {
-                  type: "bottleneck",
-                  position: "topright",
-                  offset: { x: 2, y: 2 }
-                },
-                {
-                  type: "legend",
-                  position: "topright",
-                  offset: { x: 2, y: 18 }
-                },
-                {
-                  type: "scalebar",
-                  position: "bottomright",
-                  offset: { x: 2, y: 2 }
-                },
-                {
-                  type: "northarrow",
-                  position: "topleft",
-                  offset: { x: 8, y: 4 },
-                  size: 2
-                }
-              ]
-            }
-          ]);
-          resolve();
-        }, 500);
+      return new Promise((resolve, reject) => {
+        HTTP.get("/templates/print", {
+          headers: {
+            "X-Gemma-Auth": localStorage.getItem("token"),
+            "Content-type": "text/xml; charset=UTF-8"
+          }
+        })
+          .then(response => {
+            commit("pdfTemplates", response.data);
+            resolve();
+          })
+          .catch(e => {
+            reject(e);
+            const { status, data } = e.response;
+            displayError({
+              title: "Backend Error",
+              message: `${status}: ${data.message || data}`
+            });
+          });
       });
     },
-    uploadPDFTemplates({ state, commit }, files) {
+    uploadPDFTemplate({ dispatch }, files) {
       return new Promise((resolve, reject) => {
-        setTimeout(() => {
-          const reader = new FileReader();
-          reader.onload = event => {
-            let templates = state.pdfTemplates;
-            templates.push(JSON.parse(event.target.result));
-            commit("pdfTemplates", templates);
-            // TODO: send template to server
-          };
-          reader.onerror = error => reject(error);
-          reader.readAsText(files[0]);
-          resolve();
-        }, 1000);
+        const reader = new FileReader();
+        reader.onload = event => {
+          let template;
+          try {
+            template = JSON.parse(event.target.result);
+          } catch (e) {
+            displayError({
+              title: "Format Error",
+              message: "Uploaded file does not contain valid json data."
+            });
+            reject(e);
+          }
+          if (template.name) {
+            HTTP.post(
+              "/templates/print/" + template.name,
+              {
+                template_name: template.name,
+                template_data: template
+              },
+              {
+                headers: {
+                  "X-Gemma-Auth": localStorage.getItem("token"),
+                  "Content-type": "text/xml; charset=UTF-8"
+                }
+              }
+            )
+              .then(response => {
+                dispatch("loadPdfTemplates");
+                resolve(response);
+              })
+              .catch(e => {
+                reject(e);
+                const { status, data } = e.response;
+                displayError({
+                  title: "Backend Error",
+                  message: `${status}: ${data.message || data}`
+                });
+              });
+          } else {
+            reject();
+            displayError({
+              title: "Format Error",
+              message: "The provided template has no name property."
+            });
+          }
+        };
+        reader.onerror = error => reject(error);
+        reader.readAsText(files[0]);
       });
     },
     removePDFTemplate({ state, commit }, template) {
-      let templates = state.pdfTemplates;
-      let removeIndex = templates.findIndex(t => t.name === template.name);
-      if (removeIndex !== -1) {
-        templates.splice(removeIndex, 1);
-        commit("pdfTemplates", templates);
-      }
+      HTTP.delete("/templates/print/" + template.name, {
+        headers: {
+          "X-Gemma-Auth": localStorage.getItem("token"),
+          "Content-type": "text/xml; charset=UTF-8"
+        }
+      }).then(() => {
+        let templates = state.pdfTemplates;
+        let removeIndex = templates.findIndex(t => t.name === template.name);
+        if (removeIndex !== -1) {
+          templates.splice(removeIndex, 1);
+          commit("pdfTemplates", templates);
+        }
+      });
     }
   }
 };
--- a/pkg/controllers/printtemplates.go	Wed Feb 13 16:13:44 2019 +0100
+++ b/pkg/controllers/printtemplates.go	Wed Feb 13 16:41:00 2019 +0100
@@ -38,13 +38,13 @@
 ORDER BY date_info DESC`
 
 	hasPrintTemplateSQL = `
-SELECT true FROM users.templates WHERE name = $1`
+SELECT true FROM users.templates WHERE template_name = $1`
 
 	deletePrintTemplateSQL = `
-DELETE FROM users.templates WHERE name = $1`
+DELETE FROM users.templates WHERE template_name = $1`
 
 	selectPrintTemplateSQL = `
-SELECT template_data FROM users.templates WHERE name = $1`
+SELECT template_data FROM users.templates WHERE template_name = $1`
 
 	insertPrintTemplateSQL = `
 INSERT INTO users.templates (template_name, template_data)