changeset 3146:b6cc4838d2c0

client: implemented pane mechanic for diagrams regressions: diagrams are currently not collapsible anymore, animations were removed
author Markus Kottlaender <markus@intevation.de>
date Fri, 03 May 2019 10:33:51 +0200
parents d33a5c1522dc
children 25c0cbfcc515
files client/src/components/Main.vue client/src/components/Pane.vue client/src/components/fairway/Fairwayprofile.vue client/src/components/fairway/Profiles.vue client/src/components/gauge/Gauges.vue client/src/components/gauge/HydrologicalConditions.vue client/src/components/gauge/Waterlevel.vue client/src/components/map/Map.vue client/src/components/paneSetups.js client/src/store/application.js client/src/store/fairway.js
diffstat 11 files changed, 365 insertions(+), 318 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Main.vue	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/components/Main.vue	Fri May 03 10:33:51 2019 +0200
@@ -1,30 +1,33 @@
 <template>
   <div id="panes" :class="'d-flex position-absolute rotate' + paneRotate">
-    <Pane :pane="panes[0]" :class="'d-flex ' + pane1Classes" />
-
-    <template v-if="panes.length === 2">
-      <Pane :pane="panes[1]" :class="'d-flex ' + pane2Classes" />
-    </template>
-
-    <template v-if="panes.length === 3">
-      <Pane :pane="panes[2]" class="d-flex wh-50" />
-      <Pane :pane="panes[1]" class="d-flex wh-50" />
-    </template>
-
-    <template v-if="panes.length === 4">
-      <Pane :pane="panes[1]" class="d-flex wh-50" />
-      <Pane :pane="panes[3]" class="d-flex wh-50" />
-      <Pane :pane="panes[2]" class="d-flex wh-50" />
-    </template>
+    <Pane :pane="panes[0]" :key="panes[0].id" :class="paneClasses[0]" />
+    <Pane
+      :pane="panes[1]"
+      :key="panes[1].id"
+      :class="paneClasses[1]"
+      v-if="panes.length >= 2"
+    />
+    <Pane
+      :pane="panes[2]"
+      :key="panes[2].id"
+      :class="paneClasses[2]"
+      v-if="panes.length >= 3"
+    />
+    <Pane
+      :pane="panes[3]"
+      :key="panes[3].id"
+      :class="paneClasses[3]"
+      v-if="panes.length === 4"
+    />
   </div>
 </template>
 
 <style lang="sass">
 #panes
-  top: -0.5px
-  right: -0.5px
-  bottom: -0.5px
-  left: -0.5px
+  top: -1px
+  right: -1px
+  bottom: -1px
+  left: -1px
   z-index: 1
   &.rotate1
     flex-wrap: wrap
@@ -39,7 +42,7 @@
     flex-wrap: wrap
     flex-direction: column-reverse
   .pane
-    border: solid 0.5px #fff
+    border: solid 1px #dee2e6
     background: #fff
 </style>
 
@@ -60,31 +63,54 @@
  */
 
 import { mapState } from "vuex";
