diff --git a/src/assets/js/map-util.js b/src/assets/js/map-util.js index 077178e09c165ca55e7290c3c9f38d8ebe215042..bc6f2d86b8226c72d865499ea73b228adf3f8f4f 100644 --- a/src/assets/js/map-util.js +++ b/src/assets/js/map-util.js @@ -18,7 +18,7 @@ import { FillSymbolizer, PointSymbolizer, LineSymbolizer } from "@/assets/js/vec let map; let dictLayersToLeaflet = {}; var layerMVT; -let statusList=[ +let statusList = [ { name: "Brouillon", value: "draft", @@ -66,20 +66,20 @@ L.TileLayer.BetterWMS = L.TileLayer.WMS.extend({ params: params, //dataType: "json", } - ).then(response => { - let data=response.data; - var err = typeof data === 'object' ? null : data; - if (data.features || err) { - showResults(err, evt.latlng, data); - } - }) - .catch(error => { - throw (error) - //xhr.status; - //xhr.responseText; - //console.log(status) - } - ) + ).then(response => { + let data = response.data; + var err = typeof data === 'object' ? null : data; + if (data.features || err) { + showResults(err, evt.latlng, data); + } + }) + .catch(error => { + throw (error) + //xhr.status; + //xhr.responseText; + //console.log(status) + } + ) } } @@ -165,7 +165,7 @@ const mapUtil = { return map; }, - createMap: function (options) { + createMap: function (el, options) { const { lat, lng, @@ -175,8 +175,9 @@ const mapUtil = { zoomControl = true, } = options; - map = L.map('map', { + map = L.map(el, { maxZoom: 18, + minZoom: 1, zoomControl: false, }).setView( [ @@ -200,7 +201,7 @@ const mapUtil = { return map; }, - addGeocoders: function(configuration){ + addGeocoders: function (configuration) { let geocoder; const geocoderLabel = configuration.SELECTED_GEOCODER.PROVIDER; if (geocoderLabel) { @@ -278,7 +279,7 @@ const mapUtil = { } }); }, - + updateOrder(layers) { // First remove existing layers undefined layers = layers.filter(function (x) { @@ -298,78 +299,77 @@ const mapUtil = { this.addLayers(layers); }, // eslint-disable-next-line no-unused-vars - addVectorTileLayer: function (url,project_slug,featureTypes,form_filters) { + addVectorTileLayer: function (url, project_slug, featureTypes, form_filters) { layerMVT = L.vectorGrid.protobuf(url, { vectorTileLayerStyles: { - "default": function(properties, zoom) { - // console.log(properties); - - let featureType=featureTypes.find((x)=>x.slug.split('-')[0]===''+properties.feature_type_id); - let color=featureType.color; - if(featureType.colors_style && featureType.colors_style.custom_field_name){ - let currentValue=properties[featureType.colors_style.custom_field_name]; - let colorValue=featureType.colors_style.colors[currentValue]; - if(colorValue) { - color=colorValue; + "default": function (properties, zoom) { + // console.log(properties); + + let featureType = featureTypes.find((x) => x.slug.split('-')[0] === '' + properties.feature_type_id); + let color = featureType.color; + if (featureType.colors_style && featureType.colors_style.custom_field_name) { + let currentValue = properties[featureType.colors_style.custom_field_name]; + let colorValue = featureType.colors_style.colors[currentValue]; + if (colorValue) { + color = colorValue; } - } - console.log(featureType); - let hiddenStyle=({ - radius: 0, - fillOpacity: 0.5, - weight: 0, - fill: false, - color: featureType.color, - }) - // Filtre sur le feature type - if (form_filters && form_filters.type.selected) { - if(featureType.title !== form_filters.type.selected){ - return hiddenStyle; - } + } + let hiddenStyle = ({ + radius: 0, + fillOpacity: 0.5, + weight: 0, + fill: false, + color: featureType.color, + }) + // Filtre sur le feature type + if (form_filters && form_filters.type.selected) { + if (featureType.title !== form_filters.type.selected) { + return hiddenStyle; } + } // Filtre sur le statut if (form_filters && form_filters.status.selected.value) { - if(properties.status !== form_filters.status.selected.value){ + if (properties.status !== form_filters.status.selected.value) { return hiddenStyle; } } // Filtre sur le titre if (form_filters && form_filters.title) { - if(!properties.title.toLowerCase().includes(form_filters.title.toLowerCase())){ + if (!properties.title.toLowerCase().includes(form_filters.title.toLowerCase())) { return hiddenStyle; } } - return ({ - radius: 4, - fillOpacity: 0.5, - weight: 3, - fill: true, - color: color, - }); - + return ({ + radius: 4, + fillOpacity: 0.5, + weight: 3, + fill: true, + color: color, + }); + }, - }, + }, // subdomains: "0123", // key: 'abcdefghi01234567890', - interactive:true, + interactive: true, maxNativeZoom: 14, - getFeatureId: function(f) { - return f.properties.id; - } + getFeatureId: function (f) { + return f.properties.id; + } }); - let self=this; - layerMVT.on('click', function(e) { // The .on method attaches an event handler - console.log(e); - const popupContent = self._createContentPopup(e.layer,featureTypes,project_slug); + let self = this; + layerMVT.on('click', function (e) { // The .on method attaches an event handler + console.log("click on mvt", e); + const popupContent = self._createContentPopup(e.layer, featureTypes, project_slug); L.popup() - .setContent(popupContent) - .setLatLng(e.latlng) - .openOn(map) - }); + .setContent(popupContent) + .setLatLng(e.latlng) + .openOn(map) + }); layerMVT.addTo(map); - window.layerMVT=layerMVT; - }, + window.layerMVT = layerMVT; + }, addFeatures: function (features, filter, addToMap = true, featureTypes) { let featureGroup = new L.FeatureGroup(); @@ -463,36 +463,36 @@ const mapUtil = { if (addToMap) { map.addLayer(featureGroup); } - + return featureGroup; }, addMapEventListener: function (eventName, callback) { map.on(eventName, callback); }, - _createContentPopup: function (feature,featureTypes,project_slug) { - const formatDate = (current_datetime)=>{ - let formatted_date = current_datetime.getFullYear() + "-" + ("0" + (current_datetime.getMonth() + 1)).slice(-2) + "-" + ("0" + current_datetime.getDate()).slice(-2) + " " + + _createContentPopup: function (feature, featureTypes, project_slug) { + const formatDate = (current_datetime) => { + let formatted_date = current_datetime.getFullYear() + "-" + ("0" + (current_datetime.getMonth() + 1)).slice(-2) + "-" + ("0" + current_datetime.getDate()).slice(-2) + " " + ("0" + current_datetime.getHours()).slice(-2) + ":" + ("0" + current_datetime.getMinutes()).slice(-2); - return formatted_date; + return formatted_date; } let feature_type; - let status=feature.properties.status; - let date_maj=feature.properties.updated_on; - let feature_type_url=feature.properties.feature_type_url; - let feature_url=feature.properties.feature_url; - if(featureTypes){ // => VectorTile - feature_type=featureTypes.find((x)=>x.slug.split('-')[0]===''+feature.properties.feature_type_id); - status=statusList.find((x)=>x.value==feature.properties.status).name; - date_maj=formatDate(new Date(feature.properties.updated_on)); - feature_type_url='/geocontrib/projet/'+project_slug+'/type_signalement/'+feature_type.slug+'/'; - feature_url=feature_type_url+'signalement/'+feature.properties.feature_id+'/'; + let status = feature.properties.status; + let date_maj = feature.properties.updated_on; + let feature_type_url = feature.properties.feature_type_url; + let feature_url = feature.properties.feature_url; + if (featureTypes) { // => VectorTile + feature_type = featureTypes.find((x) => x.slug.split('-')[0] === '' + feature.properties.feature_type_id); + status = statusList.find((x) => x.value == feature.properties.status).name; + date_maj = formatDate(new Date(feature.properties.updated_on)); + feature_type_url = '/geocontrib/projet/' + project_slug + '/type_signalement/' + feature_type.slug + '/'; + feature_url = feature_type_url + 'signalement/' + feature.properties.feature_id + '/'; //status=feature.properties.status; - }else{ - feature_type=feature.properties.feature_type; - status=feature.properties.status.label; + } else { + feature_type = feature.properties.feature_type; + status = feature.properties.status.label; } - + let author = ""; if (feature.properties.creator) { author = feature.properties.creator.full_name diff --git a/src/services/feature-api.js b/src/services/feature-api.js index 8c1a8eb3a7f0ecf1ba2e72127baa65aac36e0285..e9a02215c3a9f855c376e8ccf357d722fd63355d 100644 --- a/src/services/feature-api.js +++ b/src/services/feature-api.js @@ -77,6 +77,19 @@ const featureAPI = { return null; } }, + + async getFeaturesBlob(url) { + const response = await axios + .get(url, { responseType: "blob" }) + if ( + response.status === 200 && + response.data + ) { + return response.data; + } else { + return null; + } + }, } export default featureAPI; diff --git a/src/store/modules/feature.js b/src/store/modules/feature.js index ecf1c64799bf5daed16e1c3072f4b5c8a2a0645d..2b9eb239c3eded5a247a1572731689d54e219a94 100644 --- a/src/store/modules/feature.js +++ b/src/store/modules/feature.js @@ -120,15 +120,18 @@ const feature = { const message = routeName === "editer-signalement" ? "Le signalement a été mis à jour" : "Le signalement a été crée"; function redirect(featureId) { - commit("DISCARD_LOADER", null, { root: true }) - router.push({ - name: "details-signalement", - params: { - slug_type_signal: rootState.feature_type.current_feature_type_slug, - slug_signal: featureId, - message, - }, - }); + dispatch("GET_PROJECT_FEATURES", rootState.project_slug).then(() => { + console.log(state.feature); + commit("DISCARD_LOADER", null, { root: true }) + router.push({ + name: "details-signalement", + params: { + slug_type_signal: rootState.feature_type.current_feature_type_slug, + slug_signal: featureId, + message, + }, + }); + }) } async function handleOtherForms(featureId) { diff --git a/src/store/modules/feature_type.js b/src/store/modules/feature_type.js index 612d1d3a436943c53e56d93eda5924239064e81b..bed583d904949de35706a19a93ea4d10a95e725d 100644 --- a/src/store/modules/feature_type.js +++ b/src/store/modules/feature_type.js @@ -6,6 +6,11 @@ axios.defaults.headers.common['X-CSRFToken'] = (name => { return (value !== null) ? unescape(value[1]) : null; })('csrftoken'); +const getColorsStyles = (customForms) => customForms.filter(customForm => customForm.options && customForm.options.length).map(el => { + //* in dropdown, value is the name and name is the label to be displayed, could be changed... + return { value: el.name, name: el.label, options: el.options } +}); + const feature_type = { namespaced: true, @@ -36,26 +41,27 @@ const feature_type = { }, SET_CUSTOM_FORMS(state, customForms) { state.customForms = customForms; + state.colorsStyleList = getColorsStyles(state.customForms); }, ADD_CUSTOM_FORM(state, customForm) { state.customForms = [...state.customForms, customForm]; + state.colorsStyleList = getColorsStyles(state.customForms); }, UPDATE_CUSTOM_FORM(state, payload) { const index = state.customForms.findIndex((el) => el.dataKey === payload.dataKey); if (index !== -1) { state.customForms[index] = payload; - //* trigger update of available options for colors style in feature_type_edit - state.colorsStyleList = state.customForms.filter(cust => cust.options && cust.options.length).map(el => { - //* in dropdown, value is the name and name is the label to be displayed, could be changed... - return { value: el.name, name: el.label, options: el.options } - }) + //* trigger update of available options for colors style in feature_type_edit (getters not working) + state.colorsStyleList = getColorsStyles(state.customForms); } }, REMOVE_CUSTOM_FORM(state, payload) { state.customForms = state.customForms.filter(form => form.dataKey !== payload); + state.colorsStyleList = getColorsStyles(state.customForms); }, EMPTY_CUSTOM_FORMS(state) { state.customForms = []; + state.colorsStyleList = []; }, SET_IMPORT_FEATURE_TYPES_DATA(state, payload) { state.importFeatureTypeData = payload; diff --git a/src/store/modules/map.js b/src/store/modules/map.js index d47afc9ef721f6a3201ff1db473b051c92552a1e..c8e5ce93eab03a485b06f5a409be781a95cbe313 100644 --- a/src/store/modules/map.js +++ b/src/store/modules/map.js @@ -110,11 +110,11 @@ const map = { }); }, - INITIATE_MAP({ state, rootGetters }) { + INITIATE_MAP({ state, rootGetters }, el) { const project = rootGetters.project let mapDefaultViewCenter = [46, 2]; // defaultMapView.center; let mapDefaultViewZoom = 5; // defaultMapView.zoom; - mapUtil.createMap({ + mapUtil.createMap(el, { mapDefaultViewCenter, mapDefaultViewZoom, }); diff --git a/src/views/feature/Feature_detail.vue b/src/views/feature/Feature_detail.vue index b31ae747f01c276f33016dda3ff41ec61096753f..7631022ff1bbe4d45c2b4021c4aa81619ee85496 100644 --- a/src/views/feature/Feature_detail.vue +++ b/src/views/feature/Feature_detail.vue @@ -24,7 +24,8 @@ <router-link v-if=" (permissions && permissions.can_update_feature) || - isFeatureCreator + isFeatureCreator || + isModerator " :to="{ name: 'editer-signalement', @@ -39,7 +40,9 @@ </router-link> <!-- (permissions && permissions.can_delete_feature) || --> <a - v-if="isFeatureCreator || permissions.is_project_super_contributor" + v-if=" + isFeatureCreator || permissions.is_project_super_contributor + " @click="isCanceling = true" id="feature-delete" class="ui button button-hover-red" @@ -48,7 +51,7 @@ </a> </div> <div class="ui hidden divider"></div> - <div class="sub header"> + <div class="sub header prewrap"> {{ feature.description }} </div> </div> @@ -142,7 +145,7 @@ </div> <div class="seven wide column"> - <div id="map"></div> + <div id="map" ref="map"></div> </div> </div> @@ -386,14 +389,14 @@ export default { }, computed: { - ...mapState(["user"]), - ...mapGetters(["permissions"]), + ...mapState(["user", "USER_LEVEL_PROJECTS"]), + ...mapGetters(["permissions", "project"]), ...mapState("feature", ["linked_features", "statusChoices"]), - DJANGO_BASE_URL: function () { + DJANGO_BASE_URL() { return this.$store.state.configuration.VUE_APP_DJANGO_BASE; }, - feature: function () { + feature() { const result = this.$store.state.feature.features.find( (el) => el.feature_id === this.$route.params.slug_signal ); @@ -407,6 +410,13 @@ export default { return false; }, + isModerator() { + return this.USER_LEVEL_PROJECTS && + this.USER_LEVEL_PROJECTS[this.project.slug] === "Modérateur" + ? true + : false; + }, + statusIcon() { switch (this.feature.status) { case "archived": @@ -563,7 +573,7 @@ export default { this.$store.state.configuration.DEFAULT_MAP_VIEW.center; var mapDefaultViewZoom = this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom; - this.map = mapUtil.createMap({ + this.map = mapUtil.createMap(this.$refs.map, { mapDefaultViewCenter, mapDefaultViewZoom, }); @@ -617,7 +627,12 @@ export default { const feature = response.data; if (feature) { const currentFeature = [feature]; - const featureGroup = mapUtil.addFeatures(currentFeature,{},true,this.$store.state.feature_type.feature_types); + const featureGroup = mapUtil.addFeatures( + currentFeature, + {}, + true, + this.$store.state.feature_type.feature_types + ); mapUtil .getMap() .fitBounds(featureGroup.getBounds(), { padding: [25, 25] }); @@ -660,14 +675,16 @@ export default { }, mounted() { + this.$store.commit("DISPLAY_LOADER", "Recherche du signalement"); if (!this.project) { this.$store .dispatch("GET_PROJECT_INFO", this.$route.params.slug) - .then((data) => { - console.log(data); + .then(() => { + this.$store.commit("DISCARD_LOADER"); this.initMap(); }); } else { + this.$store.commit("DISCARD_LOADER"); this.initMap(); } }, @@ -695,4 +712,7 @@ export default { margin-left: 107px; margin-top: 0; } +.prewrap { + white-space: pre-wrap; +} </style> \ No newline at end of file diff --git a/src/views/feature/Feature_edit.vue b/src/views/feature/Feature_edit.vue index a73570f097c1a8bb320238c6f100f436a7a27988..40e10c25703b2a6db077fb1bf2736aa092422899 100644 --- a/src/views/feature/Feature_edit.vue +++ b/src/views/feature/Feature_edit.vue @@ -187,7 +187,7 @@ @blur="updateStore" /> <div class="ui tab active map-container" data-tab="map"> - <div id="map"></div> + <div id="map" ref="map"></div> <!-- // todo: ajouter v-if --> <!-- {% if serialized_base_maps|length > 0 %} {% include "geocontrib/map-layers/sidebar-layers.html" with @@ -693,12 +693,13 @@ export default { } if (is_valid) { - //* if moderate project modified by someone else than admin or moderator, switch status to pending + //* in a moderate project, at edition of a published feature by someone else than admin or moderator, switch published status to draft. if ( this.project.moderation && + this.currentRouteName === "editer-signalement" && + this.form.status.value.value === "published" && !this.permissions.is_project_administrator && - !this.permissions.is_project_moderator && - this.feature.status === "pending" //* allow (super)contributor to change status to pending + !this.permissions.is_project_moderator ) { this.form.status.value = { name: "Brouillon", value: "draft" }; this.updateStore(); @@ -927,7 +928,7 @@ export default { this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom; // Create the map, then init the layers and features - this.map = mapUtil.createMap({ + this.map = mapUtil.createMap(this.$refs.map, { mapDefaultViewCenter, mapDefaultViewZoom, }); diff --git a/src/views/feature/Feature_list.vue b/src/views/feature/Feature_list.vue index def2b92101ce09c7bcaf24e104651c05d30743ae..0f65d85bf8663308deebe67edc1a048a4fa790c6 100644 --- a/src/views/feature/Feature_list.vue +++ b/src/views/feature/Feature_list.vue @@ -138,7 +138,7 @@ </form> <div v-show="showMap" class="ui tab active map-container" data-tab="map"> - <div id="map"></div> + <div id="map" ref="map"></div> <SidebarLayers v-if="baseMaps && map" /> </div> <FeatureListTable @@ -364,7 +364,7 @@ export default { var mapDefaultViewZoom = this.$store.state.configuration.DEFAULT_MAP_VIEW.zoom; - this.map = mapUtil.createMap({ + this.map = mapUtil.createMap(this.$refs.map, { zoom: this.zoom, lat: this.lat, lng: this.lng, @@ -453,7 +453,6 @@ export default { created() { if (!this.project) { - //this.$store.dispatch("GET_PROJECT_MESSAGES", this.$route.params.slug); this.$store.dispatch("GET_PROJECT_INFO", this.$route.params.slug); } }, diff --git a/src/views/feature_type/Feature_type_detail.vue b/src/views/feature_type/Feature_type_detail.vue index d3e7f8a2b7ae1810a590497c636fac93fa8328a0..80e1e6eb516e735b21fd0cabc7c7ed37f8fd5b91 100644 --- a/src/views/feature_type/Feature_type_detail.vue +++ b/src/views/feature_type/Feature_type_detail.vue @@ -102,7 +102,8 @@ </div> <div :class="['content', { active: !showImport }]"> <p> - Vous pouvez télécharger tous les signalements qui vous sont accessibles. + Vous pouvez télécharger tous les signalements qui vous sont + accessibles. </p> <button type="button" @@ -192,6 +193,7 @@ <script> import { mapGetters, mapState } from "vuex"; import ImportTask from "@/components/ImportTask"; +import featureAPI from "@/services/feature-api"; export default { name: "Feature_type_detail", @@ -284,14 +286,10 @@ export default { options: el.options, }; }); - console.log({ json, fields }); for (const feature of json.features) { - console.log(feature.properties); for (const { name, field_type, options } of fields) { - console.log("name", name, "field_type", field_type); //* check if custom field is present if (!(name in feature.properties)) { - console.log("NOT present"); return false; } const fieldInFeature = feature.properties[name]; @@ -302,12 +300,10 @@ export default { if (field_type === "list") { //*then check if the value is an available option if (!options.includes(fieldInFeature)) { - console.log("NOT an element of list options"); return false; } } else if (customType !== field_type) { //* check if custom field value match - console.log("NOT matched"); this.importError = `Le fichier est invalide: Un champ de type ${field_type} ne peut pas avoir la valeur [ ${fieldInFeature} ]`; return false; } @@ -344,8 +340,15 @@ export default { exportFeatures() { const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature-type/${this.$route.params.feature_type_slug}/export/`; - console.log(url); - window.open(url); + featureAPI.getFeaturesBlob(url).then((blob) => { + if (blob) { + const link = document.createElement("a"); + link.href = URL.createObjectURL(blob); + link.download = `${this.project.title}-${this.structure.title}.json`; + link.click(); + URL.revokeObjectURL(link.href); + } + }); }, }, diff --git a/src/views/feature_type/Feature_type_edit.vue b/src/views/feature_type/Feature_type_edit.vue index 4478db72b1bd4153a0395cf63200a70d6c920942..d4890fe479c76744e7ae01d8c223e65693f11176 100644 --- a/src/views/feature_type/Feature_type_edit.vue +++ b/src/views/feature_type/Feature_type_edit.vue @@ -98,7 +98,7 @@ </div> <div class="colors_selection" id="id_colors_selection" hidden> <div - v-for="(value, key, index) in this.form.colors_style.value.colors" + v-for="(value, key, index) in form.colors_style.value.colors" :key="'colors_style-' + index" > <div v-if="key" class="color-input"> @@ -278,11 +278,11 @@ export default { : name; }, set(newValue) { - //* update only if different than custom_form if (newValue.value !== this.form.colors_style.value.custom_field_name) { //* get back values from original feature_type if ( + this.feature_type && //* if the feature_type exists already newValue.value === this.feature_type.colors_style.custom_field_name ) { this.form.colors_style.value = this.feature_type.colors_style; @@ -309,6 +309,19 @@ export default { this.fillFormData(newValue); } }, + customForms(newValue, oldValue) { + if (newValue !== oldValue) { + const name = this.form.colors_style.value.custom_field_name; + const customField = this.customForms.find((el) => el.name === name); + if (!customField || customField.length === 0) { + //* if the customForm corresponding doesn't exist reset colors_style values + this.form.colors_style.value = { + colors: {}, + custom_field_name: "", + }; + } + } + }, }, methods: { @@ -327,11 +340,19 @@ export default { }, addCustomForm(customForm) { + if ( + customForm && + this.customForms.some((cf) => cf.name === customForm.name) + ) { + //* abort if customForm already exists (because watcher can update again) + return; + } this.dataKey += 1; // * increment counter for key in v-for let newCustomForm = { dataKey: this.dataKey, }; if (customForm) { + //* if adding an existing customForm -> add its property to newCustomForm containing only dataKey newCustomForm = { ...newCustomForm, ...customForm }; } this.$store.commit("feature_type/ADD_CUSTOM_FORM", newCustomForm); // * create an object with the counter in store diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue index e6d01d3626c751ca3343b507e78a1139ab97840a..71134d543e880f02a55f35dcaf18fdd525c50949 100644 --- a/src/views/project/Project_detail.vue +++ b/src/views/project/Project_detail.vue @@ -69,7 +69,7 @@ user && permissions && permissions.can_view_project && - isOffline() != true + isOffline() !== true " id="subscribe-button" class="ui button button-hover-green" @@ -84,7 +84,7 @@ v-if=" permissions && permissions.can_update_project && - isOffline() != true + isOffline() !== true " :to="{ name: 'project_edit', params: { slug: project.slug } }" class="ui button button-hover-orange" @@ -108,6 +108,14 @@ <div class="seven wide column"> <h3 class="ui header">Types de signalements</h3> <div class="ui middle aligned divided list"> + <div + :class="{ active: featureTypeLoading }" + class="ui inverted dimmer" + > + <div class="ui text loader"> + Récupération des types de signalements en cours... + </div> + </div> <div v-for="(type, index) in feature_types" :key="type.title + '-' + index" @@ -177,7 +185,7 @@ project && permissions && permissions.can_create_feature_type && - isOffline() != true + isOffline() !== true " class=" ui @@ -204,7 +212,7 @@ type.is_editable && permissions && permissions.can_create_feature_type && - isOffline() != true + isOffline() !== true " class=" ui @@ -260,7 +268,7 @@ v-if=" permissions && permissions.can_update_project && - isOffline() != true + isOffline() !== true " :to="{ name: 'ajouter-type-signalement', @@ -276,7 +284,7 @@ v-if=" permissions && permissions.can_update_project && - isOffline() != true + isOffline() !== true " class=" ui @@ -318,7 +326,7 @@ </div> </div> <div class="seven wide column"> - <div id="map"></div> + <div id="map" ref="map"></div> </div> </div> @@ -536,9 +544,9 @@ export default { }, filters: { - setDate: function (value) { - let date = new Date(value); - let d = date.toLocaleDateString("fr", { + setDate(value) { + const date = new Date(value); + const d = date.toLocaleDateString("fr", { year: "2-digit", month: "numeric", day: "numeric", @@ -557,6 +565,7 @@ export default { isModalOpen: false, is_suscriber: false, tempMessage: null, + featureTypeLoading: true, }; }, @@ -565,10 +574,10 @@ export default { ...mapState("feature_type", ["feature_types"]), ...mapState("feature", ["features"]), ...mapState(["last_comments", "user"]), - DJANGO_BASE_URL: function () { + DJANGO_BASE_URL() { return this.$store.state.configuration.VUE_APP_DJANGO_BASE; }, - last_features: function () { + last_features() { // * limit to last five element of array (looks sorted chronologically, but not sure...) return this.$store.state.feature.features.slice(-5); }, @@ -579,7 +588,7 @@ export default { return "?ver=" + Math.random(); }, isOffline() { - return navigator.onLine == false; + return navigator.onLine === false; }, checkForOfflineFeature() { let arraysOffline = []; @@ -587,7 +596,7 @@ export default { if (localStorageArray) { arraysOffline = JSON.parse(localStorageArray); this.arraysOffline = arraysOffline.filter( - (x) => x.project == this.project.slug + (x) => x.project === this.project.slug ); } }, @@ -595,7 +604,7 @@ export default { var promises = []; this.arraysOffline.forEach((feature, index, object) => { console.log(feature); - if (feature.type == "post") { + if (feature.type === "post") { promises.push( axios .post( @@ -612,7 +621,7 @@ export default { console.log(error); }) ); - } else if (feature.type == "put") { + } else if (feature.type === "put") { promises.push( axios .put( @@ -643,7 +652,7 @@ export default { arraysOffline = JSON.parse(localStorageArray); } let arraysOfflineOtherProject = arraysOffline.filter( - (x) => x.project != this.project.slug + (x) => x.project !== this.project.slug ); arraysOffline = arraysOfflineOtherProject.concat(this.arraysOffline); localStorage.setItem("geocontrib_offline", JSON.stringify(arraysOffline)); @@ -699,9 +708,8 @@ export default { }, initMap() { if (this.project && this.permissions.can_view_project) { - this.$store.dispatch("map/INITIATE_MAP"); + this.$store.dispatch("map/INITIATE_MAP", this.$refs.map); const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature/?output=geojson`; - let self = this; this.checkForOfflineFeature(); let project_id = this.$route.params.slug.split("-")[0]; const mvtUrl = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features.mvt/?tile={z}/{x}/{y}&project_id=${project_id}`; @@ -714,11 +722,11 @@ export default { .get(url) .then((response) => { let features = response.data.features; - self.arraysOffline.forEach( + this.arraysOffline.forEach( (x) => (x.geojson.properties.color = "red") ); features = response.data.features.concat( - self.arraysOffline.map((x) => x.geojson) + this.arraysOffline.map((x) => x.geojson) ); const featureGroup = mapUtil.addFeatures( features, @@ -749,13 +757,14 @@ export default { .getProjectSubscription({ projectSlug: this.$route.params.slug }) .then((data) => (this.is_suscriber = data.is_suscriber)); } + this.$store.commit("feature_type/SET_FEATURE_TYPES", []); //* empty feature_types remaining from previous project }, mounted() { - let self = this; - this.$store - .dispatch("GET_PROJECT_INFO", this.slug) - .then(setTimeout(self.initMap, 1000)); + this.$store.dispatch("GET_PROJECT_INFO", this.slug).then(() => { + this.featureTypeLoading = false; + setTimeout(this.initMap, 1000); + }); if (this.message) { this.tempMessage = this.message; document