diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/map/MapPopup.vue	Wed May 08 17:10:17 2019 +0200
@@ -0,0 +1,243 @@
+<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>