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é <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é <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