<template> <div class="ui segment"> <div class="field required"> <label for="basemap-title">Titre</label> <!-- eslint-disable --> <input :value="basemap.title" @input="updateTitle" type="text" name="basemap-title" required > <ul v-if="basemap.errors && basemap.errors.length > 0" id="errorlist-title" class="errorlist" > <li> {{ basemap.errors }} </li> </ul> </div> <div class="nested"> <div :id="`list-${basemap.id}`" :class="[basemap.layers.length > 0 ? 'ui segments': '', 'layers-container']" > <ProjectMappingContextLayer v-for="layer in basemap.layers" :key="'layer-' + layer.dataKey" :layer="layer" :basemapid="basemap.id" /> </div> <div class="ui buttons"> <a class="ui compact small icon left floated button green" @click="addLayer" > <i class="ui plus icon" /> <span>Ajouter une couche</span> </a> </div> <div class="ui buttons" @click="deleteBasemap" > <a class=" ui compact red small icon right floated button button-hover-green " > <i class="ui trash alternate icon" /> <span>Supprimer ce fond cartographique</span> </a> </div> </div> </div> </template> <script> /* eslint-disable */ import Sortable from 'sortablejs'; import ProjectMappingContextLayer from '@/components/project/ProjectMappingContextLayer.vue'; export default { name: 'ProjectMappingBasemap', components: { ProjectMappingContextLayer, }, props: { basemap: { type: Object, default: null, } }, computed: { maxLayersCount: function () { return this.basemap.layers.reduce((acc, curr) => { if (curr.dataKey > acc) { return curr.dataKey; } else { return acc; } }, 0); }, }, created() { if (this.basemap.layers) { //* add datakeys to layers coming from api this.fillLayersWithDatakey(this.basemap.layers); } }, mounted() { this.initSortable(); }, methods: { deleteBasemap() { this.$store.commit('map/DELETE_BASEMAP', this.basemap.id); }, addLayer(layer) { const newLayer = { dataKey: this.maxLayersCount + 1, opacity: '1.00', order: 0, queryable: false, title: 'Open street map', ...layer, }; this.$store.commit('map/UPDATE_BASEMAP', { layers: [...this.basemap.layers, newLayer], id: this.basemap.id, title: this.basemap.title, errors: this.basemap.errors, }); }, updateTitle(evt) { let errors = ''; if(evt.target.value === '') { //* delete or add error message while typing errors = "Veuillez compléter ce champ."; } this.$store.commit('map/UPDATE_BASEMAP', { id: this.basemap.id, title: evt.target.value, errors, }); }, removeLayer(dataKey) { this.layers = this.layers.filter((layer) => layer.dataKey !== dataKey); }, fillLayersWithDatakey(layers) { let dataKey = 0; this.$store.commit('map/REPLACE_BASEMAP_LAYERS', { basemapId: this.basemap.id, layers: layers.map((el) => { dataKey += 1; return { dataKey, ...el }; }), }); }, //* drag & drop *// onlayerMove() { //* Get the names of the current layers in order. const currentLayersNamesInOrder = Array.from( document.getElementsByClassName('layer-item') ).map((el) => el.id); //* increment value 'order' in this.basemap.layers looping over layers from template ^ let order = 0; let movedLayers = []; for (let id of currentLayersNamesInOrder) { let matchingLayer = this.basemap.layers.find( (el) => el.dataKey === Number(id) ); if (matchingLayer) { matchingLayer['order'] = order; movedLayers.push(matchingLayer); order += 1; } } //* update the store this.$store.commit('map/UPDATE_BASEMAP', { layers: movedLayers, id: this.basemap.id, title: this.basemap.title, errors: this.basemap.errors, }); }, initSortable() { new Sortable(document.getElementById(`list-${this.basemap.id}`), { 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), }); }, }, }; </script> <style scoped> .button { margin-right: 0.5em !important; } </style>