view client/src/components/map/Map.vue @ 3044:c71373594719

client: map: prepared store to hold multiple map objects This will be necessary to sync maps, toggle layers per map, etc. Therefore the methods to move the map (moveToExtent, etc.) became actions instead of mutations.
author Markus Kottlaender <markus@intevation.de>
date Sat, 13 Apr 2019 16:02:06 +0200
parents 2e2a271c1026
children 051a3f446ac2
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", "paneMode"]),
    ...mapState("imports", ["selectedStretchId"]),
    layers() {
      return layers();
    },
    hasActiveInteractions() {
      return (
        (this.lineTool && this.lineTool.getActive()) ||
        (this.polygonTool && this.polygonTool.getActive()) ||
        (this.cutTool && this.cutTool.getActive())
      );
    }
  },
  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());
    },
    paneMode() {
      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/disableIdentifyTool");
    this.$store.dispatch("map/enableIdentifyTool");
  }
};
</script>