changeset 4612:a5dccbc5920d geoserver_sql_views

Merge default into geoserver_sql_views
author Tom Gottfried <tom@intevation.de>
date Fri, 06 Sep 2019 16:26:34 +0200
parents b5aa1eb83bb0 (current diff) 6a1fef54d49f (diff)
children 0c5829ff4dea
files pkg/geoserver/boot.go
diffstat 5 files changed, 126 insertions(+), 381 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/importoverview/LogDetail.vue	Fri Sep 06 11:58:03 2019 +0200
+++ b/client/src/components/importoverview/LogDetail.vue	Fri Sep 06 16:26:34 2019 +0200
@@ -102,7 +102,7 @@
       return this.kind === "BN" || this.kind === "UBN";
     },
     isST() {
-      return this.kind === "ST";
+      return this.kind === "STSH";
     },
     isSEC() {
       return this.kind === "SEC";
--- a/client/src/components/importoverview/StretchDetails.vue	Fri Sep 06 11:58:03 2019 +0200
+++ b/client/src/components/importoverview/StretchDetails.vue	Fri Sep 06 16:26:34 2019 +0200
@@ -5,30 +5,32 @@
       split: showLogs
     }"
   >
-    <div v-if="!details.summary.stretch" class="d-flex">
-      <UISpinnerButton
-        @click="showDetails = !showDetails"
-        :state="showDetails"
-        :icons="['angle-right', 'angle-down']"
-        classes="text-info"
-      />
-      <a @click="zoomToStretch()" class="text-info pointer"
-        >{{ details.summary.objnam }} (
-        {{ details.summary.countries.join(", ") }} )</a
+    <div v-if="details.summary.length > 0" class="d-flex flex-column">
+      <div
+        class="d-flex"
+        v-for="(stretch, index) in details.summary"
+        :key="index"
       >
-    </div>
-    <div>
-      <div v-if="showDetails">
+        <UISpinnerButton
+          @click="showDetailsFor(index)"
+          :state="showDetails == index"
+          :icons="['angle-right', 'angle-down']"
+          classes="text-info"
+        /><a @click="zoomToStretch(stretch)" class="text-info pointer">{{
+          linkText(stretch)
+        }}</a>
+      </div>
+      <div v-if="showDetails !== $options.NODETAILS">
         <div
-          v-for="(entry, index) in Object.keys(details.summary)"
+          v-for="(entry, index) in Object.keys(selectedDetails)"
           :key="index"
-          class="comparison row no-gutters px-4 text-left"
+          class="d-flex comparison row no-gutters px-4 text-left"
         >
           <span class="col-4">{{ entry }}</span>
           <span v-if="entry === 'countries'" class="col-4">{{
-            details.summary[entry].join(", ")
+            listCountries(selectedDetails[entry])
           }}</span>
-          <span v-else class="col-4">{{ details.summary[entry] }}</span>
+          <span v-else class="col-4">{{ selectedDetails[entry] }}</span>
         </div>
       </div>
     </div>
@@ -71,10 +73,12 @@
 import { displayError } from "@/lib/errors";
 import { mapState, mapGetters } from "vuex";
 
+const NODETAILS = -99;
+
 export default {
   data() {
     return {
-      showDetails: true
+      showDetails: NODETAILS
     };
   },
   props: ["entry"],
@@ -83,11 +87,34 @@
   },
   computed: {
     ...mapState("imports", ["showAdditional", "showLogs", "details"]),
-    ...mapGetters("map", ["openLayersMap"])
+    ...mapGetters("map", ["openLayersMap"]),
+    selectedDetails() {
+      if (this.showDetails === NODETAILS) return [];
+      return this.details.summary[this.showDetails];
+    }
   },
   methods: {
-    zoomToStretch() {
-      const { name } = this.details.summary;
+    listCountries(countries) {
+      if (!countries) return "";
+      return countries.join(", ");
+    },
+    showDetailsFor(index) {
+      if (index === this.showDetails) {
+        this.showDetails = NODETAILS;
+        return;
+      }
+      this.showDetails = index;
+    },
+    linkText(stretch) {
+      const name = stretch.objnam;
+      const { countries } = stretch;
+      const countryNames = !countries
+        ? ""
+        : `(${this.listCountries(countries)})`;
+      return `${name} ${countryNames}`;
+    },
+    zoomToStretch(stretch) {
+      const { name } = stretch;
       this.openLayersMap()
         .getLayer("STRETCHES")
         .setVisible(true);
@@ -115,6 +142,7 @@
           });
         });
     }
-  }
+  },
+  NODETAILS: NODETAILS
 };
 </script>
--- a/client/src/components/stretches/StretchForm.vue	Fri Sep 06 11:58:03 2019 +0200
+++ b/client/src/components/stretches/StretchForm.vue	Fri Sep 06 16:26:34 2019 +0200
@@ -1,194 +1,17 @@
 <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>
+    <div class="ml-2 mr-2 my-3">
+      <div class="custom-file mt-3">
         <input
