diff --git a/conf_apache_dev.md b/conf_apache_dev.md
new file mode 100644
index 0000000000000000000000000000000000000000..03d656dfd0c6e211460a41be3ea4b98e472c4c0c
--- /dev/null
+++ b/conf_apache_dev.md
@@ -0,0 +1,39 @@
+
+# intro
+
+ceci permet de faire tourner le front en local sur /geocontrib 
+et de faire pointer /api sur n'importe quel backend (dev, local ou autre )
+
+# configuration apache
+
+dans la configuration apache generale (httpd.conf ou commande a2enmod ), activer les modules :
+* mod_headers
+* mod_proxy
+* mod_ssl
+* mod_proxy_http
+
+
+```
+ <Location /geocontrib >  
+   ProxyPass http://localhost:8080/geocontrib
+ </Location>
+
+
+ SSLProxyEngine On
+ <Location /api >  
+    ProxyPass https://geocontrib.dev.neogeo.fr/geocontrib/api
+    RequestHeader set Referer https://geocontrib.dev.neogeo.fr/
+ </Location>
+ ```
+
+
+# configuration projet vueJS
+
+remplacer dans le fichier config.json du projet 
+```
+DOMAIN":"http://localhost:8010/", par "DOMAIN":"http://localhost/",
+```
+et 
+```
+"VUE_APP_DJANGO_API_BASE":"http://localhost:8010/api/", par "VUE_APP_DJANGO_API_BASE":"http://localhost/api/",
+```
diff --git a/nginx.conf b/nginx.conf
index b1a4d31d8d61c35ab78d0b999c673d28a23b5a2d..3ea3849f16c06b3f6da02bfaff5147374320b925 100644
--- a/nginx.conf
+++ b/nginx.conf
@@ -27,6 +27,18 @@ server {
         proxy_pass http://geocontrib_site;
     }
 
