From d662ac55580b69c906edecc0d80ef8b58fac545e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e?= <tpoussard@neogeo.fr>
Date: Fri, 24 Jun 2022 18:12:14 +0200
Subject: [PATCH] seperate layer selectors in a new component

---
 src/components/Map/LayerSelector.vue | 229 +++++++++++++++++++++++++++
 src/components/Map/SidebarLayers.vue | 202 ++---------------------
 2 files changed, 243 insertions(+), 188 deletions(-)
 create mode 100644 src/components/Map/LayerSelector.vue

diff --git a/src/components/Map/LayerSelector.vue b/src/components/Map/LayerSelector.vue
new file mode 100644
index 00000000..d7b80563
--- /dev/null
+++ b/src/components/Map/LayerSelector.vue
@@ -0,0 +1,229 @@
+<template>
+  <div class="basemaps-items ui accordion styled">
+    <div
+      :class="['basemap-item title', { active }]"
+      @click="activateGroup(basemap)"
+    >
+      {{ basemap.title }}
+    </div>
+    <div
+      v-if="isQueryable(basemap)"
+      :id="`queryable-layers-selector-${basemap.id}`"
+    >
+      <strong>Couche requêtable</strong>
+      <Dropdown
+        :options="getQueryableLayers(basemap)"
+        :selected="selectedQueryLayer"
+        :search="true"
+        @update:selection="onQueryLayerChange($event)"
+      />
+    </div>
+    <div
+      :id="`list-${basemap.id}`"
+      :class="['content', { active }]"
+      :data-basemap-index="basemap.id"
+    >
+      <div
+        v-for="(layer, index) in basemap.layers"
+        :key="basemap.id + '-' + layer.id + '-' + index"
+        class="layer-item transition visible item list-group-item"
+        :data-id="layer.id"
+      >
+        <!-- layer id is used for retrieving layer when changing order -->
+        <p class="layer-handle-sort">
+          <i
+            class="th icon"
+            aria-hidden="true"
+          />
+          {{ layer.title }}
+        </p>
+        <label>Opacité &nbsp;<span>(%)</span></label>
+        <div class="range-container">
+          <input
+            type="range"
+            min="0"
+            max="1"
+            :value="layer.opacity"
+            step="0.01"
+            @change="updateOpacity($event, layer)"
+          ><output class="range-output-bubble">{{
+            getOpacity(layer.opacity)
+          }}</output>
+        </div>
+        <div class="ui divider" />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Sortable from 'sortablejs';
+
+import Dropdown from '@/components/Dropdown.vue';
+import mapService from '@/services/map-service';
+
+
+export default {
+  name: 'LayerSelector',
+
+  components: {
+    Dropdown,
+  },
+
+  props: {
+    basemap: {
+      type: Object,
+      default: null,
+    },
+    baseMaps: {
+      type: Array,
+      default: () => [],
+    },
+    activeBasemap: {
+      type: Object,
+      default: () => {},
+    },
+  },
+
+  data() {
+    return {
+      selectedQueryLayer: null,
+    };
+  },
+
+  computed: {
+    active() {
+      return this.basemap.active !== undefined && this.basemap.active;
+    },
+  },
+
+  mounted() {
+    setTimeout(this.initSortable.bind(this), 1000);
+  },
+
+  methods: {
+    isQueryable(baseMap) {
+      const queryableLayer = baseMap.layers.filter((l) => l.queryable === true);
+      return queryableLayer.length > 0;
+    },
+
+    setLocalstorageMapOptions(basemaps) {
+      let mapOptions = localStorage.getItem('geocontrib-map-options') || {};
+      mapOptions = mapOptions.length ? JSON.parse(mapOptions) : {};
+      const project = this.$route.params.slug;
+      mapOptions[project] = {
+        ...mapOptions[project],
+        basemaps: basemaps,
+      };
+      localStorage.setItem(
+        'geocontrib-map-options',
+        JSON.stringify(mapOptions)
+      );
+    },
+
+    onlayerMove() {
+      // Get the names of the current layers in order.
+      const currentLayersNamesInOrder = Array.from(
+        document.getElementsByClassName('layer-item transition visible')
+      ).map((el) => parseInt(el.attributes['data-id'].value));
+      // Create an array to put the layers in order.
+      let movedLayers = [];
+
+      for (const layerName of currentLayersNamesInOrder) {
+        movedLayers.push(
+          this.activeBasemap.layers.filter((el) => el.id === layerName)[0]
+        );
+      }
+      // Remove existing layers undefined
+      movedLayers = movedLayers.filter(function (x) {
+        return x !== undefined;
+      });
+      const eventOrder = new CustomEvent('change-layers-order', {
+        detail: {
+          layers: movedLayers,
+        },
+      });
+      document.dispatchEvent(eventOrder);
+      // Save the basemaps options into the localstorage
+      this.setLocalstorageMapOptions(this.baseMaps);
+    },
+
+    initSortable() {
+      this.baseMaps.forEach((basemap) => {
+        const element = document.getElementById(`list-${basemap.id}`);
+        if (element) {
+          this. sortable = new Sortable(element, {
+            animation: 150,
+            handle: '.layer-handle-sort', // The element that is active to drag
+            ghostClass: 'blue-background-class',
+            dragClass: 'white-opacity-background-class',
+            onEnd: this.onlayerMove.bind(this),
+          });
+        } else {
+          console.error(`list-${basemap.id} not found in dom`);
+        }
+      });
+    },
+
+    onQueryLayerChange(layer) {
+      this.selectedQueryLayer = layer.name;
+      const baseMap = this.baseMaps[0].layers.find((l) => l.title === layer.name);
+      if (baseMap) {
+        baseMap.query = true;
+      } else {
+        console.error('No such param \'query\' found among basemap[0].layers');
+      }
+      layer.query = true;
+    },
+
+    getQueryableLayers(baseMap) {
+      const queryableLayer = baseMap.layers.filter((l) => l.queryable === true);
+      return queryableLayer.map((x) => {
+        return {
+          name: x.title,
+          value: x,
+        };
+      });
+    },
+    
+    activateGroup(basemap) {
+      this.baseMaps.forEach((basemap) => (basemap.active = false));
+      basemap.active = true;
+      this.$emit('setActiveBasemap', basemap);
+      basemap.title += ' '; //weird!! Force refresh
+      this.$emit('addLayers', basemap);
+
+      let mapOptions = localStorage.getItem('geocontrib-map-options') || {};
+      mapOptions = mapOptions.length ? JSON.parse(mapOptions) : {};
+      const project = this.$route.params.slug;
+      mapOptions[project] = {
+        ...mapOptions[project],
+        'current-basemap-index': basemap.id,
+      };
+      localStorage.setItem(
+        'geocontrib-map-options',
+        JSON.stringify(mapOptions)
+      );
+    },
+
+
+    getOpacity(opacity) {
+      return Math.round(parseFloat(opacity) * 100);
+    },
+
+    updateOpacity(event, layer) {
+      mapService.updateOpacity(layer.id, event.target.value);
+      layer.opacity = event.target.value;
+    },
+  }
+};
+</script>
+
+<style>
+.queryable-layers-dropdown {
+  margin-bottom: 1em;
+}
+.queryable-layers-dropdown > label {
+  font-weight: bold;
+}
+</style>
diff --git a/src/components/Map/SidebarLayers.vue b/src/components/Map/SidebarLayers.vue
index c2faef52..030c181b 100644
--- a/src/components/Map/SidebarLayers.vue
+++ b/src/components/Map/SidebarLayers.vue
@@ -46,85 +46,33 @@
         Fonds cartographiques
       </h4>
     </div>
