diff --git a/js/Client/axios.js b/js/Client/axios.js
new file mode 100644
index 0000000000000000000000000000000000000000..61f37e7ffb10ca4fe39ccfd5614cec12e6790185
--- /dev/null
+++ b/js/Client/axios.js
@@ -0,0 +1,77 @@
+import axios from 'axios';
+import flashMessenger from './flashMessenger';
+
+// uvAxios est un clone du axops standard
+let uvAxios = { ...axios};
+
+/* Tunning d'Axios pour gérer l'interconnexion avec le serveur avec gestion des toasts */
+
+// Permet d'afficher une animation de chargement dans un popover si l'objet submitter a été transmis
+uvAxios.interceptors.request.use(config => {
+    if (config.submitter) {
+        let msg = config.msg ? config.msg : 'Action en cours';
+        if (config.popover != undefined) {
+            config.popover.dispose();
+        }
+        config.popover = new bootstrap.Popover(config.submitter, {
+            content: "<div class=\"spinner-border text-primary\" role=\"status\">\n" +
+                "  <span class=\"visually-hidden\">Loading...</span>\n" +
+                "</div> " + msg,
+            html: true,
+            trigger: 'focus'
+        });
+        config.popover.show();
+    }
+    return config;
+});
+
+// On capte la réponse pour afficher le résultat si on avait un submitter, sinon on affiche des toasts
+uvAxios.interceptors.response.use(response => {
+    response.messages = response.data.messages;
+    response.data = response.data.data;
+    response.hasErrors = response.messages && response.messages.error && response.messages.error.length > 0 ? true : false;
+
+    if (response.config.popover) {
+        var popover = response.config.popover;
+
+        let content = '';
+        for (ns in response.messages) {
+            for (mid in response.messages[ns]) {
+                content += '<div class="alert fade show alert-' + (ns == 'error' ? 'danger' : ns) + '" role="alert">' + response.messages[ns][mid] + '</div>';
+            }
+        }
+
+        // S'il y a un truc à afficher
+        if (content) {
+            popover._config.content = content;
+            popover.setContent();
+            setTimeout(() => {
+                popover.dispose();
+            }, 5000)
+        } else {
+            // la popover est masquée si tout est fini
+            popover.dispose();
+        }
+    }
+    if (response.messages) {
+        flashMessenger.toasts(response.messages);
+    }
+
+    return response;
+}, (error) => {
+    let message = error.response.data;
+
+    if (error.response.status == 403){
+        message = '<h4>403 - Accès interdit</h4><br />Vous n\'êtes pas autorisé(e) à faire cette action.';
+    }else{
+        message = error.response.data;
+    }
+
+    flashMessenger.toast(message, 'error');
+});
+
+uvAxios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
+
+export default {
+    uvAxios
+}
\ No newline at end of file
diff --git a/js/Client/flashMessenger.js b/js/Client/flashMessenger.js
index 049dc592521dc3ccac408d0789040fed42ffcc94..69571935018c60df50d637ebd486333bf7a3664c 100644
--- a/js/Client/flashMessenger.js
+++ b/js/Client/flashMessenger.js
@@ -1,5 +1,4 @@
-function toasts(messages)
-{
+function toasts(messages) {
     for (let s in messages) {
         for (let m in messages[s]) {
             toast(messages[s][m], s);
@@ -8,6 +7,50 @@ function toasts(messages)
 }
 
 
+function toastContainer() {
+    let toastContainer = document.getElementById('unicaen-vue-toast-container');
+    if (!toastContainer) {
+        toastContainer = document.createElement('div');
+        toastContainer.id = 'unicaen-vue-toast-container';
+        toastContainer.classList.add('toast-container', 'position-fixed', 'top-0', 'end-0', 'p-3');
+        document.body.appendChild(toastContainer);
+    }
+    return toastContainer;
+}
+
+
+function prepareMessage(message) {
+    message = removeAlert(message);
+    message = removeIcon(message);
+
+    return message;
+}
+
+
+function removeAlert(message) {
+    const el = document.createElement("div");
+    el.innerHTML = message;
+
+    // Si on trouve une alert, alors on la retire pour éviter de faire double affichage
+    const alert = el.querySelector('.alert');
+    if (alert) {
+        return alert.innerHTML;
+    } else {
+        return el.innerHTML;
+    }
+}
+
+
+function removeIcon(message) {
+    const el = document.createElement("div");
+    el.innerHTML = message;
+
+    // on masque l'icône /!\ qui fait doublon si on en trouve
+    const fasIcons = el.querySelectorAll('i.fas');
+    fasIcons.forEach(icon => icon.style.display = "none");
+
+    return el.innerHTML;
+}
 
 
 function toast(message, severity) {
@@ -24,41 +67,57 @@ function toast(message, severity) {
         error: 'exclamation-triangle'
     };
 
-    let toastContainer = document.getElementById('unicaen-vue-toast-container');
-    if (!toastContainer) {
-        toastContainer = document.createElement('div');
-        toastContainer.id = 'unicaen-vue-toast-container';
-        toastContainer.classList.add('toast-container', 'position-fixed', 'top-0', 'end-0', 'p-3');
-        document.body.appendChild(toastContainer);
-    }
+    // Crée le bouton de fermeture
+    const closeButton = document.createElement('button');
+    closeButton.classList.add('btn-close', 'btn-close-white', 'h5');
+    closeButton.style.float = 'right';
+    closeButton.setAttribute('data-bs-dismiss', 'toast');
+    closeButton.setAttribute('aria-label', 'Close');
+
+    // Crée l'icône
+    const icon = document.createElement('i');
+    icon.classList.add('icon', 'fas', `fa-${iconClasses[severity]}`);
+    icon.style.float = 'left';
+    icon.style.fontSize = '26pt';
+    icon.style.paddingLeft = '.4rem';
+    icon.style.marginTop = '.4rem';
+    icon.style.paddingRight = '1rem';
+
+    // Crée le corps du toast
+    const body = document.createElement('div');
+    body.classList.add('toast-body');
+    body.innerHTML = prepareMessage(message);
+
+    // Crée le contenu du toast en ajoutant les éléments créés précédemment
+    const content = document.createElement('div');
+    content.appendChild(closeButton);
+    content.appendChild(icon);
+    content.appendChild(body);
 
     // Création de l'élément HTML pour le toast
     const toast = document.createElement('div');
-    toast.classList.add('toast', 'show', 'text-white', bgClasses[severity] ? bgClasses[severity] : 'bg-secondary');
+    toast.classList.add('toast', 'text-white', bgClasses[severity] ? bgClasses[severity] : 'bg-secondary');
     toast.setAttribute('role', 'alert');
     toast.setAttribute('aria-live', 'assertive');
     toast.setAttribute('aria-atomic', 'true');
 
-    if (severity === 'error' && message.length > 500){
+    // On élargit le toast pour ahhicher tout ça...
+    if (severity === 'error' && message.length > 500) {
         toast.setAttribute('style', 'width:700px');
     }
-
-    const toastContent =
-        '<button class="btn-close btn-close-white h5" style="float:right" data-bs-dismiss="toast" aria-label="Close"></button>' +
-        '<i class="icon fas fa-' + iconClasses[severity] + '" style="float: left;font-size: 26pt;padding-left: .4rem;margin-top:.4rem;padding-right: 1rem;"></i>' +
-        '<div class="toast-body">' + message + '  </div>';
-
-    toast.innerHTML = toastContent;
+    toast.appendChild(content);
 
     // Ajout du toast à l'élément du conteneur de toasts
-    toastContainer.appendChild(toast);
+    toastContainer().appendChild(toast);
 
-    // Masquage du toast si ce n'est pas une erreur
-    if (severity !== 'error') {
-        setTimeout(() => {
-            toast.classList.remove('show');
-        }, 5000);
-    }
+    // Création et affichage du toast avec bootstrap
+    const options = {
+        animation: true,
+        delay: 5000,
+        autohide: severity !== 'error'
+    };
+    let bsToast = new bootstrap.Toast(toast, options);
+    bsToast.show();
 }
 
 
diff --git a/js/Client/unicaenVue.js b/js/Client/unicaenVue.js
index 471090325852e3d2c720e94747f22cf081cb5f13..ac1debf3ac43d9bd604ae99de032584b53fe671f 100644
--- a/js/Client/unicaenVue.js
+++ b/js/Client/unicaenVue.js
@@ -1,8 +1,8 @@
-import axios from 'axios';
+import axios from './axios';
 import flashMessenger from './flashMessenger';
 
 const unicaenVue = {
-    axios: axios,
+    axios: axios.uvAxios,
     flashMessenger: flashMessenger,
 
     /**
@@ -31,84 +31,6 @@ const unicaenVue = {
 };
 
 
-/* Tunning d'Axios pour gérer l'interconnexion avec le serveur avec gestion des alertes */
-unicaenVue.axios.interceptors.request.use(config => {
-    if (config.submitter) {
-        let msg = config.msg ? config.msg : 'Action en cours';
-        if (config.popover != undefined) {
-            config.popover.dispose();
-        }
-        config.popover = new bootstrap.Popover(config.submitter, {
-            content: "<div class=\"spinner-border text-primary\" role=\"status\">\n" +
-                "  <span class=\"visually-hidden\">Loading...</span>\n" +
-                "</div> " + msg,
-            html: true,
-            trigger: 'focus'
-        });
-        config.popover.show();
-    }
-    return config;
-});
-
-unicaenVue.axios.interceptors.response.use(response => {
-    response.messages = response.data.messages;
-    response.data = response.data.data;
-    response.hasErrors = response.messages && response.messages.error && response.messages.error.length > 0 ? true : false;
-
-    if (response.config.popover) {
-        var popover = response.config.popover;
-
-        let content = '';
-        for (ns in response.messages) {
-            for (mid in response.messages[ns]) {
-                content += '<div class="alert fade show alert-' + (ns == 'error' ? 'danger' : ns) + '" role="alert">' + response.messages[ns][mid] + '</div>';
-            }
-        }
-
-        // S'il y a un truc à afficher
-        if (content) {
-            popover._config.content = content;
-            popover.setContent();
-            setTimeout(() => {
-                popover.dispose();
-            }, 3000)
-        } else {
-            // la popover est masquée si tout est fini
-            popover.dispose();
-        }
-    }
-    if (response.messages) {
-        flashMessenger.toasts(response.messages);
-    }
-
-    return response;
-}, (error) => {
-    let message = error.response.data;
-
-    if (error.response.status == 403){
-        message = '<h4>403 - Accès interdit</h4><br />Vous n\'êtes pas autorisé(e) à faire cette action.';
-    }else if (error.response.status == 500) {
-        const text = document.createElement("div");
-        text.innerHTML = error.response.data;
-
-        // on masque l'icône /!\ qui fait doublon si on en trouve
-        const fasIcons = text.querySelectorAll('i.fas');
-        fasIcons.forEach(icon => icon.style.display = "none");
-
-        message = text.querySelector('.alert').innerHTML;
-        if (message === undefined){
-            message = error.response.data;
-        }
-    }else{
-        message = error.response.data;
-    }
-
-    flashMessenger.toast(message, 'error');
-});
-
-unicaenVue.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
-
-
 // workaround pour rendre unicaenVue disponible de partout
 window.unicaenVue = unicaenVue;