changeset 4334:8ac59c8183e8

client: add showNumbers to AvailableFairwayDepth diagram * Add bootstrap button to the diagram legend. Below the the other options because of its lesser importance. * Change calculation of days from hours to use one precision after the decimal point to show that we are coming from summed hours. This shall lead to clarification what users expect, see code comment. * Draw the numbers close to the bars: Above for LDC and highestLevel, below for the "lowerLevels". * Enchance test data in docs/developers.md to cover more interesting cases.
author Bernhard Reiter <bernhard@intevation.de>
date Thu, 05 Sep 2019 14:50:05 +0200
parents 3f0422751cb4
children 2f212f520a04
files client/docs/developers.md client/src/components/fairway/AvailableFairwayDepth.vue
diffstat 2 files changed, 91 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/client/docs/developers.md	Thu Sep 05 10:41:34 2019 +0200
+++ b/client/docs/developers.md	Thu Sep 05 14:50:05 2019 +0200
@@ -20,10 +20,15 @@
 data = store.state.fairwayavailability.csv
 
 data=`#time,# < LDC (164.0) [h],# >= LDC (164.0) [h],# < 230.0 [h],# >= 230.0 [h],# >= 250.0 [h]
-05-2019,140,80,80,45,50
-06-2019,0,230.000,0.000,0.000
-07-2019,0,300,0.000,0.000,0.000
-08-2019,0.000,120.000,0.000,0.000,120.000
+01-2019,0  ,744,  0,  0,744
+02-2019,324,324,150,174,324
+03-2019, 24,696, 80, 45, 50
+04-2019,120,600, 24, 24,672.5
+05-2019,140,80 , 80, 45, 50
+06-2019,  0,  0,  0,  0,  0.000
+07-2019,  0,300,  0,  0,  0
+08-2019,  0,  0,744,  0,  0
+09-2019,  0,720,  0, 96,624
 `
 
 store.commit("fairwayavailability/setAvailableFairwayDepthData", data)
--- a/client/src/components/fairway/AvailableFairwayDepth.vue	Thu Sep 05 10:41:34 2019 +0200
+++ b/client/src/components/fairway/AvailableFairwayDepth.vue	Thu Sep 05 14:50:05 2019 +0200
@@ -42,6 +42,17 @@
             >Download CSV</a
           >
         </div>
+        <div class="btn-group-toggle w-100 mt-2">
+          <label
+            class="btn btn-outline-secondary btn-sm"
+            :class="{ active: showNumbers }"
+            ><input
+              type="checkbox"
+              v-model="showNumbers"
+              autocomplete="off"
+            />Numbers
+          </label>
+        </div>
       </DiagramLegend>
       <div
         ref="diagramContainer"
@@ -69,6 +80,7 @@
  * * Thomas Junk <thomas.junk@intevation.de>
  * * Markus Kottländer <markus.kottlaender@intevation.de>
  * * Fadi Abbud <fadi.abbud@intevation.de>
+ * * Bernhard Reiter <bernhard.reiter@intevation.de>
  */
 import * as d3 from "d3";
 import app from "@/main";
@@ -81,7 +93,14 @@
 import { FREQUENCIES } from "@/store/fairwayavailability";
 import { defaultDiagramTemplate } from "@/lib/DefaultDiagramTemplate";
 
-const hoursInDays = x => Math.round(x / 24);
+// FIXME This is a rounding methods that shows that we have fractions,
+// because we are coming from hours.  Users will understand the underlying
+// math better and we can see if this is wanted.
+// With the backend just giving us the summarized hours, we cannot do
+// a classification of each day into a category.
+// (The name of the function is kept to keep the diff more readable and
+// should changed if this is more clarified.)
+const hoursInDays = x => Math.round((x * 10) / 24) / 10;
 
 export default {
   mixins: [diagram, pdfgen, templateLoader],
@@ -106,7 +125,8 @@
       },
       templateData: null,
       templates: [],
-      defaultTemplate: defaultDiagramTemplate
+      defaultTemplate: defaultDiagramTemplate,
+      showNumbers: false
     };
   },
   created() {
@@ -454,9 +474,8 @@
           const dy = document
             .querySelector(".diagram-container")
             .getBoundingClientRect().left;
-          const value = Number.parseFloat(hoursInDays(d.height)).toFixed(2);
           d3.select("#tooltip")
-            .text(Math.round(value))
+            .text(hoursInDays(d.height))
             .attr("y", y - 10)
             .attr("x", d3.event.pageX - dy);
           //d3.event.pageX gives coordinates relative to SVG
@@ -472,9 +491,32 @@
         })
         .attr("x", ldcOffset + spaceBetween / 2)
         .attr("width", widthPerItem - ldcOffset - spaceBetween)
