changeset 2977:ab26fb7a76f6 unified_import

unified_imports: soundingresults moved to new UI
author Thomas Junk <thomas.junk@intevation.de>
date Tue, 09 Apr 2019 12:38:23 +0200
parents ac5ba5a0e963
children d6dd158b8071
files client/src/components/ImportSoundingresults.vue client/src/components/Sidebar.vue client/src/components/importconfiguration/ImportDetails.vue client/src/components/importconfiguration/ImportSoundingresults.vue client/src/router.js
diffstat 5 files changed, 364 insertions(+), 381 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/ImportSoundingresults.vue	Tue Apr 09 08:51:02 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-<template>
-  <div class="main d-flex flex-column">
-    <div class="d-flex flex-row">
-      <Spacer />
-      <div class="card shadow-xs mt-2 mr-2 w-100 h-100">
-        <UIBoxHeader icon="upload" :title="importSoundingresultsLabel" />
-        <div v-if="editState">
-          <div
-            v-for="(message, index) in messages"
-            :key="index"
-            class="alert alert-warning small rounded-0"
-          >
-            {{ message }}
-          </div>
-          <div class="container">
-            <div class="row">
-              <div class="col-5">
-                <small class="text-muted">
-                  <translate>Bottleneck</translate>
-                </small>
-                <select v-model="bottleneck" class="custom-select">
-                  <option
-                    v-for="bottleneck in availableBottlenecks"
-                    :value="bottleneck"
-                    :key="bottleneck.properties.objnam"
-                  >
-                    {{ bottleneck.properties.objnam }}
-                  </option>
-                </select>
-                <span class="text-danger">
-                  <small v-if="!bottleneck">
-                    <translate>Please select a bottleneck</translate>
-                  </small>
-                </span>
-              </div>
-              <div class="col-2">
-                <small class="text-muted">
-                  <translate>Projection</translate>&nbsp;(EPSG)
-                </small>
-                <input
-                  class="form-control"
-                  v-model="projection"
-                  value="4326"
-                  placeholder="e.g. 4326"
-                  type="number"
-                />
-                <span class="text-left text-danger">
-                  <small v-if="!projection">
-                    <translate>Please enter a projection</translate>
-                  </small>
-                </span>
-              </div>
-              <div class="col-2">
-                <small class="text-muted">
-                  <translate>Depthreference</translate>
-                </small>
-                <select
-                  v-model="depthReference"
-                  class="custom-select"
-                  id="depthreference"
-                >
-                  <option
-                    v-for="option in this.depthReferenceOptions"
-                    :key="option"
-                    >{{ option }}</option
-                  >
-                </select>
-                <span class="text-left text-danger">
-                  <small v-if="!depthReference">
-                    <translate>Please enter a reference</translate>
-                  </small>
-                </span>
-              </div>
-              <div class="col-3">
-                <small class="text-muted"> <translate>Date</translate> </small>
-                <input
-                  id="importdate"
-                  type="date"
-                  class="form-control"
-                  placeholder="Date of import"
-                  aria-label="bottleneck"
-                  aria-describedby="bottlenecklabel"
-                  v-model="importDate"
-                />
-                <span class="text-left text-danger">
-                  <small v-if="!importDate">
-                    <translate>Please enter a date</translate>
-                  </small>
-                </span>
-              </div>
-            </div>
-            <div class="row"></div>
-          </div>
-        </div>
-        <div class="container py-5">
-          <div v-if="uploadState" class="input-group">
-            <div class="custom-file">
-              <input
-                accept=".zip"
-                type="file"
-                @change="fileSelected"
-                class="custom-file-input"
-                id="uploadFile"
-              />
-              <label class="pointer custom-file-label" for="uploadFile">
-                {{ uploadLabel }}
-              </label>
-            </div>
-          </div>
-          <div class="d-flex justify-content-between" v-if="editState">
-            <a
-              download="meta.json"
-              :href="dataLink"
-              :class="[
-                'btn btn-outline-info',
-                { disabled: !bottleneck || !importDate || !depthReference }
-              ]"
-            >
-              <translate>Download Meta.json</translate>
-            </a>
-            <span>
-              <button
-                @click="deleteTempData"
-                class="btn btn-danger"
-                type="button"
-              >
-                <translate>Cancel Upload</translate>
-              </button>
-              <button
-                :disabled="disableUploadButton"
-                @click="confirm"
-                class="btn btn-info ml-2"
-                type="button"
-              >
-                <translate>Confirm</translate>
-              </button>
-            </span>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-/* 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 <markus.kottlaender@intevation.de>
- */
-import { HTTP } from "@/lib/http";
-import { displayError, displayInfo } from "@/lib/errors.js";
-import { mapState } from "vuex";
-
-const IMPORTSTATE = { UPLOAD: "UPLOAD", EDIT: "EDIT" };
-
-export default {
-  name: "imports",
-  components: {
-    Spacer: () => import("@/components/Spacer")
-  },
-  data() {
-    return {
-      importState: IMPORTSTATE.UPLOAD,
-      depthReference: "",
-      bottleneck: "",
-      projection: "",
-      importDate: "",
-      uploadLabel: this.$gettext("choose .zip- file"),
-      uploadFile: null,
-      disableUpload: false,
-      token: null,
-      messages: []
-    };
-  },
-  methods: {
-    initialState() {
-      this.importState = IMPORTSTATE.UPLOAD;
-      this.depthReference = "";
-      this.bottleneck = null;
-      this.projection = "";
-      this.importDate = "";
-      this.uploadLabel = this.$gettext("choose .zip- file");
-      this.uploadFile = null;
-      this.disableUpload = false;
-      this.token = null;
-      this.messages = [];
-    },
-    fileSelected(e) {
-      const files = e.target.files || e.dataTransfer.files;
-      if (!files) return;
-      this.uploadLabel = files[0].name;
-      this.uploadFile = files[0];
-      this.upload();
-    },
-    deleteTempData() {
-      HTTP.delete("/imports/sr-upload/" + this.token, {
-        headers: {
-          "X-Gemma-Auth": localStorage.getItem("token")
-        }
-      })
-        .then(() => {
-          this.initialState();
-        })
-        .catch(error => {
-          const { status, data } = error.response;
-          displayError({
-            title: this.$gettext("Backend Error"),
-            message: `${status}: ${data.message || data}`
-          });
-        });
-    },
-    upload() {
-      let formData = new FormData();
-      formData.append("soundingresult", this.uploadFile);
-      HTTP.post("/imports/sr-upload", formData, {
-        headers: {
-          "X-Gemma-Auth": localStorage.getItem("token"),
-          "Content-Type": "multipart/form-data"
-        }
-      })
-        .then(response => {
-          if (response.data.meta) {
-            const { bottleneck, date, epsg } = response.data.meta;
-            const depthReference = response.data.meta["depth-reference"];
-            this.bottleneck = this.bottlenecks.find(
-              bn => bn.properties.objnam === bottleneck
-            );
-            this.depthReference = depthReference;
-            this.importDate = new Date(date).toISOString().split("T")[0];
-            this.projection = epsg;
-          }
-          this.importState = IMPORTSTATE.EDIT;
-          this.token = response.data.token;
-          this.messages = response.data.messages;
-        })
-        .catch(error => {
-          const { status, data } = error.response;
-          const messages = data.messages ? data.messages.join(", ") : "";
-          displayError({
-            title: this.$gettext("Backend Error"),
-            message: `${status}: ${messages}`
-          });
-        });
-    },
-    confirm() {
-      let formData = new FormData();
-      formData.append("token", this.token);
-      if (this.bottleneck)
-        formData.append("bottleneck", this.bottleneck.properties.objnam);
-      if (this.importDate)
-        formData.append("date", this.importDate.split("T")[0]);
-      if (this.depthReference)
-        formData.append("depth-reference", this.depthReference);
-      if (this.projection) formData.append("", this.projection);
-
-      HTTP.post("/imports/sr", formData, {
-        headers: {
-          "X-Gemma-Auth": localStorage.getItem("token"),
-          "Content-Type": "multipart/form-data"
-        }
-      })
-        .then(() => {
-          displayInfo({
-            title: this.$gettext("Import"),
-            message:
-              this.$gettext("Starting import for ") +
-              this.bottleneck.properties.objnam
-          });
-          this.initialState();
-        })
-        .catch(error => {
-          const { status, data } = error.response;
-          displayError({
-            title: this.$gettext("Backend Error"),
-            message: `${status}: ${data.message || data}`
-          });
-        });
-    }
-  },
-  mounted() {
-    this.$store.dispatch("bottlenecks/loadBottlenecks");
-  },
-  watch: {
-    showContextBox() {
-      if (!this.showContextBox && this.token) this.deleteTempData();
-    }
-  },
-  computed: {
-    ...mapState("application", ["showContextBox"]),
-    ...mapState("bottlenecks", ["bottlenecks"]),
-    importSoundingresultsLabel() {
-      return this.$gettext("Import Soundingresults");
-    },
-    disableUploadButton() {
-      if (this.importState === IMPORTSTATE.UPLOAD) return this.disableUpload;
-      if (
-        !this.bottleneck ||
-        !this.importDate ||
-        !this.depthReference ||
-        !this.projection
-      )
-        return true;
-      return this.disableUpload;
-    },
-    availableBottlenecks() {
-      return this.bottlenecks;
-    },
-    editState() {
-      return this.importState === IMPORTSTATE.EDIT;
-    },
-    uploadState() {
-      return this.importState === IMPORTSTATE.UPLOAD;
-    },
-    Upload() {
-      return this.$gettext("Upload");
-    },
-    Confirm() {
-      return this.$gettext("Confirm");
-    },
-    dataLink() {
-      if (this.bottleneck && this.depthReference && this.import) {
-        return (
-          "data:text/json;charset=utf-8," +
-          encodeURIComponent(
-            JSON.stringify({
-              depthReference: this.depthReference,
-              bottleneck: this.bottleneck.properties.objnam,
-              date: this.importDate
-            })
-          )
-        );
-      }
-    },
-    depthReferenceOptions() {
-      if (
-        this.bottleneck &&
-        this.bottleneck.properties.reference_water_levels
-      ) {
-        return Object.keys(
-          JSON.parse(this.bottleneck.properties.reference_water_levels)
-        );
-      }
-      return [];
-    }
-  }
-};
-</script>
--- a/client/src/components/Sidebar.vue	Tue Apr 09 08:51:02 2019 +0200
+++ b/client/src/components/Sidebar.vue	Tue Apr 09 12:38:23 2019 +0200
@@ -43,12 +43,6 @@
           </router-link>
         </div>
         <div v-if="isWaterwayAdmin">