+import * as paneSetups from "./paneSetups";
 
 export default {
   components: {
     Pane: () => import("./Pane")
   },
   computed: {
-    ...mapState("application", ["panes", "paneRotate"]),
-    // pane 1 and 2 are the only ones that can have varying size
-    // thats why tehre is no pane3class or pane4class
-    pane1Classes() {
-      if (this.panes.length === 1) return "wh-100";
-      if (this.panes.length === 2 || this.panes.length === 3) {
-        if (this.paneRotate === 1 || this.paneRotate === 3) return "w-100 h-50";
-        if (this.paneRotate === 2 || this.paneRotate === 4) return "w-50 h-100";
+    ...mapState("application", ["paneSetup", "paneRotate"]),
+    panes() {
+      return Object.values(paneSetups[this.paneSetup]);
+    },
+    paneClasses() {
+      if (this.paneSetup === "DEFAULT") {
+        return ["wh-100"];
+      }
+
+      if (this.paneSetup === "COMPARESURVEYS") {
+        return [2, 4].includes(this.paneRotate)
+          ? ["w-100 h-50", "w-100 h-50"]
+          : ["w-50 h-100", "w-50 h-100"];
+      }
+
+      if (this.paneSetup === "FAIRWAYPROFILE") {
+        return [1, 3].includes(this.paneRotate)
+          ? ["w-100 h-50", "w-100 h-50"]
+          : ["w-50 h-100", "w-50 h-100"];
       }
-      if (this.panes.length === 4) {
-        return "wh-50";
+
+      if (this.paneSetup === "COMPARESURVEYS_FAIRWAYPROFILE") {
+        return [1, 3].includes(this.paneRotate)
+          ? ["wh-50", "wh-50", "w-100 h-50"]
+          : ["wh-50", "wh-50", "w-50 h-100"];
       }
-    },
-    pane2Classes() {
-      if (this.panes.length === 2) {
-        if (this.paneRotate === 1 || this.paneRotate === 3) return "w-100 h-50";
-        if (this.paneRotate === 2 || this.paneRotate === 4) return "w-50 h-100";
-      } else {
-        return "wh-50";
+
+      if (
+        ["GAUGE_WATERLEVEL", "GAUGE_HYDROLOGICALCONDITIONS"].includes(
+          this.paneSetup
+        )
+      ) {
+        return [1, 3].includes(this.paneRotate)
+          ? ["w-100 h-50", "w-100 h-50"]
+          : ["w-50 h-100", "w-50 h-100"];
+      }
+
+      if (this.paneSetup === "GAUGE_WATERLEVEL_HYDROLOGICALCONDITIONS") {
+        return [1, 3].includes(this.paneRotate)
+          ? ["w-100 h-50", "wh-50", "wh-50"]
+          : ["h-100 w-50", "wh-50", "wh-50"];
       }
     }
   }
--- a/client/src/components/Pane.vue	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/components/Pane.vue	Fri May 03 10:33:51 2019 +0200
@@ -1,13 +1,6 @@
 <template>
-  <div :id="pane.id" class="pane">
-    <component
-      :is="pane.component"
-      :key="pane.id"
-      :paneCreated="pane.created"
-      :paneMounted="pane.mounted"
-      :paneUpdated="pane.updated"
-      :paneDestroyed="pane.destroyed"
-    />
+  <div :id="pane.id" class="pane d-flex position-relative">
+    <component :is="pane.component" :key="pane.id" />
   </div>
 </template>
 
--- a/client/src/components/fairway/Fairwayprofile.vue	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/components/fairway/Fairwayprofile.vue	Fri May 03 10:33:51 2019 +0200
@@ -1,32 +1,35 @@
 <template>
-  <div class="d-flex flex-fill">
-    <DiagramLegend>
-      <div class="legend">
-        <span style="background-color: #5995ff"></span> Water
-      </div>
-      <div class="legend">
-        <span style="background-color: #1f4fff"></span> Fairway
-      </div>
-      <div class="legend">
-        <span style="background-color: #4a2f06"></span>
-        Ground
-      </div>
-      <div>
-        <button
-          @click="downloadPDF"
-          type="button"
-          class="btn btn-sm btn-info d-block w-100 mt-2"
-        >
-          <translate>Export to PDF</translate>
-        </button>
-      </div>
-    </DiagramLegend>
-    <div
-      ref="diagramContainer"
-      class="d-flex flex-fill justify-content-center align-items-center diagram-container"
-    >
-      <div v-if="!fairwayData">
-        <translate>No data available.</translate>
+  <div class="d-flex flex-column flex-fill">
+    <UIBoxHeader icon="chart-area" :title="title" :closeCallback="close" />
+    <div class="d-flex flex-fill">
+      <DiagramLegend>
+        <div class="legend">
+          <span style="background-color: #5995ff"></span> Water
+        </div>
+        <div class="legend">
+          <span style="background-color: #1f4fff"></span> Fairway
+        </div>
+        <div class="legend">
+          <span style="background-color: #4a2f06"></span>
+          Ground
+        </div>
+        <div>
+          <button
+            @click="downloadPDF"
+            type="button"
+            class="btn btn-sm btn-info d-block w-100 mt-2"
+          >
+            <translate>Export to PDF</translate>
+          </button>
+        </div>
+      </DiagramLegend>
+      <div
+        ref="diagramContainer"
+        class="d-flex flex-fill justify-content-center align-items-center diagram-container"
+      >
+        <div v-if="!fairwayData">
+          <translate>No data available.</translate>
+        </div>
       </div>
     </div>
   </div>
@@ -86,6 +89,15 @@
       "selectedWaterLevel",
       "waterLevels"
     ]),
+    ...mapState("application", ["paneSetup"]),
+    title() {
+      let dates = [this.selectedSurvey.date_info];
+      if (this.additionalSurvey) dates.push(this.additionalSurvey.date_info);
+      dates.map(d => this.$options.filters.dateTime(d, true));
+      return `${this.$gettext("Fairwayprofile")}: ${
+        this.selectedBottleneck
+      } (${dates.join(", ")})`;
+    },
     selectedSurvey: {
       get() {
         return this.$store.state.bottlenecks.selectedSurvey;
@@ -151,6 +163,15 @@
     }
   },
   methods: {
+    close() {
+      this.$store.commit(
+        "application/paneSetup",
+        this.paneSetup === "COMPARESURVEYS_FAIRWAYPROFILE"
+          ? "COMPARESURVEYS"
+          : "DEFAULT"
+      );
+      this.$store.dispatch("fairwayprofile/clearCurrentProfile");
+    },
     downloadPDF() {
       var svg = this.$refs.diagramContainer.innerHTML;
       if (svg) {
--- a/client/src/components/fairway/Profiles.vue	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/components/fairway/Profiles.vue	Fri May 03 10:33:51 2019 +0200
@@ -107,6 +107,7 @@
               >
             </button>
             <button
+              v-if="!paneSetup.includes('FAIRWAYPROFILE')"
               class="btn btn-info btn-xs ml-2"
               @click="$store.commit('application/paneRotate')"
               v-tooltip="rotatePanesTooltip"
@@ -271,6 +272,7 @@
 import LineString from "ol/geom/LineString";
 import { displayError, displayInfo } from "@/lib/errors";
 import { HTTP } from "@/lib/http";
+import { COMPARESURVEYS } from "@/components/paneSetups";
 
 export default {
   name: "profiles",
@@ -278,12 +280,11 @@
     return {
       coordinatesInput: "",
       cutLabel: "",
-      showLabelInput: false,
-      comparePaneId: "compare-sounding-results"
+      showLabelInput: false
     };
   },
   computed: {
-    ...mapState("application", ["showProfiles"]),
+    ...mapState("application", ["showProfiles", "paneSetup"]),
     ...mapState("map", ["openLayersMaps", "syncedMaps", "cutToolEnabled"]),
     ...mapState("bottlenecks", [
       "bottlenecksList",
@@ -296,7 +297,8 @@
       "endPoint",
       "profileLoading",
       "differencesLoading",
-      "waterLevels"
+      "waterLevels",
+      "currentProfile"
     ]),
     ...mapGetters("map", ["openLayersMap"]),
     orderedBottlenecks() {
@@ -400,11 +402,11 @@
     },
     differencesVisible() {
       return (
-        this.openLayersMap(this.comparePaneId) &&
-        !this.openLayersMap(this.comparePaneId)
+        this.openLayersMap(COMPARESURVEYS.compare.id) &&
+        !this.openLayersMap(COMPARESURVEYS.compare.id)
           .getLayer("BOTTLENECKISOLINE")
           .getVisible() &&
-        this.openLayersMap(this.comparePaneId)
+        this.openLayersMap(COMPARESURVEYS.compare.id)
           .getLayer("DIFFERENCES")
           .getVisible()
       );
@@ -418,7 +420,7 @@
       );
     },
     mapsAreSynced() {
-      return this.syncedMaps.includes(this.comparePaneId);
+      return this.syncedMaps.includes(COMPARESURVEYS.compare.id);
     }
   },
   watch: {
@@ -433,15 +435,18 @@
     additionalSurvey(survey) {
       if (survey) {
         this.loadDifferences();
-        this.$store.commit("map/syncedMaps", [this.comparePaneId]);
-        this.$store.commit("application/addPane", {
-          id: this.comparePaneId,
-          component: "Map"
-        });
-        this.$store.commit("application/paneRotate", 4);
+        this.$store.commit(
+          "application/paneSetup",
+          Object.keys(this.currentProfile).length
+            ? "COMPARESURVEYS_FAIRWAYPROFILE"
+            : "COMPARESURVEYS"
+        );
+        this.$store.commit("map/syncedMaps", [COMPARESURVEYS.compare.id]);
       } else {
-        this.$store.commit("application/removePane", this.comparePaneId);
-        this.$store.commit("application/paneRotate", 1);
+        this.$store.commit(
+          "application/paneSetup",
+          Object.keys(this.currentProfile).length ? "FAIRWAYPROFILE" : "DEFAULT"
+        );
         this.$store.commit("map/syncedMaps", []);
       }
       this.loadProfile(survey);
@@ -457,10 +462,10 @@
       if (this.mapsAreSynced) {
         this.$store.commit(
           "map/syncedMaps",
-          this.syncedMaps.filter(m => m !== this.comparePaneId)
+          this.syncedMaps.filter(m => m !== COMPARESURVEYS.compare.id)
         );
       } else {
-        this.$store.commit("map/syncedMaps", [this.comparePaneId]);
+        this.$store.commit("map/syncedMaps", [COMPARESURVEYS.compare.id]);
       }
     },
     loadDifferences() {
@@ -490,18 +495,18 @@
         });
     },
     showDifferences() {
-      this.openLayersMap(this.comparePaneId)
+      this.openLayersMap(COMPARESURVEYS.compare.id)
         .getLayer("BOTTLENECKISOLINE")
         .setVisible(false);
-      this.openLayersMap(this.comparePaneId)
+      this.openLayersMap(COMPARESURVEYS.compare.id)
         .getLayer("DIFFERENCES")
         .setVisible(true);
     },
     showSurvey() {
-      this.openLayersMap(this.comparePaneId)
+      this.openLayersMap(COMPARESURVEYS.compare.id)
         .getLayer("BOTTLENECKISOLINE")
         .setVisible(true);
-      this.openLayersMap(this.comparePaneId)
+      this.openLayersMap(COMPARESURVEYS.compare.id)
         .getLayer("DIFFERENCES")
         .setVisible(false);
     },
@@ -511,12 +516,10 @@
     loadProfile(survey) {
       if (survey) {
         this.$store.commit("fairwayprofile/profileLoading", true);
-        this.$store.commit("application/splitscreenLoading", true);
         this.$store
           .dispatch("fairwayprofile/loadProfile", survey)
           .finally(() => {
             this.$store.commit("fairwayprofile/profileLoading", false);
-            this.$store.commit("application/splitscreenLoading", false);
           });
       }
     },
--- a/client/src/components/gauge/Gauges.vue	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/components/gauge/Gauges.vue	Fri May 03 10:33:51 2019 +0200
@@ -113,7 +113,7 @@
     };
   },
   computed: {
-    ...mapState("application", ["showGauges", "activeSplitscreenId"]),
+    ...mapState("application", ["showGauges", "paneSetup"]),
     ...mapState("gauges", ["gauges", "longtermInterval"]),
     ...mapGetters("gauges", ["selectedGauge"]),
     gaugesLabel() {
@@ -165,12 +165,16 @@
     }
   },
   watch: {
-    selectedGaugeISRS() {
-      if (this.activeSplitscreenId === "gauge-waterlevel") {
-        this.showWaterlevelDiagram();
-      }
-      if (this.activeSplitscreenId === "gauge-hydrological-conditions") {
-        this.showHydrologicalConditionsDiagram();
+    selectedGaugeISRS(gauge) {
+      if (gauge) {
+        let coordinates = this.selectedGauge.geometry.coordinates;
+        this.$store.dispatch("map/moveMap", {
+          coordinates,
+          zoom: null,
+          preventZoomOut: true
+        });
+      } else {
+        this.$store.commit("application/paneSetup", "DEFAULT");
       }
     }
   },
@@ -187,37 +191,7 @@
       });
     },
     showWaterlevelDiagram() {
-      // for panning the map to the gauge on opening the diagram: needs to be
-      // set outside of the expandCallback to not always refer to the currently
-      // selectedGauge
-      let coordinates = this.selectedGauge.geometry.coordinates;
-
-      // configure splitscreen
-      let splitscreenConf = {
-        id: "gauge-waterlevel",
-        component: "waterlevel",
-        title: `${this.gaugeLabel(this.selectedGauge)}: ${this.$gettext(
-          "Waterlevel"
-        )} ${this.dateFrom.toLocaleDateString()} - ${this.dateTo.toLocaleDateString()}`,
-        icon: "ruler-vertical",
-        closeCallback: () => {
-          this.$store.commit("gauges/selectedGaugeISRS", null);
-          this.$store.commit("gauges/waterlevels", []);
-        },
-        expandCallback: () => {
-          this.$store.dispatch("map/moveMap", {
-            coordinates,
-            zoom: null,
-            preventZoomOut: true
-          });
-        }
-      };
-      this.$store.commit("application/addSplitscreen", splitscreenConf);
-      this.$store.commit("application/activeSplitscreenId", splitscreenConf.id);
-      this.$store.commit("application/splitscreenLoading", true);
       this.loading = true;
-      this.$store.commit("application/showSplitscreen", true);
-
       Promise.all([
         this.$store.dispatch("gauges/loadWaterlevels"),
         this.$store.dispatch("gauges/loadNashSutcliffe")
@@ -230,53 +204,25 @@
           });
         })
         .finally(() => {
-          this.$store.commit("application/splitscreenLoading", false);
+          this.$store.commit(
+            "application/paneSetup",
+            [
+              "GAUGE_HYDROLOGICALCONDITIONS",
+              "GAUGE_WATERLEVEL_HYDROLOGICALCONDITIONS"
+            ].includes(this.paneSetup)
+              ? "GAUGE_WATERLEVEL_HYDROLOGICALCONDITIONS"
+              : "GAUGE_WATERLEVEL"
+          );
           this.loading = false;
         });
     },
     showHydrologicalConditionsDiagram() {
-      // for panning the map to the gauge on opening the diagram: needs to be
-      // set outside of the expandCallback to not always refer to the currently
-      // selectedGauge
-      let coordinates = this.selectedGauge.geometry.coordinates;
-
-      // configure splitscreen
-      let splitscreenConf = {
-        id: "gauge-hydrological-conditions",
-        component: "hydrological-conditions",
-        title: `${this.gaugeLabel(this.selectedGauge)}: ${this.$gettext(
-          "Hydrological Conditions"
-        )}`,
-        icon: "ruler-vertical",
-        closeCallback: () => {
-          this.$store.commit("gauges/selectedGaugeISRS", null);
-          this.$store.commit("gauges/longtermWaterlevels", []);
-          this.$store.commit("gauges/yearWaterlevels", []);
-        },
-        expandCallback: () => {
-          this.$store.dispatch("map/moveMap", {
-            coordinates,
-            zoom: null,
-            preventZoomOut: true
-          });
-        }
-      };
-      this.$store.commit("application/addSplitscreen", splitscreenConf);
-      this.$store.commit("application/activeSplitscreenId", splitscreenConf.id);
-      this.$store.commit("application/splitscreenLoading", true);
       this.loading = true;
-      this.$store.commit("application/showSplitscreen", true);
 
       Promise.all([
         this.$store.dispatch("gauges/loadLongtermWaterlevels"),
         this.$store.dispatch("gauges/loadYearWaterlevels")
       ])
-        .then(() => {
-          splitscreenConf.title = `${
-            splitscreenConf.title
-          } ${this.longtermInterval.join(" - ")}`;
-          this.$store.commit("application/addSplitscreen", splitscreenConf);
-        })
         .catch(error => {
           const { status, data } = error.response;
           displayError({
@@ -285,7 +231,15 @@
           });
         })
         .finally(() => {
-          this.$store.commit("application/splitscreenLoading", false);
+          this.$store.commit(
+            "application/paneSetup",
+            [
+              "GAUGE_WATERLEVEL",
+              "GAUGE_WATERLEVEL_HYDROLOGICALCONDITIONS"
+            ].includes(this.paneSetup)
+              ? "GAUGE_WATERLEVEL_HYDROLOGICALCONDITIONS"
+              : "GAUGE_HYDROLOGICALCONDITIONS"
+          );
           this.loading = false;
         });
     },
