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