changeset 1296:99c039e86624

replaced manual store cleanup on logout with central store reset The store files now provide a init method with which the store can be resetted on logout. This is reasonable because missing store cleanups on logout caused bugs. Furthermore the localStorage.clear() was replaced specific removal of values since currently there are also saved cross profiles which should be persistent. The initialization of the cut/line/polygon tool was moved from their respective buttons to the map store right after saving the ol map object in the store. Before that change the map object was not present sometimes when trying to initiate those tools.
author Markus Kottlaender <markus@intevation.de>
date Thu, 22 Nov 2018 17:00:26 +0100
parents cf041cf30418
children 1c0c9190fcf2 2738a6ae9ad8
files client/src/components/Sidebar.vue client/src/components/map/Maplayer.vue client/src/components/map/toolbar/Cuttool.vue client/src/components/map/toolbar/Linetool.vue client/src/components/map/toolbar/Polygontool.vue client/src/router.js client/src/store/application.js client/src/store/bottlenecks.js client/src/store/fairway.js client/src/store/imports.js client/src/store/index.js client/src/store/map.js client/src/store/user.js client/src/store/usermanagement.js
diffstat 14 files changed, 190 insertions(+), 152 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Sidebar.vue	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/components/Sidebar.vue	Thu Nov 22 17:00:26 2018 +0100
@@ -102,10 +102,8 @@
   },
   methods: {
     logoff() {
+      this.$store.commit("reset");
       this.$store.commit("user/clearAuth");
-      this.$store.commit("application/showSidebar", false);
-      this.$store.commit("application/showSplitscreen", false);
-      this.$store.dispatch("fairwayprofile/clearSelection");
       this.$router.push("/login");
     },
     toggleContextBox(context) {
--- a/client/src/components/map/Maplayer.vue	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/components/map/Maplayer.vue	Thu Nov 22 17:00:26 2018 +0100
@@ -241,7 +241,7 @@
     split() {
       const map = this.openLayersMap;
       this.$nextTick(() => {
-        map.updateSize();
+        map && map.updateSize();
       });
     },
     selectedSurvey(newSelectedSurvey) {
@@ -266,7 +266,7 @@
         projection: this.projection
       })
     });
-    this.$store.commit("map/setOpenLayersMap", map);
+    this.$store.dispatch("map/openLayersMap", map);
 
     // TODO make display of layers more dynamic, e.g. from a list
 
--- a/client/src/components/map/toolbar/Cuttool.vue	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/components/map/toolbar/Cuttool.vue	Thu Nov 22 17:00:26 2018 +0100
@@ -18,15 +18,12 @@
  * Author(s):
  * Markus Kottländer <markus.kottlaender@intevation.de>
  */
-import { mapState, mapGetters } from "vuex";
-import Draw from "ol/interaction/Draw.js";
-import { Stroke, Style, Circle, Fill } from "ol/style.js";
+import { mapState } from "vuex";
 
 export default {
   name: "cuttool",
   computed: {
-    ...mapGetters("map", ["getLayerByName"]),
-    ...mapState("map", ["lineTool", "polygonTool", "cutTool", "openLayersMap"]),
+    ...mapState("map", ["lineTool", "polygonTool", "cutTool"]),
     ...mapState("bottlenecks", ["selectedSurvey"])
   },
   methods: {
@@ -37,38 +34,6 @@
         this.polygonTool.setActive(false);
         this.$store.commit("map/setCurrentMeasurement", null);
       }
-    },
-    cutEnd(event) {
-      this.$store.dispatch("fairwayprofile/cut", event.feature);
-    }
-  },
-  created() {
-    if (!this.cutTool) {
-      const cutVectorSrc = this.getLayerByName("Cut Tool").data.getSource();
-      const cutTool = new Draw({
-        source: cutVectorSrc,
-        type: "LineString",
-        maxPoints: 2,
-        style: new Style({
-          stroke: new Stroke({
-            color: "#444",
-            width: 2,
-            lineDash: [7, 7]
-          }),
-          image: new Circle({
-            fill: new Fill({ color: "#333" }),
-            stroke: new Stroke({ color: "#fff", width: 1.5 }),
-            radius: 6
-          })
-        })
-      });
-      cutTool.setActive(false);
-      cutTool.on("drawstart", () => {
-        cutVectorSrc.clear();
-      });
-      cutTool.on("drawend", this.cutEnd);
-      this.$store.commit("map/cutTool", cutTool);
-      this.openLayersMap.addInteraction(cutTool);
     }
   }
 };