-          <small class="text-muted pl-3"> <translate>Import</translate> </small>
-          <hr class="m-0" />
-          <router-link to="/importsoundingresults">
-            <font-awesome-icon class="fa-fw mr-2" fixed-width icon="upload" />
-            <span class="fix-trans-space" v-translate>Soundingresults</span>
-          </router-link>
           <router-link to="/importschedule">
             <font-awesome-icon class="fa-fw mr-2" fixed-width icon="clock" />
             <translate class="fix-trans-space">Imports</translate>
--- a/client/src/components/importconfiguration/ImportDetails.vue	Tue Apr 09 08:51:02 2019 +0200
+++ b/client/src/components/importconfiguration/ImportDetails.vue	Tue Apr 09 12:38:23 2019 +0200
@@ -1,5 +1,8 @@
 <template>
   <div class="mt-3 mb-3 mr-3 ml-3">
+    <small class="text-muted">
+      <translate>Please choose an import type</translate>
+    </small>
     <select v-model="Import" class="custom-select" id="importtype">
       <optgroup :label="regularLabel">
         <option :value="$options.IMPORTTYPES.BOTTLENECK">
@@ -44,8 +47,16 @@
     </select>
     <ApprovedGaugeMeasurement
       v-if="Import === $options.IMPORTTYPES.APPROVEDGAUGEMEASUREMENTS"
