view client/src/components/map/MapPopup.vue @ 3204:1253fe15e3e3

client: identify: implemented popup when clicking the map and the intention is not clear... ...because multiple features were identified. In that case no dialog will be opened automatically but a popup with possible options is shown.
author Markus Kottlaender <markus@intevation.de>
date Wed, 08 May 2019 17:10:17 +0200
parents
children dffcf1cc8a8b
line wrap: on
line source

<template>
  <div class="map-popup rounded" ref="map-popup">
    <UIBoxHeader :title="title" :closeCallback="close" small />
    <div class="p-1 small text-nowrap">
      <div
        class="d-flex flex-nowrap justify-content-between align-items-center"
        v-if="bottlenecks.length"
        v-for="bottleneck in bottlenecks"
        :key="bottleneck.get('objnam')"
      >
        <div class="mr-2">
          <font-awesome-icon icon="ship" class="mr-1" fixed-width />
          {{ bottleneck.get("objnam") }}
        </div>
        <div>
          <button
            class="btn btn-xs btn-info"
            v-tooltip="surveysLabel"
            @click="openSurveys(bottleneck)"
          >
            <font-awesome-icon icon="chart-area" fixed-width />
          </button>
          <button
            class="btn btn-xs btn-info ml-1"
            v-tooltip="fairwayAvailabilityLabel"
            @click="openFairwayAvailabilityForBottleneck(bottleneck)"
          >
            <font-awesome-icon icon="chart-line" fixed-width />
          </button>
        </div>
      </div>

      <div
        class="d-flex flex-nowrap justify-content-between align-items-center mt-1"
        v-if="gauges.length"
        v-for="gauge in gauges"
        :key="gauge.get('objname')"
      >
        <div class="mr-2">
          <font-awesome-icon icon="ruler-vertical" class="mr-1" fixed-width />
          {{ gauge.get("objname") }}
        </div>
        <button
          class="btn btn-xs btn-info"
          v-tooltip="waterlevelsLabel"
          @click="openGauges(gauge)"
        >
          <font-awesome-icon icon="ruler-vertical" fixed-width />
        </button>
      </div>

      <div
        class="d-flex flex-nowrap justify-content-between align-items-center mt-1"
        v-if="stretches.length"
        v-for="stretch in stretches"
        :key="stretch.get('objnam')"
      >
        <div class="mr-2">
          <font-awesome-icon icon="road" class="mr-1" fixed-width />
          {{ stretch.get("objnam") }}
        </div>
        <button
          class="btn btn-xs btn-info"
          v-tooltip="fairwayAvailabilityLabel"
          @click="openFairwayAvailabilityForStretch(stretch)"
        >
          <font-awesome-icon icon="chart-line" fixed-width />
        </button>
      </div>

      <div
        class="d-flex flex-nowrap justify-content-between align-items-center mt-1"
        v-if="sections.length"
        v-for="section in sections"
        :key="section.get('objnam')"
      >
        <div class="mr-2">
          <font-awesome-icon icon="road" class="mr-1" fixed-width />
          {{ section.get("objnam") }}
        </div>
        <button
          class="btn btn-xs btn-info"
          v-tooltip="fairwayAvailabilityLabel"
        >
          <font-awesome-icon icon="chart-line" fixed-width />
        </button>
      </div>
    </div>
    <div
      v-if="identifiedCoordinates"
      class="border-top text-muted p-1 coordinates"
    >
      Lat: {{ identifiedCoordinates[1].toFixed(8) }}, Lon:
      {{ identifiedCoordinates[0].toFixed(8) }}
    </div>
  </div>
</template>

<style lang="sass">
.map-popup
  position: absolute
  background: #fff
  min-width: 200px
  min-height: 85px
  box-shadow: 0 0.1rem 0.5rem rgba(0, 0, 0, 0.2)
  border-top-left-radius: 0 !important
  margin-left: 10px
  &::before
    content: ""
    position: absolute
    top: 0
    left: -10px
    border: 5px solid transparent
    border-top: 5px solid white
    border-right: 5px solid white
  .coordinates
    font-size: 70%
</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 { mapState } from "vuex";
import Overlay from "ol/Overlay.js";
import { getCenter } from "ol/extent";

export default {
  computed: {
    ...mapState("map", [
      "mapPopup",
      "identifiedFeatures",
      "identifiedCoordinates"
    ]),
    title() {
      return this.$gettext("Identified Features");
    },
    bottlenecks() {
      return this.identifiedFeatures.filter(f =>
        /^bottlenecks/.test(f.getId())
      );
    },
    gauges() {
      return this.identifiedFeatures.filter(f => /^gauges/.test(f.getId()));
    },
    stretches() {
      return this.identifiedFeatures.filter(f => /^stretches/.test(f.getId()));
    },
    sections() {
      return this.identifiedFeatures.filter(f => /^sections/.test(f.getId()));
    },
    surveysLabel() {
      return this.$gettext("Surveys");
    },
    fairwayAvailabilityLabel() {
      return this.$gettext("Fairway Availability");
    },
    waterlevelsLabel() {
      return this.$gettext("Waterlevels");
    }
  },
  methods: {
    close() {
      this.mapPopup.setPosition(undefined);
    },
    openSurveys(bottleneck) {
      this.$store.commit("application/showProfiles", true);
      this.$store.dispatch(
        "bottlenecks/setSelectedBottleneck",
        bottleneck.get("objnam")
      );
      this.$store.dispatch("map/moveMap", {
        coordinates: getCenter(
          bottleneck
            .getGeometry()
            .clone()
            .transform("EPSG:3857", "EPSG:4326")
            .getExtent()
        ),
        zoom: 17,
        preventZoomOut: true
      });
      this.close();
    },
    openGauges(gauge) {
      this.$store.commit("application/showGauges", true);
      this.$store.dispatch("gauges/selectedGaugeISRS", gauge.get("isrs_code"));
      this.close();
    },
    openFairwayAvailability() {
      this.$store.commit("application/showStatistics", true);
      this.close();
    },
    openFairwayAvailabilityForBottleneck(bottleneck) {
      this.$store.dispatch(
        "bottlenecks/setSelectedBottleneck",
        bottleneck.get("objnam")
      );
      this.$store.dispatch("map/moveMap", {
        coordinates: getCenter(
          bottleneck
            .getGeometry()
            .clone()
            .transform("EPSG:3857", "EPSG:4326")
            .getExtent()
        ),
        zoom: 17,
        preventZoomOut: true
      });
      this.openFairwayAvailability();
    },
    openFairwayAvailabilityForStretch(stretch) {
      this.$store.commit("imports/selectedStretchId", stretch.getId());
      this.$store.dispatch("map/moveToFeauture", {
        feature: stretch,
        zoom: 17
      });
      this.openFairwayAvailability();
    }
  },
  mounted() {
    const mapPopup = new Overlay({
      element: this.$refs["map-popup"],
      autoPan: true,
      autoPanAnimation: {
        duration: 250
      }
    });
    this.$store.commit("map/mapPopup", mapPopup);
  }
};
</script>