--- a/client/src/components/map/toolbar/Linetool.vue	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/components/map/toolbar/Linetool.vue	Thu Nov 22 17:00:26 2018 +0100
@@ -19,14 +19,12 @@
  * Markus Kottländer <markus.kottlaender@intevation.de>
  */
 import { mapState, mapGetters } from "vuex";
-import { getLength } from "ol/sphere.js";
-import Draw from "ol/interaction/Draw.js";
 
 export default {
   name: "linetool",
   computed: {
     ...mapGetters("map", ["getLayerByName"]),
-    ...mapState("map", ["lineTool", "polygonTool", "cutTool", "openLayersMap"])
+    ...mapState("map", ["lineTool", "polygonTool", "cutTool"])
   },
   methods: {
     toggleLineTool() {
@@ -37,33 +35,6 @@
       this.getLayerByName("Draw Tool")
         .data.getSource()
         .clear();
-    },
-    lineEnd(event) {
-      const length = getLength(event.feature.getGeometry());
-      this.$store.commit("map/setCurrentMeasurement", {
-        quantity: "Length",
-        unitSymbol: "m",
-        value: Math.round(length * 10) / 10
-      });
-      this.$store.commit("application/showIdentify", true);
-    }
-  },
-  created() {
-    if (!this.lineTool) {
-      const drawVectorSrc = this.getLayerByName("Draw Tool").data.getSource();
-      const lineTool = new Draw({
-        source: drawVectorSrc,
-        type: "LineString",
-        maxPoints: 2
-      });
-      lineTool.setActive(false);
-      lineTool.on("drawstart", () => {
-        drawVectorSrc.clear();
-        this.$store.commit("map/setCurrentMeasurement", null);
-      });
-      lineTool.on("drawend", this.lineEnd);
-      this.$store.commit("map/lineTool", lineTool);
-      this.openLayersMap.addInteraction(lineTool);
     }
   }
 };
--- a/client/src/components/map/toolbar/Polygontool.vue	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/components/map/toolbar/Polygontool.vue	Thu Nov 22 17:00:26 2018 +0100
@@ -19,14 +19,12 @@
  * Markus Kottländer <markus.kottlaender@intevation.de>
  */
 import { mapState, mapGetters } from "vuex";
-import { getArea } from "ol/sphere.js";
-import Draw from "ol/interaction/Draw.js";
 
 export default {
   name: "polygontool",
   computed: {
     ...mapGetters("map", ["getLayerByName"]),
-    ...mapState("map", ["lineTool", "polygonTool", "cutTool", "openLayersMap"])
+    ...mapState("map", ["lineTool", "polygonTool", "cutTool"])
   },
   methods: {
     togglePolygonTool() {
@@ -37,36 +35,6 @@
       this.getLayerByName("Draw Tool")
         .data.getSource()
         .clear();
-    },
-    polygonEnd(event) {
-      const areaSize = getArea(event.feature.getGeometry());
-      this.$store.commit("map/setCurrentMeasurement", {
-        quantity: "Area",
-        unitSymbol: areaSize > 100000 ? "km²" : "m²",
-        value:
-          areaSize > 100000
-            ? Math.round(areaSize / 1000) / 1000 // convert into 1 km² == 1000*1000 m² and round to 1000 m²
-            : Math.round(areaSize)
-      });
-      this.$store.commit("application/showIdentify", true);
-    }
-  },
-  created() {
-    if (!this.polygonTool) {
-      const drawVectorSrc = this.getLayerByName("Draw Tool").data.getSource();
-      const polygonTool = new Draw({
-        source: drawVectorSrc,
-        type: "Polygon",
-        maxPoints: 50
-      });
-      polygonTool.setActive(false);
-      polygonTool.on("drawstart", () => {
-        drawVectorSrc.clear();
-        this.$store.commit("map/setCurrentMeasurement", null);
-      });
-      polygonTool.on("drawend", this.polygonEnd);
-      this.$store.commit("map/polygonTool", polygonTool);
-      this.openLayersMap.addInteraction(polygonTool);
     }
   }
 };