-          id="id"
-          type="text"
-          class="form-control form-control-sm"
-          placeholder="AT_Stretch_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"
+          accept=".zip,.txt"
+          type="file"
+          @change="fileSelected"
+          class="custom-file-input"
+          id="uploadFile"
         />
-        <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>
+        <label class="pointer custom-file-label" for="uploadFile">
+          {{ uploadLabel }}
+        </label>
       </div>
     </div>
     <div class="d-flex justify-content-between mt-2 p-2 border-top">
@@ -199,6 +22,7 @@
         @click="save"
         type="submit"
         class="shadow-sm btn btn-sm btn-info submit-button"
+        :disabled="!uploadFile"
       >
         <translate>Submit</translate>
       </button>
@@ -206,14 +30,6 @@
   </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.
@@ -230,155 +46,55 @@
  * 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";
+import { HTTP } from "@/lib/http";
 
 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
-      }
+      uploadLabel: this.$gettext(this.$options.UPLOADLABEL),
+      uploadFile: null
     };
   },
-  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);
-      }
+  computed: {},
+  methods: {
+    initialState() {
+      this.uploadFile = null;
+      this.uploadLabel = this.$options.UPLOADLABEL;
+      this.$parent.showForm = false;
+    },
+    fileSelected(e) {
+      const files = e.target.files || e.dataTransfer.files;
+      if (!files) return;
+      this.uploadLabel = files[0].name;
+      this.uploadFile = files[0];
+    },
+    save() {
+      let formData = new FormData();
+      formData.append("stsh", this.uploadFile);
+      HTTP.post(`/imports/stsh`, formData, {
+        headers: {
+          "X-Gemma-Auth": localStorage.getItem("token")
+        }
+      })
+        .then(() => {
+          displayInfo({
+            title: this.$gettext("Import"),
+            message: this.$gettext("Upload of stretch complete")
+          });
+          this.initialState();
+        })
+        .catch(error => {
+          const { status, data } = error.response;
+          displayError({
+            title: this.$gettext("Backend Error"),
+            message: `${status}: ${data.message || data}`
+          });
+        });
     }
   },
-  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;
-    }
-  }
+  mounted() {},
+  UPLOADLABEL: "choose a .zip shapefile"
 };
 </script>
--- a/client/src/lib/mixins.js	Fri Sep 06 11:58:03 2019 +0200
+++ b/client/src/lib/mixins.js	Fri Sep 06 16:26:34 2019 +0200
@@ -483,8 +483,8 @@
         width = this.pdf.doc.getTextWidth(text) + 2 * padding;
       }
       let textWidth = width - 2 * padding;
+      let textLines = this.pdf.doc.splitTextToSize(text, textWidth);
       if (!height) {
-        let textLines = this.pdf.doc.splitTextToSize(text, textWidth);
         height = this.getTextHeight(textLines.length) + 2 * padding;
       }
       this.addBox(
@@ -499,7 +499,7 @@
       if (["bottomright", "bottomleft"].indexOf(position) !== -1) {
         this.addText(
           position,
-          { x: offset.x + padding, y: offset.y - padding / 2 },
+          { x: offset.x + padding, y: offset.y },
           textWidth,
           fontSize,
           color,
@@ -508,7 +508,10 @@
       } else {
         this.addText(
           position,
-          { x: offset.x + padding, y: offset.y + padding * 2 },
+          {
+            x: offset.x + padding,
+            y: offset.y + height - this.getTextHeight(textLines.length)
+          },
           textWidth,
           fontSize,
           color,
--- a/pkg/geoserver/boot.go	Fri Sep 06 11:58:03 2019 +0200
+++ b/pkg/geoserver/boot.go	Fri Sep 06 16:26:34 2019 +0200
@@ -567,28 +567,26 @@
 
 	// Third associate with layer
 
-	if create {
-		req, err := http.NewRequest(
-			http.MethodPost,
-			geoURL+"/rest/layers/"+
-				url.PathEscape(workspaceName+":"+entry.Name)+
-				"/styles?default=true",
-			toStream(&styleFilename))
-		if err != nil {
-			return err
-		}
-		auth(req)
-		asJSON(req)
+	req, err = http.NewRequest(
+		http.MethodPost,
+		geoURL+"/rest/layers/"+
+			url.PathEscape(workspaceName+":"+entry.Name)+
+			"/styles?default=true",
+		toStream(&styleFilename))
+	if err != nil {
+		return err
+	}
+	auth(req)
+	asJSON(req)
 
-		resp, err = http.DefaultClient.Do(req)
-		if err != nil {
-			return err
-		}
+	resp, err = http.DefaultClient.Do(req)
+	if err != nil {
+		return err
+	}
 
-		if resp.StatusCode != http.StatusCreated {
-			return fmt.Errorf("cannot connect style %s with layer (%s)",
-				entry.Name, http.StatusText(resp.StatusCode))
-		}
+	if resp.StatusCode != http.StatusCreated {
+		return fmt.Errorf("cannot connect style %s with layer (%s)",
+			entry.Name, http.StatusText(resp.StatusCode))
 	}
 
 	return nil