comparison client/src/components/gauge/Waterlevel.vue @ 3137:35c0da49eb89

client: pdf-gen: prepare pdf template for waterlevel diagram * use default template when nothings come from backend * adjust and add some functions to handle the generation of template elements
author Fadi Abbud <fadi.abbud@intevation.de>
date Thu, 02 May 2019 10:46:50 +0200
parents f34277674926
children 5daaabc2e7fc
comparison
equal deleted inserted replaced
3136:e52ba854bfe8 3137:35c0da49eb89
13 <div class="legend"> 13 <div class="legend">
14 <span style="background-color: rgba(0, 255, 0, 0.1)"></span> Navigable 14 <span style="background-color: rgba(0, 255, 0, 0.1)"></span> Navigable
15 Range 15 Range
16 </div> 16 </div>
17 <div> 17 <div>
18 <select
19 v-model="form.template"
20 class="form-control d-block custom-select-sm w-100"
21 >
22 <option
23 v-for="template in templates"
24 :value="template"
25 :key="template.name"
26 >
27 {{ template.name }}
28 </option>
29 </select>
18 <button 30 <button
19 @click="downloadPDF" 31 @click="downloadPDF"
20 type="button" 32 type="button"
21 class="btn btn-sm btn-info d-block w-100 mt-2" 33 class="btn btn-sm btn-info d-block w-100 mt-2"
22 > 34 >
56 import { lineChunked } from "d3-line-chunked"; 68 import { lineChunked } from "d3-line-chunked";
57 import { endOfDay } from "date-fns"; 69 import { endOfDay } from "date-fns";
58 import debounce from "debounce"; 70 import debounce from "debounce";
59 import jsPDF from "jspdf"; 71 import jsPDF from "jspdf";
60 import canvg from "canvg"; 72 import canvg from "canvg";
61 73 import { pdfgen } from "@/lib/mixins";
62 // we should load only d3 modules we need but for now we'll go with the lazy way 74 // we should load only d3 modules we need but for now we'll go with the lazy way
63 // https://www.giacomodebidda.com/how-to-import-d3-plugins-with-webpack/ 75 // https://www.giacomodebidda.com/how-to-import-d3-plugins-with-webpack/
64 // d3-line-chunked plugin: https://github.com/pbeshai/d3-line-chunked 76 // d3-line-chunked plugin: https://github.com/pbeshai/d3-line-chunked
65 const d3 = Object.assign(d3Base, { lineChunked }); 77 const d3 = Object.assign(d3Base, { lineChunked });
66 78
67 export default { 79 export default {
80 mixins: [pdfgen],
68 components: { 81 components: {
69 DiagramLegend: () => import("@/components/DiagramLegend") 82 DiagramLegend: () => import("@/components/DiagramLegend")
70 }, 83 },
71 data() { 84 data() {
72 return { 85 return {
74 diagram: null, 87 diagram: null,
75 navigation: null, 88 navigation: null,
76 dimensions: null, 89 dimensions: null,
77 extent: null, 90 extent: null,
78 scale: null, 91 scale: null,
79 axes: null 92 axes: null,
93 form: {
94 template: null
95 },
96 templates: [
97 {
98 name: "Default",
99 properties: {
100 format: "landscape",
101 paperSize: "a3",
102 resolution: "80"
103 },
104 elements: [
105 {
106 type: "diagramlegend",
107 position: "topleft",
108 offset: { x: 60, y: 190 },
109 color: "black"
110 },
111 {
112 type: "diagramtitle",
113 position: "topleft",
114 offset: { x: 108, y: 30 },
115 fontsize: 22,
116 color: "steelblue"
117 },
118 {
119 type: "text",
120 position: "topleft",
121 offset: { x: 7, y: 5 },
122 fontsize: 14,
123 width: 90,
124 text: this.$gettext("Generated by") + " " + "{user}, {date}"
125 }
126 ]
127 }
128 ],
129 pdf: {
130 doc: null,
131 width: 420,
132 height: 297
133 },
134 templateData: null
80 }; 135 };
81 }, 136 },
82 computed: { 137 computed: {
83 ...mapState("gauges", ["dateFrom", "waterlevels", "nashSutcliffe"]), 138 ...mapState("gauges", ["dateFrom", "waterlevels", "nashSutcliffe"]),
84 ...mapGetters("gauges", ["selectedGauge"]), 139 ...mapGetters("gauges", ["selectedGauge"]),
140 ...mapState("user", ["user"]),
85 dateFrom: { 141 dateFrom: {
86 get() { 142 get() {
87 return this.$store.state.gauges.dateFrom; 143 return this.$store.state.gauges.dateFrom;
88 } 144 }
89 }, 145 },
102 downloadPDF() { 158 downloadPDF() {
103 var svg = this.$refs.diagramContainer.innerHTML; 159 var svg = this.$refs.diagramContainer.innerHTML;
104 if (svg) { 160 if (svg) {
105 svg = svg.replace(/\r?\n|\r/g, "").trim(); 161 svg = svg.replace(/\r?\n|\r/g, "").trim();
106 } 162 }
107 var pdf = new jsPDF("l", "mm", "a3"); 163 this.pdf.doc = new jsPDF("l", "mm", "a3");
108 var canvas = document.createElement("canvas"); 164 var canvas = document.createElement("canvas");
109 canvas.width = window.innerWidth; 165 canvas.width = window.innerWidth;
110 canvas.height = window.innerHeight / 2; 166 canvas.height = window.innerHeight / 2;
111 canvg(canvas, svg, { 167 canvg(canvas, svg, {
112 ignoreMouse: true, 168 ignoreMouse: true,
113 ignoreAnimation: true, 169 ignoreAnimation: true,
114 ignoreDimensions: true 170 ignoreDimensions: true
115 }); 171 });
116 var imgData = canvas.toDataURL("image/png"); 172 var imgData = canvas.toDataURL("image/png");
117 pdf.addImage(imgData, "PNG", 40, 60, 380, 130); 173 this.pdf.doc.addImage(imgData, "PNG", 40, 60, 380, 130);
118 // Gauge info as a title for pdf 174 if (this.templateData) {
119 this.addDiagramTitle(pdf, 108, 30, 22, "steelblue"); 175 let defaultFontSize = 11,
120 this.addDiagramLegend(pdf, 60, 190, "black"); 176 defaultColor = "black",
121 pdf.save( 177 defaultWidth = 70,
178 defaultTextColor = "black",
179 defaultOffset = { x: 0, y: 0 };
180 this.templateData.elements.forEach(e => {
181 switch (e.type) {
182 case "diagramlegend": {
183 this.addDiagramLegend(
184 e.position,
185 e.offset || defaultOffset,
186 e.color || defaultColor
187 );
188 break;
189 }
190 case "diagramtitle": {
191 this.addDiagramTitle(e.position, e.offset, e.fontsize, e.color);
192 break;
193 }
194 case "text": {
195 this.addText(
196 e.position,
197 e.offset || defaultOffset,
198 e.width || defaultWidth,
199 e.fontSize || defaultFontSize,
200 e.color || defaultTextColor,
201 e.text
202 );
203 break;
204 }
205 case "image": {
206 this.addImage(
207 e.url,
208 e.format,
209 e.position,
210 e.offset || defaultOffset,
211 e.width,
212 e.height
213 );
214 break;
215 }
216 }
217 });
218 }
219 this.pdf.doc.save(
122 this.selectedGauge.properties.objname + " Waterlevel-Diagram.pdf" 220 this.selectedGauge.properties.objname + " Waterlevel-Diagram.pdf"
123 ); 221 );
124 }, 222 },
125 addDiagramTitle(pdf, x, y, size, color) { 223 // Gauge info as a title for pdf
224 addDiagramTitle(position, offset, size, color) {
126 let gaugeInfo = 225 let gaugeInfo =
127 this.selectedGauge.properties.objname + 226 this.selectedGauge.properties.objname +
128 " (" + 227 " (" +
129 this.selectedGauge.id 228 this.selectedGauge.id
130 .split(".")[1] 229 .split(".")[1]
133 "):" + 232 "):" +
134 " Waterlevel " + 233 " Waterlevel " +
135 this.dateFrom.toLocaleDateString() + 234 this.dateFrom.toLocaleDateString() +
136 " - " + 235 " - " +
137 this.dateTo.toLocaleDateString(); 236 this.dateTo.toLocaleDateString();
138 pdf.setTextColor(color); 237 let x = offset.x;
139 pdf.setFontSize(size); 238 let y = offset.y;
140 pdf.setFontStyle("bold"); 239 this.pdf.doc.setTextColor(color);
141 pdf.text(gaugeInfo, x, y); 240 this.pdf.doc.setFontSize(size);
241 this.pdf.doc.setFontStyle("bold");
242 let width = this.pdf.doc.getTextWidth(gaugeInfo) + size / 2;
243 console.log("width", width);
244
245 if (["topright", "bottomright"].indexOf(position) !== -1) {
246 x = this.pdf.width - offset.x - width;
247 }
248 if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
249 y = this.pdf.height - offset.y - this.getTextHeight(1);
250 }
251 //let y1 = y === 0 ? y + this.getTextHeigt(1) : y1;
252 console.log("y1", y);
253 console.log("x", x);
254 console.log("position", position);
255 this.pdf.doc.text(gaugeInfo, x, y, {
256 baseline: "hanging"
257 });
258 },
259 getTextHeight(numberOfLines) {
260 return (
261 numberOfLines *
262 ((this.pdf.doc.getFontSize() * 25.4) / 80) *
263 this.pdf.doc.getLineHeightFactor()
264 );
142 }, 265 },
143 // Diagram legend 266 // Diagram legend
144 addDiagramLegend(pdf, x, y, color) { 267 addDiagramLegend(position, offset, color) {
145 pdf.setFontSize(10); 268 let x = offset.x;
146 pdf.setTextColor(color); 269 let y = offset.y;
147 pdf.setDrawColor("white"); 270 let width = this.pdf.doc.getTextWidth("Navigable Range") + 12;
148 pdf.setFillColor("steelblue"); 271 console.log("width for legend", width);
149 pdf.circle(x, y, 2, "FD"); 272 let height = 15;
150 pdf.text(x + 3, y + 1, "Waterlevel"); 273 if (["topright", "bottomright"].indexOf(position) !== -1) {
151 pdf.setFillColor("#dae6f0"); 274 x = this.pdf.width - offset.x - width;
152 pdf.circle(x, y + 5, 2, "FD"); 275 }
153 pdf.setFillColor("#e5ffe5"); 276 if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
154 pdf.circle(x, y + 10, 2, "FD"); 277 y = this.pdf.height - offset.y - height;
155 pdf.text(x + 3, y + 11, "Navigable Range"); 278 }
156 pdf.setDrawColor("#90b4d2"); 279 this.pdf.doc.setFontSize(10);
157 pdf.setFillColor("#90b4d2"); 280 this.pdf.doc.setTextColor(color);
158 pdf.circle(x, y + 5, 0.6, "FD"); 281 this.pdf.doc.setDrawColor("white");
159 pdf.text(x + 3, y + 6, "Prediction"); 282 this.pdf.doc.setFillColor("steelblue");
283 this.pdf.doc.circle(x, y, 2, "FD");
284 this.pdf.doc.text(x + 3, y + 1, "Waterlevel");
285 this.pdf.doc.setFillColor("#dae6f0");
286 this.pdf.doc.circle(x, y + 5, 2, "FD");
287 this.pdf.doc.setFillColor("#e5ffe5");
288 this.pdf.doc.circle(x, y + 10, 2, "FD");
289 this.pdf.doc.text(x + 3, y + 11, "Navigable Range");
290 this.pdf.doc.setDrawColor("#90b4d2");
291 this.pdf.doc.setFillColor("#90b4d2");
292 this.pdf.doc.circle(x, y + 5, 0.6, "FD");
293 this.pdf.doc.text(x + 3, y + 6, "Prediction");
160 }, 294 },
161 drawDiagram() { 295 drawDiagram() {
162 // remove old diagram and exit if necessary data is missing 296 // remove old diagram and exit if necessary data is missing
163 d3.select(".diagram-container svg").remove(); 297 d3.select(".diagram-container svg").remove();
164 if (!this.selectedGauge || !this.waterlevels.length) return; 298 if (!this.selectedGauge || !this.waterlevels.length) return;
905 created() { 1039 created() {
906 window.addEventListener("resize", debounce(this.drawDiagram), 100); 1040 window.addEventListener("resize", debounce(this.drawDiagram), 100);
907 }, 1041 },
908 mounted() { 1042 mounted() {
909 this.drawDiagram(); 1043 this.drawDiagram();
1044 this.form.template = this.templates[0];
1045 this.templateData = this.form.template;
910 }, 1046 },
911 updated() { 1047 updated() {
912 this.drawDiagram(); 1048 this.drawDiagram();
913 }, 1049 },
914 destroyed() { 1050 destroyed() {