changeset 3055:b3c24c47931c

client: layers legend: support multiple maps If there is more than one map, there's a layer checkbox for each of them, so layers can be toggle for each map separately.
author Markus Kottlaender <markus@intevation.de>
date Tue, 16 Apr 2019 09:26:51 +0200
parents 1ef2f4179d30
children 5ada194e27fc
files client/src/components/layers/Layers.vue client/src/components/layers/Layerselect.vue
diffstat 2 files changed, 74 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/layers/Layers.vue	Tue Apr 16 09:00:42 2019 +0200
+++ b/client/src/components/layers/Layers.vue	Tue Apr 16 09:26:51 2019 +0200
@@ -5,30 +5,27 @@
       { expanded: showLayers }
     ]"
   >
-    <div style="width: 18rem">
-      <UIBoxHeader
-        icon="layer-group"
-        :title="layersLabel"
-        :closeCallback="close"
-      />
-      <div class="box-body small" v-if="openLayersMap">
-        <Layerselect :layer="openLayersMap.getLayer('OPENSTREETMAP')" />
-        <Layerselect :layer="openLayersMap.getLayer('INLANDECDIS')" />
-        <Layerselect :layer="openLayersMap.getLayer('WATERWAYAREA')" />
-        <Layerselect :layer="openLayersMap.getLayer('STRETCHES')" />
-        <Layerselect :layer="openLayersMap.getLayer('FAIRWAYDIMENSIONSLOS3')" />
-        <Layerselect :layer="openLayersMap.getLayer('FAIRWAYDIMENSIONSLOS2')" />
-        <Layerselect :layer="openLayersMap.getLayer('FAIRWAYDIMENSIONSLOS1')" />
-        <Layerselect :layer="openLayersMap.getLayer('WATERWAYAXIS')" />
-        <Layerselect :layer="openLayersMap.getLayer('WATERWAYPROFILES')" />
-        <Layerselect :layer="openLayersMap.getLayer('BOTTLENECKS')" />
-        <Layerselect :layer="openLayersMap.getLayer('BOTTLENECKISOLINE')" />
-        <Layerselect :layer="openLayersMap.getLayer('DIFFERENCES')" />
-        <Layerselect :layer="openLayersMap.getLayer('BOTTLENECKSTATUS')" />
-        <Layerselect :layer="openLayersMap.getLayer('DISTANCEMARKS')" />
-        <Layerselect :layer="openLayersMap.getLayer('DISTANCEMARKSAXIS')" />
-        <Layerselect :layer="openLayersMap.getLayer('GAUGES')" />
+    <div class="position-relative" style="width: 18rem; min-height: 350px;">
+      <UIBoxHeader icon="layer-group" :title="label" :closeCallback="close" />
+      <div class="small" v-if="openLayersMaps.length">
+        <Layerselect layerId="OPENSTREETMAP" />
+        <Layerselect layerId="INLANDECDIS" />
+        <Layerselect layerId="WATERWAYAREA" />
+        <Layerselect layerId="STRETCHES" />
+        <Layerselect layerId="FAIRWAYDIMENSIONSLOS3" />
+        <Layerselect layerId="FAIRWAYDIMENSIONSLOS2" />
+        <Layerselect layerId="FAIRWAYDIMENSIONSLOS1" />
+        <Layerselect layerId="WATERWAYAXIS" />
+        <Layerselect layerId="WATERWAYPROFILES" />
+        <Layerselect layerId="BOTTLENECKS" />
+        <Layerselect layerId="BOTTLENECKISOLINE" />
+        <Layerselect layerId="DIFFERENCES" />
+        <Layerselect layerId="BOTTLENECKSTATUS" />
+        <Layerselect layerId="DISTANCEMARKS" />
+        <Layerselect layerId="DISTANCEMARKSAXIS" />
+        <Layerselect layerId="GAUGES" />
       </div>
+      <UISpinnerOverlay v-else style="top: 34px;" />
     </div>
   </div>
 </template>
@@ -48,16 +45,16 @@
  * Thomas Junk <thomas.junk@intevation.de>
  * Markus Kottländer <markus.kottlaender@intevation.de>
  */
