view client/src/components/fairway/AvailableFairwayDepth.vue @ 3210:66e90b48387a

available_fairway-depth: store refactored
author Thomas Junk <thomas.junk@intevation.de>
date Thu, 09 May 2019 09:53:02 +0200
parents cd076b7a2227
children b3a1ecdda797
line wrap: on
line source

<template>
  <div class="d-flex flex-column flex-fill">
    <UIBoxHeader icon="chart-area" :title="title" :closeCallback="close" />
    <UISpinnerOverlay v-if="loading" />
    <div class="mt-3 d-flex flex-row my-auto">
      <div :id="containerId" class="ml-auto diagram-container"></div>
    </div>
  </div>
</template>

<style></style>

<script>
/* This is Free Software under GNU Affero General Public License v >= 3.0
 * without warranty, see README.md and license for details.
 *
 * SPDX-License-Identifier: AGPL-3.0-or-later
 * License-Filename: LICENSES/AGPL-3.0.txt
 *
 * Copyright (C) 2018 by via donau
 *   – Österreichische Wasserstraßen-Gesellschaft mbH
 * Software engineering by Intevation GmbH
 *
 * Author(s):
 * Thomas Junk <thomas.junk@intevation.de>
 * Markus Kottländer <markus.kottlaender@intevation.de>
 */
import * as d3 from "d3";
import app from "@/main";
import debounce from "debounce";
import { diagram } from "@/lib/mixins";
import { mapState } from "vuex";
import filters from "@/lib/filters.js";

export default {
  mixins: [diagram],
  data() {
    return {
      containerId: "availablefairwaydepth",
      loading: false,
      width: 1000,
      height: 600,
      paddingRight: 100,
      spaceBetween: 80,
      labelPaddingTop: 15,
      scalePaddingLeft: 50,
      paddingTop: 10,
      legend: "",
      diagram: null,
      yScale: null,
      barsWidth: 60,
      dimensions: null
    };
  },
  created() {
    window.addEventListener("resize", debounce(this.drawDiagram), 100);
  },
  mounted() {
    this.drawDiagram();
  },
  computed: {
    ...mapState("fairwayavailability", [
      "selectedFairwayAvailabilityFeature",
      "fwData",
      "from",
      "to",
      "frequency"
    ]),
    fromDate() {
      return this.from;
    },
    toDate() {
      return this.to;
    },
    availability() {
      return this.plainAvailability;
    },
    title() {
      return `Available Fairway Depth: ${
        this.featureName
      } (${filters.surveyDate(this.fromDate)} - ${filters.surveyDate(
        this.toDate
      )}) ${this.$gettext(this.frequency)}`;
    },
    featureName() {
      return this.selectedFairwayAvailabilityFeature.properties.name;
    }
  },
  methods: {
    close() {
      this.$store.commit("application/paneSetup", "DEFAULT");
    },
    drawDiagram() {
      this.dimensions = this.getDimensions();
      this.yScale = d3
        .scaleLinear()
        .domain([-33, 33])
        .range([this.dimensions.mainHeight - 30, 0]);
      d3.select(".diagram-container svg").remove();
      this.generateDiagramContainer();
      this.drawBars();
      this.drawScaleLabel();
      this.drawScale();
    },
    generateDiagramContainer() {
      const diagram = d3
        .select(".diagram-container")
        .append("svg")
        .attr("width", this.dimensions.width)
        .attr("height", this.dimensions.mainHeight);
      this.diagram = diagram
        .append("g")
        .attr("transform", `translate(0 ${this.paddingTop})`);
    },
    drawBars() {
      const everyBar = this.diagram
        .selectAll("g")
        .data(this.fwData)
        .enter()
        .append("g")
        .attr("transform", (d, i) => {
          const dx = this.paddingRight + i * this.spaceBetween;
          return `translate(${dx})`;
        });
      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("y", this.yScale(0))
        .attr("height", d => {
          return this.yScale(0) - this.yScale(d);
        })
        .attr("width", this.barsWidth)
        .attr("fill", (d, i) => {
          return this.$options.COLORS.REST[i];
        });
    },
    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.dimensions.mainHeight / 2;
      this.diagram
        .append("text")
        .text(this.$options.LEGEND)
        .attr("text-anchor", "middle")
        .attr("x", 0)
        .attr("y", 0)
        .attr("dy", "1em")
        .attr("transform", `translate(0, ${center}), rotate(-90)`);
    },
    drawScale() {
      const yAxis = d3.axisLeft().scale(this.yScale);
      this.diagram
        .append("g")
        .attr("transform", `translate(${this.scalePaddingLeft})`)
        .call(yAxis);
    }
  },
  LEGEND: app.$gettext("sum of days / Summe der Tage"),
  COLORS: {
    LDC: "#59C6FF",
    HIGHEST: "#2D84B3",
    REST: ["#FF424F", "#FF737C", "#FF99A0"]
  }
};
</script>