# HG changeset patch # User Thomas Junk # Date 1562328023 -7200 # Node ID 6c3e5dd2b59668392bbc8110e6802cb7fc528a32 # Parent 08eed1328ec922c551578f3fddf522fe652e6ea4# Parent d2142ff30cf414ac1f08a44032b6fb6229cb2eab merge with yworks-svg2pdf diff -r 08eed1328ec9 -r 6c3e5dd2b596 client/package.json --- a/client/package.json Fri Jul 05 13:50:34 2019 +0200 +++ b/client/package.json Fri Jul 05 14:00:23 2019 +0200 @@ -39,13 +39,13 @@ "debounce": "^1.2.0", "file-saver": "^2.0.2", "glob-all": "^3.1.0", - "jspdf": "^1.5.3", "locale2": "^2.2.0", "lodash.debounce": "^4.0.8", "ol": "^5.3.0", "path": "^0.12.7", "prettier": "^1.15.3", "purgecss-webpack-plugin": "^1.4.0", + "svg2pdf.js": "https://github.com/Intevation/svg2pdf.js.git#production", "v-tooltip": "^2.0.0-rc.33", "vue": "^2.5.16", "vue-clipboard2": "^0.2.1", diff -r 08eed1328ec9 -r 6c3e5dd2b596 client/src/components/Pdftool.vue --- a/client/src/components/Pdftool.vue Fri Jul 05 13:50:34 2019 +0200 +++ b/client/src/components/Pdftool.vue Fri Jul 05 14:00:23 2019 +0200 @@ -101,12 +101,12 @@ * * Fadi Abbud */ import { mapState, mapGetters } from "vuex"; -import jsPDF from "jspdf"; +import jsPDF from "jspdf-yworks"; import "@/lib/font-linbiolinum"; import { getPointResolution } from "ol/proj"; import { HTTP } from "@/lib/http"; import { displayError } from "@/lib/errors"; -import { pdfgen } from "@/lib/mixins"; +import { pdfgen, templateLoader } from "@/lib/mixins"; var paperSizes = { // in millimeter, landscape [width, height] @@ -115,7 +115,7 @@ }; export default { - mixins: [pdfgen], + mixins: [pdfgen, templateLoader], name: "pdftool", data() { return { @@ -211,23 +211,21 @@ // applied to the rest of the form. applyTemplateToForm() { if (this.form.template) { - HTTP.get( - "/templates/" + - this.form.template.type + - "/" + - this.form.template.name, - { - headers: { - "X-Gemma-Auth": localStorage.getItem("token"), - "Content-type": "text/xml; charset=UTF-8" - } - } + this.loadTemplates( + `/templates/${this.form.template.type}/${this.form.template.name}` ) .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; + this.prepareImages(response.data.template_data.elements).then( + values => { + this.templateData = response.data.template_data; + values.forEach(v => { + response.data.template_data.elements[v.index].url = v.url; + }); + 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; @@ -794,18 +792,9 @@ textOptions ); } - }, - getTextHeight(numberOfLines) { - return ( - numberOfLines * - ((this.pdf.doc.getFontSize() * 25.4) / parseInt(this.form.resolution)) * - this.pdf.doc.getLineHeightFactor() - ); } }, mounted() { - this.form.template = this.templates[0]; - this.templateData = this.form.template; HTTP.get("/templates/map", { headers: { "X-Gemma-Auth": localStorage.getItem("token"), @@ -817,6 +806,9 @@ this.templates = response.data; this.form.template = this.templates[0]; this.applyTemplateToForm(); + } else { + this.form.template = this.templates[0]; + this.templateData = this.form.template; } }) .catch(e => { diff -r 08eed1328ec9 -r 6c3e5dd2b596 client/src/components/fairway/AvailableFairwayDepth.vue --- a/client/src/components/fairway/AvailableFairwayDepth.vue Fri Jul 05 13:50:34 2019 +0200 +++ b/client/src/components/fairway/AvailableFairwayDepth.vue Fri Jul 05 14:00:23 2019 +0200 @@ -61,24 +61,22 @@ * 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): - * Thomas Junk - * Markus Kottländer - * Fadi Abbud + * * Thomas Junk + * * Markus Kottländer + * * Fadi Abbud */ import * as d3 from "d3"; import app from "@/main"; import debounce from "debounce"; -import { diagram } from "@/lib/mixins"; import { mapState } from "vuex"; import filters from "@/lib/filters.js"; -import jsPDF from "jspdf"; -import canvg from "canvg"; -import { pdfgen } from "@/lib/mixins"; +import svg2pdf from "svg2pdf.js"; +import { diagram, pdfgen, templateLoader } from "@/lib/mixins"; import { HTTP } from "@/lib/http"; import { displayError } from "@/lib/errors"; import { FREQUENCIES } from "@/store/fairwayavailability"; @@ -86,7 +84,7 @@ const hoursInDays = x => x / 24; export default { - mixins: [diagram, pdfgen], + mixins: [diagram, pdfgen, templateLoader], components: { DiagramLegend: () => import("@/components/DiagramLegend") }, @@ -122,7 +120,7 @@ { type: "diagram", position: "topleft", - offset: { x: 20, y: 60 }, + offset: { x: 20, y: 30 }, width: 290, height: 100 }, @@ -136,7 +134,7 @@ { type: "diagramlegend", position: "topleft", - offset: { x: 30, y: 160 }, + offset: { x: 30, y: 170 }, color: "black" } ] @@ -268,14 +266,16 @@ 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" - } - }) + this.loadTemplates("/templates/diagram/" + this.form.template.name) .then(response => { - this.templateData = response.data.template_data; + this.prepareImages(response.data.template_data.elements).then( + values => { + values.forEach(v => { + response.data.template_data.elements[v.index].url = v.url; + }); + this.templateData = response.data.template_data; + } + ); }) .catch(e => { const { status, data } = e.response; @@ -287,119 +287,18 @@ } }, downloadPDF() { - 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; - if (this.templateData) { - // default values if some are missing in template - let defaultFontSize = 11, - defaultColor = "black", - defaultWidth = 70, - defaultTextColor = "black", - defaultBorderColor = "white", - defaultBgColor = "white", - defaultRounding = 2, - defaultPadding = 2, - defaultOffset = { x: 0, y: 0 }; - this.templateData.elements.forEach(e => { - switch (e.type) { - case "diagram": { - this.addDiagram( - e.position, - e.offset || defaultOffset, - e.width, - e.height - ); - break; - } - case "diagramtitle": { - let title = `Available Fairway Depth: ${this.featureName}`; - this.addDiagramTitle( - e.position, - e.offset || defaultOffset, - e.fontsize || defaultFontSize, - e.color || defaultColor, - title - ); - break; - } - case "diagramlegend": { - this.addDiagramLegend( - e.position, - e.offset || defaultOffset, - e.color || defaultColor - ); - break; - } - case "text": { - this.addText( - e.position, - e.offset || defaultOffset, - e.width || defaultWidth, - e.fontsize || defaultFontSize, - e.color || defaultTextColor, - e.text || "" - ); - break; - } - case "image": { - this.addImage( - e.url, - e.format || "", - e.position, - e.offset || defaultOffset, - e.width || 90, - e.height || 60 - ); - break; - } - case "box": { - this.addBox( - e.position, - e.offset || defaultOffset, - e.width || 90, - e.height || 60, - e.rounding === 0 || e.rounding ? e.rounding : defaultRounding, - e.color || defaultBgColor, - e.brcolor || defaultBorderColor - ); - break; - } - case "textbox": { - this.addTextBox( - e.position, - e.offset || defaultOffset, - e.width, - e.height, - e.rounding === 0 || e.rounding ? e.rounding : defaultRounding, - e.padding || defaultPadding, - e.fontsize || defaultFontSize, - e.color || defaultTextColor, - e.background || defaultBgColor, - e.text || "", - e.brcolor || defaultBorderColor - ); - break; - } - } - }); - } + let title = `Available Fairway Depth: ${this.featureName}`; + this.generatePDF({ + templateData: this.templateData, + diagramTitle: title + }); this.pdf.doc.save(`Available Fairway Depth: ${this.featureName}`); }, 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 svgElement = this.$refs.diagramContainer.firstElementChild; + // use default width,height if they are missing in the template definition if (!width) { width = this.templateData.properties.paperSize === "a3" ? 380 : 290; @@ -413,16 +312,12 @@ 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; - canvg(canvas, svg, { - ignoreMouse: true, - ignoreAnimation: true, - ignoreDimensions: true + + svg2pdf(svgElement, this.pdf.doc, { + xOffset: x, + yOffset: y, + scale: this.templateData.properties.paperSize === "a3" ? 0.45 : 0.18 // TODO depend on the size and aspect ration on paper }); - var imgData = canvas.toDataURL("image/png"); - this.pdf.doc.addImage(imgData, "PNG", x, y, width, height); }, addDiagramLegend(position, offset, color) { let x = offset.x, @@ -639,7 +534,7 @@ .attr("y", this.dimensions.mainHeight - this.labelPaddingBottom) .attr("x", this.widthPerItem / 2) .attr("text-anchor", "middle") - .attr("font-size", "smaller"); + .attr("font-size", "9"); }, drawScaleLabel() { const center = this.dimensions.mainHeight / 2; @@ -649,8 +544,9 @@ .attr("text-anchor", "middle") .attr("x", 0) .attr("y", 0) - .attr("dy", "1em") - .attr("transform", `translate(0, ${center}), rotate(-90)`); + .attr("dy", "10") + // translate a few mm to the right to allow for slightly higher letters + .attr("transform", `translate(2, ${center}), rotate(-90)`); }, drawScale() { const yAxis = d3.axisLeft().scale(this.yScale); diff -r 08eed1328ec9 -r 6c3e5dd2b596 client/src/components/fairway/AvailableFairwayDepthDialogue.vue --- a/client/src/components/fairway/AvailableFairwayDepthDialogue.vue Fri Jul 05 13:50:34 2019 +0200 +++ b/client/src/components/fairway/AvailableFairwayDepthDialogue.vue Fri Jul 05 14:00:23 2019 +0200 @@ -70,7 +70,7 @@ >