--- a/client/src/components/gauge/HydrologicalConditions.vue	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/components/gauge/HydrologicalConditions.vue	Fri May 03 10:33:51 2019 +0200
@@ -1,38 +1,47 @@
 <template>
-  <div class="d-flex flex-fill">
-    <DiagramLegend>
-      <div class="legend">
-        <span style="background-color: red"></span>
-        {{ yearCompare }}
-      </div>
-      <div class="legend">
-        <span style="background-color: orange"></span> Q25%
-      </div>
-      <div class="legend">
-        <span style="background-color: black"></span> Median
-      </div>
-      <div class="legend">
-        <span style="background-color: purple"></span> Q75%
-      </div>
-      <div class="legend">
-        <span style="background-color: lightsteelblue"></span>
-        Long-term Amplitude
-      </div>
-      <div>
-        <button
-          @click="downloadPDF"
-          type="button"
-          class="btn btn-sm btn-info d-block w-100 mt-2"
-        >
-          <translate>Export to PDF</translate>
-        </button>
-      </div>
-    </DiagramLegend>
-    <div
-      class="d-flex flex-fill justify-content-center align-items-center diagram-container"
-    >
-      <div v-if="!longtermWaterlevels.length">
-        <translate>No data available.</translate>
+  <div class="d-flex flex-column flex-fill">
+    <UIBoxHeader
+      icon="ruler-vertical"
+      :title="title"
+      :closeCallback="close"
+      class="rounded-0"
+    />
+    <div class="d-flex flex-fill">
+      <DiagramLegend>
+        <div class="legend">
+          <span style="background-color: red"></span>
+          {{ yearCompare }}
+        </div>
+        <div class="legend">
+          <span style="background-color: orange"></span> Q25%
+        </div>
+        <div class="legend">
+          <span style="background-color: black"></span> Median
+        </div>
+        <div class="legend">
+          <span style="background-color: purple"></span> Q75%
+        </div>
+        <div class="legend">
+          <span style="background-color: lightsteelblue"></span>
+          Long-term Amplitude
+        </div>
+        <div>
+          <button
+            @click="downloadPDF"
+            type="button"
+            class="btn btn-sm btn-info d-block w-100 mt-2"
+          >
+            <translate>Export to PDF</translate>
+          </button>
+        </div>
+      </DiagramLegend>
+      <div
+        class="d-flex flex-fill justify-content-center align-items-center"
+        :id="containerId"
+      >
+        <div v-if="!longtermWaterlevels.length">
+          <translate>No data available.</translate>
+        </div>
       </div>
     </div>
   </div>