-
-    <div
+    <LayerSelector
       v-for="basemap in baseMaps"
       :key="`list-${basemap.id}`"
-      class="basemaps-items ui accordion styled"
-    >
-      <div
-        :class="['basemap-item title', { active: isActive(basemap) }]"
-        @click="activateGroup(basemap)"
-      >
-        {{ basemap.title }}
-      </div>
-      <div
-        v-if="isQueryable(basemap)"
-        :id="`queryable-layers-selector-${basemap.id}`"
-      >
-        <strong>Couche requêtable</strong>
-        <Dropdown
-          :options="getQueryableLayers(basemap)"
-          :selected="selectedQueryLayer"
-          :search="true"
-          @update:selection="onQueryLayerChange($event)"
-        />
-      </div>
-      <div
-        :id="`list-${basemap.id}`"
-        :class="['content', { active: isActive(basemap) }]"
-        :data-basemap-index="basemap.id"
-      >
-        <div
-          v-for="(layer, index) in basemap.layers"
-          :key="basemap.id + '-' + layer.id + '-' + index"
-          class="layer-item transition visible item list-group-item"
-          :data-id="layer.id"
-        >
-          <!-- layer id is used for retrieving layer when changing order -->
-          <p class="layer-handle-sort">
-            <i
-              class="th icon"
-              aria-hidden="true"
-            />
-            {{ layer.title }}
-          </p>
-          <label>Opacité &nbsp;<span>(%)</span></label>
-          <div class="range-container">
-            <input
-              type="range"
-              min="0"
-              max="1"
-              :value="layer.opacity"
-              step="0.01"
-              @change="updateOpacity($event, layer)"
-            ><output class="range-output-bubble">{{
-              getOpacity(layer.opacity)
-            }}</output>
-          </div>
-          <div class="ui divider" />
-        </div>
-      </div>
-    </div>
+      :basemap="basemap"
+      :base-maps="baseMaps"
+      :active-basemap="activeBasemap"
+      @addLayers="addLayers"
+      @setActiveBasemap="setActiveBasemap"
+    />
   </div>
 </template>
 
 <script>
 import { mapState } from 'vuex';