-import { mapState, mapGetters } from "vuex";
+import { mapState } from "vuex";
 
 export default {
   components: {
     Layerselect: () => import("./Layerselect")
   },
   computed: {
-    ...mapGetters("map", ["openLayersMap"]),
     ...mapState("application", ["showLayers"]),
-    layersLabel() {
+    ...mapState("map", ["openLayersMaps"]),
+    label() {
       return this.$gettext("Layers");
     }
   },
--- a/client/src/components/layers/Layerselect.vue	Tue Apr 16 09:00:42 2019 +0200
+++ b/client/src/components/layers/Layerselect.vue	Tue Apr 16 09:26:51 2019 +0200
@@ -1,25 +1,29 @@
 <template>
-  <div>
-    <div class="form-check d-flex flex-start">
+  <div
+    class="d-flex flex-column flex-start px-2 border-bottom"
+    style="border-bottom-style: dashed !important;"
+  >
+    <div class="d-flex">
       <input
-        class="form-check-input"
+        v-for="map in openLayersMaps"
+        :key="map.getTarget()"
+        class="mt-1 mr-1"
         type="checkbox"
-        @change="visibilityToggled"
-        :checked="layer.getVisible()"
+        @change="toggle(map)"
+        :checked="isVisible(map)"
       />
-      <LegendElement :layer="layer"></LegendElement>
-      <label
-        class="pointer layername form-check-label ml-2"
-        @click="visibilityToggled"
-      >
+      <LegendElement class="pointer" :layer="layer" @click.native="toggle()" />
+      <label class="pointer layername form-check-label ml-1" @click="toggle()">
         {{ label }}
       </label>
     </div>
-    <div v-if="layer.getVisible() && layer.get('id') === 'BOTTLENECKISOLINE'">
-      <img class="rounded my-1 d-block" :src="isolinesLegendImgDataURL" />
-    </div>
-    <div v-if="layer.getVisible() && layer.get('id') === 'DIFFERENCES'">
-      <img class="rounded my-1 d-block" :src="differencesLegendImgDataURL" />
+    <div>
+      <div v-if="isVisible() && layer.get('id') === 'BOTTLENECKISOLINE'">
+        <img class="rounded my-1 d-block" :src="isolinesLegendImgDataURL" />
+      </div>
+      <div v-if="isVisible() && layer.get('id') === 'DIFFERENCES'">
+        <img class="rounded my-1 d-block" :src="differencesLegendImgDataURL" />
+      </div>
     </div>
   </div>
 </template>
@@ -41,26 +45,53 @@
  */
 import { HTTP } from "@/lib/http";
 import { displayError } from "@/lib/errors";
-import { mapState } from "vuex";
+import { mapState, mapGetters } from "vuex";
 
 export default {
-  props: ["layer"],
   components: {
     LegendElement: () => import("./LegendElement")
   },
+  props: ["layerId"],
   computed: {
     ...mapState("map", [
-      "layers",
+      "openLayersMaps",
       "isolinesLegendImgDataURL",
       "differencesLegendImgDataURL"
     ]),
+    ...mapGetters("map", ["openLayersMap"]),
+    layer() {
+      return this.openLayersMap.getLayer(this.layerId);
+    },
     label() {
       return this.$gettext(this.layer.get("label"));
     }
   },
   methods: {
-    visibilityToggled() {
-      this.layer.setVisible(!this.layer.getVisible());
+    toggle(map) {
+      if (map) {
+        map
+          .getLayer(this.layerId)
+          .setVisible(!map.getLayer(this.layerId).getVisible());
+      } else {
+        this.openLayersMaps.forEach(m => {
+          m.getLayer(this.layerId).setVisible(
+            !m.getLayer(this.layerId).getVisible()
+          );
+        });
+      }
+    },
+    isVisible(map) {
+      if (map) {
+        return map.getLayer(this.layerId).getVisible();
+      } else {
+        let isVisible = false;
+        this.openLayersMaps.forEach(m => {
+          if (m.getLayer(this.layerId).getVisible()) {
+            isVisible = true;
+          }
+        });
+        return isVisible;
+      }
     },
     loadLegendImage(layer, storeTarget) {
       HTTP.get(