+      class="mt-3"
     />
-    <WaterwayProfiles v-if="Import === $options.IMPORTTYPES.WATERWAYPROFILES" />
+    <WaterwayProfiles
+      class="mt-3"
+      v-if="Import === $options.IMPORTTYPES.WATERWAYPROFILES"
+    />
+    <SoundingResults
+      class="mt-3"
+      v-if="Import === $options.IMPORTTYPES.SOUNDINGRESULTS"
+    />
   </div>
 </template>
 
@@ -80,7 +91,8 @@
   components: {
     ApprovedGaugeMeasurement: () =>
       import("./ImportApprovedGaugeMeasurement.vue"),
-    WaterwayProfiles: () => import("./ImportWaterwayProfiles")
+    WaterwayProfiles: () => import("./ImportWaterwayProfiles"),
+    SoundingResults: () => import("./ImportSoundingresults.vue")
   },
   data() {
     return {};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/importconfiguration/ImportSoundingresults.vue	Tue Apr 09 12:38:23 2019 +0200
@@ -0,0 +1,350 @@
+<template>
+  <div>
+    <div v-if="editState" class="mb-3">
+      <div
+        v-for="(message, index) in messages"
+        :key="index"
+        class="alert alert-warning small rounded-0"
+      >
+        {{ message }}
+      </div>
+      <div class="d-flex flex-row w-100">
+        <div class="w-50 mr-2 text-left">
+          <small class="text-muted">
+            <translate>Bottleneck</translate>
+          </small>
+          <select v-model="bottleneck" class="custom-select">
+            <option
+              v-for="bottleneck in availableBottlenecks"
+              :value="bottleneck"
+              :key="bottleneck.properties.objnam"
+            >
+              {{ bottleneck.properties.objnam }}
+            </option>
+          </select>
+          <span class="text-danger">
+            <small v-if="!bottleneck">
+              <translate>Please select a bottleneck</translate>
+            </small>
+          </span>
+        </div>
+        <div class="w-50 ml-3 text-left">
+          <small class="text-muted">
+            <translate>Projection</translate>&nbsp;(EPSG)
+          </small>
+          <input
+            class="form-control"
+            v-model="projection"
+            value="4326"
+            placeholder="e.g. 4326"
+            type="number"
+          />
+          <span class="text-left text-danger">
+            <small v-if="!projection">
+              <translate>Please enter a projection</translate>
+            </small>
+          </span>
+        </div>
+      </div>
+      <div class="d-flex flex-row w-100 mt-3">
+        <div class="w-50 mr-2 text-left">
+          <small class="text-muted">
+            <translate>Depthreference</translate>
+          </small>
+          <select
+            v-model="depthReference"
+            class="custom-select"
+            id="depthreference"
+          >
+            <option
+              v-for="option in this.depthReferenceOptions"
+              :key="option"
+              >{{ option }}</option
+            >
+          </select>
+          <span class="text-left text-danger">
+            <small v-if="!depthReference">
+              <translate>Please enter a reference</translate>
+            </small>
+          </span>
+        </div>
+        <div class="w-50 ml-3 text-left">
+          <small class="text-muted"> <translate>Date</translate> </small>
+          <input
+            id="importdate"
+            type="date"
+            class="form-control"
+            placeholder="Date of import"
+            aria-label="bottleneck"
+            aria-describedby="bottlenecklabel"
+            v-model="importDate"
+          />
+          <span class="text-left text-danger">
+            <small v-if="!importDate">
+              <translate>Please enter a date</translate>
+            </small>
+          </span>
+        </div>
+      </div>
+    </div>
+    <div class="mt-3">
+      <div v-if="uploadState" class="input-group">
+        <div class="custom-file">
+          <input
+            accept=".zip"
+            type="file"
+            @change="fileSelected"
+            class="custom-file-input"
+            id="uploadFile"
+          />
+          <label class="pointer custom-file-label" for="uploadFile">
+            {{ uploadLabel }}
+          </label>
+        </div>
+      </div>
+      <div class="d-flex justify-content-between mt-3" v-if="editState">
+        <a
+          download="meta.json"
+          :href="dataLink"
+          :class="[
+            'btn btn-outline-info',
+            { disabled: !bottleneck || !importDate || !depthReference }
+          ]"
+        >
+          <translate>Download Meta.json</translate>
+        </a>
+        <span>
+          <button
+            :disabled="disableUploadButton"
+            @click="confirm"
+            class="btn btn-info mr-2"
+            type="button"
+          >
+            <translate>Confirm</translate>
+          </button>
+          <button :key="1" @click="deleteTempData()" class="btn btn-warning">
+            Back
+          </button>
+        </span>
+      </div>
+      <div v-if="uploadState" class="d-flex flex-row-100 mt-3">
+        <button :key="2" @click="back()" class="ml-auto btn btn-warning">
+          Back
+        </button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+/* 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 <markus.kottlaender@intevation.de>
+ */
+import { HTTP } from "@/lib/http";
+import { displayError, displayInfo } from "@/lib/errors.js";
+import { mapState } from "vuex";
+
+const IMPORTSTATE = { UPLOAD: "UPLOAD", EDIT: "EDIT" };
+
+export default {
+  data() {
+    return {
+      importState: IMPORTSTATE.UPLOAD,
+      depthReference: "",
+      bottleneck: "",
+      projection: "",
+      importDate: "",
+      uploadLabel: this.$gettext("choose .zip- file"),
+      uploadFile: null,
+      disableUpload: false,
+      token: null,
+      messages: []
+    };
+  },
+  methods: {
+    back() {
+      this.$store.commit("importschedule/setListMode");
+    },
+    initialState() {
+      this.importState = IMPORTSTATE.UPLOAD;
+      this.depthReference = "";
+      this.bottleneck = null;
+      this.projection = "";
+      this.importDate = "";
+      this.uploadLabel = this.$gettext("choose .zip- file");
+      this.uploadFile = null;
+      this.disableUpload = false;
+      this.token = null;
+      this.messages = [];
+    },
+    fileSelected(e) {
+      const files = e.target.files || e.dataTransfer.files;
+      if (!files) return;
+      this.uploadLabel = files[0].name;
+      this.uploadFile = files[0];
+      this.upload();
+    },
+    deleteTempData() {
+      HTTP.delete("/imports/sr-upload/" + this.token, {
+        headers: {
+          "X-Gemma-Auth": localStorage.getItem("token")
+        }
+      })
+        .then(() => {
+          this.initialState();
+        })
+        .catch(error => {
+          const { status, data } = error.response;
+          displayError({
+            title: this.$gettext("Backend Error"),
+            message: `${status}: ${data.message || data}`
+          });
+        });
+    },
+    upload() {
+      let formData = new FormData();
+      formData.append("soundingresult", this.uploadFile);
+      HTTP.post("/imports/sr-upload", formData, {
+        headers: {
+          "X-Gemma-Auth": localStorage.getItem("token"),
+          "Content-Type": "multipart/form-data"
+        }
+      })
+        .then(response => {
+          if (response.data.meta) {
+            const { bottleneck, date, epsg } = response.data.meta;
+            const depthReference = response.data.meta["depth-reference"];
+            this.bottleneck = this.bottlenecks.find(
+              bn => bn.properties.objnam === bottleneck
+            );
+            this.depthReference = depthReference;
+            this.importDate = new Date(date).toISOString().split("T")[0];
+            this.projection = epsg;
+          }
+          this.importState = IMPORTSTATE.EDIT;
+          this.token = response.data.token;
+          this.messages = response.data.messages;
+        })
+        .catch(error => {
+          const { status, data } = error.response;
+          const messages = data.messages ? data.messages.join(", ") : "";
+          displayError({
+            title: this.$gettext("Backend Error"),
+            message: `${status}: ${messages}`
+          });
+        });
+    },
+    confirm() {
+      let formData = new FormData();
+      formData.append("token", this.token);
+      if (this.bottleneck)
+        formData.append("bottleneck", this.bottleneck.properties.objnam);
+      if (this.importDate)
+        formData.append("date", this.importDate.split("T")[0]);
+      if (this.depthReference)
+        formData.append("depth-reference", this.depthReference);
+      if (this.projection) formData.append("", this.projection);
+
+      HTTP.post("/imports/sr", formData, {
+        headers: {
+          "X-Gemma-Auth": localStorage.getItem("token"),
+          "Content-Type": "multipart/form-data"
+        }
+      })
+        .then(() => {
+          displayInfo({
+            title: this.$gettext("Import"),
+            message:
+              this.$gettext("Starting import for ") +
+              this.bottleneck.properties.objnam
+          });
+          this.initialState();
+        })
+        .catch(error => {
+          const { status, data } = error.response;
+          displayError({
+            title: this.$gettext("Backend Error"),
+            message: `${status}: ${data.message || data}`
+          });
+        });
+    }
+  },
+  mounted() {
+    this.$store.dispatch("bottlenecks/loadBottlenecks");
+  },
+  watch: {
+    showContextBox() {
+      if (!this.showContextBox && this.token) this.deleteTempData();
+    }
+  },
+  computed: {
+    ...mapState("application", ["showContextBox"]),
+    ...mapState("bottlenecks", ["bottlenecks"]),
+    importSoundingresultsLabel() {
+      return this.$gettext("Import Soundingresults");
+    },
+    disableUploadButton() {
+      if (this.importState === IMPORTSTATE.UPLOAD) return this.disableUpload;
+      if (
+        !this.bottleneck ||
+        !this.importDate ||
+        !this.depthReference ||
+        !this.projection
+      )
+        return true;
+      return this.disableUpload;
+    },
+    availableBottlenecks() {
+      return this.bottlenecks;
+    },
+    editState() {
+      return this.importState === IMPORTSTATE.EDIT;
+    },
+    uploadState() {
+      return this.importState === IMPORTSTATE.UPLOAD;
+    },
+    Upload() {
+      return this.$gettext("Upload");
+    },
+    Confirm() {
+      return this.$gettext("Confirm");
+    },
+    dataLink() {
+      if (this.bottleneck && this.depthReference && this.import) {
+        return (
+          "data:text/json;charset=utf-8," +
+          encodeURIComponent(
+            JSON.stringify({
+              depthReference: this.depthReference,
+              bottleneck: this.bottleneck.properties.objnam,
+              date: this.importDate
+            })
+          )
+        );
+      }
+    },
+    depthReferenceOptions() {
+      if (
+        this.bottleneck &&
+        this.bottleneck.properties.reference_water_levels
+      ) {
+        return Object.keys(
+          JSON.parse(this.bottleneck.properties.reference_water_levels)
+        );
+      }
+      return [];
+    }
+  }
+};
+</script>
--- a/client/src/router.js	Tue Apr 09 08:51:02 2019 +0200
+++ b/client/src/router.js	Tue Apr 09 12:38:23 2019 +0200
@@ -81,22 +81,6 @@
       }
     },
     {
-      path: "/importsoundingresults",
-      name: "importsoundingresults",
-      component: () => import("./components/ImportSoundingresults.vue"),
-      meta: {
-        requiresAuth: true
-      },
-      beforeEnter: (to, from, next) => {
-        const isWaterwayAdmin = store.getters["user/isWaterwayAdmin"];
-        if (!isWaterwayAdmin) {
-          next("/login");
-        } else {
-          next();
-        }
-      }
-    },
-    {
       path: "/importschedule",
       name: "importschedule",
       component: () => import("./components/importschedule/Importschedule.vue"),