Mercurial > gemma
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"),