@@ -67,6 +76,7 @@
   },
   data() {
     return {
+      containerId: "hydrologicalconditions-diagram-container",
       svg: null,
       diagram: null,
       navigation: null,
@@ -77,15 +87,22 @@
     };
   },
   computed: {
+    ...mapState("application", ["paneSetup"]),
     ...mapState("gauges", [
       "longtermWaterlevels",
       "yearWaterlevels",
       "yearCompare",
       "longtermInterval"
     ]),
-    ...mapGetters("gauges", ["selectedGauge"])
+    ...mapGetters("gauges", ["selectedGauge"]),
+    title() {
+      return this.$gettext("Hydrological Conditions");
+    }
   },
   watch: {
+    paneSetup() {
+      this.$nextTick(() => this.drawDiagram());
+    },
     longtermWaterlevels() {
       this.drawDiagram();
     },
@@ -94,8 +111,16 @@
     }
   },
   methods: {
+    close() {
+      this.$store.commit(
+        "application/paneSetup",
+        this.paneSetup === "GAUGE_WATERLEVEL_HYDROLOGICALCONDITIONS"
+          ? "GAUGE_WATERLEVEL"
+          : "DEFAULT"
+      );
+    },
     downloadPDF() {
-      var svg = this.svg._groups[0][0].outerHTML;
+      var svg = document.getElementById(this.containerId).innerHTML;
       if (svg) {
         svg = svg.replace(/\r?\n|\r/g, "").trim();
       }
@@ -156,9 +181,8 @@
     },
     drawDiagram() {
       // remove old diagram
-      d3.select(".diagram-container svg").remove();
+      d3.select("#" + this.containerId + " svg").remove();
       if (!this.selectedGauge || !this.longtermWaterlevels.length) return;
-
       // PREPARE HELPERS
 
       // HDC/LDC/MW for the selected gauge
@@ -182,7 +206,7 @@
 
       // create svg
       this.svg = d3
-        .select(".diagram-container")
+        .select("#" + this.containerId)
         .append("svg")
         .attr("width", "100%")
         .attr("height", "100%");
@@ -338,8 +362,9 @@
     },
     getDimensions() {
       // dimensions and margins
-      const svgWidth = document.querySelector(".diagram-container").clientWidth;
-      const svgHeight = document.querySelector(".diagram-container")
+      const svgWidth = document.querySelector("#" + this.containerId)
+        .clientWidth;
+      const svgHeight = document.querySelector("#" + this.containerId)
         .clientHeight;
       const mainMargin = { top: 20, right: 20, bottom: 110, left: 80 };
       const navMargin = {
--- a/client/src/components/gauge/Waterlevel.vue	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/components/gauge/Waterlevel.vue	Fri May 03 10:33:51 2019 +0200
@@ -1,48 +1,56 @@
 <template>
-  <div class="d-flex flex-fill">
-    <DiagramLegend>
-      <div class="legend">
-        <span style="background-color: steelblue"></span> Waterlevel
-      </div>
-      <div class="legend">
-        <span
-          style="width: 4px; height: 4px; background-color: rgba(70, 130, 180, 0.6); border: solid 4px rgba(70, 130, 180, 0.2); background-clip: padding-box; box-sizing: content-box;"
-        ></span>
-        Prediction
-      </div>
-      <div class="legend">
-        <span style="background-color: rgba(0, 255, 0, 0.1)"></span> Navigable
-        Range
-      </div>
-      <div>
-        <select
-          @change="applyChange"
-          v-model="form.template"
-          class="form-control d-block custom-select-sm w-100"
-        >
-          <option
-            v-for="template in templates"
-            :value="template"
-            :key="template.name"
+  <div class="d-flex flex-column flex-fill">
+    <UIBoxHeader
+      icon="ruler-vertical"
+      :title="title"
+      :closeCallback="close"
+      class="rounded-0"
+    />
+    <div class="d-flex flex-fill">
+      <DiagramLegend>
+        <div class="legend">
+          <span style="background-color: steelblue"></span> Waterlevel
+        </div>
+        <div class="legend">
+          <span
+            style="width: 4px; height: 4px; background-color: rgba(70, 130, 180, 0.6); border: solid 4px rgba(70, 130, 180, 0.2); background-clip: padding-box; box-sizing: content-box;"
+          ></span>
+          Prediction
+        </div>
+        <div class="legend">
+          <span style="background-color: rgba(0, 255, 0, 0.1)"></span> Navigable
+          Range
+        </div>
+        <div>
+          <select
+            @change="applyChange"
+            v-model="form.template"
+            class="form-control d-block custom-select-sm w-100"
           >
-            {{ template.name }}
-          </option>
-        </select>
-        <button
-          @click="downloadPDF"
-          type="button"
-          class="btn btn-sm btn-info d-block w-100 mt-2"
-        >
-          <translate>Export to PDF</translate>
-        </button>
-      </div>
-    </DiagramLegend>
-    <div
-      ref="diagramContainer"
-      class="d-flex flex-fill justify-content-center align-items-center diagram-container"
-    >
-      <div v-if="!waterlevels.length">
-        <translate>No data available.</translate>
+            <option
+              v-for="template in templates"
+              :value="template"
+              :key="template.name"
+            >
+              {{ template.name }}
+            </option>
+          </select>
+          <button
+            @click="downloadPDF"
+            type="button"
+            class="btn btn-sm btn-info d-block w-100 mt-2"
+          >
+            <translate>Export to PDF</translate>
+          </button>
+        </div>
+      </DiagramLegend>
+      <div
+        class="d-flex flex-fill justify-content-center align-items-center"
+        :id="containerId"
+      >
+        <div v-if="!waterlevels.length">
+          <translate>No data available.</translate>
+        </div>
       </div>
     </div>
   </div>
@@ -86,6 +94,7 @@
   },
   data() {
     return {
+      containerId: "waterlevel-diagram-container",
       svg: null,
       diagram: null,
       navigation: null,
@@ -138,9 +147,13 @@
     };
   },
   computed: {
+    ...mapState("application", ["paneSetup"]),
     ...mapState("gauges", ["dateFrom", "waterlevels", "nashSutcliffe"]),
     ...mapGetters("gauges", ["selectedGauge"]),
     ...mapState("user", ["user"]),
+    title() {
+      return this.$gettext("Waterlevel");
+    },
     dateFrom: {
       get() {
         return this.$store.state.gauges.dateFrom;
@@ -153,13 +166,24 @@
     }
   },
   watch: {
+    paneSetup() {
+      this.$nextTick(() => this.drawDiagram());
+    },
     waterlevels() {
       this.drawDiagram();
     }
   },
   methods: {
+    close() {
+      this.$store.commit(
+        "application/paneSetup",
+        this.paneSetup === "GAUGE_WATERLEVEL_HYDROLOGICALCONDITIONS"
+          ? "GAUGE_HYDROLOGICALCONDITIONS"
+          : "DEFAULT"
+      );
+    },
     downloadPDF() {
-      var svg = this.$refs.diagramContainer.innerHTML;
+      var svg = document.getElementById(this.containerId).innerHTML;
       if (svg) {
         svg = svg.replace(/\r?\n|\r/g, "").trim();
       }
@@ -345,7 +369,7 @@
     },
     drawDiagram() {
       // remove old diagram and exit if necessary data is missing
-      d3.select(".diagram-container svg").remove();
+      d3.select("#" + this.containerId + " svg").remove();
       if (!this.selectedGauge || !this.waterlevels.length) return;
 
       // PREPARE HELPERS
@@ -381,7 +405,7 @@
 
       // create svg
       this.svg = d3
-        .select(".diagram-container")
+        .select("#" + this.containerId)
         .append("svg")
         .attr("width", "100%")
         .attr("height", "100%");
@@ -564,8 +588,9 @@
     },
     getDimensions() {
       // dimensions and margins
-      const svgWidth = document.querySelector(".diagram-container").clientWidth;
-      const svgHeight = document.querySelector(".diagram-container")
+      const svgWidth = document.querySelector("#" + this.containerId)
+        .clientWidth;
+      const svgHeight = document.querySelector("#" + this.containerId)
         .clientHeight;
       const mainMargin = { top: 20, right: 20, bottom: 110, left: 80 };
       const navMargin = {
--- a/client/src/components/map/Map.vue	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/components/map/Map.vue	Fri May 03 10:33:51 2019 +0200
@@ -57,7 +57,7 @@
     ...mapState("map", ["initialLoad", "extent", "syncedMaps", "syncedView"]),
     ...mapState("bottlenecks", ["selectedSurvey"]),
     ...mapState("fairwayprofile", ["additionalSurvey"]),
-    ...mapState("application", ["panes", "paneRotate"]),
+    ...mapState("application", ["paneSetup", "paneRotate"]),
     ...mapState("imports", ["selectedStretchId"]),
     layers() {
       return layers();
@@ -77,7 +77,7 @@
     }
   },
   watch: {
-    panes() {
+    paneSetup() {
       this.$nextTick(() => this.map.updateSize());
     },
     paneRotate() {
@@ -107,7 +107,7 @@
       }
     },
     additionalSurvey(survey) {
-      if (this.paneId === "compare-sounding-results") {
+      if (this.paneId === "compare-survey") {
         if (survey) {
           this.updateBottleneckFilter(survey.bottleneck_id, survey.date_info);
         } else {
@@ -244,10 +244,7 @@
             this.selectedSurvey.date_info
           );
         }
-        if (
-          this.additionalSurvey &&
-          this.paneId === "compare-sounding-results"
-        ) {
+        if (this.additionalSurvey && this.paneId === "compare-survey") {
           this.updateBottleneckFilter(
             this.additionalSurvey.bottleneck_id,
             this.additionalSurvey.date_info
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/paneSetups.js	Fri May 03 10:33:51 2019 +0200
@@ -0,0 +1,35 @@
+const main = { id: "main", component: "Map" };
+
+export const DEFAULT = { main };
+export const COMPARESURVEYS = {
+  main,
+  compare: { id: "compare-survey", component: "Map" }
+};
+export const FAIRWAYPROFILE = {
+  main,
+  fairwayprofile: { id: "fairwayprofile", component: "Fairwayprofile" }
+};
+export const COMPARESURVEYS_FAIRWAYPROFILE = {
+  main,
+  compare: { id: "compare-survey", component: "Map" },
+  fairwayprofile: { id: "fairwayprofile", component: "Fairwayprofile" }
+};
+export const GAUGE_WATERLEVEL = {
+  main,
+  waterlevel: { id: "gauge-waterlevel", component: "Waterlevel" }
+};
+export const GAUGE_HYDROLOGICALCONDITIONS = {
+  main,
+  hydrological: {
+    id: "gauge-hydrologicalconditions",
+    component: "HydrologicalConditions"
+  }
+};
+export const GAUGE_WATERLEVEL_HYDROLOGICALCONDITIONS = {
+  main,
+  waterlevel: { id: "gauge-waterlevel", component: "Waterlevel" },
+  hydrological: {
+    id: "gauge-hydrologicalconditions",
+    component: "HydrologicalConditions"
+  }
+};
--- a/client/src/store/application.js	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/store/application.js	Fri May 03 10:33:51 2019 +0200
@@ -24,7 +24,7 @@
     secondaryLogo: process.env.VUE_APP_SECONDARY_LOGO_URL,
     logoForPDF: process.env.VUE_APP_LOGO_FOR_PDF_URL,
     popup: null,
-    panes: [{ id: "main", component: "Map" }],
+    paneSetup: "DEFAULT",
     paneRotate: 1,
     splitscreens: [],
     splitscreenLoading: false,
@@ -83,14 +83,8 @@
     popup: (state, popup) => {
       state.popup = popup;
     },
-    addPane: (state, pane) => {
-      state.panes.push(pane);
-    },
-    removePane: (state, paneId) => {
-      const index = state.panes.findIndex(p => p.id === paneId);
-      if (index !== -1) {
-        state.panes.splice(index, 1);
-      }
+    paneSetup: (state, setup) => {
+      state.paneSetup = setup;
     },
     paneRotate: (state, rotate) => {
       if (rotate) {
--- a/client/src/store/fairway.js	Fri May 03 10:31:40 2019 +0200
+++ b/client/src/store/fairway.js	Fri May 03 10:33:51 2019 +0200
@@ -109,7 +109,6 @@
       state.fairwayData = [];
     },
     clearCurrentProfile: state => {
-      state.additionalSurvey = null;
       state.currentProfile = {};
       state.minAlt = null;
       state.maxAlt = null;
@@ -132,8 +131,7 @@
     }
   },
   actions: {
-    clearSelection({ commit, dispatch, rootState }) {
-      dispatch("bottlenecks/setSelectedBottleneck", null, { root: true });
+    clearCurrentProfile({ commit, rootState }) {
       commit("clearCurrentProfile");
       commit("map/cutToolEnabled", false, { root: true });
       rootState.map.openLayersMaps.forEach(m => {
@@ -213,8 +211,6 @@
             );
           }
 
-          commit("application/showSplitscreen", true, { root: true });
-          commit("application/splitscreenLoading", true, { root: true });
           commit("profileLoading", true);
           Promise.all(profileLoaders)
             .then(() => {
@@ -295,40 +291,18 @@
               });
             })
             .finally(() => {
-              let splitscreenConf = {
-                id: "fairwayprofile",
-                component: "fairwayprofile",
-                title: `${rootState.bottlenecks.selectedBottleneck} (${
-                  rootState.bottlenecks.selectedSurvey.date_info
-                })`,
-                icon: "chart-area",
-                closeCallback: () => {
-                  dispatch("clearSelection");
-                },
-                expandCallback: () => {
-                  let bottleneck = rootState.bottlenecks.bottlenecksList.find(
-                    bn =>
-                      bn.properties.name ===
-                      rootState.bottlenecks.selectedBottleneck
-                  );
-                  dispatch(
-                    "map/moveToFeauture",
-                    {
-                      feature: bottleneck,
-                      zoom: 17,
-                      preventZoomOut: true
-                    },
-                    { root: true }
-                  );
-                }
-              };
-              commit("application/addSplitscreen", splitscreenConf, {
-                root: true
-              });
-              commit("application/activeSplitscreenId", "fairwayprofile", {
-                root: true
-              });
-              commit("application/splitscreenLoading", false, { root: true });
+              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);
             });
         }