changeset 3207:ba7bc3740fb3

client: renamed store modules to better reflect their context
author Markus Kottlaender <markus@intevation.de>
date Wed, 08 May 2019 17:43:18 +0200
parents dffcf1cc8a8b
children 3bba82bcb6a6
files client/src/components/Statistics.vue client/src/components/map/MapPopup.vue client/src/store/diagram.js client/src/store/fairway.js client/src/store/fairwayavailability.js client/src/store/fairwayprofile.js client/src/store/index.js client/src/store/map.js
diffstat 8 files changed, 454 insertions(+), 447 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Statistics.vue	Wed May 08 17:29:50 2019 +0200
+++ b/client/src/components/Statistics.vue	Wed May 08 17:43:18 2019 +0200
@@ -149,7 +149,7 @@
     openFairwaydepth() {
       this.loading = true;
       this.$store
-        .dispatch("diagram/loadAvailableFairwayDepth", {
+        .dispatch("fairwayavailability/loadAvailableFairwayDepth", {
           feature: this.selectedFairwayAvailabilityFeature,
           from: this.from,
           to: this.to,
@@ -201,12 +201,15 @@
       const bn = this.bottlenecksList.filter(
         x => x.properties.name === this.selectedBottleneck
       )[0];
-      this.$store.commit("diagram/setSelectedFairwayAvailability", bn);
+      this.$store.commit(
+        "fairwayavailability/setSelectedFairwayAvailability",
+        bn
+      );
     }
   },
   computed: {
     ...mapState("application", ["showStatistics", "paneSetup", "showProfiles"]),
-    ...mapState("diagram", [
+    ...mapState("fairwayavailability", [
       "selectedFairwayAvailabilityFeature",
       "from",
       "to",
@@ -226,10 +229,10 @@
     },
     type: {
       get() {
-        return this.$store.state.diagram.type;
+        return this.$store.state.fairwayavailability.type;
       },
       set(type) {
-        this.$store.commit("diagram/type", type);
+        this.$store.commit("fairwayavailability/type", type);
       }
     },
     los: {
@@ -237,7 +240,7 @@
         return this.LOS;
       },
       set(value) {
-        this.$store.commit("diagram/setLOS", value);
+        this.$store.commit("fairwayavailability/setLOS", value);
       }
     },
     fromDate: {
@@ -245,7 +248,7 @@
         return this.from;
       },
       set(value) {
-        this.$store.commit("diagram/setFrom", value);
+        this.$store.commit("fairwayavailability/setFrom", value);
       }
     },
     toDate: {
@@ -253,7 +256,7 @@
         return this.to;
       },
       set(value) {
-        this.$store.commit("diagram/setTo", value);
+        this.$store.commit("fairwayavailability/setTo", value);
       }
     },
     selectedFrequency: {
@@ -261,7 +264,7 @@
         return this.frequency;
       },
       set(value) {
-        this.$store.commit("diagram/setFrequency", value);
+        this.$store.commit("fairwayavailability/setFrequency", value);
       }
     },
     selectedEntry: {
@@ -269,7 +272,10 @@
         return this.selectedFairwayAvailabilityFeature;
       },
       set(feature) {
-        this.$store.commit("diagram/setSelectedFairwayAvailability", feature);
+        this.$store.commit(
+          "fairwayavailability/setSelectedFairwayAvailability",
+          feature
+        );
       }
     },
     entries() {
@@ -297,7 +303,10 @@
       if (this.type === this.$options.BOTTLENECKS && this.selectedBottleneck) {
         this.setSelectedBottleneck();
       } else {
-        this.$store.commit("diagram/setSelectedFairwayAvailability", null);
+        this.$store.commit(
+          "fairwayavailability/setSelectedFairwayAvailability",
+          null
+        );
       }
       this.openLayersMap()
         .getLayer("STRETCHES")
--- a/client/src/components/map/MapPopup.vue	Wed May 08 17:29:50 2019 +0200
+++ b/client/src/components/map/MapPopup.vue	Wed May 08 17:43:18 2019 +0200
@@ -203,7 +203,7 @@
       this.close();
     },
     openFairwayAvailabilityForBottleneck(bottleneck) {
-      this.$store.commit("diagram/type", "bottlenecks");
+      this.$store.commit("fairwayavailability/type", "bottlenecks");
       this.$store.dispatch(
         "bottlenecks/setSelectedBottleneck",
         bottleneck.get("objnam")
@@ -222,7 +222,7 @@
       this.openFairwayAvailability();
     },
     openFairwayAvailabilityForStretch(stretch) {
-      this.$store.commit("diagram/type", "stretches");
+      this.$store.commit("fairwayavailability/type", "stretches");
       this.$store.commit("imports/selectedStretchId", stretch.getId());
       this.$store.dispatch("map/moveToFeauture", {
         feature: stretch,
--- a/client/src/store/diagram.js	Wed May 08 17:29:50 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/* This is Free Software under GNU Affero General Public License v >= 3.0
- * without warranty, see README.md and license for details.
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- * License-Filename: LICENSES/AGPL-3.0.txt
- *
- * Copyright (C) 2018 by via donau
- *   – Österreichische Wasserstraßen-Gesellschaft mbH
- * Software engineering by Intevation GmbH
- *
- * Author(s):
- * Thomas Junk <thomas.junk@intevation.de>
- */
-
-import { HTTP } from "@/lib/http";
-
-const init = () => {
-  return {
-    type: "bottlenecks",
-    selectedFairwayAvailabilityFeature: null,
-    from: null,
-    to: null,
-    frequency: null,
-    fwData: null,
-    legend: null,
-    LOS: null
-  };
-};
-
-const diagram = {
-  init,
-  namespaced: true,
-  state: init(),
-  mutations: {
-    type: (state, type) => {
-      state.type = type;
-    },
-    setLOS: (state, LOS) => {
-      state.LOS = LOS;
-    },
-    setFrequency: (state, frequency) => {
-      state.frequency = frequency;
-    },
-    setFrom: (state, from) => {
-      state.from = from;
-    },
-    setTo: (state, to) => {
-      state.to = to;
-    },
-    setSelectedFairwayAvailability: (state, feature) => {
-      state.selectedFairwayAvailabilityFeature = feature;
-    },
-    setFwData: (state, fwData) => {
-      state.fwData = fwData;
-    },
-    setLegend: (state, header) => {
-      const headerEntries = header.split(",");
-      headerEntries.shift();
-      state.legend = headerEntries.map(x => {
-        return x.split("#")[1].trim();
-      });
-    }
-  },
-  actions: {
-    loadAvailableFairwayDepth: ({ commit }, options) => {
-      return new Promise((resolve, reject) => {
-        const { feature, from, to, frequency, LOS } = options;
-        const start = encodeURIComponent("00:00:00+00:00");
-        const end = encodeURIComponent("23:59:59+00:00");
-        const URL = `/data/bottleneck/fairway-depth/${encodeURIComponent(
-          feature.properties.name
-        )}?from=${from}T${start}&to=${to}T${end}&mode=${frequency}&los=${LOS}`;
-        HTTP.get(URL, {
-          headers: { "X-Gemma-Auth": localStorage.getItem("token") }
-        })
-          .then(response => {
-            const { data } = response;
-            const csv = data.split("\n");
-            commit("setLegend", csv.shift());
-            let transformed = csv.map(e => {
-              const result = e.split(",");
-              const label = result.shift();
-              const ldc = result.shift();
-              const highestLevel = result.pop();
-              return {
-                label: label,
-                ldc: ldc,
-                highestLevel: highestLevel,
-                lowerLevels: result
-              };
-            });
-            commit("setFwData", transformed);
-            resolve(response);
-          })
-          .catch(error => {
-            reject(error);
-          });
-      });
-    }
-  }
-};
-
-export { diagram };
--- a/client/src/store/fairway.js	Wed May 08 17:29:50 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,326 +0,0 @@
-/* This is Free Software under GNU Affero General Public License v >= 3.0
- * without warranty, see README.md and license for details.
- *
- * SPDX-License-Identifier: AGPL-3.0-or-later
- * License-Filename: LICENSES/AGPL-3.0.txt
- *
- * Copyright (C) 2018 by via donau
- *   – Österreichische Wasserstraßen-Gesellschaft mbH
- * Software engineering by Intevation GmbH
- *
- * Author(s):
- * Thomas Junk <thomas.junk@intevation.de>
- * Markus Kottländer <markuks.kottlaender@intevation.de>
- */
-import Vue from "vue";
-import { HTTP } from "@/lib/http";
-import { prepareProfile } from "@/lib/geo";
-import LineString from "ol/geom/LineString";
-import { generateFeatureRequest } from "@/lib/geo";
-import { getLength } from "ol/sphere";
-import { displayError } from "@/lib/errors";
-import { featureToFairwayCoordinates } from "@/lib/geo";
-
-// initial state
-const init = () => {
-  return {
-    additionalSurvey: null,
-    minAlt: 0,
-    maxAlt: 0,
-    currentProfile: {},
-    referenceWaterLevel: null,
-    waterLevels: {},
-    selectedWaterLevel: "",
-    fairwayData: [],
-    startPoint: null,
-    endPoint: null,
-    previousCuts: [],
-    profileLoading: false,
-    selectedCut: null,
-    differencesLoading: false
-  };
-};
-
-export default {
-  init,
-  namespaced: true,
-  state: init(),
-  getters: {
-    totalLength: state => {
-      const keys = Object.keys(state.currentProfile);
-      return keys.length
-        ? Math.max(...keys.map(x => state.currentProfile[x].length))
-        : 0;
-    },
-    additionalSurvey: state => {
-      return state.additionalSurvey;
-    }
-  },
-  mutations: {
-    additionalSurvey: (state, additionalSurvey) => {
-      state.additionalSurvey = additionalSurvey;
-    },
-    setSelectedWaterLevel: (state, level) => {
-      state.selectedWaterLevel = state.waterLevels[level];
-    },
-    setDifferencesLoading: (state, value) => {
-      state.differencesLoading = value;
-    },
-    profileLoaded: (state, answer) => {
-      const { response, surveyDate } = answer;
-      const { data } = response;
-      const { waterlevel } = response.data.properties;
-      const { value, when } = waterlevel;
-      const coordinates = data.geometry.coordinates;
-      if (!coordinates) return;
-      const startPoint = state.startPoint;
-      const endPoint = state.endPoint;
-      const geoJSON = data;
-      const result = prepareProfile({ geoJSON, startPoint, endPoint });
-      // Use Vue.set() to make new object properties rective
-      // https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
-      const entry = {
-        date: when,
-        value: value
-      };
-      state.waterLevels = { [when]: entry };
-      state.selectedWaterLevel = entry;
-      Vue.set(state.currentProfile, surveyDate, {
-        points: result.points,
-        length: result.lengthPolyLine
-      });
-      if (!state.minAlt || state.minAlt > result.minAlt) {
-        state.minAlt = result.minAlt;
-      }
-      if (!state.maxAlt || state.maxAlt < result.maxAlt) {
-        state.maxAlt = result.maxAlt;
-      }
-    },
-    setStartPoint: (state, start) => {
-      state.startPoint = start;
-    },
-    setEndPoint: (state, end) => {
-      state.endPoint = end;
-    },
-    addFairwayData: (state, coordinates) => {
-      state.fairwayData.push(coordinates);
-    },
-    clearFairwayData: state => {
-      state.fairwayData = [];
-    },
-    clearCurrentProfile: state => {
-      state.currentProfile = {};
-      state.minAlt = null;
-      state.maxAlt = null;
-      state.totalLength = null;
-      state.fairwayData = [];
-      state.startPoint = null;
-      state.endPoint = null;
-      state.referenceWaterLevel = null;
-      state.waterLevels = {};
-      state.selectedWaterLevel = "";
-    },
-    previousCuts: (state, previousCuts) => {
-      state.previousCuts = previousCuts;
-    },
-    profileLoading: (state, loading) => {
-      state.profileLoading = loading;
-    },
-    selectedCut: (state, cut) => {
-      state.selectedCut = cut;
-    }
-  },
-  actions: {
-    clearCurrentProfile({ commit, rootState }) {
-      commit("clearCurrentProfile");
-      commit("map/cutToolEnabled", false, { root: true });
-      rootState.map.openLayersMaps.forEach(m => {
-        m.getLayer("CUTTOOL")
-          .getSource()
-          .clear();
-      });
-    },
-    loadProfile({ commit, state }, survey) {
-      if (state.startPoint && state.endPoint) {
-        return new Promise((resolve, reject) => {
-          const profileLine = new LineString([
-            state.startPoint,
-            state.endPoint
-          ]);
-          const geoJSON = generateFeatureRequest(
-            profileLine,
-            survey.bottleneck_id,
-            survey.date_info
-          );
-          HTTP.post("/cross", geoJSON, {
-            headers: { "X-Gemma-Auth": localStorage.getItem("token") }
-          })
-            .then(response => {
-              if (response.data.geometry.coordinates.length) {
-                commit("profileLoaded", {
-                  response: response,
-                  surveyDate: survey.date_info
-                });
-                resolve(response);
-              } else {
-                commit("clearCurrentProfile");
-                reject({
-                  response: {
-                    status: null,
-                    data: "No intersection with sounding data."
-                  }
-                });
-              }
-            })
-            .catch(error => reject(error));
-        });
-      }
-    },
-    cut({ commit, dispatch, state, rootState, rootGetters }, cut) {
-      return new Promise(resolve => {
-        const length = getLength(cut.getGeometry());
-        commit(
-          "map/setCurrentMeasurement",
-          {
-            quantity: "Length",
-            unitSymbol: "m",
-            value: Math.round(length * 10) / 10
-          },
-          { root: true }
-        );
-        commit("clearFairwayData");
-        // if a survey has been selected, request a profile
-        // TODO an improvement could be to check if the line intersects
-        // with the bottleneck area's polygon before trying the server request
-        if (rootState.bottlenecks.selectedSurvey) {
-          const inputLineString = cut.getGeometry().clone();
-          inputLineString.transform("EPSG:3857", "EPSG:4326");
-          const [start, end] = inputLineString
-            .getCoordinates()
-            .map(coords => coords.map(coord => parseFloat(coord.toFixed(8))));
-          commit("setStartPoint", start);
-          commit("setEndPoint", end);
-          const profileLine = new LineString([start, end]);
-
-          const profileLoaders = [
-            dispatch("loadProfile", rootState.bottlenecks.selectedSurvey)
-          ];
-          if (state.additionalSurvey) {
-            profileLoaders.push(
-              dispatch("loadProfile", state.additionalSurvey)
-            );
-          }
-
-          commit("profileLoading", true);
-          Promise.all(profileLoaders)
-            .then(() => {
-              commit("map/cutToolEnabled", false, { root: true });
-              const los3 = rootGetters["map/openLayersMap"]().getLayer(
-                "FAIRWAYDIMENSIONSLOS3"
-              );
-              los3.getSource().forEachFeatureIntersectingExtent(
-                profileLine
-                  .clone()
-                  .transform("EPSG:4326", "EPSG:3857")
-                  .getExtent(),
-                feature => {
-                  const fairwayCoordinates = featureToFairwayCoordinates(
-                    feature,
-                    profileLine
-                  );
-                  let fairwayData = {
-                    coordinates: fairwayCoordinates,
-                    style: los3.getStyle()
-                  };
-                  if (fairwayCoordinates.length > 0) {
-                    commit("addFairwayData", fairwayData);
-                  }
-                }
-              );
-              const los2 = rootGetters["map/openLayersMap"]().getLayer(
-                "FAIRWAYDIMENSIONSLOS2"
-              );
-              los2.getSource().forEachFeatureIntersectingExtent(
-                profileLine
-                  .clone()
-                  .transform("EPSG:4326", "EPSG:3857")
-                  .getExtent(),
-                feature => {
-                  let fairwayCoordinates = featureToFairwayCoordinates(
-                    feature,
-                    profileLine
-                  );
-                  let fairwayData = {
-                    coordinates: fairwayCoordinates,
-                    style: los2.getStyle()
-                  };
-                  if (fairwayCoordinates.length > 0) {
-                    commit("addFairwayData", fairwayData);
-                  }
-                }
-              );
-              const los1 = rootGetters["map/openLayersMap"]().getLayer(
-                "FAIRWAYDIMENSIONSLOS1"
-              );
-              los1.getSource().forEachFeatureIntersectingExtent(
-                profileLine
-                  .clone()
-                  .transform("EPSG:4326", "EPSG:3857")
-                  .getExtent(),
-                feature => {
-                  const fairwayCoordinates = featureToFairwayCoordinates(
-                    feature,
-                    profileLine
-                  );
-                  let fairwayData = {
-                    coordinates: fairwayCoordinates,
-                    style: los1.getStyle()
-                  };
-                  if (fairwayCoordinates.length > 0) {
-                    commit("addFairwayData", fairwayData);
-                  }
-                }
-              );
-              resolve();
-            })
-            .catch(error => {
-              const { status, data } = error.response;
-              displayError({
-                title: "Backend Error",
-                message: `${status ? status + ":" : ""} ${data.message || data}`
-              });
-            })
-            .finally(() => {
-              commit("application/paneRotate", 1, { root: true });
-              if (state.additionalSurvey) {
-                commit(
-                  "application/paneSetup",
-                  "COMPARESURVEYS_FAIRWAYPROFILE",
-                  { root: true }
-                );
-              } else {
-                commit("application/paneSetup", "FAIRWAYPROFILE", {
-                  root: true
-                });
-              }
-              commit("profileLoading", false);
-            });
-        }
-      });
-    },
-    previousCuts({ commit, rootState }) {
-      const previousCuts =
-        JSON.parse(localStorage.getItem("previousCuts")) || [];
-      commit(
-        "previousCuts",
-        previousCuts
-          .filter(cut => {
-            return (
-              cut.bottleneckName === rootState.bottlenecks.selectedBottleneck
-            );
-          })
-          .sort((a, b) => (a.timestamp < b.timestamp ? 1 : -1))
-      );
-    }
-  }
-};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/store/fairwayavailability.js	Wed May 08 17:43:18 2019 +0200
@@ -0,0 +1,101 @@
+/* This is Free Software under GNU Affero General Public License v >= 3.0
+ * without warranty, see README.md and license for details.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ * License-Filename: LICENSES/AGPL-3.0.txt
+ *
+ * Copyright (C) 2018 by via donau
+ *   – Österreichische Wasserstraßen-Gesellschaft mbH
+ * Software engineering by Intevation GmbH
+ *
+ * Author(s):
+ * Thomas Junk <thomas.junk@intevation.de>
+ */
+
+import { HTTP } from "@/lib/http";
+
+const init = () => {
+  return {
+    type: "bottlenecks",
+    selectedFairwayAvailabilityFeature: null,
+    from: null,
+    to: null,
+    frequency: null,
+    fwData: null,
+    legend: null,
+    LOS: null
+  };
+};
+
+export default {
+  init,
+  namespaced: true,
+  state: init(),
+  mutations: {
+    type: (state, type) => {
+      state.type = type;
+    },
+    setLOS: (state, LOS) => {
+      state.LOS = LOS;
+    },
+    setFrequency: (state, frequency) => {
+      state.frequency = frequency;
+    },
+    setFrom: (state, from) => {
+      state.from = from;
+    },
+    setTo: (state, to) => {
+      state.to = to;
+    },
+    setSelectedFairwayAvailability: (state, feature) => {
+      state.selectedFairwayAvailabilityFeature = feature;
+    },
+    setFwData: (state, fwData) => {
+      state.fwData = fwData;
+    },
+    setLegend: (state, header) => {
+      const headerEntries = header.split(",");
+      headerEntries.shift();
+      state.legend = headerEntries.map(x => {
+        return x.split("#")[1].trim();
+      });
+    }
+  },
+  actions: {
+    loadAvailableFairwayDepth: ({ commit }, options) => {
+      return new Promise((resolve, reject) => {
+        const { feature, from, to, frequency, LOS } = options;
+        const start = encodeURIComponent("00:00:00+00:00");
+        const end = encodeURIComponent("23:59:59+00:00");
+        const URL = `/data/bottleneck/fairway-depth/${encodeURIComponent(
+          feature.properties.name
+        )}?from=${from}T${start}&to=${to}T${end}&mode=${frequency}&los=${LOS}`;
+        HTTP.get(URL, {
+          headers: { "X-Gemma-Auth": localStorage.getItem("token") }
+        })
+          .then(response => {
+            const { data } = response;
+            const csv = data.split("\n");
+            commit("setLegend", csv.shift());
+            let transformed = csv.map(e => {
+              const result = e.split(",");
+              const label = result.shift();
+              const ldc = result.shift();
+              const highestLevel = result.pop();
+              return {
+                label: label,
+                ldc: ldc,
+                highestLevel: highestLevel,
+                lowerLevels: result
+              };
+            });
+            commit("setFwData", transformed);
+            resolve(response);
+          })
+          .catch(error => {
+            reject(error);
+          });
+      });
+    }
+  }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/store/fairwayprofile.js	Wed May 08 17:43:18 2019 +0200
@@ -0,0 +1,326 @@
+/* This is Free Software under GNU Affero General Public License v >= 3.0
+ * without warranty, see README.md and license for details.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ * License-Filename: LICENSES/AGPL-3.0.txt
+ *
+ * Copyright (C) 2018 by via donau
+ *   – Österreichische Wasserstraßen-Gesellschaft mbH
+ * Software engineering by Intevation GmbH
+ *
+ * Author(s):
+ * Thomas Junk <thomas.junk@intevation.de>
+ * Markus Kottländer <markuks.kottlaender@intevation.de>
+ */
+import Vue from "vue";
+import { HTTP } from "@/lib/http";
+import { prepareProfile } from "@/lib/geo";
+import LineString from "ol/geom/LineString";
+import { generateFeatureRequest } from "@/lib/geo";
+import { getLength } from "ol/sphere";
+import { displayError } from "@/lib/errors";
+import { featureToFairwayCoordinates } from "@/lib/geo";
+
+// initial state
+const init = () => {
+  return {
+    additionalSurvey: null,
+    minAlt: 0,
+    maxAlt: 0,
+    currentProfile: {},
+    referenceWaterLevel: null,
+    waterLevels: {},
+    selectedWaterLevel: "",
+    fairwayData: [],
+    startPoint: null,
+    endPoint: null,
+    previousCuts: [],
+    profileLoading: false,
+    selectedCut: null,
+    differencesLoading: false
+  };
+};
+
+export default {
+  init,
+  namespaced: true,
+  state: init(),
+  getters: {
+    totalLength: state => {
+      const keys = Object.keys(state.currentProfile);
+      return keys.length
+        ? Math.max(...keys.map(x => state.currentProfile[x].length))
+        : 0;
+    },
+    additionalSurvey: state => {
+      return state.additionalSurvey;
+    }
+  },
+  mutations: {
+    additionalSurvey: (state, additionalSurvey) => {
+      state.additionalSurvey = additionalSurvey;
+    },
+    setSelectedWaterLevel: (state, level) => {
+      state.selectedWaterLevel = state.waterLevels[level];
+    },
+    setDifferencesLoading: (state, value) => {
+      state.differencesLoading = value;
+    },
+    profileLoaded: (state, answer) => {
+      const { response, surveyDate } = answer;
+      const { data } = response;
+      const { waterlevel } = response.data.properties;
+      const { value, when } = waterlevel;
+      const coordinates = data.geometry.coordinates;
+      if (!coordinates) return;
+      const startPoint = state.startPoint;
+      const endPoint = state.endPoint;
+      const geoJSON = data;
+      const result = prepareProfile({ geoJSON, startPoint, endPoint });
+      // Use Vue.set() to make new object properties rective
+      // https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats
+      const entry = {
+        date: when,
+        value: value
+      };
+      state.waterLevels = { [when]: entry };
+      state.selectedWaterLevel = entry;
+      Vue.set(state.currentProfile, surveyDate, {
+        points: result.points,
+        length: result.lengthPolyLine
+      });
+      if (!state.minAlt || state.minAlt > result.minAlt) {
+        state.minAlt = result.minAlt;
+      }
+      if (!state.maxAlt || state.maxAlt < result.maxAlt) {
+        state.maxAlt = result.maxAlt;
+      }
+    },
+    setStartPoint: (state, start) => {
+      state.startPoint = start;
+    },
+    setEndPoint: (state, end) => {
+      state.endPoint = end;
+    },
+    addFairwayData: (state, coordinates) => {
+      state.fairwayData.push(coordinates);
+    },
+    clearFairwayData: state => {
+      state.fairwayData = [];
+    },
+    clearCurrentProfile: state => {
+      state.currentProfile = {};
+      state.minAlt = null;
+      state.maxAlt = null;
+      state.totalLength = null;
+      state.fairwayData = [];
+      state.startPoint = null;
+      state.endPoint = null;
+      state.referenceWaterLevel = null;
+      state.waterLevels = {};
+      state.selectedWaterLevel = "";
+    },
+    previousCuts: (state, previousCuts) => {
+      state.previousCuts = previousCuts;
+    },
+    profileLoading: (state, loading) => {
+      state.profileLoading = loading;
+    },
+    selectedCut: (state, cut) => {
+      state.selectedCut = cut;
+    }
+  },
+  actions: {
+    clearCurrentProfile({ commit, rootState }) {
+      commit("clearCurrentProfile");
+      commit("map/cutToolEnabled", false, { root: true });
+      rootState.map.openLayersMaps.forEach(m => {
+        m.getLayer("CUTTOOL")
+          .getSource()
+          .clear();
+      });
+    },
+    loadProfile({ commit, state }, survey) {
+      if (state.startPoint && state.endPoint) {
+        return new Promise((resolve, reject) => {
+          const profileLine = new LineString([
+            state.startPoint,
+            state.endPoint
+          ]);
+          const geoJSON = generateFeatureRequest(
+            profileLine,
+            survey.bottleneck_id,
+            survey.date_info
+          );
+          HTTP.post("/cross", geoJSON, {
+            headers: { "X-Gemma-Auth": localStorage.getItem("token") }
+          })
+            .then(response => {
+              if (response.data.geometry.coordinates.length) {
+                commit("profileLoaded", {
+                  response: response,
+                  surveyDate: survey.date_info
+                });
+                resolve(response);
+              } else {
+                commit("clearCurrentProfile");
+                reject({
+                  response: {
+                    status: null,
+                    data: "No intersection with sounding data."
+                  }
+                });
+              }
+            })
+            .catch(error => reject(error));
+        });
+      }
+    },
+    cut({ commit, dispatch, state, rootState, rootGetters }, cut) {
+      return new Promise(resolve => {
+        const length = getLength(cut.getGeometry());
+        commit(
+          "map/setCurrentMeasurement",
+          {
+            quantity: "Length",
+            unitSymbol: "m",
+            value: Math.round(length * 10) / 10
+          },
+          { root: true }
+        );
+        commit("clearFairwayData");
+        // if a survey has been selected, request a profile
+        // TODO an improvement could be to check if the line intersects
+        // with the bottleneck area's polygon before trying the server request
+        if (rootState.bottlenecks.selectedSurvey) {
+          const inputLineString = cut.getGeometry().clone();
+          inputLineString.transform("EPSG:3857", "EPSG:4326");
+          const [start, end] = inputLineString
+            .getCoordinates()
+            .map(coords => coords.map(coord => parseFloat(coord.toFixed(8))));
+          commit("setStartPoint", start);
+          commit("setEndPoint", end);
+          const profileLine = new LineString([start, end]);
+
+          const profileLoaders = [
+            dispatch("loadProfile", rootState.bottlenecks.selectedSurvey)
+          ];
+          if (state.additionalSurvey) {
+            profileLoaders.push(
+              dispatch("loadProfile", state.additionalSurvey)
+            );
+          }
+
+          commit("profileLoading", true);
+          Promise.all(profileLoaders)
+            .then(() => {
+              commit("map/cutToolEnabled", false, { root: true });
+              const los3 = rootGetters["map/openLayersMap"]().getLayer(
+                "FAIRWAYDIMENSIONSLOS3"
+              );
+              los3.getSource().forEachFeatureIntersectingExtent(
+                profileLine
+                  .clone()
+                  .transform("EPSG:4326", "EPSG:3857")
+                  .getExtent(),
+                feature => {
+                  const fairwayCoordinates = featureToFairwayCoordinates(
+                    feature,
+                    profileLine
+                  );
+                  let fairwayData = {
+                    coordinates: fairwayCoordinates,
+                    style: los3.getStyle()
+                  };
+                  if (fairwayCoordinates.length > 0) {
+                    commit("addFairwayData", fairwayData);
+                  }
+                }
+              );
+              const los2 = rootGetters["map/openLayersMap"]().getLayer(
+                "FAIRWAYDIMENSIONSLOS2"
+              );
+              los2.getSource().forEachFeatureIntersectingExtent(
+                profileLine
+                  .clone()
+                  .transform("EPSG:4326", "EPSG:3857")
+                  .getExtent(),
+                feature => {
+                  let fairwayCoordinates = featureToFairwayCoordinates(
+                    feature,
+                    profileLine
+                  );
+                  let fairwayData = {
+                    coordinates: fairwayCoordinates,
+                    style: los2.getStyle()
+                  };
+                  if (fairwayCoordinates.length > 0) {
+                    commit("addFairwayData", fairwayData);
+                  }
+                }
+              );
+              const los1 = rootGetters["map/openLayersMap"]().getLayer(
+                "FAIRWAYDIMENSIONSLOS1"
+              );
+              los1.getSource().forEachFeatureIntersectingExtent(
+                profileLine
+                  .clone()
+                  .transform("EPSG:4326", "EPSG:3857")
+                  .getExtent(),
+                feature => {
+                  const fairwayCoordinates = featureToFairwayCoordinates(
+                    feature,
+                    profileLine
+                  );
+                  let fairwayData = {
+                    coordinates: fairwayCoordinates,
+                    style: los1.getStyle()
+                  };
+                  if (fairwayCoordinates.length > 0) {
+                    commit("addFairwayData", fairwayData);
+                  }
+                }
+              );
+              resolve();
+            })
+            .catch(error => {
+              const { status, data } = error.response;
+              displayError({
+                title: "Backend Error",
+                message: `${status ? status + ":" : ""} ${data.message || data}`
+              });
+            })
+            .finally(() => {
+              commit("application/paneRotate", 1, { root: true });
+              if (state.additionalSurvey) {
+                commit(
+                  "application/paneSetup",
+                  "COMPARESURVEYS_FAIRWAYPROFILE",
+                  { root: true }
+                );
+              } else {
+                commit("application/paneSetup", "FAIRWAYPROFILE", {
+                  root: true
+                });
+              }
+              commit("profileLoading", false);
+            });
+        }
+      });
+    },
+    previousCuts({ commit, rootState }) {
+      const previousCuts =
+        JSON.parse(localStorage.getItem("previousCuts")) || [];
+      commit(
+        "previousCuts",
+        previousCuts
+          .filter(cut => {
+            return (
+              cut.bottleneckName === rootState.bottlenecks.selectedBottleneck
+            );
+          })
+          .sort((a, b) => (a.timestamp < b.timestamp ? 1 : -1))
+      );
+    }
+  }
+};
--- a/client/src/store/index.js	Wed May 08 17:29:50 2019 +0200
+++ b/client/src/store/index.js	Wed May 08 17:43:18 2019 +0200
@@ -19,11 +19,11 @@
 import user from "./user";
 import usermanagement from "./usermanagement";
 import map from "./map";
-import fairwayprofile from "./fairway";
+import fairwayavailability from "./fairwayavailability";
+import fairwayprofile from "./fairwayprofile";
 import bottlenecks from "./bottlenecks";
 import { imports } from "./imports";
 import { importschedule } from "./importschedule";
-import { diagram } from "./diagram";
 import gauges from "./gauges";
 
 Vue.use(Vuex);
@@ -33,7 +33,7 @@
     reset() {
       this.replaceState({
         application: application.init(),
-        diagram: diagram.init(),
+        fairwayavailability: fairwayavailability.init(),
         fairwayprofile: fairwayprofile.init(),
         imports: imports.init(),
         importschedule: importschedule.init(),
@@ -47,7 +47,7 @@
   },
   modules: {
     application,
-    diagram,
+    fairwayavailability,
     fairwayprofile,
     imports,
     importschedule,
--- a/client/src/store/map.js	Wed May 08 17:29:50 2019 +0200
+++ b/client/src/store/map.js	Wed May 08 17:43:18 2019 +0200
@@ -374,7 +374,7 @@
               });
             } else {
               commit("application/showStatistics", true, { root: true });
-              commit("diagram/type", "stretches", { root: true });
+              commit("fairwayavailability/type", "stretches", { root: true });
               commit("imports/selectedStretchId", stretches[0].getId(), {
                 root: true
               });