--- a/client/src/router.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/router.js	Thu Nov 22 17:00:26 2018 +0100
@@ -117,6 +117,7 @@
           store.commit("user/setRoles", localStorage.getItem("roles"));
           store.commit("user/setIsAuthenticate", true);
         } else {
+          store.commit("reset");
           store.commit("user/clearAuth");
         }
         next();
--- a/client/src/store/application.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/store/application.js	Thu Nov 22 17:00:26 2018 +0100
@@ -16,9 +16,9 @@
 
 import { version } from "../../package.json";
 
-export default {
-  namespaced: true,
-  state: {
+// initial state
+const init = () => {
+  return {
     appTitle: process.env.VUE_APP_TITLE,
     secondaryLogo: process.env.VUE_APP_SECONDARY_LOGO_URL,
     showSidebar: false,
@@ -35,7 +35,13 @@
     countries: ["AT", "SK", "HU", "HR", "RS", "BiH", "BG", "RO", "UA"],
     searchQuery: "",
     version
-  },
+  };
+};
+
+export default {
+  init,
+  namespaced: true,
+  state: init(),
   getters: {
     versionStr: state => {
       // version number from package.json
--- a/client/src/store/bottlenecks.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/store/bottlenecks.js	Thu Nov 22 17:00:26 2018 +0100
@@ -16,14 +16,20 @@
 import { WFS } from "ol/format.js";
 import { displayError } from "../lib/errors.js";
 
-export default {
-  namespaced: true,
-  state: {
+// initial state
+const init = () => {
+  return {
     bottlenecks: [],
     selectedBottleneck: null,
     surveys: [],
     selectedSurvey: null
-  },
+  };
+};
+
+export default {
+  init,
+  namespaced: true,
+  state: init(),
   mutations: {
     setBottlenecks: (state, bottlenecks) => {
       state.bottlenecks = bottlenecks;
--- a/client/src/store/fairway.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/store/fairway.js	Thu Nov 22 17:00:26 2018 +0100
@@ -25,9 +25,9 @@
 const DEMOLEVEL = 149.345;
 const DEMODATA = 2.5;
 
-export default {
-  namespaced: true,
-  state: {
+// initial state
+const init = () => {
+  return {
     additionalSurvey: "",
     totalLength: 0,
     minAlt: 0,
@@ -39,7 +39,13 @@
     startPoint: null,
     endPoint: null,
     previousCuts: []
-  },
+  };
+};
+
+export default {
+  init,
+  namespaced: true,
+  state: init(),
   getters: {
     length: state => {
       return state.totalLength;
--- a/client/src/store/imports.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/store/imports.js	Thu Nov 22 17:00:26 2018 +0100
@@ -15,11 +15,17 @@
 
 import { HTTP } from "../lib/http";
 
-const Imports = {
+// initial state
+const init = () => {
+  return {
+    imports: {}
+  };
+};
+
+export default {
+  init,
   namespaced: true,
-  state: {
-    imports: {}
-  },
+  state: init(),
   mutations: {
     setImports: (state, imports) => {
       state.imports = imports;
@@ -42,5 +48,3 @@
     }
   }
 };
-
-export default Imports;
--- a/client/src/store/index.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/store/index.js	Thu Nov 22 17:00:26 2018 +0100
@@ -27,6 +27,19 @@
 Vue.use(Vuex);
 
 export default new Vuex.Store({
+  mutations: {
+    reset() {
+      this.replaceState({
+        application: application.init(),
+        fairwayprofile: fairwayprofile.init(),
+        imports: imports.init(),
+        bottlenecks: bottlenecks.init(),
+        map: map.init(),
+        user: user.init(),
+        usermanagement: usermanagement.init()
+      });
+    }
+  },
   modules: {
     application,
     fairwayprofile,
--- a/client/src/store/map.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/store/map.js	Thu Nov 22 17:00:26 2018 +0100
@@ -18,23 +18,18 @@
 import TileWMS from "ol/source/TileWMS.js";
 import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer.js";
 import OSM from "ol/source/OSM";
-import {
-  Icon,
-  Stroke,
-  Style,
-  Fill,
-  Text,
-  Circle as CircleStyle
-} from "ol/style.js";
+import Draw from "ol/interaction/Draw.js";
+import { Icon, Stroke, Style, Fill, Text, Circle } from "ol/style.js";
 import VectorSource from "ol/source/Vector.js";
 import Point from "ol/geom/Point.js";
 import { bbox as bboxStrategy } from "ol/loadingstrategy";
 import { HTTP } from "../lib/http";
 import { fromLonLat } from "ol/proj";
+import { getLength, getArea } from "ol/sphere.js";
 
-export default {
-  namespaced: true,
-  state: {
+// initial state
+const init = () => {
+  return {
     openLayersMap: null,
     identifiedFeatures: [], // map features identified by clicking on the map
     currentMeasurement: null, // distance or area from line-/polygon-/cutTool
@@ -208,7 +203,7 @@
           style: function(feature, resolution) {
             if (resolution < 10) {
               var s = new Style({
-                image: new CircleStyle({
+                image: new Circle({
                   radius: 5,
                   fill: new Fill({ color: "rgba(255, 0, 0, 0.1)" }),
                   stroke: new Stroke({ color: "blue", width: 1 })
@@ -333,13 +328,22 @@
         showInLegend: false
       }
     ]
-  },
+  };
+};
+
+export default {
+  init,
+  namespaced: true,
+  state: init(),
   getters: {
     layersForLegend: state => {
       return state.layers.filter(layer => layer.showInLegend);
     },
     getLayerByName: state => name => {
       return state.layers.find(layer => layer.name === name);
+    },
+    getVSourceByName: (state, getters) => name => {
+      return getters.getLayerByName(name).data.getSource();
     }
   },
   mutations: {
@@ -347,7 +351,7 @@
       state.layers[layer].isVisible = !state.layers[layer].isVisible;
       state.layers[layer].data.setVisible(state.layers[layer].isVisible);
     },
-    setOpenLayersMap: (state, map) => {
+    openLayersMap: (state, map) => {
       state.openLayersMap = map;
     },
     setIdentifiedFeatures: (state, identifiedFeatures) => {
@@ -374,5 +378,90 @@
         duration: 700
       });
     }
+  },
+  actions: {
+    openLayersMap({ commit, dispatch, getters }, map) {
+      const drawVectorSrc = getters.getVSourceByName("Draw Tool");
+      const cutVectorSrc = getters.getVSourceByName("Cut Tool");
+
+      // init line tool
+      const lineTool = new Draw({
+        source: drawVectorSrc,
+        type: "LineString",
+        maxPoints: 2
+      });
+      lineTool.setActive(false);
+      lineTool.on("drawstart", () => {
+        drawVectorSrc.clear();
+        commit("setCurrentMeasurement", null);
+      });
+      lineTool.on("drawend", event => {
+        commit("setCurrentMeasurement", {
+          quantity: "Length",
+          unitSymbol: "m",
+          value: Math.round(getLength(event.feature.getGeometry()) * 10) / 10
+        });
+        commit("application/showIdentify", true, { root: true });
+      });
+
+      // init polygon tool
+      const polygonTool = new Draw({
+        source: drawVectorSrc,
+        type: "Polygon",
+        maxPoints: 50
+      });
+      polygonTool.setActive(false);
+      polygonTool.on("drawstart", () => {
+        drawVectorSrc.clear();
+        commit("setCurrentMeasurement", null);
+      });
+      polygonTool.on("drawend", event => {
+        const areaSize = getArea(event.feature.getGeometry());
+        commit("setCurrentMeasurement", {
+          quantity: "Area",
+          unitSymbol: areaSize > 100000 ? "km²" : "m²",
+          value:
+            areaSize > 100000
+              ? Math.round(areaSize / 1000) / 1000 // convert into 1 km² == 1000*1000 m² and round to 1000 m²
+              : Math.round(areaSize)
+        });
+        commit("application/showIdentify", true, { root: true });
+      });
+
+      // init cut tool
+      const cutTool = new Draw({
+        source: cutVectorSrc,
+        type: "LineString",
+        maxPoints: 2,
+        style: new Style({
+          stroke: new Stroke({
+            color: "#444",
+            width: 2,
+            lineDash: [7, 7]
+          }),
+          image: new Circle({
+            fill: new Fill({ color: "#333" }),
+            stroke: new Stroke({ color: "#fff", width: 1.5 }),
+            radius: 6
+          })
+        })
+      });
+      cutTool.setActive(false);
+      cutTool.on("drawstart", () => {
+        cutVectorSrc.clear();
+      });
+      cutTool.on("drawend", event => {
+        dispatch("fairwayprofile/cut", event.feature, { root: true });
+      });
+
+      map.addInteraction(lineTool);
+      map.addInteraction(cutTool);
+      map.addInteraction(polygonTool);
+
+      commit("lineTool", lineTool);
+      commit("polygonTool", polygonTool);
+      commit("cutTool", cutTool);
+      commit("openLayersMap", map);
+    }
   }
 };
--- a/client/src/store/user.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/store/user.js	Thu Nov 22 17:00:26 2018 +0100
@@ -15,14 +15,19 @@
 
 import { HTTP } from "../lib/http";
 
-export default {
-  namespaced: true,
-  state: {
+const init = () => {
+  return {
     isAuthenticated: false,
     expires: null,
     roles: [],
     user: ""
-  },
+  };
+};
+
+export default {
+  init,
+  namespaced: true,
+  state: init(),
   getters: {
     isWaterwayAdmin: state => {
       return state.roles.includes("waterway_admin");
@@ -43,12 +48,11 @@
       state.user = user;
       state.authenticated = true;
     },
-    clearAuth: state => {
-      state.authenticated = false;
-      state.expires = null;
-      state.roles = [];
-      state.user = "";
-      localStorage.clear();
+    clearAuth: () => {
+      localStorage.removeItem("expires");
+      localStorage.removeItem("roles");
+      localStorage.removeItem("token");
+      localStorage.removeItem("user");
     },
     setUser: (state, name) => {
       state.user = name;
@@ -73,6 +77,7 @@
             resolve(response);
           })
           .catch(error => {
+            commit("reset", null, { root: true });
             commit("clearAuth");
             reject(error);
           });
--- a/client/src/store/usermanagement.js	Thu Nov 22 16:54:39 2018 +0100
+++ b/client/src/store/usermanagement.js	Thu Nov 22 17:00:26 2018 +0100
@@ -15,6 +15,15 @@
 
 import { HTTP } from "../lib/http";
 
+// initial state
+const init = () => {
+  return {
+    users: null,
+    currentUser: null,
+    userDetailsVisible: false
+  };
+};
+
 const newUser = () => {
   return {
     user: "",
@@ -28,12 +37,9 @@
 };
 
 export default {
+  init,
   namespaced: true,
-  state: {
-    users: null,
-    currentUser: null,
-    userDetailsVisible: false
-  },
+  state: init(),
   getters: {
     isUserDetailsVisible: state => {
       return state.userDetailsVisible;