changeset 3153:8159bd2aaf93

fairway_depth_diagram: display of mockdata
author Thomas Junk <thomas.junk@intevation.de>
date Fri, 03 May 2019 14:23:47 +0200
parents 8e31e5b9b37a
children b6c10b30d6bd
files client/src/components/fairway/AvailableFairwayDepth.vue
diffstat 1 files changed, 163 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/fairway/AvailableFairwayDepth.vue	Fri May 03 13:51:09 2019 +0200
+++ b/client/src/components/fairway/AvailableFairwayDepth.vue	Fri May 03 14:23:47 2019 +0200
@@ -2,24 +2,33 @@
   <div>
     <h1>Available Fairway Depth</h1>
     <UISpinnerOverlay v-if="loading" />
-    <div class="d-flex flex-row ml-3">
-      <div class="mr-3 ml-auto">
-        <select class="mr-3">
-          <option>Monthly</option>
-          <option>Quaterly</option>
-          <option>Yearly</option>
-        </select>
+    <div class="d-flex flex-row">
+      <div class="ml-3 mr-auto">
+        <ul>
+          <li v-for="(entry, index) in legend" :key="index">{{ entry }}</li>
+        </ul>
       </div>
-      <div class="mr-3">
-        <label for="from" class="mr-3"><translate>from</translate></label
-        ><input />
-      </div>
-      <div class="mr-auto">
-        <label for="to" class="mr-3"><translate>to</translate></label
-        ><input />
+      <div class="d-flex flex-column mr-auto">
+        <div class="d-flex flex-row">
+          <div class="mr-3 ml-auto">
+            <select class="mr-3">
+              <option>Monthly</option>
+              <option>Quaterly</option>
+              <option>Yearly</option>
+            </select>
+          </div>
+          <div class="mr-3">
+            <label for="from" class="mr-3"><translate>from</translate></label
+            ><input />
+          </div>
+          <div class="mr-auto">
+            <label for="to" class="mr-3"><translate>to</translate></label
+            ><input />
+          </div>
+        </div>
+        <div class="diagram-container"></div>
       </div>
     </div>
-    <div class="diagram-container"></div>
   </div>
 </template>
 
@@ -42,20 +51,40 @@
  */
 import * as d3 from "d3";
 import app from "@/main";
