view client/src/components/map/Map.vue @ 3062:87e0422cffa7

client: draw/cut tools work now with multiple maps
author Markus Kottlaender <markus@intevation.de>
date Tue, 16 Apr 2019 12:49:29 +0200
parents 40a4a808b9b6
children 333aff79197d
line wrap: on
line source

<template>
  <div
    :id="'map-' + uuid"
    :class="[
      'map',
      {
        splitscreen: this.splitscreen,
        nocursor: this.hasActiveInteractions
      }
    ]"
  ></div>
</template>

<style lang="sass" scoped>
.map
  width: 100%
  height: 100%

  &.splitscreen
    height: 50%

  &.nocursor
    cursor: none
</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, 2019 by via donau
 *   – Österreichische Wasserstraßen-Gesellschaft mbH
 * Software engineering by Intevation GmbH
 *
 * Author(s):
 * * Thomas Junk <thomas.junk@intevation.de>
 * * Bernhard E. Reiter <bernhard.reiter@intevation.de>
 */
import { HTTP } from "@/lib/http";
import { mapState } from "vuex";
import { Map, View } from "ol";
import { Stroke, Style, Fill } from "ol/style";
import { displayError } from "@/lib/errors";
import { uuid } from "@/lib/mixins";
import layers from "@/components/map/layers";
import "ol/ol.css";

/* for the sake of debugging */
/* eslint-disable no-console */
export default {
  mixins: [uuid],
  data() {
    return {
      map: null,
      splitscreen: false
    };
  },
  computed: {
    ...mapState("map", [
      "initialLoad",
      "extent",
      "lineTool",
      "polygonTool",
      "cutTool"
    ]),
    ...mapState("bottlenecks", ["selectedSurvey"]),
    ...mapState("application", ["showSplitscreen", "panes", "paneRotate"]),
    ...mapState("imports", ["selectedStretchId"]),
    layers() {
      return layers();
    },
    hasActiveInteractions() {
      let active = false;
      if (this.map) {
        this.map
          .getInteractions()
          .getArray()
          .filter(i =>
            ["linetool", "polygontool", "cuttool"].includes(i.get("id"))
          )
          .forEach(i => {
            if (i.getActive()) {
              active = true;
            }
          });
      }
      return active;
    }
  },
  methods: {
    updateBottleneckFilter(bottleneck_id, datestr) {
      const exists = bottleneck_id != "does_not_exist";

      if (exists) {
        this.layers
          .get("BOTTLENECKISOLINE")
          .getSource()
          .updateParams({
            cql_filter: `date_info='${datestr}' AND bottleneck_id='${bottleneck_id}'`
          });
      }
      this.layers.get("BOTTLENECKISOLINE").setVisible(exists);
    }
  },
  watch: {
    showSplitscreen(show) {
      if (show) {
        setTimeout(() => {
          this.splitscreen = true;
        }, 350);
      } else {
        this.splitscreen = false;
      }
    },
    panes() {
      this.$nextTick(() => this.map.updateSize());
    },
    paneRotate() {
      this.$nextTick(() => this.map.updateSize());
    },
    splitscreen() {
      this.$nextTick(() => this.map.updateSize());
    },
    selectedSurvey(newSelectedSurvey) {
      if (newSelectedSurvey) {
        this.updateBottleneckFilter(
          newSelectedSurvey.bottleneck_id,
          newSelectedSurvey.date_info
        );
      } else {
        this.updateBottleneckFilter("does_not_exist", "1999-10-01");
      }
    },
    selectedStretchId(id) {
      this.layers
        .get("STRETCHES")
        .getSource()
        .getFeatures()
        .forEach(f => {
          f.set("highlighted", false);
          if (id === f.getId()) {
            f.set("highlighted", true);
          }
        });
    }
  },
  mounted() {
    this.map = new Map({
      layers: this.layers.config,
      target: "map-" + this.uuid,
      controls: [],
      view: new View({
        center: [this.extent.lon, this.extent.lat],
        minZoom: 5, // restrict zooming out to ~size of Europe for width 1000px
        zoom: this.extent.zoom,
        projection: "EPSG:3857"
      })
    });
    this.map.getLayer = id => this.layers.get(id);

    // store map position on every move
    // will be obsolete once we abandoned the separated admin context
    this.map.on("moveend", event => {
      const center = event.map.getView().getCenter();
      this.$store.commit("map/extent", {
        lat: center[1],
        lon: center[0],
        zoom: event.map.getView().getZoom()
      });
    });
    this.$store.dispatch("map/openLayersMap", this.map);

    // move to user specific default extent if map loads for the first timeout
    // checking initialLoad will be obsolete once we abandoned the separated admin context
    if (this.initialLoad) {
      this.$store.commit("map/initialLoad", false);
      var currentUser = this.$store.state.user.user;
      HTTP.get("/users/" + currentUser, {
        headers: {
          "X-Gemma-Auth": localStorage.getItem("token"),
          "Content-type": "text/xml; charset=UTF-8"
        }
      })
        .then(response => {
          this.$store.dispatch("map/moveToBoundingBox", {
            boundingBox: [
              response.data.extent.x1,
              response.data.extent.y1,
              response.data.extent.x2,
              response.data.extent.y2
            ],
            zoom: 17,
            preventZoomOut: true
          });
        })
        .catch(error => {
          const { status, data } = error.response;
          displayError({
            title: this.$gettext("Backend Error"),
            message: `${status}: ${data.message || data}`
          });
        });
    }

    // load configured bottleneck colors
    HTTP.get("/system/style/Bottlenecks/stroke", {
      headers: { "X-Gemma-Auth": localStorage.getItem("token") }
    })
      .then(response => {
        let btlnStrokeC = response.data.code;
        HTTP.get("/system/style/Bottlenecks/fill", {
          headers: { "X-Gemma-Auth": localStorage.getItem("token") }
        })
          .then(response => {
            let btlnFillC = response.data.code;
            var newStyle = new Style({
              stroke: new Stroke({
                color: btlnStrokeC,
                width: 4
              }),
              fill: new Fill({
                color: btlnFillC
              })
            });
            this.layers.get("BOTTLENECKS").setStyle(newStyle);
          })
          .catch(error => {
            console.log(error);
          });
      })
      .catch(error => {
        console.log(error);
      });

    this.$store.dispatch("map/initIdentifyTool", this.map);
  },
  destroyed() {
    this.$store.commit("map/removeOpenLayersMap", this.map);
  }
};
</script>