+    location /geocontrib/cas {
+        proxy_pass_header Set-Cookie;
+        proxy_set_header X-NginX-Proxy true;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_set_header Host $host;
+        proxy_read_timeout 300s;
+        proxy_redirect off;
+    
+        proxy_pass http://geocontrib_site;
+    }
+
     location /geocontrib/admin {
         proxy_pass_header Set-Cookie;
         proxy_set_header X-NginX-Proxy true;
diff --git a/package.json b/package.json
index 8f55afdbe57b2ad2089383f64f4e017bdb6981cb..fa44bcd1207b3c48ee3f17186f546b7cdc42e50b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "geocontrib-frontend",
-  "version": "2.3.2-rc2",
+  "version": "2.3.2",
   "private": true,
   "scripts": {
     "serve": "npm run init-proxy & npm run init-serve",
diff --git a/public/config/config.json b/public/config/config.json
index 9651190e5aa2d349aead14b9d85304d92d6f2356..537e865a61060fc9fb1cb617d31a0b89c50d93db 100644
--- a/public/config/config.json
+++ b/public/config/config.json
@@ -1,6 +1,6 @@
 {
     "BASE_URL":"/geocontrib/",
-    "DOMAIN":"http://localhost:8010/",
+    "DOMAIN":"http://localhost/",
     "NODE_ENV":"development",
     "VUE_APP_LOCALE":"fr-FR",
     "VUE_APP_APPLICATION_NAME":"GéoContrib",
diff --git a/src/App.vue b/src/App.vue
index baf1424a94b25471cd7c4694bc7a68fb40c1b92c..964cfd77ac5e2480361fb249dc59952ae2d3d255 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -155,13 +155,14 @@
     <main>
       <div id="content" class="ui stackable grid centered container">
         <transition name="fadeDownUp">
-        <div v-if="messages && messages.length > 0" class="row">
+        <div v-if="messages && messages.length > 0" class="row over-content">
           <div class="fourteen wide column">
             <div
               v-for="(message, index) in messages"
               :key="'message-' + index"
-              class="ui info message"
+              :class="['ui', message.level ? message.level : 'info', 'message']"
             >
+              <i class="close icon" @click="DISCARD_MESSAGE(message)"></i>
               <div class="header">
                 <i class="info circle icon"></i>
                 Informations
@@ -197,8 +198,7 @@
 
 <script>
 import frag from "vue-frag";
-import { mapState } from "vuex";
-import { mapGetters } from "vuex";
+import { mapMutations, mapState, mapGetters } from "vuex";
 
 export default {
   name: "App",
@@ -256,6 +256,7 @@ export default {
   },
 
   methods: {
+    ...mapMutations(['DISCARD_MESSAGE']),
     logout() {
       this.$store.dispatch("LOGOUT");
     },
@@ -383,23 +384,10 @@ footer {
   transition: none !important;
 }
 
-
-.bounce-enter-active {
-  animation: bounce-in .5s;
-}
-.bounce-leave-active {
-  animation: bounce-in .5s reverse;
-}
-@keyframes bounce-in {
-  0% {
-    transform: scale(0);
-  }
-  50% {
-    transform: scale(1.5);
-  }
-  100% {
-    transform: scale(1);
-  }
+.ui.grid > .row.over-content {
+  position: absolute;
+  z-index: 99;
+  opacity: 0.95;
 }
 
 .fadeDownUp-enter-active {
@@ -431,6 +419,17 @@ footer {
   }
 }
 
+.ui.message > .close.icon {
+  cursor: pointer;
+  position: absolute;
+  margin: 0em;
+  top: 0.78575em;
+  right: 0.5em;
+  opacity: 0.7;
+  -webkit-transition: opacity 0.1s ease;
+  transition: opacity 0.1s ease;
+}
+
 </style>
  
  <style scoped>
diff --git a/src/assets/js/map-util.js b/src/assets/js/map-util.js
index b89c5a07dcc1d1ed39225ad038c1870d03ab3b36..9c279ef6e2634edb7751f6122e349debf5952bc2 100644
--- a/src/assets/js/map-util.js
+++ b/src/assets/js/map-util.js
@@ -298,8 +298,7 @@ const mapUtil = {
       const currentValue = properties[colorsStyle.custom_field_name];
       const colorStyle = colorsStyle.colors[currentValue];
       return colorStyle ? colorStyle : featureType.color
-    }
-    else{
+    } else {
       return featureType.color;
     }
   },
@@ -310,7 +309,12 @@ const mapUtil = {
       vectorTileLayerStyles: {
         "default": (properties) => {
           const featureType = featureTypes.find((x) => x.slug.split('-')[0] === '' + properties.feature_type_id);
-          const color = this.retrieveFeatureColor(featureType, properties)
+
+          const color = this.retrieveFeatureColor(featureType, properties);
+          const colorValue =
+          color.value && color.value.length ?
+            color.value : typeof color === 'string' && color.length ?
+              color : '#000000';
 
           const hiddenStyle = ({
             radius: 0,
@@ -318,7 +322,17 @@ const mapUtil = {
             weight: 0,
             fill: false,
             color: featureType.color,
-          })
+          });
+
+          const defaultStyle = {
+            radius: 4,
+            fillOpacity: 0.5,
+            weight: 3,
+            fill: true,
+            color: colorValue,
+          };
+            
+
           // Filtre sur le feature type
           if (form_filters && form_filters.type.selected) {
             if (featureType.title !== form_filters.type.selected) {
@@ -337,13 +351,7 @@ const mapUtil = {
               return hiddenStyle;
             }
           }
-          return ({
-            radius: 4,
-            fillOpacity: 0.5,
-            weight: 3,
-            fill: true,
-            color: color,
-          });
+          return defaultStyle;
         },
       },
       // subdomains: "0123",
diff --git a/src/assets/styles/base.css b/src/assets/styles/base.css
index 0777e8e3742e08d03179550ddfff9e40778efb21..6f7a4e7c4823bf725373cdbbab5450879bdf84ed 100644
--- a/src/assets/styles/base.css
+++ b/src/assets/styles/base.css
@@ -10,6 +10,13 @@ main {
   padding: 2em 0em;
 }
 
+/* ---------------------------------- */
+            /* UTILS */
+/* ---------------------------------- */
+.ellipsis {
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
 /* ---------------------------------- */
             /* MAIN */
 /* ---------------------------------- */
diff --git a/src/components/ImportTask.vue b/src/components/ImportTask.vue
index 8c15409397ac5d0d13a97a7f65e8633ab81fbc6c..9f307cab0b604209193b23289677ab5afe8d2a36 100644
--- a/src/components/ImportTask.vue
+++ b/src/components/ImportTask.vue
@@ -46,7 +46,7 @@
             >
               <i
                 v-on:click="fetchImports()"
-                :class="['orange icon', ready ? 'sync' : 'hourglass half']"
+                :class="['orange icon', ready && !reloading ? 'sync' : 'hourglass half rotate']"
               />
             </span>
           </td>
@@ -68,7 +68,7 @@ export default {
     };
   },
 
-  props: ["data"],
+  props: ["data", "reloading"],
 
   filters: {
     setDate: function (value) {
@@ -122,23 +122,19 @@ export default {
   padding-top: 1em;
 }
 
-@keyframes rotateIn {
-  from {
-    transform: rotate3d(0, 0, 1, -200deg);
-    opacity: 0;
-  }
-
-  to {
-    transform: translate3d(0, 0, 0);
-    opacity: 1;
-  }
+i.icon {
+  width: 20px !important;
+  height: 20px !important;
 }
 
-.rotateIn {
-  animation-name: rotateIn;
-  transform-origin: center;
-  animation: 2s;
+.rotate {
+  -webkit-animation:spin 1s linear infinite;
+  -moz-animation:spin 1s linear infinite;
+  animation:spin 1s linear infinite;
 }
+@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
+@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
+@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
 
 /* 
 Max width before this PARTICULAR table gets nasty
diff --git a/src/components/feature/FeatureListTable.vue b/src/components/feature/FeatureListTable.vue
index 5817a4fa2ab3f7acb9aadf77cef804e68c27e0be..5aa26043cf82cb948b39470a50b4cae4fc274e64 100644
--- a/src/components/feature/FeatureListTable.vue
+++ b/src/components/feature/FeatureListTable.vue
@@ -1,12 +1,20 @@
 
 <template>
   <div data-tab="list" class="dataTables_wrapper no-footer">
-    <table id="table-features" class="ui compact table">
+    <table id="table-features" class="ui compact table dataTable">
       <thead>
         <tr>
-          <th class="center"></th>
+          <th class="dt-center">
+            <div @click="switchMode" class="switch-buttons pointer" :data-tooltip="`Passer en mode ${mode === 'modify' ? 'suppression':'édition'}`">
+              <div><i :class="['icon pencil', {disabled: mode !== 'modify'}]"></i></div>
+              <span class="grey">|&nbsp;</span>
+              <div><i :class="['icon trash', {disabled: mode !== 'delete'}]"></i></div>
+            </div>
+          </th>
+
+          <th class="dt-center">
+            <div class="pointer" @click="changeSort('status')">
 
-          <th class="center">
             Statut
             <i
               :class="{
@@ -14,21 +22,23 @@
                 up: isSortedDesc('status'),
               }"
               class="icon sort"
-              @click="changeSort('status')"
             />
+            </div>
           </th>
-          <th class="center">
-            Type
-            <i
-              :class="{
-                down: isSortedAsc('feature_type'),
-                up: isSortedDesc('feature_type'),
-              }"
-              class="icon sort"
-              @click="changeSort('feature_type')"
-            />
+          <th class="dt-center">
+            <div class="pointer" @click="changeSort('feature_type')">
+              Type
+              <i
+                :class="{
+                  down: isSortedAsc('feature_type'),
+                  up: isSortedDesc('feature_type'),
+                }"
+                class="icon sort"
+              />
+            </div>
           </th>
-          <th class="center">
+          <th class="dt-center">
+            <div class="pointer" @click="changeSort('title')">
             Nom
             <i
               :class="{
@@ -36,10 +46,11 @@
                 up: isSortedDesc('title'),
               }"
               class="icon sort"
-              @click="changeSort('title')"
             />
+            </div>
           </th>
-          <th class="center">
+          <th class="dt-center">
+            <div class="pointer" @click="changeSort('updated_on')">
             Dernière modification
             <i
               :class="{
@@ -47,62 +58,57 @@
                 up: isSortedDesc('updated_on'),
               }"
               class="icon sort"
-              @click="changeSort('updated_on')"
             />
+            </div>
           </th>
-          <th class="center" v-if="user">
-            Auteur
-            <i
-              :class="{
-                down: isSortedAsc('display_creator'),
-                up: isSortedDesc('display_creator'),
-              }"
-              class="icon sort"
-              @click="changeSort('display_creator')"
-            />
+          <th class="dt-center" v-if="user">
+            <div class="pointer" @click="changeSort('display_creator')">
+              Auteur
+              <i
+                :class="{
+                  down: isSortedAsc('display_creator'),
+                  up: isSortedDesc('display_creator'),
+                }"
+                class="icon sort"
+              />
+            </div>
           </th>
-          <th class="center" v-if="user">
-            Dernier éditeur
-            <i
-              :class="{
-                down: isSortedAsc('display_last_editor'),
-                up: isSortedDesc('display_last_editor'),
-              }"
-              class="icon sort"
-              @click="changeSort('display_last_editor')"
-            />
+          <th class="dt-center" v-if="user">
+            <div class="pointer" @click="changeSort('display_last_editor')">
+              Dernier éditeur
+              <i
+                :class="{
+                  down: isSortedAsc('display_last_editor'),
+                  up: isSortedDesc('display_last_editor'),
+                }"
+                class="icon sort"
+              />
+            </div>
           </th>
         </tr>
       </thead>
       <tbody>
         <tr v-for="(feature, index) in paginatedFeatures" :key="index">
-          <td class="center">
+          <td class="dt-center">
             <div
-              class="ui checkbox"
-              :class="
-                feature.properties.creator.username !== user.username &&
-                !user.is_superuser &&
-                !isUserProjectAdministrator
-                  ? 'disabled'
-                  : ''
-              "
+              :class="['ui checkbox', {disabled: !checkRights(feature)}]"
             >
               <input
                 type="checkbox"
+                v-model="checked"
+                @input="storeClickedFeature(feature)"
                 :id="feature.id"
                 :value="feature.id"
-                v-model="checked"
-                :disabled="
-                  feature.properties.creator.username !== user.username &&
-                  !user.is_superuser &&
-                  !isUserProjectAdministrator
-                "
+                :disabled="!checkRights(feature)"
+                name="select"
               />
-              <label></label>
+              <label for="select"></label>
             </div>
+            <!-- {{canDeleteFeature(feature)}}
+            {{canEditFeature(feature)}} -->
           </td>
 
-          <td class="center">
+          <td class="dt-center">
             <div
               v-if="feature.properties.status.value === 'archived'"
               data-tooltip="Archivé"
@@ -128,7 +134,7 @@
               <i class="orange pencil alternate icon"></i>
             </div>
           </td>
-          <td class="center">
+          <td class="dt-center">
             <router-link
               :to="{
                 name: 'details-type-signalement',
@@ -140,7 +146,7 @@
               {{ feature.properties.feature_type.title }}
             </router-link>
           </td>
-          <td class="center">
+          <td class="dt-center">
             <router-link
               :to="{
                 name: 'details-signalement',
@@ -152,13 +158,13 @@
               >{{ getFeatureDisplayName(feature) }}</router-link
             >
           </td>
-          <td class="center">
+          <td class="dt-center">
             {{ feature.properties.updated_on }}
           </td>
-          <td class="center" v-if="user">
+          <td class="dt-center" v-if="user">
             {{ getUserName(feature) }}
           </td>
-          <td class="center" v-if="user">
+          <td class="dt-center" v-if="user">
             {{ feature.properties.display_last_editor }}
           </td>
         </tr>
@@ -261,18 +267,17 @@ export default {
   props: [
     "paginatedFeatures",
     "checkedFeatures",
+    "clickedFeatures",
     "featuresCount",
     "pagination",
     "sort",
+    "mode"
   ],
 
   computed: {
     ...mapState(["user"]),
     ...mapGetters(["project", "permissions"]),
-
-    isUserProjectAdministrator() {
-      return this.permissions.is_project_administrator;
-    },
+    ...mapState(["user", "USER_LEVEL_PROJECTS"]),
 
     checked: {
       get() {
@@ -304,16 +309,18 @@ export default {
     },
 
     displayedPageNumbers() {
+      //* s'il y a moins de 5 pages, renvoyer toutes les pages
+      if (this.lastPageNumber < 5) return this.pageNumbers
       //* si la page courante est inférieur à 5, la liste commence à l'index 0 et on retourne 5 pages
       let firstPageInList = 0;
       let pagesQuantity = 5;
-        //* à partir de la 5ième page et jusqu'à la 4ième page avant la fin : n'afficher que 3 page entre les ellipses et la page courante doit être au milieu
-      if (this.pagination.currentPage >= 5 && !(this.lastPageNumber - this.pagination.currentPage < 4)) {
+      //* à partir de la 5ième page et jusqu'à la 4ième page avant la fin : n'afficher que 3 page entre les ellipses et la page courante doit être au milieu
+      if (this.pagination.currentPage >= 5 && !((this.lastPageNumber - this.pagination.currentPage) < 4)) {
         firstPageInList = this.pagination.currentPage - 2;
         pagesQuantity = 3
       }
-      //* a partir de 4 résultat avant la fin afficher seulement les 5 derniers résultats
-      if (this.lastPageNumber - this.pagination.currentPage < 4) {
+      //* à partir de 4 résultat avant la fin afficher seulement les 5 derniers résultats
+      if ((this.lastPageNumber - this.pagination.currentPage) < 4) {
         firstPageInList = this.lastPageNumber - 5;
       }
       return this.pageNumbers.slice(firstPageInList, firstPageInList + pagesQuantity);
@@ -321,6 +328,50 @@ export default {
   },
 
   methods: {
+    storeClickedFeature(feature) {
+      this.clickedFeatures.push({feature_id: feature.id, feature_type: feature.properties.feature_type.slug})
+    },
+
+    canDeleteFeature(feature) {
+      return feature.properties.creator.username !== this.user.username &&
+                  !this.user.is_superuser &&
+                  !this.permissions.is_project_administrator
+    },
+
+    canEditFeature(feature) {
+      const userStatus = this.USER_LEVEL_PROJECTS[this.project.slug];
+      const access = {
+        "Administrateur projet" : ["draft", "published", "archived"],
+        "Modérateur" : ["pending"],
+        "Super Contributeur" : ["draft", this.project.moderation ? "pending" : "published"],
+        "Contributeur" : ["draft", this.project.moderation ? "pending" : "published"],
+      };
+
+      //if (userStatus === "Super Contributeur" || userStatus === "Contributeur") { //? should super contributeur behave the same, I don't think so
+      if (userStatus === "Contributeur" && feature.properties.creator.username !== this.user.username) {
+        return false;
+      } else if (access[userStatus]) {
+        return access[userStatus].includes(feature.properties.status.value);
+      } else {
+        return false
+      }
+    },
+
+    checkRights(feature) {
+      switch (this.mode) {
+        case 'modify':
+          return this.canEditFeature(feature)
+        case 'delete':
+          return this.canDeleteFeature(feature)
+      } 
+    },
+
+    switchMode() {
+      this.$emit('update:mode', this.mode === 'modify' ? 'delete' : 'modify');
+      this.$emit('update:clickedFeatures', []);
+      this.$store.commit("feature/UPDATE_CHECKED_FEATURES", []);
+    },
+    
     getUserName(feature) {
       if (!feature.properties.creator) {
         return " ---- ";
@@ -352,6 +403,9 @@ export default {
       }
     },
   },
+  destroyed() {
+    this.$store.commit("feature/UPDATE_CHECKED_FEATURES", []);
+  },
 };
 </script>
 
@@ -361,6 +415,9 @@ export default {
   position: relative;
   clear: both;
 }
+table.dataTable th.dt-center, table.dataTable td.dt-center, table.dataTable td.dataTables_empty {
+  text-align: center;
+}
 .dataTables_wrapper .dataTables_length,
 .dataTables_wrapper .dataTables_filter,
 .dataTables_wrapper .dataTables_info,
@@ -443,7 +500,23 @@ export default {
 i.icon.sort:not(.down):not(.up) {
   color: rgb(220, 220, 220);
 }
+.pointer:hover {
+  cursor: pointer;
+}
+
+.switch-buttons {
+  display: flex;
+  justify-content: center;
+  align-items: baseline;
+}
 
+.grey {
+  color: #bbbbbb;
+}
+
+.ui.dropdown .menu .left.menu, .ui.dropdown > .left.menu .menu {
+  margin-right: 0 !important;
+}
 /* 
 Max width before this PARTICULAR table gets nasty
 This query will take effect for any screen smaller than 760px
@@ -513,8 +586,8 @@ and also iPads specifically.
     content: "Auteur";
   }
 
-  .center {
-    text-align: right !important;
+  table.dataTable th.dt-center, table.dataTable td.dt-center, table.dataTable td.dataTables_empty {
+    text-align: right;
   }
 
   #table-features {
diff --git a/src/components/feature_type/SymbologySelector.vue b/src/components/feature_type/SymbologySelector.vue
index cd3c2409e6c8a375c139fd075818b7c58b25aa56..32c201bc0748bb34e354670d69974ee016be0af1 100644
--- a/src/components/feature_type/SymbologySelector.vue
+++ b/src/components/feature_type/SymbologySelector.vue
@@ -14,7 +14,7 @@
           v-model.lazy="form.color.value"
         />
       </div>
-      <div class="required inline field">
+      <!-- <div class="required inline field">
         <label>Symbole</label>
         <button
           class="ui icon button picker-button"
@@ -27,7 +27,7 @@
             class="icon alt"
           />
         </button>
-      </div>
+      </div> -->
     </div>
     <div
       :class="isIconPickerModalOpen ? 'active' : ''"
diff --git a/src/service-worker.js b/src/service-worker.js
index dac6068b2cb19d00474c971971347d4f6fbb87a1..8a743071b19d358e8943689d387cd3225c77e0c8 100644
--- a/src/service-worker.js
+++ b/src/service-worker.js
@@ -14,7 +14,7 @@ if (workbox) {
     // Since we have a SPA here, this should be index.html always.
     // https://stackoverflow.com/questions/49963982/vue-router-history-mode-with-pwa-in-offline-mode
     workbox.routing.registerNavigationRoute('/geocontrib/index.html', {
-        blacklist: [/\/api/,/\/admin/,/\/media/],
+        blacklist: [/\/api/,/\/admin/,/\/media/,/\/cas/],
       })
 
     workbox.routing.registerRoute(
diff --git a/src/services/feature-api.js b/src/services/feature-api.js
index 30b3fb8e55ab30d617b6abf4e2564aa186f86a12..3b21882327d377f1ea9013f83801ad40519f7c49 100644
--- a/src/services/feature-api.js
+++ b/src/services/feature-api.js
@@ -62,6 +62,21 @@ const featureAPI = {
     }
   },
 
+  async updateFeature({ feature_id, feature_type__slug, project__slug, newStatus }) {
+    let url = `${baseUrl}features/${feature_id}/?feature_type__slug=${feature_type__slug}&project__slug=${project__slug}`
+
+    const response = await axios({
+      url,
+      method: "PATCH",
+      data: { id: feature_id, status: newStatus, feature_type: feature_type__slug }
+    })
+    if (response.status === 200 && response.data) {
+      return response;
+    } else {
+      return null;
+    }
+  },
+
   async postComment({ featureId, comment }) {
     const response = await axios.post(
       `${baseUrl}features/${featureId}/comments/`, { comment }
diff --git a/src/services/featureType-api.js b/src/services/featureType-api.js
new file mode 100644
index 0000000000000000000000000000000000000000..dca96343ae4d474d3b612c83ce585912162f40ae
--- /dev/null
+++ b/src/services/featureType-api.js
@@ -0,0 +1,22 @@
+import axios from "@/axios-client.js";
+import store from '../store'
+
+const baseUrl = store.state.configuration.VUE_APP_DJANGO_API_BASE;
+
+const featureTypeAPI = {
+  async deleteFeatureType(featureType_slug) {
+    const response = await axios.delete(
+      `${baseUrl}feature-types/${featureType_slug}`
+    );
+    if (
+      response.status === 204
+    ) {
+      return 'success'
+    } else {
+      return null;
+    }
+  },
+
+}
+
+export default featureTypeAPI;
diff --git a/src/services/project-api.js b/src/services/project-api.js
index f3d439cd4b4648a8080ec68e540dfbcf451d8810..6c9e7a83746313983b4feb658012b2ea4a985d3f 100644
--- a/src/services/project-api.js
+++ b/src/services/project-api.js
@@ -35,6 +35,17 @@ const projectAPI = {
       return null;
     }
   },
+
+  async deleteProject(projectSlug) {
+    const response = await axios.delete(
+      `${baseUrl}projects/${projectSlug}`
+    );
+    if ( response.status === 204 ) {
+      return 'success';
+    } else {
+      return null;
+    }
+  },
 }
 
 export default projectAPI;
diff --git a/src/store/index.js b/src/store/index.js
index 379fa608c2708203b34037bece57fe1aa6e730af..a6c2008102fb6e5ace554cbc6339f6303893e276 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -93,13 +93,16 @@ export default new Vuex.Store({
     SET_EVENTS(state, events) {
       state.events = events;
     },
-    DISPLAY_MESSAGE(state, comment) {
-      state.messages = [{ comment }, ...state.messages];
+    DISPLAY_MESSAGE(state, message) {
+      state.messages = [message, ...state.messages];
       if (document.getElementById("content")) document.getElementById("content").scrollIntoView({ block: "start", inline: "nearest" });
       setTimeout(() => {
         state.messages = [];
       }, 3000);
     },
+    DISCARD_MESSAGE(state, message) {
+      state.messages = state.messages.filter((el) => el.comment !== message.comment)
+    },
     CLEAR_MESSAGES(state) {
       state.messages = [];
     },
diff --git a/src/store/modules/feature.js b/src/store/modules/feature.js
index fd331b50afb9e4fcb3aa32a7db9b895167c7cf90..436e57097da5f67c7cb72d13e3aa6f1436305790 100644
--- a/src/store/modules/feature.js
+++ b/src/store/modules/feature.js
@@ -172,7 +172,6 @@ const feature = {
 
     SEND_FEATURE({ state, rootState, commit, dispatch }, routeName) {
       commit("DISPLAY_LOADER", "Le signalement est en cours de création", { root: true })
-      const message = routeName === "editer-signalement" ? "Le signalement a été mis à jour" : "Le signalement a été crée";
       function redirect(featureId) {
         dispatch(
           'GET_PROJECT_FEATURE',
@@ -188,7 +187,7 @@ const feature = {
               params: {
                 slug_type_signal: rootState.feature_type.current_feature_type_slug,
                 slug_signal: featureId,
-                message,
+                message: routeName === "editer-signalement" ? "Le signalement a été mis à jour" : "Le signalement a été crée"
               },
             });
             dispatch("GET_ALL_PROJECTS", null, {root:true}) //* & refresh project list
@@ -201,30 +200,32 @@ const feature = {
         redirect(featureId);
       }
 
-      //* prepare feature data to send
-      let extraFormObject = {}; //* prepare an object to be flatten in properties of geojson
-      for (const field of state.extra_form) {
-        extraFormObject[field.name] = field.value;
-      }
-      const geojson = {
-        "id": state.form.feature_id,
-        "type": "Feature",
-        "geometry": state.form.geometry,
-        "properties": {
-          "title": state.form.title,
-          "description": state.form.description.value,
-          "status": state.form.status.value,
-          "project": rootState.project_slug,
-          "feature_type": rootState.feature_type.current_feature_type_slug,
-          ...extraFormObject
+      function createGeojson() { //* prepare feature data to send
+        let extraFormObject = {}; //* prepare an object to be flatten in properties of geojson
+        for (const field of state.extra_form) {
+          extraFormObject[field.name] = field.value;
+        }
+        return {
+          "id": state.form.feature_id,
+          "type": "Feature",
+          "geometry": state.form.geometry,
+          "properties": {
+            "title": state.form.title,
+            "description": state.form.description.value,
+            "status": state.form.status.value,
+            "project": rootState.project_slug,
+            "feature_type": rootState.feature_type.current_feature_type_slug,
+            ...extraFormObject
+          }
         }
       }
 
+      const geojson = createGeojson();
       let url = `${rootState.configuration.VUE_APP_DJANGO_API_BASE}features/`
       if (routeName === "editer-signalement") {
-        url += `${state.form.feature_id}/?` +
-        `feature_type__slug=${rootState.feature_type.current_feature_type_slug}` +
-        `&project__slug=${rootState.project_slug}`
+        url += `${state.form.feature_id}/?
+        feature_type__slug=${rootState.feature_type.current_feature_type_slug} 
+        &project__slug=${rootState.project_slug}`
       }
 
       return axios({
@@ -250,7 +251,7 @@ const feature = {
             }
             let updateMsg = {
               project: rootState.project_slug,
-              type: 'put',
+              type: routeName === "editer-signalement" ? "put" : "post",
               featureId: state.form.feature_id,
               geojson: geojson
             };
diff --git a/src/store/modules/feature_type.js b/src/store/modules/feature_type.js
index 5ad047abd1203dfde68efcb5bd30c3d692334c3b..05a611c4d8cc9dd871f551e321e8c332aaaed7df 100644
--- a/src/store/modules/feature_type.js
+++ b/src/store/modules/feature_type.js
@@ -194,7 +194,7 @@ const feature_type = {
           })
           .then((response) => {
             if (response && response.status === 200) {
-              dispatch("GET_IMPORTS", {
+              return dispatch("GET_IMPORTS", {
                 feature_type: feature_type_slug
               });
             }
@@ -214,12 +214,13 @@ const feature_type = {
       if (feature_type) {
         url = url.concat('', `${url.includes('?') ? '&' : '?'}feature_type_slug=${feature_type}`);
       }
-      axios
+      return axios
         .get(url)
         .then((response) => {
           if (response) {
             commit("SET_IMPORT_FEATURE_TYPES_DATA", response.data);
           }
+          return response;
         })
         .catch((error) => {
           throw (error);
diff --git a/src/views/feature/Feature_detail.vue b/src/views/feature/Feature_detail.vue
index 1203b2652d9c91605698d6ffcfba74894a23a46a..bf97c9702bd6405d6966a05d84b05fd3e83242dc 100644
--- a/src/views/feature/Feature_detail.vue
+++ b/src/views/feature/Feature_detail.vue
@@ -504,7 +504,7 @@ export default {
     },
 
     confirmComment() {
-      this.$store.commit("DISPLAY_MESSAGE", "Ajout du commentaire confirmé");
+      this.$store.commit("DISPLAY_MESSAGE", {comment: "Ajout du commentaire confirmé", level: "positive"});
       this.getFeatureEvents(); //* display new comment on the page
       this.comment_form.attachment_file.file = null;
       this.comment_form.attachment_file.fileName = "";
diff --git a/src/views/feature/Feature_list.vue b/src/views/feature/Feature_list.vue
index e72194a62133f38071157354004fc5d170ad3aa3..9f08055a416e30b2b9627ff828d3ee9d23b37f13 100644
--- a/src/views/feature/Feature_list.vue
+++ b/src/views/feature/Feature_list.vue
@@ -36,18 +36,19 @@
               feature_types.length > 0 &&
               permissions.can_create_feature
             "
+            id="button-dropdown"
             class="item right"
           >
             <div
-              @click="showAddFeature = !showAddFeature"
+              @click="toggleAddFeature"
               class="ui dropdown button compact button-hover-green"
               data-tooltip="Ajouter un signalement"
-              data-position="bottom left"
+              data-position="bottom right"
             >
               <i class="plus fitted icon"></i>
               <div
                 v-if="showAddFeature"
-                class="menu transition visible"
+                class="menu left transition visible"
                 style="z-index: 9999"
               >
                 <div class="header">Ajouter un signalement du type</div>
@@ -67,13 +68,40 @@
               </div>
             </div>
 
+
             <div
-              v-if="checkedFeatures.length"
+              v-if="checkedFeatures.length > 0 && mode === 'modify'"
+              @click="toggleModifyStatus"
+              class="ui dropdown button compact button-hover-green margin-left-25"
+              data-tooltip="Modifier le statut des Signalements"
+              data-position="bottom right"
+            >
+              <i class="pencil fitted icon"></i>
+              <div
+                v-if="showModifyStatus"
+                class="menu left transition visible"
+                style="z-index: 9999"
+              >
+                <div class="header">Modifier le statut des Signalements</div>
+                <div class="scrolling menu text-wrap">
+                  <span
+                    v-for="status in availableStatus"
+                    :key="status.value"
+                    @click="modifyStatus(status.value)"
+                    class="item"
+                  >
+                    {{ status.name }}
+                  </span>
+                </div>
+              </div>
+            </div>
+
+            <div
+              v-if="checkedFeatures.length > 0 && mode === 'delete'"
               @click="modalAllDelete"
               class="ui button compact button-hover-red margin-left-25"
               data-tooltip="Effacer tous les types de signalements sélectionnés"
-              data-position="left center"
-              data-variation="mini"
+              data-position="bottom right"
             >
               <i class="grey trash fitted icon"></i>
             </div>
@@ -136,12 +164,15 @@
       <SidebarLayers v-if="basemaps && map" />
     </div>
     <!-- | -->
+      <!-- v-on:update:clickedFeatures="handleClickedFeatures" -->
     <FeatureListTable
       v-show="!showMap"
       v-on:update:page="handlePageChange"
       v-on:update:sort="handleSortChange"
       :paginatedFeatures="paginatedFeatures"
-      :checkedFeatures.sync="checkedFeatures"
+      :checkedFeatures="checkedFeatures"
+      :clickedFeatures.sync="clickedFeatures"
+      :mode.sync="mode"
       :featuresCount="featuresCount"
       :pagination="pagination"
       :sort="sort"
@@ -228,7 +259,9 @@ export default {
         title: null,
       },
       baseUrl: this.$store.state.configuration.BASE_URL,
+      clickedFeatures: [],
       modalAllDeleteOpen: false,
+      mode: "modify",
       map: null,
       zoom: null,
       lat: null,
@@ -250,6 +283,7 @@ export default {
       },
       showMap: true,
       showAddFeature: false,
+      showModifyStatus: false,
     };
   },
 
@@ -298,6 +332,7 @@ export default {
   },
 
   computed: {
+    ...mapState(["user", "USER_LEVEL_PROJECTS"]),
     ...mapGetters([
       'project', 'permissions'
     ]),
@@ -322,6 +357,58 @@ export default {
       );
     },
 
+    availableStatus() { //* attente de réponse sur le ticket
+      //return this.statusChoices.filter((status) => status)
+
+      if (this.project) {
+        const isModerate = this.project.moderation;
+        const userStatus = this.USER_LEVEL_PROJECTS[this.project.slug];
+        const isOwnFeature = this.feature
+          ? this.feature.creator === this.user.id //* prevent undefined feature
+          : false; //* si le contributeur est l'auteur du signalement
+        if (
+          //* si admin, modérateur ou super contributeur, statuts toujours disponible: Brouillon, Publié, Archivé
+          userStatus === "Administrateur projet" ||
+          (userStatus === "Super Contributeur" && !isModerate)
+        ) {
+          return this.statusChoices.filter((el) => el.value !== "pending");
+        } else if (userStatus === "Super Contributeur" && isModerate) {
+          return this.statusChoices.filter(
+            (el) => el.value === "draft" || el.value === "pending"
+          );
+        } else if (userStatus === "Modérateur") {
+          return this.statusChoices.filter(
+            (el) => el.value === "draft" || el.value === "published"
+          );
+        } else if (userStatus === "Contributeur") {
+          //* cas particuliers du contributeur
+          if (
+            this.currentRouteName === "ajouter-signalement" ||
+            !isOwnFeature
+          ) {
+            //* même cas à l'ajout d'une feature ou si feature n'a pas été créé par le contributeur
+            return isModerate
+              ? this.statusChoices.filter(
+                  (el) => el.value === "draft" || el.value === "pending"
+                )
+              : this.statusChoices.filter(
+                  (el) => el.value === "draft" || el.value === "published"
+                );
+          } else {
+            //* à l'édition d'une feature et si le contributeur est l'auteur de la feature
+            return isModerate
+              ? this.statusChoices.filter(
+                  (el) => el.value !== "published" //* toutes sauf "Publié"
+                )
+              : this.statusChoices.filter(
+                  (el) => el.value !== "pending" //* toutes sauf "En cours de publication"
+                );
+          }
+        }
+      }
+      return [];
+    },
+
     featureTypeChoices() {
       return this.feature_types.map((el) => el.title);
     },
@@ -329,15 +416,76 @@ export default {
 
   methods: {
     ...mapActions('feature', [
-      'GET_PROJECT_FEATURES'
+      'GET_PROJECT_FEATURES',
+      'SEND_FEATURE'
     ]),
+
+    toggleAddFeature() {
+      this.showAddFeature = !this.showAddFeature;
+      this.showModifyStatus = false;
+    },
+
+    toggleModifyStatus() {
+      this.showModifyStatus = !this.showModifyStatus;
+      this.showAddFeature = false;
+    },
+
     modalAllDelete() {
       this.modalAllDeleteOpen = !this.modalAllDeleteOpen;
     },
 
+    clickOutsideDropdown(e) {
+      if (!e.target.closest("#button-dropdown")) {
+        this.showModifyStatus = false;
+        setTimeout(() => { //* timout necessary to give time to click on link to add feature
+          this.showAddFeature = false;
+        }, 500);
+      }
+    },
+
+    async modifyStatus(newStatus) {
+      let errorCount = 0
+      const promises = this.checkedFeatures.map((feature_id) => {
+        let feature = this.clickedFeatures.find((el) => el.feature_id === feature_id)
+        if (feature) {
+        return featureAPI.updateFeature({
+          feature_id,
+          feature_type__slug: feature.feature_type,
+          project__slug: this.$route.params.slug, newStatus
+        })
+        } else {
+          errorCount += 1;
+        }
+      })
+      const promisesResult = await Promise.all(promises)
+      promisesResult.forEach((response) => {
+        if (response && response.data && response.status === 200) {
+          this.checkedFeatures.splice(this.checkedFeatures.indexOf(response.data.id), 2);
+        } else {
+          errorCount += 1;
+        }
+      })
+      let message = {
+        comment: "Tous les signalements ont été modifié avec succès.",
+        level: "positive"
+      } 
+      if (errorCount) {
+        //* display error message
+        if(errorCount === 1) {
+          message.comment = "Un signalement n'a pas pu être modifié. (Il reste sélectionné)"
+        } else {
+          message.comment = `${errorCount} signalements n'ont pas pu être modifiés. (Ils restent sélectionnés)`
+        }
+        message.level = "negative"
+      }
+      this.fetchPagedFeatures();
+      this.$store.commit("DISPLAY_MESSAGE", message);
+    },
+
+
     deleteFeature(feature_id) {
       const url = `${this.API_BASE_URL}features/${feature_id}/?project__slug=${this.project.slug}`;
-      axios
+      axios //TODO: REFACTO -> Delete function already exist in store
         .delete(url, {})
         .then(() => {
           if (!this.modalAllDeleteOpen) {
@@ -346,7 +494,6 @@ export default {
             })
               .then(() => {
                 this.fetchPagedFeatures();
-                this.getNloadGeojsonFeatures();
                 this.checkedFeatures.splice(feature_id);
               });
           }
@@ -359,8 +506,8 @@ export default {
     deleteAllFeatureSelection() {
       let feature = {};
       this.checkedFeatures.forEach((feature_id) => {
-        feature = { feature_id: feature_id };
-        this.deleteFeature(feature.feature_id);
+        feature = { feature_id: feature_id }; // ? Is this usefull ?
+        this.deleteFeature(feature.feature_id); //? since property feature_id is directly used after...
       });
       this.modalAllDelete();
     },
@@ -461,8 +608,8 @@ export default {
     fetchPagedFeatures(newUrl) {
       this.onFilterChange(); //* use paginated event to watch change in filters and modify features on map
       let url = `${this.API_BASE_URL}projects/${this.$route.params.slug}/feature-paginated/?output=geojson&limit=${this.pagination.pagesize}&offset=${this.pagination.start}`;
+      //* if receiving next & previous url
       if (newUrl && typeof newUrl === "string") {
-        //* if receiving next & previous url
         //newUrl = newUrl.replace("8000", "8010"); //* for dev uncomment to use proxy link
         url = newUrl;
       }
@@ -550,9 +697,11 @@ export default {
       this.initMap();
     }
     this.fetchPagedFeatures();
+    window.addEventListener("mousedown", this.clickOutsideDropdown);
   },
 
   destroyed() {
+    window.removeEventListener("mousedown", this.clickOutsideDropdown);
     //* allow user to change page if ever stuck on loader
     this.$store.commit("DISCARD_LOADER");
   },
@@ -570,10 +719,6 @@ export default {
   z-index: 1;
 }
 
-.center {
-  text-align: center !important;
-}
-
 #feature-list-container {
   justify-content: flex-start;
 }
@@ -600,20 +745,23 @@ export default {
   padding: 0 !important;
 }
 
+.ui.dropdown .menu .left.menu, .ui.dropdown > .left.menu .menu {
+  margin-right: 0 !important;
+}
+
 @media screen and (min-width: 767px) {
   .twelve-wide {
     width: 75% !important;
   }
 }
+
 @media screen and (max-width: 767px) {
   #feature-list-container > .mobile-fullwidth {
     width: 100% !important;
   }
-
   .no-margin-mobile {
     margin: 0 !important;
   }
-
   .no-padding-mobile {
     padding-top: 0 !important;
     padding-bottom: 0 !important;
@@ -621,10 +769,12 @@ export default {
   .mobile-column {
     flex-direction: column !important;
   }
+  #button-dropdown {
+    transform: translate(-50px, -60px);
+  }
   #form-filters > .field.column {
     width: 100% !important;
   }
-
   .map-container {
     width: 100%;
   }
diff --git a/src/views/feature_type/Feature_type_detail.vue b/src/views/feature_type/Feature_type_detail.vue
index 6cc002d45fe4ad1acdb48a008074eb93b708ba1c..4ae9047be983251672f63302e2545a1ba9dbae48 100644
--- a/src/views/feature_type/Feature_type_detail.vue
+++ b/src/views/feature_type/Feature_type_detail.vue
@@ -2,7 +2,7 @@
   <div v-if="structure" class="row">
     <div class="five wide column">
       <div class="ui attached secondary segment">
-        <h1 class="ui center aligned header">
+        <h1 class="ui center aligned header ellipsis">
           <img
             v-if="structure.geom_type === 'point'"
             class="ui medium image"
@@ -72,7 +72,7 @@
               :class="loadingImportFile ? 'loading' : ''"
             >
               <div class="field">
-                <label class="ui icon button" for="json_file">
+                <label class="ui icon button ellipsis" for="json_file">
                   <i class="file icon"></i>
                   <span class="label">{{ fileToImport.name }}</span>
                 </label>
@@ -100,6 +100,7 @@
               <ImportTask
                 v-if="importFeatureTypeData && importFeatureTypeData.length"
                 :data="importFeatureTypeData"
+                :reloading="reloadingImport"
               />
             </div>
           </div>
@@ -149,6 +150,15 @@
           Pour suivre le statut de l'import, cliquez sur "Importer des Signalements".
         </p>
       </div>
+      <div
+        v-else-if="waitMessage"
+        class="ui message info"
+      >
+        <p>
+          L'import des signalements a été lancé.
+          Vous pourrez suivre le statut de l'import dans quelques instants...
+        </p>
+      </div>
       <div
         v-for="(feature, index) in lastFeatures"
         :key="feature.feature_id + index"
@@ -243,7 +253,9 @@ export default {
       },
       showImport: false,
       featuresLoading: true,
-      loadingImportFile: false
+      loadingImportFile: false,
+      waitMessage: false,
+      reloadingImport: false,
     };
   },
 
@@ -260,6 +272,9 @@ export default {
       'project',
       'permissions'
     ]),
+    ...mapState([
+      'reloadIntervalId'
+    ]),
     ...mapState('feature', [
       'features',
       'features_count'
@@ -307,9 +322,27 @@ export default {
       if (newValue.slug){
         this.GET_IMPORTS({
           feature_type: this.$route.params.feature_type_slug
-        });
+        })
       }
-    }
+    },
+
+    importFeatureTypeData: {
+      deep: true,
+      handler(newValue) {
+        if (newValue && newValue.some(el => el.status === 'pending')) {
+          setTimeout(() => {
+            this.reloadingImport = true;
+            this.GET_IMPORTS({
+              feature_type: this.$route.params.feature_type_slug
+            }).then(()=> {
+              setTimeout(() => {
+                this.reloadingImport = false;
+              }, 1000);
+            })
+          }, this.$store.state.configuration.VUE_APP_RELOAD_INTERVAL);
+        }
+      }
+    },
   },
 
   created() {
@@ -341,9 +374,8 @@ export default {
     toggleShowImport() {
       this.showImport = !this.showImport;
       if (this.showImport) {
-        this.$store.dispatch("feature_type/GET_IMPORTS", {
-          feature_type: this.$route.params.feature_type_slug
-        });
+        this.GET_IMPORTS({
+          feature_type: this.$route.params.feature_type_slug        });
       }
     },
 
@@ -432,11 +464,14 @@ export default {
     },
 
     importGeoJson() {
+      this.waitMessage = true;
       this.$store.dispatch('feature_type/SEND_FEATURES_FROM_GEOJSON', {
         slug: this.$route.params.slug,
         feature_type_slug: this.$route.params.feature_type_slug,
         fileToImport: this.fileToImport,
-      });
+      }).then(() => {
+        this.waitMessage = false;
+      })
     },
 
     exportFeatures() {
diff --git a/src/views/feature_type/Feature_type_edit.vue b/src/views/feature_type/Feature_type_edit.vue
index dfa8937c9abfed92bd24493900020aac8916ea56..823914679f737ce657ffa3fc09024a00b0e0216f 100644
--- a/src/views/feature_type/Feature_type_edit.vue
+++ b/src/views/feature_type/Feature_type_edit.vue
@@ -104,6 +104,23 @@
               :placeholder="'Sélectionner la liste de valeurs'"
             />
           </div>
+          <div class="colors_selection" id="id_colors_selection" hidden>
+            <div
+              v-for="(value, key, index) in form.colors_style.value.colors"
+              :key="'colors_style-' + index"
+            >
+              <div v-if="key" class="color-input">
+                <label>{{ key }}</label
+                ><input
+                  :name="key"
+                  type="color"
+                  :value="value"
+                  @input="setColorStyles"
+                />
+              </div>
+            </div>
+          </div>
+
         </div>
 
         <span v-if="action === 'duplicate' || action === 'edit'"> </span>
diff --git a/src/views/feature_type/Feature_type_symbology.vue b/src/views/feature_type/Feature_type_symbology.vue
index f49cb9053473aba19eb9a4ee789cde9316b44406..6baac62261e7ecb6a52ee4a6d6a9f46edbe2891f 100644
--- a/src/views/feature_type/Feature_type_symbology.vue
+++ b/src/views/feature_type/Feature_type_symbology.vue
@@ -191,13 +191,17 @@ export default {
     }
     this.SET_CURRENT_FEATURE_TYPE_SLUG(this.$route.params.slug_type_signal);
     if (this.feature_type) {
-      // Init form
-      this.form.color = JSON.parse(JSON.stringify(this.feature_type.color));
-      this.form.icon = JSON.parse(JSON.stringify(this.feature_type.icon));
-      this.form.colors_style = {
-        ...this.form.colors_style,
-        ...JSON.parse(JSON.stringify(this.feature_type.colors_style))
-      };
+      this.initForm();
+    } else {
+      this.loading = true;
+      this.GET_PROJECT_FEATURE_TYPES(this.$route.params.slug)
+        .then(() => {
+          this.initForm();
+          this.loading = false;
+        })
+        .catch(() => {
+          this.loading = false;
+        });
     }
   },
 
@@ -213,6 +217,19 @@ export default {
       'GET_PROJECT_INFO'
     ]),
 
+    initForm() {
+      this.form.color = JSON.parse(JSON.stringify(this.feature_type.color));
+      this.form.icon = JSON.parse(JSON.stringify(this.feature_type.icon));
+      this.form.colors_style = {
+        ...this.form.colors_style,
+        ...JSON.parse(JSON.stringify(this.feature_type.colors_style))
+      };
+      if (this.feature_type.colors_style && Object.keys(this.feature_type.colors_style.colors).length > 0) {
+        this.selectedCustomfield =
+          this.feature_type.customfield_set.find(el => el.name === this.feature_type.colors_style.custom_field_name).name;
+      }
+    },
+
     setDefaultStyle(e) {
       const value  = e.value;
       this.form.color = value.color.value;
@@ -235,7 +252,7 @@ export default {
             .then(() => {
               this.loading = false;
               this.success =
-                'La modification de la symbologie a été prise en compte. Vous allez être redirigé vers la page d\'acceuil du projet.';
+                'La modification de la symbologie a été prise en compte. Vous allez être redirigé vers la page d\'accueil du projet.';
               setTimeout(() => {
                 this.$router.push({
                   name: 'project_detail',
diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue
index 9cf071f4e9bd662c0b0683157023ccc6a03bb792..a0cd446abded78b8bc41a6cc956d65f3ee7fa81b 100644
--- a/src/views/project/Project_detail.vue
+++ b/src/views/project/Project_detail.vue
@@ -72,7 +72,7 @@
                     data-tooltip="S'abonner au projet"
                     data-position="top center"
                     data-variation="mini"
-                    @click="isModalOpen = true"
+                    @click="modalType = 'subscribe'"
                   >
                     <i class="inverted grey envelope icon"></i>
                   </a>
@@ -90,6 +90,22 @@
                   >
                     <i class="inverted grey pencil alternate icon"></i>
                   </router-link>
+                  <a
+                    v-if="
+                      user_permissions &&
+                      user_permissions[project.slug] &&
+                      user_permissions[project.slug].is_project_administrator &&
+                      isOffline() !== true
+                    "
+                    id="delete-button"
+                    class="ui button button-hover-red"
+                    data-tooltip="Supprimer le projet"
+                    data-position="top center"
+                    data-variation="mini"
+                    @click="modalType = 'deleteProject'"
+                  >
+                    <i class="inverted grey trash icon"></i>
+                  </a>
                 </div>
                 <button
                   v-if="user && user.is_administrator && !isSharedProject && project.generate_share_link"
@@ -202,7 +218,7 @@
                       button button-hover-green
                     "
                     data-tooltip="Ajouter un signalement"
-                    data-position="left center"
+                    data-position="top right"
                     data-variation="mini"
                   >
                     <i class="ui plus icon"></i>
@@ -228,7 +244,7 @@
                       button button-hover-green
                     "
                     data-tooltip="Dupliquer un type de signalement"
-                    data-position="left center"
+                    data-position="top right"
                     data-variation="mini"
                   >
                     <i class="inverted grey copy alternate icon"></i>
@@ -241,6 +257,29 @@
                     Import en cours
                   </div>
                   <div v-else v-frag>
+                  <a
+                    v-if="
+                      user_permissions &&
+                      user_permissions[project.slug] &&
+                      user_permissions[project.slug].is_project_administrator &&
+                      isOffline() !== true
+                    "
+                    @click="toggleDeleteFeatureType(type)"
+                    class="
+                      ui
+                      compact
+                      small
+                      icon
+                      right
+                      floated
+                      button button-hover-red
+                    "
+                    data-tooltip="Supprimer le type de signalement"
+                    data-position="top center"
+                    data-variation="mini"
+                  >
+                    <i class="inverted grey trash alternate icon"></i>
+                  </a>
                   <router-link
                     :to="{
                       name: 'editer-symbologie-signalement',
@@ -260,10 +299,10 @@
                       icon
                       right
                       floated
-                      button button-hover-green
+                      button button-hover-orange
                     "
                     data-tooltip="Éditer la symbologie du type de signalement"
-                    data-position="left center"
+                    data-position="top center"
                     data-variation="mini"
                   >
                     <i class="inverted grey paint brush alternate icon"></i>
@@ -287,10 +326,10 @@
                       icon
                       right
                       floated
-                      button button-hover-green
+                      button button-hover-orange
                     "
                     data-tooltip="Éditer le type de signalement"
-                    data-position="left center"
+                    data-position="top left"
                     data-variation="mini"
                   >
                     <i class="inverted grey pencil alternate icon"></i>
@@ -565,32 +604,54 @@
     </span>
 
     <div
-      v-if="isModalOpen"
+      v-if="modalType"
       class="ui dimmer modals page transition visible active"
       style="display: flex !important"
     >
       <div
         :class="[
           'ui mini modal subscription',
-          { 'transition visible active': isModalOpen },
+          { 'transition visible active': modalType },
         ]"
       >
-        <i @click="isModalOpen = false" class="close icon"></i>
+        <i @click="modalType = false" class="close icon"></i>
         <div class="ui icon header">
-          <i class="envelope icon"></i>
-          Notifications du projet
+          <i :class="[modalType === 'subscribe' ? 'envelope' : 'trash', 'icon']"></i>
+          {{
+            modalType === 'subscribe' ? 'Notifications' : 'Suppression'
+          }} du {{
+            modalType === 'deleteFeatureType' ? 'type de signalement ' + featureTypeToDelete.title : 'projet'
+          }}
         </div>
-
         <div class="content">
+          <div  v-if="modalType !== 'subscribe'" >
+
+          <p class="centered-text">
+            Confirmez vous la suppression du {{ modalType === 'deleteProject' ? 'projet, ainsi que les types de signalements' : 'type de signalement'}} et tous les signalements associés&nbsp;?
+          </p>
+          <p class="centered-text alert">
+            Attention cette action est irreversible !
+          </p>
+          </div>
           <button
-            @click="subscribeProject"
-            :class="['ui compact fluid button', is_suscriber ? 'red' : 'green']"
+            @click="handleModalClick"
+            :class="['ui compact fluid button', modalType === 'subscribe' && !is_suscriber ? 'green' : 'red']"
           >
+          <span v-if="modalType === 'subscribe'">
             {{
               is_suscriber
                 ? "Se désabonner de ce projet"
                 : "S'abonner à ce projet"
             }}
+          </span>
+          <span v-else>
+            Supprimer le 
+            {{
+              modalType === 'deleteProject'
+              ? 'projet'
+              : 'type de signalement'
+            }}
+          </span>
           </button>
         </div>
       </div>
@@ -631,6 +692,7 @@ import frag from "vue-frag";
 import { mapUtil } from "@/assets/js/map-util.js";
 import { mapGetters, mapState, mapActions, mapMutations } from "vuex";
 import projectAPI from "@/services/project-api";
+import featureTypeAPI from "@/services/featureType-api";
 import featureAPI from "@/services/feature-api";
 
 import axios from "@/axios-client.js";
@@ -668,11 +730,12 @@ export default {
       geojsonImport: [],
       fileToImport: { name: "", size: 0 },
       slug: this.$route.params.slug,
-      isModalOpen: false,
+      modalType: false,
       is_suscriber: false,
       tempMessage: null,
       projectInfoLoading: true,
       featureTypeImporting: false,
+      featureTypeToDelete: null,
       featuresLoading: true,
       isFileSizeModalOpen: false,
       // mapFeatures: null,
@@ -683,7 +746,7 @@ export default {
   computed: {
     ...mapGetters([
       'project',
-      'permissions'
+      'permissions',
     ]),
     ...mapState('feature_type', [
       'feature_types',
@@ -695,7 +758,8 @@ export default {
     ...mapState([
       'last_comments',
       'user',
-      'reloadIntervalId'
+      'user_permissions',
+      'reloadIntervalId',
     ]),
     ...mapState('map', [
       'map'
@@ -741,26 +805,6 @@ export default {
         }
       }
     },
-
-    features: {
-      deep: true,
-      handler(newValue, oldValue) {
-        if (newValue && newValue.length && newValue !== oldValue) {
-          mapUtil.addFeatures(
-            this.features,
-            {},
-            true,
-            this.feature_types
-          );
-          this.mapLoading = false;
-        }
-      }
-    },
-    featuresLoading(newValue) {
-      if (!newValue && this.features && this.features.length === 0) {
-        this.mapLoading = false;
-      }
-    }
   },
 
   created() {
@@ -775,15 +819,7 @@ export default {
   },
 
   mounted() {
-    this.GET_PROJECT_INFO(this.slug)
-      .then(() => {
-        this.projectInfoLoading = false;
-        setTimeout(this.initMap, 1000);
-      })
-      .catch((err) => {
-        console.error(err)
-        this.projectInfoLoading = false;
-      });
+    this.retrieveProjectInfo();
 
     if (this.message) {
       this.tempMessage = this.message;
@@ -801,10 +837,12 @@ export default {
   methods: {
     ...mapMutations([
       'SET_RELOAD_INTERVAL_ID',
-      'CLEAR_RELOAD_INTERVAL_ID'
+      'CLEAR_RELOAD_INTERVAL_ID',
+      'DISPLAY_MESSAGE',
     ]),
     ...mapActions([
-      'GET_PROJECT_INFO'
+      'GET_PROJECT_INFO',
+      'GET_ALL_PROJECTS',
     ]),
     ...mapActions('map', [
       'INITIATE_MAP'
@@ -849,6 +887,22 @@ export default {
       )
     },
 
+    retrieveProjectInfo() {
+      this.GET_PROJECT_INFO(this.slug)
+        .then(() => {
+          this.projectInfoLoading = false;
+          setTimeout(() => {
+            let map = mapUtil.getMap();
+            if (map) map.remove();
+            this.initMap();
+          }, 1000);
+        })
+        .catch((err) => {
+          console.error(err)
+          this.projectInfoLoading = false;
+        });
+    },
+
     checkForOfflineFeature() {
       let arraysOffline = [];
       let localStorageArray = localStorage.getItem("geocontrib_offline");
@@ -980,7 +1034,7 @@ export default {
         })
         .then((data) => {
           this.is_suscriber = data.is_suscriber;
-          this.isModalOpen = false;
+          this.modalType = false;
           if (this.is_suscriber)
             this.infoMessage =
               "Vous êtes maintenant abonné aux notifications de ce projet.";
@@ -990,6 +1044,54 @@ export default {
           setTimeout(() => (this.infoMessage = ""), 3000);
         });
     },
+
+    deleteProject() {
+      projectAPI.deleteProject(this.project.slug)
+        .then((response) => {
+          if (response === 'success') {
+            this.GET_ALL_PROJECTS();
+            this.$router.push('/');
+            this.DISPLAY_MESSAGE(`Le projet ${this.project.title} a bien été supprimé.`)
+          } else {
+            this.DISPLAY_MESSAGE(`Une erreur est survenu lors de la suppression du projet ${this.project.title}.`)
+          }
+        })
+    },
+
+    deleteFeatureType() {
+      featureTypeAPI.deleteFeatureType(this.featureTypeToDelete.slug)
+        .then((response) => {
+          this.modalType = false;
+          if (response === 'success') {
+            this.GET_ALL_PROJECTS();
+            this.retrieveProjectInfo();
+            this.DISPLAY_MESSAGE(`Le type de signalement ${this.featureTypeToDelete.title} a bien été supprimé.`)
+          } else {
+            this.DISPLAY_MESSAGE(`Une erreur est survenu lors de la suppression du type de signalement ${this.featureTypeToDelete.title}.`)
+          }
+          this.featureTypeToDelete = null;
+        })
+    },
+
+    handleModalClick() {
+      switch (this.modalType) {
+        case 'subscribe':
+          this.subscribeProject();
+          break;
+        case 'deleteProject':
+          this.deleteProject();
+          break;
+        case 'deleteFeatureType':
+          this.deleteFeatureType();
+          break;
+        }
+    },
+
+    toggleDeleteFeatureType(featureType) {
+      this.featureTypeToDelete = featureType;
+      this.modalType = 'deleteFeatureType';
+    },
+
     async initMap() {
       if (this.project && this.permissions.can_view_project) {
         await this.INITIATE_MAP(this.$refs.map);
@@ -1009,6 +1111,7 @@ export default {
           true,
           this.$store.state.feature_type.feature_types
         );
+        this.mapLoading = false;
 
         this.GET_PROJECT_FEATURES({
           project_slug: this.slug,
@@ -1114,4 +1217,10 @@ export default {
 .ui.button, .ui.button .button, .tiny-margin {
   margin:  0.1rem 0 0.1rem 0.1rem !important;
 }
-</style>
\ No newline at end of file
+.alert {
+  color: red;
+}
+.centered-text {
+  text-align: center;
+}
+</style>
diff --git a/src/views/project/Project_members.vue b/src/views/project/Project_members.vue
index aea8f4b1340c1ea3ed81f8ee426985195632eb74..dc2dff3db450ad731794a04efdeaa16d70b010fb 100644
--- a/src/views/project/Project_members.vue
+++ b/src/views/project/Project_members.vue
@@ -273,11 +273,14 @@ export default {
         .then((response) => {
           if (response.status === 200) {
             this.$store.dispatch("GET_USER_LEVEL_PROJECTS"); //* update user status in top right menu
-            this.$store.commit("DISPLAY_MESSAGE", "Permissions mises à jour");
+            this.$store.commit("DISPLAY_MESSAGE", {comment: "Permissions mises à jour", level: "positive"});
           } else {
             this.$store.commit(
               "DISPLAY_MESSAGE",
-              "Une erreur s'est produite pendant la mises à jour des permissions"
+              {
+                comment : "Une erreur s'est produite pendant la mises à jour des permissions",
+                level: "negative"
+              }
             );
           }
         })
diff --git a/src/views/registration/Login.vue b/src/views/registration/Login.vue
index f26884b1113a2d6bb9728c6e84c49ed48826a2b5..f9614efa8e415cb53704a50200c3668d964152cb 100644
--- a/src/views/registration/Login.vue
+++ b/src/views/registration/Login.vue
@@ -102,7 +102,7 @@ export default {
     if (this.$store.state.user) {
       this.$store.commit(
         "DISPLAY_MESSAGE",
-        "Vous êtes déjà connecté, vous allez être redirigé vers la page d'accueil."
+        {comment :"Vous êtes déjà connecté, vous allez être redirigé vers la page d'accueil."}
       );
       setTimeout(() => this.$router.push("/"), 3100);
     }