From de1fd4e0bc10ef583dc089ba5e2ecbc970283d50 Mon Sep 17 00:00:00 2001
From: DESPRES Damien <ddespres@neogeo.fr>
Date: Fri, 8 Oct 2021 17:39:36 +0200
Subject: [PATCH] gestion mode offline

---
 src/main.js                           | 62 ++++++++++++++++-------
 src/store/modules/feature.js          | 54 +++++++++++++++++++-
 src/views/feature/Feature_detail.vue  |  2 +-
 src/views/feature/Feature_offline.vue | 41 +++++++++++++++
 src/views/project/Project_detail.vue  | 73 ++++++++++++++++++++++++++-
 5 files changed, 209 insertions(+), 23 deletions(-)
 create mode 100644 src/views/feature/Feature_offline.vue

diff --git a/src/main.js b/src/main.js
index 22fdd2b3..99f5a839 100644
--- a/src/main.js
+++ b/src/main.js
@@ -10,29 +10,53 @@ import 'leaflet-draw/dist/leaflet.draw.css';
 import '@/assets/resources/leaflet-control-geocoder-1.13.0/Control.Geocoder.css';
 Vue.config.productionTip = false
 
+// gestion mise à jour du serviceWorker et du precache
+var refreshing=false;
+navigator.serviceWorker.addEventListener('controllerchange', () => {
+  // We'll also need to add 'refreshing' to our data originally set to false.
+  if (refreshing) return
+  refreshing = true
+  // Here the actual reload of the page occurs
+  window.location.reload()
+})
+
+
+let onConfigLoaded = function(config){
+  store.commit("SET_CONFIG", config);
+  window.proxy_url=config.VUE_APP_DJANGO_API_BASE+"proxy/";
+  axios.all([store.dispatch("USER_INFO"),
+    store.dispatch("GET_ALL_PROJECTS"),
+    store.dispatch("GET_STATIC_PAGES"),
+    store.dispatch("GET_USER_LEVEL_PROJECTS"),
+    store.dispatch("map/GET_LAYERS"),
+    store.dispatch("GET_USER_LEVEL_PERMISSIONS"),
+  ]).then(axios.spread(function () {
+    new Vue({
+      router,
+      store,
+      render: h => h(App)
+    }).$mount('#app')
+  }));
+
+}
 
 axios.get("/config/config.json")
+  .catch((error)=>{
+    console.log(error);
+    console.log("try to get From Localstorage");
+    let conf=localStorage.getItem("geontrib_conf");
+    if(conf){
+      onConfigLoaded(JSON.parse(conf))
+    }
+  })
   .then((response) => {
     if (response && response.status === 200) {
-            store.commit("SET_CONFIG", response.data);
-            window.proxy_url=response.data.VUE_APP_DJANGO_API_BASE+"proxy/"
-            axios.all([store.dispatch("USER_INFO"),
-              store.dispatch("GET_ALL_PROJECTS"),
-              store.dispatch("GET_STATIC_PAGES"),
-              store.dispatch("GET_USER_LEVEL_PROJECTS"),
-              store.dispatch("map/GET_LAYERS"),
-              store.dispatch("GET_USER_LEVEL_PERMISSIONS"),
-            ]).then(axios.spread(function () {
-              new Vue({
-                router,
-                store,
-                render: h => h(App)
-              }).$mount('#app')
-            }))
-          }
-        })
-        .catch((error) => {
-          throw error;
+      localStorage.setItem("geontrib_conf",JSON.stringify(response.data));
+      onConfigLoaded(response.data)
+    }
+  })
+  .catch((error) => {
+    throw error;
   });
 
 
diff --git a/src/store/modules/feature.js b/src/store/modules/feature.js
index 2d83107e..a239cada 100644
--- a/src/store/modules/feature.js
+++ b/src/store/modules/feature.js
@@ -132,7 +132,32 @@ const feature = {
             }
           })
           .catch((error) => {
-            throw error;
+            if(error.message=="Network Error" ||window.navigator.onLine==false){
+              let arraysOffline=[];
+              let localStorageArray=localStorage.getItem("geocontrib_offline");
+              if(localStorageArray){
+                arraysOffline=JSON.parse(localStorageArray);
+              }
+              let updateMsg={
+                project:rootState.project_slug,
+                type:'put',
+                featureId:state.form.feature_id,
+                geojson:geojson
+              };
+              arraysOffline.push(updateMsg);
+              localStorage.setItem("geocontrib_offline",JSON.stringify(arraysOffline));
+              router.push({
+                name: "offline-signalement",
+                params: {
+                  slug_type_signal: rootState.feature_type.current_feature_type_slug
+                },
+              });
+
+            }
+            else{
+              console.log(error)
+              throw error;
+            }
           });
       } else {
         axios
@@ -147,7 +172,32 @@ const feature = {
             }
           })
           .catch((error) => {
-            throw error;
+            if(error.message=="Network Error" ||window.navigator.onLine==false){
+              let arraysOffline=[];
+              let localStorageArray=localStorage.getItem("geocontrib_offline");
+              if(localStorageArray){
+                arraysOffline=JSON.parse(localStorageArray);
+              }
+              let updateMsg={
+                project:rootState.project_slug,
+                type:'post',
+                geojson:geojson
+              };
+              arraysOffline.push(updateMsg);
+              localStorage.setItem("geocontrib_offline",JSON.stringify(arraysOffline));
+              router.push({
+                name: "offline-signalement",
+                params: {
+                  slug_type_signal: rootState.feature_type.current_feature_type_slug
+                },
+              });
+
+            }
+            else{
+              console.log(error)
+              throw error;
+            }
+            
           });
       }
     },