-import Sortable from 'sortablejs';
-import Dropdown from '@/components/Dropdown.vue';
+
+import LayerSelector from '@/components/Map/LayerSelector.vue';
 import mapService from '@/services/map-service';
 
 export default {
   name: 'SidebarLayers',
 
   components: {
-    Dropdown,
+    LayerSelector
   },
 
   data() {
     return {
-      selectedQueryLayer: null,
       activeBasemap: null,
       baseMaps: [],
       expanded: false,
@@ -182,120 +130,13 @@ export default {
         this.$store.state.configuration.DEFAULT_BASE_MAP_SCHEMA_TYPE
       );
     }
-    setTimeout(this.initSortable.bind(this), 1000);
   },
 
   methods: {
-    isActive(basemap) {
-      return basemap.active !== undefined && basemap.active;
-    },
-
     toggleSidebar(value) {
       this.expanded = value !== undefined ? value : !this.expanded;
     },
 
-    activateGroup(basemap) {
-      this.baseMaps.forEach((basemap) => (basemap.active = false));
-      basemap.active = true;
-      this.activeBasemap = basemap;
-      basemap.title += ' '; //weird!! Force refresh
-      this.addLayers(basemap);
-
-      let mapOptions = localStorage.getItem('geocontrib-map-options') || {};
-      mapOptions = mapOptions.length ? JSON.parse(mapOptions) : {};
-      const project = this.$route.params.slug;
-      mapOptions[project] = {
-        ...mapOptions[project],
-        'current-basemap-index': basemap.id,
-      };
-      localStorage.setItem(
-        'geocontrib-map-options',
-        JSON.stringify(mapOptions)
-      );
-    },
-
-    updateOpacity(event, layer) {
-      mapService.updateOpacity(layer.id, event.target.value);
-      layer.opacity = event.target.value;
-    },
-
-    getOpacity(opacity) {
-      return Math.round(parseFloat(opacity) * 100);
-    },
-
-    onQueryLayerChange(layer) {
-      this.selectedQueryLayer = layer.name;
-      if (this.baseMaps[0].layers.find((l) => l.title === layer.name)) {
-        this.baseMaps[0].layers.find((l) => l.title === layer.name).query = true;
-      } else {
-        console.error('No such param \'query\' found among basemap[0].layers');
-      }
-      layer.query = true;
-    },
-
-    isQueryable(baseMap) {
-      const queryableLayer = baseMap.layers.filter((l) => l.queryable === true);
-      return queryableLayer.length > 0;
-    },
-
-    onlayerMove() {
-      // Get the names of the current layers in order.
-      const currentLayersNamesInOrder = Array.from(
-        document.getElementsByClassName('layer-item transition visible')
-      ).map((el) => parseInt(el.attributes['data-id'].value));
-      // Create an array to put the layers in order.
-      let movedLayers = [];
-
-      for (const layerName of currentLayersNamesInOrder) {
-        movedLayers.push(
-          this.activeBasemap.layers.filter((el) => el.id === layerName)[0]
-        );
-      }
-      // Remove existing layers undefined
-      movedLayers = movedLayers.filter(function (x) {
-        return x !== undefined;
-      });
-      const eventOrder = new CustomEvent('change-layers-order', {
-        detail: {
-          layers: movedLayers,
-        },
-      });
-      document.dispatchEvent(eventOrder);
-      // Save the basemaps options into the localstorage
-      this.setLocalstorageMapOptions(this.baseMaps);
-    },
-
-    setLocalstorageMapOptions(basemaps) {
-      let mapOptions = localStorage.getItem('geocontrib-map-options') || {};
-      mapOptions = mapOptions.length ? JSON.parse(mapOptions) : {};
-      const project = this.$route.params.slug;
-      mapOptions[project] = {
-        ...mapOptions[project],
-        basemaps: basemaps,
-      };
-      localStorage.setItem(
-        'geocontrib-map-options',
-        JSON.stringify(mapOptions)
-      );
-    },
-
-    initSortable() {
-      this.baseMaps.forEach((basemap) => {
-        const element = document.getElementById(`list-${basemap.id}`);
-        if (element) {
-          this. sortable = new Sortable(element, {
-            animation: 150,
-            handle: '.layer-handle-sort', // The element that is active to drag
-            ghostClass: 'blue-background-class',
-            dragClass: 'white-opacity-background-class',
-            onEnd: this.onlayerMove.bind(this),
-          });
-        } else {
-          console.error(`list-${basemap.id} not found in dom`);
-        }
-
-      });
-    },
     // Check if there are changes in the basemaps settings. Changes are detected if:
     // - one basemap has been added or deleted
     // - one layer has been added or deleted to a basemap
@@ -354,16 +195,6 @@ export default {
       return !(isSameBasemaps && isSameLayers && isSameTitles);
     },
 
-    getQueryableLayers(baseMap) {
-      const queryableLayer = baseMap.layers.filter((l) => l.queryable === true);
-      return queryableLayer.map((x) => {
-        return {
-          name: x.title,
-          value: x,
-        };
-      });
-    },
-
     addLayers(baseMap) {
       baseMap.layers.forEach((layer) => {
         const layerOptions = this.availableLayers.find((l) => l.id === layer.id);
@@ -375,15 +206,10 @@ export default {
       // Slice is done because reverse() changes the original array, so we make a copy first
       mapService.addLayers(baseMap.layers.slice().reverse(), null, null, null,);
     },
+
+    setActiveBasemap(basemap) {
+      this.activeBasemap = basemap;
+    }
   },
 };
 </script>
-
-<style>
-.queryable-layers-dropdown {
-  margin-bottom: 1em;
-}
-.queryable-layers-dropdown > label {
-  font-weight: bold;
-}
-</style>
-- 
GitLab