Mercurial > gemma
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() { |