diff --git a/src/views/feature/Feature_detail.vue b/src/views/feature/Feature_detail.vue
index 6e8b2789..13a143f5 100644
--- a/src/views/feature/Feature_detail.vue
+++ b/src/views/feature/Feature_detail.vue
@@ -537,7 +537,7 @@ export default {
       mapUtil.getMap().doubleClickZoom.disable();
       mapUtil.getMap().scrollWheelZoom.disable();
       var currentFeatureId = this.$route.params.slug_signal;
-      const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features/${currentFeatureId}/?output=geojson`;
+      const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features/${currentFeatureId}/?output=geojson&project__slug=${this.$route.params.slug}`;
       axios
         .get(url)
         .then((response) => {
diff --git a/src/views/feature/Feature_offline.vue b/src/views/feature/Feature_offline.vue
new file mode 100644
index 00000000..fb8a89bd
--- /dev/null
+++ b/src/views/feature/Feature_offline.vue
@@ -0,0 +1,41 @@
+<template>
+  <div v-frag>
+    Erreur Réseau lors de l'envoi du signalement. Votre signalement devra être envoyé au serveur quand vous aurez de nouveau accès à internet.
+    Veuillez à ce moment là cliquer sur Envoyer sur la page principale du projet 
+    <router-link
+            :to="{
+              name: 'project_detail',
+              params: { slug: $route.params.slug },
+            }"
+            class="header"
+            >Retour au projet</router-link
+          >
+  </div>
+</template>
+
+<script>
+import frag from "vue-frag";
+
+export default {
+  name: "Feature_offline",
+
+  directives: {
+    frag,
+  },
+
+  data() {
+    return {
+    };
+  },
+
+  computed: {
+  },
+  methods: {
+    
+  }
+};
+</script>
+
+<style>
+
+</style>
\ No newline at end of file
diff --git a/src/views/project/Project_detail.vue b/src/views/project/Project_detail.vue
index 495d0d8e..af796368 100644
--- a/src/views/project/Project_detail.vue
+++ b/src/views/project/Project_detail.vue
@@ -52,6 +52,16 @@
           <h1 class="ui header">
             <div class="content">
               {{ project.title }}
+              <div v-if="arraysOffline.length>0">{{arraysOffline.length}} modifications en attente
+                <button
+                :disabled="isOffline()"
+                @click="sendOfflineFeatures()"
+                class="ui fluid teal icon button"
+              >
+                <i class="upload icon"></i> Envoyer au serveur
+              </button>
+
+              </div>
               <div class="ui icon right floated compact buttons">
                 <a
                   v-if="permissions && permissions.can_view_project"
@@ -485,6 +495,7 @@ export default {
   data() {
     return {
       infoMessage: "",
+      arraysOffline: [],
       geojsonImport: [],
       fileToImport: { name: "", size: 0 },
       slug: this.$route.params.slug,
@@ -512,7 +523,65 @@ export default {
     refreshId() {
       return "?ver=" + Math.random();
     },
-
+    isOffline(){
+      return navigator.onLine==false;
+    },
+    checkForOfflineFeature(){
+      let arraysOffline=[];
+      let localStorageArray=localStorage.getItem("geocontrib_offline");
+      if(localStorageArray){
+        arraysOffline=JSON.parse(localStorageArray);
+        this.arraysOffline=arraysOffline.filter(x=>x.project==this.project.slug);
+      }
+    },
+    sendOfflineFeatures(){
+      var promises = [];
+      this.arraysOffline.forEach((feature, index, object)=>{
+        console.log(feature);
+        if(feature.type=='post') {
+          promises.push(
+          axios
+          .post(`${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features/`, feature.geojson)
+          .then((response) => {
+            console.log(response)
+            if (response.status === 201 && response.data) {
+              object.splice(index, 1);
+            }
+          })
+          .catch((error) => {
+            console.log(error);
+          }));
+        }
+        else if(feature.type=='put') {
+          promises.push(
+          axios
+          .put(`${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}features/${feature.featureId}`, feature.geojson)
+          .then((response) => {
+            console.log(response)
+            if (response.status === 200 && response.data) {
+              object.splice(index, 1);
+            }
+          })
+          .catch((error) => {
+            console.log(error);
+          }));
+        }
+      });
+      Promise.all(promises).then(() => 
+          this.updateLocalStorage()
+      );
+      
+    },
+    updateLocalStorage(){
+      let arraysOffline=[];
+      let localStorageArray=localStorage.getItem("geocontrib_offline");
+      if(localStorageArray){
+        arraysOffline=JSON.parse(localStorageArray);
+      }
+      let arraysOfflineOtherProject = arraysOffline.filter(x=>x.project!=this.project.slug);
+      arraysOffline=arraysOfflineOtherProject.concat(this.arraysOffline);
+      localStorage.setItem("geocontrib_offline",JSON.stringify(arraysOffline));
+    },
     toNewFeatureType() {
       this.$router.push({
         name: "ajouter-type-signalement",
@@ -596,6 +665,8 @@ export default {
         .catch((error) => {
           throw error;
         });
+      this.checkForOfflineFeature();
+
     }
 
     if (this.message) {
-- 
GitLab