+        .attr("id", "lower")
         .attr("fill", (d, i) => {
           return this.$options.COLORS.REST[i];
         });
+      if (this.showNumbers) {
+        everyBar
+          .selectAll("g.bars")
+          .data(d => d.lowerLevels)
+          .enter()
+          .filter(d => hoursInDays(d.height) > 0)
+          .insert("text")
+          .attr("y", d => {
+            return ( 2 * yScale(0)
+              - yScale(hoursInDays(d.translateY))
+              + this.paddingTop
+              + (yScale(0) - yScale(hoursInDays(d.height)))
+              + (yScale(0) - yScale(1.9)) //instead o alignment-baseline hanging
+            );
+          })
+          .attr("x", widthPerItem / 2)
+          .text(d => hoursInDays(d.height))
+          // does not work with svg2pdf .attr("alignment-baseline", "hanging")
+          .attr("text-anchor", "middle")
+          .attr("font-size", "8")
+          .attr("fill", "black");
+      }
     },
     fnheight({ name, yScale }) {
       return d => yScale(0) - yScale(hoursInDays(d[name]));
@@ -484,7 +526,7 @@
       everyBar
         .append("rect")
         .on("mouseover", function() {
-          d3.select(this).attr("opacity", "0.8");
+          d3.select(this).attr("opacity", "0.7");
           d3.select("#tooltip").attr("opacity", 1);
         })
         .on("mouseout", function() {
@@ -496,9 +538,8 @@
           const dy = document
             .querySelector(".diagram-container")
             .getBoundingClientRect().left;
-          const value = Number.parseFloat(hoursInDays(d.ldc)).toFixed(2);
           d3.select("#tooltip")
-            .text(Math.round(value))
+            .text(hoursInDays(d.ldc))
             .attr("y", y - 50)
             .attr("x", d3.event.pageX - dy);
           //d3.event.pageX gives coordinates relative to SVG
@@ -514,6 +555,21 @@
         )
         .attr("fill", this.$options.COLORS.LDC)
         .attr("id", "ldc");
+      if (this.showNumbers) {
+        everyBar
+          .filter(d => hoursInDays(d.ldc) > 0)
+          .append("text")
+          .attr("y", yScale(0.5)) // some distance from the bar
+          .attr("x",  spaceBetween / 2)
+          .text(d => hoursInDays(d.ldc))
+          .attr("text-anchor", "left")
+          .attr("font-size", "8")
+          .attr(
+            "transform",
+            d => `translate(0 ${this.paddingTop + -1 * height(d)})`
+          )
+          .attr("fill", "black");
+      }
     },
     drawHighestLevel({
       everyBar,
@@ -538,11 +594,8 @@
           const dy = document
             .querySelector(".diagram-container")
             .getBoundingClientRect().left;
-          const value = Number.parseFloat(hoursInDays(d.highestLevel)).toFixed(
-            2
-          );
           d3.select("#tooltip")
-            .text(Math.round(value))
+            .text(hoursInDays(d.highestLevel))
             .attr("y", y - 50)
             .attr("x", d3.event.pageX - dy);
           //d3.event.pageX gives coordinates relative to SVG
@@ -557,6 +610,21 @@
           d => `translate(0 ${this.paddingTop + -1 * height(d)})`
         )
         .attr("fill", this.$options.COLORS.HIGHEST);
+      if (this.showNumbers) {
+        everyBar
+          .filter(d => hoursInDays(d.highestLevel) > 0)
+          .append("text")
+          .attr("y", yScale(0.5)) // some distance from the bar
+          .attr("x", widthPerItem / 2)
+          .text(d => hoursInDays(d.highestLevel))
+          .attr("text-anchor", "middle")
+          .attr("font-size", "8")
+          .attr(
+            "transform",
+            d => `translate(0 ${this.paddingTop + -1 * height(d)})`
+          )
+          .attr("fill", "black");
+      }
     },
     drawLabelPerBar({ everyBar, dimensions, widthPerItem }) {
       everyBar
@@ -647,6 +715,9 @@
   watch: {
     fwData() {
       this.drawDiagram();
+    },
+    showNumbers() {
+      this.drawDiagram();
     }
   },
   LEGEND: app.$gettext("Sum of days"),