+import { displayError } from "@/lib/errors";
+import { HTTP } from "@/lib/http";
+
+const MOCKDATA = `#label,# >= LDC [h],# < 200.00 [h],# >= 200.00 [h],# >= 230.00 [h],# >= 250.00 [h]
+01-2019, 22.000,1.000, 4.000,6.000, 20.000
+02-2019, 24.000,0.000,0.000,0.000, 23.000
+03-2019, 30.000,0.000,0.000,0.000, 30.000
+04-2019, 30.000,0.000,0.000,0.000, 30.000
+05-2019, 30.000,0.000,0.000,0.000, 30.000`;
 
 export default {
   data() {
     return {
       loading: false,
-      colors: ["red", "green", "blue", "purple"],
       fwData: null,
       width: 1000,
-      height: 600
+      height: 600,
+      paddingRight: 100,
+      spaceBetween: 80,
+      labelPaddingTop: 15,
+      scalePaddingLeft: 50,
+      paddingTop: 10,
+      legend: "",
+      diagram: null,
+      yScale: null,
+      barsWidth: 60
     };
   },
   mounted() {
+    this.yScale = d3
+      .scaleLinear()
+      .domain([-33, 33])
+      .range([this.height - 30, 0]);
     this.loadData();
-    this.drawDiagram();
   },
   computed: {
     availability() {
@@ -63,65 +92,132 @@
     }
   },
   methods: {
-    loadData() {},
+    prepareLegend(header) {
+      const headerEntries = header.split(",");
+      headerEntries.shift();
+      return headerEntries.map(x => {
+        return x.split("#")[1].trim();
+      });
+    },
+    prepare(data) {
+      const csv = data.split("\n");
+      this.legend = this.prepareLegend(csv.shift());
+      let transformed = csv.map(e => {
+        const result = e.split(",");
+        const label = result.shift();
+        const ldc = result.shift();
+        const highestLevel = result.pop();
+        return {
+          label: label,
+          ldc: ldc,
+          highestLevel: highestLevel,
+          lowerLevels: result
+        };
+      });
+      this.fwData = transformed;
+    },
+    loadData() {
+      const URL =
+        "/data/bottleneck/fairway-depth/Furt%20Wendeplatz%20Theben?from=2019-01-01T15:04:05%2b00:00&to=2019-05-02T15:04:05%2b07:00&mode=monthly";
+      HTTP.get(URL, {
+        headers: { "X-Gemma-Auth": localStorage.getItem("token") }
+      })
+        .then(() => {
+          // const { data } = response;
+          this.prepare(MOCKDATA);
+          this.drawDiagram();
+        })
+        .catch(error => {
+          console.log(error);
+          const { status, data } = error.response;
+          displayError({
+            title: this.$gettext("Backend Error"),
+            message: `${status}: ${data.message || data}`
+          });
+        });
+    },
     drawDiagram() {
-      const data = [
-        { month: "feb", values: [30, 20, 10, 0] },
-        { month: "mar", values: [25, 23, 0, 0] },
-        { month: "apr", values: [17, 18, 16, 13] }
-      ];
-
       d3.select(".diagram-container svg").remove();
-      const yScale = d3
-        .scaleLinear()
-        .domain([-30, 30])
-        .range([this.height - 30, 0]);
-
+      this.generateDiagramContainer();
+      this.drawBars();
+      this.drawScaleLabel();
+      this.drawScale();
+    },
+    generateDiagramContainer() {
       const diagram = d3
         .select(".diagram-container")
         .append("svg")
         .attr("width", this.width)
         .attr("height", this.height);
-      this.drawBars({ diagram, data, yScale });
-      this.drawLabel(diagram, this.height);
-      this.drawScale(diagram, yScale);
+      this.diagram = diagram
+        .append("g")
+        .attr("transform", `translate(0 ${this.paddingTop})`);
     },
-    drawBars({ diagram, data, yScale }) {
-      const paddingRight = 100;
-      const paddingTop = 10;
-
-      const allBars = diagram
+    drawBars() {
+      const everyBar = this.diagram
         .selectAll("g")
-        .data(data)
+        .data(this.fwData)
         .enter()
         .append("g")
         .attr("transform", (d, i) => {
-          return `translate(${paddingRight + i * 95} ${paddingTop})`;
+          const dx = this.paddingRight + i * this.spaceBetween;
+          return `translate(${dx})`;
         });
-      // bars per month
-      allBars
-        .selectAll("rect")
-        .data(d => d.values)
+      this.drawSingleBars(everyBar);
+      this.drawLabelPerBar(everyBar);
+    },
+    drawSingleBars(everyBar) {
+      this.drawLDC(everyBar);
+      this.drawHighestLevel(everyBar);
+      this.drawLowerLevels(everyBar);
+    },
+    drawLowerLevels(everyBar) {
+      everyBar
+        .selectAll("g")
+        .data(d => d.lowerLevels.reverse())
         .enter()
         .append("rect")
-        .attr("x", 0)
-        .attr("y", yScale(0))
+        .attr("y", this.yScale(0))
         .attr("height", d => {
-          return Math.abs(yScale(0) - yScale(d));
+          return this.yScale(0) - this.yScale(d);
         })
-        .attr("transform", d => {
-          if (d > 0)
-            return "translate(0 -" + Math.abs(yScale(0) - yScale(d)) + ")";
-          return "translate(0 " + 0 + ")";
-        })
-        .attr("width", 60)
+        .attr("width", this.barsWidth)
         .attr("fill", (d, i) => {
-          return this.colors[i];
+          return this.$options.COLORS.REST[i];
         });
     },
-    drawLabel(diagram, height) {
-      const center = height / 2;
-      diagram
+    fnheight(name) {
+      return d => this.yScale(0) - this.yScale(d[name]);
+    },
+    drawLDC(everyBar) {
+      const height = this.fnheight("ldc");
+      everyBar
+        .append("rect")
+        .attr("y", this.yScale(0))
+        .attr("height", height)
+        .attr("width", this.barsWidth)
+        .attr("transform", d => `translate(0 ${-1 * height(d)})`)
+        .attr("fill", this.$options.COLORS.LDC);
+    },
+    drawHighestLevel(everyBar) {
+      const height = this.fnheight("highestLevel");
+      everyBar
+        .append("rect")
+        .attr("y", this.yScale(0))
+        .attr("height", height)
+        .attr("width", this.barsWidth)
+        .attr("transform", d => `translate(0 ${-1 * height(d)})`)
+        .attr("fill", this.$options.COLORS.HIGHEST);
+    },
+    drawLabelPerBar(everyBar) {
+      everyBar
+        .append("text")
+        .text(d => d.label)
+        .attr("y", this.yScale(0) + this.labelPaddingTop);
+    },
+    drawScaleLabel() {
+      const center = this.height / 2;
+      this.diagram
         .append("text")
         .text(this.$options.LEGEND)
         .attr("text-anchor", "middle")
@@ -130,16 +226,19 @@
         .attr("dy", "1em")
         .attr("transform", `translate(0, ${center}), rotate(-90)`);
     },
-    drawScale(diagram, yScale) {
-      const paddingLeft = 50;
-      const paddingTop = 10;
-      const yAxis = d3.axisLeft().scale(yScale);
-      diagram
+    drawScale() {
+      const yAxis = d3.axisLeft().scale(this.yScale);
+      this.diagram
         .append("g")
-        .attr("transform", `translate(${paddingLeft} ${paddingTop})`)
+        .attr("transform", `translate(${this.scalePaddingLeft})`)
         .call(yAxis);
     }
   },
-  LEGEND: app.$gettext("sum of days / Summe der Tage")
+  LEGEND: app.$gettext("sum of days / Summe der Tage"),
+  COLORS: {
+    LDC: "#59C6FF",
+    HIGHEST: "#2D84B3",
+    REST: ["#FF424F", "#FF737C", "#FF99A0"]
+  }
 };
 </script>