diff client/src/components/stretches/StretchForm.vue @ 3289:c2cba529658d

client: define stretches: seperated list and form into two components
author Markus Kottlaender <markus@intevation.de>
date Thu, 16 May 2019 12:50:20 +0200
parents
children c9b60130cdfb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/stretches/StretchForm.vue	Thu May 16 12:50:20 2019 +0200
@@ -0,0 +1,384 @@
+<template>
+  <div class="d-flex flex-column">
+    <div class="d-flex justify-content-between mt-2 px-2">
+      <div class="text-left flex-fill mr-1">
+        <small class="text-muted">
+          <translate>ID</translate>
+        </small>
+        <input
+          id="id"
+          type="text"
+          class="form-control form-control-sm"
+          placeholder="AT_Section_12"
+          v-model="id"
+          :disabled="editStretch"
+        />
+        <span class="text-left text-danger">
+          <small v-if="errors.id && !id">
+            <translate>Please enter an id</translate>
+          </small>
+        </span>
+      </div>
+      <div class="text-left flex-fill ml-1">
+        <small class="text-muted">
+          <translate>Countrycode</translate>
+        </small>
+        <input
+          id="countryCode"
+          type="text"
+          class="form-control form-control-sm"
+          placeholder="AT"
+          v-model="countryCode"
+        />
+        <span class="text-left text-danger">
+          <small v-if="errors.countryCode && !countryCode">
+            <translate>Please enter a countrycode </translate>
+          </small>
+        </span>
+      </div>
+    </div>
+    <div class="d-flex justify-content-between mt-2 px-2">
+      <div class="text-left flex-fill">
+        <small class="text-muted">
+          <translate>Start rhm</translate>
+        </small>
+        <div class="d-flex flex-row position-relative">
+          <input
+            id="startrhm"
+            type="text"
+            class="form-control form-control-sm"
+            placeholder="e.g. ATXXX000010000019900"
+            v-model="startrhm"
+            ref="startrhm"
+            @focus="enablePipette('start')"
+            @blur="disablePipette('start')"
+          />
+          <span
+            class="input-group-text position-absolute input-button"
+            @click="$refs.startrhm.focus()"
+            v-tooltip="pipetteTooltip"
+          >
+            <font-awesome-icon
+              :class="{ 'text-info': pipetteStart }"
+              icon="crosshairs"
+            />
+          </span>
+        </div>
+        <span class="text-left text-danger">
+          <small v-if="errors.startrhm && !startrhm">
+            <translate>Please enter a start point</translate>
+          </small>
+        </span>
+      </div>
+      <div class="text-left flex-fill ml-2">
+        <small class="text-muted">
+          <translate>End rhm</translate>
+        </small>
+        <div class="d-flex flex-row position-relative">
+          <input
+            id="endrhm"
+            type="text"
+            class="form-control form-control-sm"
+            placeholder="e.g. ATXXX000010000019900"
+            v-model="endrhm"
+            ref="endrhm"
+            @focus="enablePipette('end')"
+            @blur="disablePipette('end')"
+          />
+          <span
+            class="input-group-text position-absolute input-button"
+            @click="$refs.endrhm.focus()"
+            v-tooltip="pipetteTooltip"
+          >
+            <font-awesome-icon
+              :class="{ 'text-info': pipetteEnd }"
+              icon="crosshairs"
+            />
+          </span>
+        </div>
+        <span class="text-left text-danger">
+          <small v-if="errors.endrhm && !endrhm">
+            <translate>Please enter an end point</translate>
+          </small>
+        </span>
+      </div>
+      <div class="text-left ml-2" v-if="!editStretch">
+        <small class="text-muted">
+          <translate>Tolerance for snapping to axis</translate>
+        </small>
+        <div class="d-flex flex-row position-relative">
+          <input
+            class="form-control form-control-sm"
+            v-model.number="tolerance"
+            type="number"
+            min="0"
+            step="any"
+            id="tolerance"
+          />
+          <span class="input-group-text position-absolute input-button">
+            m
+          </span>
+        </div>
+        <span class="text-left text-danger">
+          <small v-if="errors.tolerance && !tolerance">
+            <translate>Please enter a tolerance value</translate>
+          </small>
+        </span>
+      </div>
+    </div>
+    <div class="d-flex flex-row justify-content-between px-2">
+      <div class="mt-2 mr-2 w-50 text-left">
+        <small class="text-muted">
+          <translate>Object name</translate>
+        </small>
+        <input
+          id="objbn"
+          type="text"
+          class="form-control form-control-sm"
+          placeholder=""
+          v-model="objbn"
+        />
+        <span class="text-left text-danger">
+          <small v-if="errors.objbn && !objbn">
+            <translate>Please enter an objectname</translate>
+          </small>
+        </span>
+      </div>
+      <div class="mt-2 w-50 text-left">
+        <small class="text-muted">
+          <translate>National Object name</translate>
+        </small>
+        <input
+          id="nobjbn"
+          type="text"
+          class="form-control form-control-sm"
+          v-model="nobjbn"
+        />
+      </div>
+    </div>
+    <div class="d-flex flex-row justify-content-between px-2">
+      <div class="mt-2 w-50 text-left">
+        <small class="text-muted">
+          <translate>Date info</translate>
+        </small>
+        <input
+          id="date_info"
+          type="date"
+          class="form-control form-control-sm"
+          placeholder="date_info"
+          v-model="date_info"
+        />
+        <span class="text-left text-danger">
+          <small v-if="errors.date_info && !date_info">
+            <translate>Please enter a date</translate>
+          </small>
+        </span>
+      </div>
+      <div class="mt-2 ml-2 w-50 text-left">
+        <small class="text-muted">
+          <translate>Source Organization</translate>
+        </small>
+        <input
+          id="source_organization"
+          type="text"
+          class="form-control form-control-sm"
+          v-model="source_organization"
+        />
+        <span class="text-left text-danger">
+          <small v-if="errors.source_organization && !source_organization">
+            <translate>Please enter a source organization</translate>
+          </small>
+        </span>
+      </div>
+    </div>
+    <div class="d-flex justify-content-between mt-2 p-2 border-top">
+      <button @click="$parent.showForm = false" class="btn btn-sm btn-warning">
+        <translate>Back</translate>
+      </button>
+      <button
+        @click="save"
+        type="submit"
+        class="shadow-sm btn btn-sm btn-info submit-button"
+      >
+        <translate>Submit</translate>
+      </button>
+    </div>
+  </div>
+</template>
+
+<style lang="sass" scoped>
+.input-button
+  border-top-left-radius: 0
+  border-bottom-left-radius: 0
+  right: 0
+  height: 31px
+</style>
+
+<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, 2019 by via donau
+ *   – Österreichische Wasserstraßen-Gesellschaft mbH
+ * Software engineering by Intevation GmbH
+ *
+ * Author(s):
+ * Thomas Junk <thomas.junk@intevation.de>
+ * Tom Gottfried <tom.gottfried@intevation.de>
+ * Markus Kottländer <markus.kottlaender@intevation.de>
+ */
+import { mapState, mapGetters } from "vuex";
+import { displayError, displayInfo } from "@/lib/errors";
+import { sortTable } from "@/lib/mixins";
+
+export default {
+  mixins: [sortTable],
+  props: ["editStretch"],
+  data() {
+    return {
+      pipetteStart: false,
+      pipetteEnd: false,
+      id: null,
+      startrhm: null,
+      endrhm: null,
+      tolerance: 5,
+      objbn: null,
+      nobjbn: null,
+      date_info: new Date().toISOString().split("T")[0],
+      source_organization: null,
+      countryCode: null,
+      errors: {
+        id: false,
+        startrhm: false,
+        endrhm: false,
+        tolerance: false,
+        objbn: false,
+        nobjbn: false,
+        date_info: false,
+        source_organization: false,
+        countryCode: false
+      }
+    };
+  },
+  computed: {
+    ...mapState("map", ["identifiedFeatures"]),
+    ...mapGetters("map", ["openLayersMap"]),
+    pipetteTooltip() {
+      return this.$gettext("Choose a distance mark by clicking on the map.");
+    }
+  },
+  watch: {
+    identifiedFeatures() {
+      const distanceMark = this.identifiedFeatures.find(x =>
+        /^distance_marks_geoserver/.test(x["id_"])
+      );
+      if (distanceMark) {
+        const location = distanceMark.get("location");
+        this.startrhm = this.pipetteStart ? location : this.startrhm;
+        this.endrhm = this.pipetteEnd ? location : this.endrhm;
+        this.pipetteStart = false;
+        this.pipetteEnd = false;
+        this.$store.commit("map/mapPopupEnabled", true);
+      }
+    }
+  },
+  methods: {
+    enablePipette(t) {
+      this.openLayersMap()
+        .getLayer("DISTANCEMARKSAXIS")
+        .setVisible(true);
+      this.$store.commit("map/mapPopupEnabled", false);
+      if (t === "start") {
+        this.pipetteStart = true;
+        this.pipetteEnd = false;
+      } else {
+        this.pipetteStart = false;
+        this.pipetteEnd = true;
+      }
+    },
+    disablePipette() {
+      this.$store.commit("map/mapPopupEnabled", true);
+      this.pipetteStart = false;
+      this.pipetteEnd = false;
+    },
+    validate() {
+      const fields = [
+        "id",
+        "startrhm",
+        "endrhm",
+        "objbn",
+        "countryCode",
+        "date_info",
+        "source_organization"
+      ];
+      if (!this.editStretch) fields.push("tolerance");
+      fields.forEach(field => {
+        if (!this[field]) {
+          this.errors[field] = true;
+        } else {
+          this.errors[field] = false;
+        }
+      });
+
+      // return true if no errors
+      return !Object.values(this.errors).reduce((a, b) => a + b, 0);
+    },
+    save() {
+      if (this.validate()) {
+        const data = {
+          name: this.id,
+          from: this.startrhm,
+          to: this.endrhm,
+          "source-organization": this.source_organization,
+          "date-info": this.date_info,
+          objnam: this.objbn,
+          nobjnam: this.nobjbn,
+          countries: this.countryCode.split(",").map(x => {
+            return x.trim();
+          })
+        };
+        if (!this.editStretch) {
+          data["tolerance"] = this.tolerance;
+        }
+        this.$parent.loading = true;
+        this.$store
+          .dispatch("imports/saveStretch", data)
+          .then(() => {
+            displayInfo({
+              title: this.$gettext("Import"),
+              message: this.$gettext("Starting import of stretch")
+            });
+            this.$store.dispatch("imports/loadStretches").then(() => {
+              this.$parent.loading = false;
+              this.$parent.showForm = false;
+            });
+          })
+          .catch(error => {
+            const { status, data } = error.response;
+            displayError({
+              title: this.$gettext("Backend Error"),
+              message: `${status}: ${data.message || data}`
+            });
+          });
+      }
+    }
+  },
+  mounted() {
+    if (this.editStretch) {
+      const props = this.editStretch.properties;
+      this.id = props.name;
+      this.startrhm = props.lower.replace(/[,()]/g, "");
+      this.endrhm = props.upper.replace(/[,()]/g, "");
+      this.tolerance = props.tolerance;
+      this.objbn = props.objnam;
+      this.nobjbn = props.nobjnam;
+      this.date_info = props.date_info.split("T")[0];
+      this.source_organization = props.source_organization;
+      this.countryCode = props.countries;
+    }
+  }
+};
+</script>