comparison client/src/components/fairway/Fairwayprofile.vue @ 3963:feb53713bc2f diagram-cleanup

client: moved duplicated code to mixins and unified code patterns in diagram components [WIP]
author Markus Kottlaender <markus@intevation.de>
date Fri, 12 Jul 2019 15:14:16 +0200
parents cd8ba6599a99
children afc7bca44df4
comparison
equal deleted inserted replaced
3944:0ed8af02d5a9 3963:feb53713bc2f
91 <translate>Export to PDF</translate> 91 <translate>Export to PDF</translate>
92 </button> 92 </button>
93 </div> 93 </div>
94 </DiagramLegend> 94 </DiagramLegend>
95 <div 95 <div
96 ref="pdfContainer" 96 class="d-flex flex-fill justify-content-center align-items-center position-relative"
97 id="pdfContainer" 97 :id="containerId"
98 class="d-flex flex-fill justify-content-center align-items-center diagram-container position-relative"
99 > 98 >
100 <div class="direction-indicator"></div> 99 <div class="direction-indicator"></div>
101 <div v-if="!fairwayData"> 100 <div v-if="!fairwayData.length">
102 <translate>No data available.</translate> 101 <translate>No data available.</translate>
103 </div> 102 </div>
104 </div> 103 </div>
105 </div> 104 </div>
106 </div> 105 </div>
146 * Markus Kottländer <markus.kottlaender@intevation.de> 145 * Markus Kottländer <markus.kottlaender@intevation.de>
147 * Fadi Abbud <fadi.abbud@intevation.de> 146 * Fadi Abbud <fadi.abbud@intevation.de>
148 */ 147 */
149 import * as d3 from "d3"; 148 import * as d3 from "d3";
150 import { mapState, mapGetters } from "vuex"; 149 import { mapState, mapGetters } from "vuex";
151 import debounce from "debounce";
152 import { diagram, pdfgen, templateLoader } from "@/lib/mixins"; 150 import { diagram, pdfgen, templateLoader } from "@/lib/mixins";
153 import { HTTP } from "@/lib/http";
154 import { displayError } from "@/lib/errors";
155 import { defaultDiagramTemplate } from "@/lib/DefaultDiagramTemplate";
156 151
157 const GROUND_COLOR = "#4A2F06"; 152 const GROUND_COLOR = "#4A2F06";
158 const WATER_COLOR = "#005DFF"; 153 const WATER_COLOR = "#005DFF";
159 154
160 export default { 155 export default {
161 mixins: [diagram, pdfgen, templateLoader], 156 mixins: [diagram, pdfgen, templateLoader],
162 name: "fairwayprofile",
163 components: { 157 components: {
164 DiagramLegend: () => import("@/components/DiagramLegend") 158 DiagramLegend: () => import("@/components/DiagramLegend")
165 }, 159 },
166 data() { 160 data() {
167 return { 161 return {
168 resizeListenerFunction: null, 162 containerId: "fairwayprofile-diagram-container",
169 width: null, 163 width: null,
170 height: null, 164 height: null
171 form: {
172 template: null
173 },
174 templates: [],
175 defaultTemplate: defaultDiagramTemplate,
176 pdf: {
177 doc: null,
178 width: 32,
179 height: 297
180 },
181 templateData: null
182 }; 165 };
183 }, 166 },
184 computed: { 167 computed: {
185 ...mapGetters("map", ["openLayersMap"]), 168 ...mapGetters("map", ["openLayersMap"]),
186 ...mapGetters("fairwayprofile", ["totalLength"]), 169 ...mapGetters("fairwayprofile", ["totalLength"]),
291 let strokeOpacity = strokeColor.pop(); 274 let strokeOpacity = strokeColor.pop();
292 let strokeDash = style.getStroke().getLineDash(); 275 let strokeDash = style.getStroke().getLineDash();
293 276
294 return { fillColor, fillOpacity, strokeColor, strokeOpacity, strokeDash }; 277 return { fillColor, fillOpacity, strokeColor, strokeOpacity, strokeDash };
295 }, 278 },
296 applyChange() {
297 if (this.form.template.hasOwnProperty("properties")) {
298 this.templateData = this.defaultTemplate;
299 return;
300 }
301 if (this.form.template) {
302 this.loadTemplates("/templates/diagram/" + this.form.template.name)
303 .then(response => {
304 this.prepareImages(response.data.template_data.elements).then(
305 values => {
306 values.forEach(v => {
307 response.data.template_data.elements[v.index].url = v.url;
308 });
309 this.templateData = response.data.template_data;
310 }
311 );
312 })
313 .catch(e => {
314 const { status, data } = e.response;
315 displayError({
316 title: this.$gettext("Backend Error"),
317 message: `${status}: ${data.message || data}`
318 });
319 });
320 }
321 },
322 downloadPDF() { 279 downloadPDF() {
323 let fairwayInfo = 280 let fairwayInfo =
324 this.selectedBottleneck + " (" + this.selectedSurvey.date_info + ")"; 281 this.selectedBottleneck + " (" + this.selectedSurvey.date_info + ")";
325 282
326 this.generatePDF({ 283 this.generatePDF({
381 this.pdf.doc.circle(x, y + 25, 2, "FD"); 338 this.pdf.doc.circle(x, y + 25, 2, "FD");
382 this.pdf.doc.text(x + 3, y + 26, "Sediment (Compare)"); 339 this.pdf.doc.text(x + 3, y + 26, "Sediment (Compare)");
383 }, 340 },
384 getPrintLayout() { 341 getPrintLayout() {
385 return { 342 return {
386 main: { 343 main: { top: 20, right: 80, bottom: 60, left: 80 }
387 top: 20,
388 right: 80,
389 bottom: 60,
390 left: 80
391 }
392 }; 344 };
393 }, 345 },
394 drawDiagram() { 346 drawDiagram() {
395 d3.select(".diagram-container svg").remove(); 347 d3.select("#" + this.containerId + " svg").remove();
396 this.scaleFairwayProfile(); 348 this.scaleFairwayProfile();
397 if (!this.height || !this.width) return; // do not try to render when height and width are unknown 349 if (!this.height || !this.width) return; // do not try to render when height and width are unknown
398 const layout = this.getPrintLayout(this.height); 350 const layout = this.getPrintLayout(this.height);
399 this.renderTo({ 351 this.renderTo({
400 element: ".diagram-container", 352 element: "#" + this.containerId,
401 dimensions: this.getDimensions({ 353 dimensions: this.getDimensions({
402 svgWidth: this.width, 354 svgWidth: this.width,
403 svgHeight: this.height, 355 svgHeight: this.height,
404 ...layout 356 ...layout
405 }) 357 })
672 .attr("fill-opacity", 0) 624 .attr("fill-opacity", 0)
673 .attr("d", profileLine); 625 .attr("d", profileLine);
674 } 626 }
675 }, 627 },
676 scaleFairwayProfile() { 628 scaleFairwayProfile() {
677 if (!document.querySelector(".diagram-container")) return; 629 if (!document.querySelector("#" + this.containerId)) return;
678 const clientHeight = document.querySelector(".diagram-container") 630 const clientHeight = document.querySelector("#" + this.containerId)
679 .clientHeight; 631 .clientHeight;
680 const clientWidth = document.querySelector(".diagram-container") 632 const clientWidth = document.querySelector("#" + this.containerId)
681 .clientWidth; 633 .clientWidth;
682 if (!clientHeight || !clientWidth) return; 634 if (!clientHeight || !clientWidth) return;
683 this.height = clientHeight; 635 this.height = clientHeight;
684 this.width = clientWidth; 636 this.width = clientWidth;
685 } 637 }
686 },
687 created() {
688 this.resizeListenerFunction = debounce(this.drawDiagram, 100);
689 window.addEventListener("resize", this.resizeListenerFunction);
690 },
691 mounted() {
692 // Nasty but necessary if we don't want to use the updated hook to re-draw
693 // the diagram because this would re-draw it also for irrelevant reasons.
694 // In this case we need to wait for the child component (DiagramLegend) to
695 // render. According to the docs (https://vuejs.org/v2/api/#mounted) this
696 // should be possible with $nextTick() but it doesn't work because it does
697 // not guarantee that the DOM is not only updated but also re-painted on the
698 // screen.
699 setTimeout(this.drawDiagram, 150);
700
701 this.templates[0] = this.defaultTemplate;
702 this.form.template = this.templates[0];
703 this.templateData = this.form.template;
704 HTTP.get("/templates/diagram", {
705 headers: {
706 "X-Gemma-Auth": localStorage.getItem("token"),
707 "Content-type": "text/xml; charset=UTF-8"
708 }
709 })
710 .then(response => {
711 if (response.data.length) {
712 this.templates = response.data;
713 this.form.template = this.templates[0];
714 this.templates[this.templates.length] = this.defaultTemplate;
715 this.applyChange();
716 }
717 })
718 .catch(e => {
719 const { status, data } = e.response;
720 displayError({
721 title: this.$gettext("Backend Error"),
722 message: `${status}: ${data.message || data}`
723 });
724 });
725 },
726 updated() {
727 this.drawDiagram();
728 },
729 destroyed() {
730 window.removeEventListener("resize", this.resizeListenerFunction);
731 } 638 }
732 }; 639 };
733 </script> 640 </script>