Mercurial > gemma
view client/src/components/ImportStretches.vue @ 2624:9dbaf69c7a66
Improve geoserver config to better calculate bounding boxes
* Disable the use of estimated extents for the postgis storage
configuration for geoserver, which is set via the gemma middleware.
This way we are able to get better bounding boxes for many layers
where the postgis function `ST_EstimatedExtent()` would be far off.
author | Bernhard Reiter <bernhard@intevation.de> |
---|---|
date | Wed, 13 Mar 2019 16:18:39 +0100 |
parents | 8d767359fddb |
children | 4bcb26542767 |
line wrap: on
line source
<template> <div class="d-flex flex-column mb-3"> <UIBoxHeader icon="road" title="Define Stretches" :closeCallback="$parent.close" /> <div v-if="!edit" class="mb-3"> <UITableHeader :columns="[ { id: 'name', title: 'Name', class: 'col-4' }, { id: 'date', title: 'Date', class: 'col-2' }, { id: 'srcorg', title: 'Source organization', class: 'col-3' } ]" :sortable="false" /> <UITableBody :data="stretches" v-slot="{ item: stretch }"> <div class="py-2 col-4 "> <a class="linkto text-info" v-if="isInStaging(stretch.properties.name)" @click="gotoStaging(getStagingLink(stretch.properties.name))" > {{ stretch.properties.name }}<font-awesome-icon class="ml-1 text-danger" icon="exclamation-triangle" fixed-width ></font-awesome-icon ><small class="ml-1">review</small> </a> <a v-else @click="moveMapToStretch(stretch)" href="#">{{ stretch.properties.name }}</a> </div> <div class="py-2 col-2"> {{ stretch.properties["date_info"] | surveyDate }} </div> <div class="py-2 col-3"> {{ stretch.properties["source_organization"] }} </div> <div class="py-2 col text-right"> <button class="btn btn-sm btn-dark mr-1" @click="editStretch(stretch)" > <font-awesome-icon icon="pencil-alt" fixed-width /> </button> <button class="btn btn-sm btn-dark" @click="deleteStretch(stretch)"> <font-awesome-icon icon="trash" fixed-width /> </button> </div> </UITableBody> </div> <div v-if="edit"> <div class="ml-3 mr-3"> <div class="d-flex flex-row justify-content-between"> <div class="mt-2 w-50 mr-2 text-left"> <small class="text-muted"> <translate>ID</translate> </small> <input id="id" type="text" class="form-control" placeholder="AT_Section_12" aria-label="id" v-model="id" :disabled="editExistingStretch" /> <span class="text-left text-danger"> <small v-if="idError && !id"> <translate>Please enter an id</translate> </small> </span> </div> <div class="mt-2 w-50 ml-2 text-left"> <div> <small class="text-muted"> <translate>Countrycode</translate> </small> <input id="countryCode" type="text" class="form-control" placeholder="AT" aria-label="id" v-model="countryCode" /> <span class="text-left text-danger"> <small v-if="countryCodeError && !countryCode"> <translate>Please enter a countrycode </translate> </small> </span> </div> <div class="w-50 ml-2"></div> </div> </div> <div class="d-flex flex-column justify-content-between"> <div class="mt-2 text-left"> <small class="text-muted"> <translate>Start rhm</translate> </small> <div class="d-flex flex-row"> <input id="startrhm" type="text" class="form-control" placeholder="e.g. ATXXX000010000019900" aria-label="startrhm" v-model="startrhm" /> <span class="input-group-text"> <font-awesome-icon @click="togglePipette('start')" :class="{ 'text-info': pipetteStart }" icon="bullseye" ></font-awesome-icon> </span> </div> <span class="text-left text-danger"> <small v-if="startrhmError && !startrhm"> <translate>Please enter a start point</translate> </small> </span> </div> <div class="mt-2 text-left"> <small class="text-muted"> <translate>End rhm</translate> </small> <div class="d-flex flex-row"> <input id="endrhm" type="text" class="form-control" placeholder="e.g. ATXXX000010000019900" aria-label="endrhm" v-model="endrhm" /> <span class="input-group-text"> <font-awesome-icon @click="togglePipette('end')" :class="{ 'text-info': pipetteEnd }" icon="bullseye" ></font-awesome-icon> </span> </div> <span class="text-left text-danger"> <small v-if="endrhmError && !endrhm"> <translate>Please enter an end point</translate> </small> </span> </div> <span class="text-left text-danger"> <small v-if="!pointsValid"> <translate>Startpoint is not before endpoint.</translate> </small> </span> </div> <div v-if="!editExistingStretch" class="d-flex flex-row justify-content-between" > <div class="mt-2 mr-2 w-50 text-left"> <small class="text-muted"> <translate>Tolerance for snapping of waterway axis [m]</translate> </small> <input class="form-control" v-model.number="tolerance" placeholder="" type="number" min="0" step="any" aria-label="tolerance" id="tolerance" /> <span class="text-left text-danger"> <small v-if="toleranceError && !tolerance"> <translate>Please enter a tolerance value</translate> </small> </span> </div> </div> <div class="d-flex flex-row justify-content-between"> <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" placeholder="" aria-label="objbn" v-model="objbn" /> <span class="text-left text-danger"> <small v-if="objbnError && !objbn"> <translate>Please enter an objectname</translate> </small> </span> </div> <div class="mt-2 ml-2 w-50 text-left"> <small class="text-muted"> <translate>National Object name</translate> </small> <input id="nobjbn" type="text" class="form-control" placeholder="" aria-label="nobjbn" v-model="nobjbn" /> </div> </div> <div class="d-flex flex-row justify-content-between"> <div class="mt-2 mr-2 w-50 text-left"> <small class="text-muted"> <translate>Date info</translate> </small> <input id="date_info" type="date" class="form-control" placeholder="date_info" aria-label="date_info" v-model="date_info" /> <span class="text-left text-danger"> <small v-if="date_infoError && !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</translate> </small> <input id="source" type="text" class="form-control" placeholder="source" aria-label="source" v-model="source" /> <span class="text-left text-danger"> <small v-if="sourceError && !source"> <translate>Please enter a source</translate> </small> </span> </div> </div> </div> <div class="text-right mt-2 mr-3 mb-3"> <button @click="edit = false" class="btn btn-warning mr-2">Back</button> <button @click="save" type="submit" class="shadow-sm btn btn-info submit-button" > <translate>Submit</translate> </button> </div> </div> <div class="text-right mr-3"> <button v-if="!edit" @click="startEdit()" class="btn btn-info"> <translate>New stretch</translate> </button> </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, 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> */ import { mapState, mapGetters } from "vuex"; import { displayError, displayInfo } from "@/lib/errors.js"; import { LAYERS } from "@/store/map.js"; export default { name: "importstretches", data() { return { edit: false, editExistingStretch: false, id: "", funktion: "", startrhm: "", endrhm: "", tolerance: 5, objbn: "", nobjbn: "", countryCode: "", date_info: new Date().toISOString().split("T")[0], source: "", pipetteStart: false, pipetteEnd: false, idError: false, funktionError: false, startrhmError: false, endrhmError: false, toleranceError: false, objbnError: false, nobjbnError: false, date_infoError: false, sourceError: false, countryCodeError: false }; }, mounted() { this.edit = false; this.loadStretches().catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); this.loadStagingData().catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); }, methods: { gotoStaging(id) { this.$router.push("/review/" + id); }, isInStaging(stretchname) { for (let s of this.stretchesInStaging) { if (s.name == stretchname) return true; } return false; }, getStagingLink(stretchname) { for (let s of this.stretchesInStaging) { if (s.name == stretchname) return s.id; } }, loadStagingData() { return new Promise((resolve, reject) => { this.$store .dispatch("imports/getStaging") .then(response => { resolve(response); }) .catch(error => { reject(error); }); }); }, editStretch(stretch) { const properties = stretch.properties; this.date_info = properties.date_info.split("T")[0]; this.id = properties.name; this.nobjbn = properties.nobjnam; this.objbn = properties.objnam; this.countryCode = properties.countries; this.source = properties["source_organization"]; this.edit = true; this.startrhm = properties.lower; this.endrhm = properties.upper; this.editExistingStretch = true; }, deleteStretch(stretch) { this.$store.commit("application/popup", { icon: "trash", title: this.$gettext("Delete Stretch"), content: this.$gettext("Do you really want to delete this stretch:") + `<br> <b>${stretch.properties.name}, ${ stretch.properties.source_organization } (${stretch.properties.countries})</b>`, confirm: { label: this.$gettext("Delete"), icon: "trash", callback: () => { displayInfo({ title: this.$gettext("Not implemented"), message: this.$gettext("Deleting ") + stretch.id }); } }, cancel: { label: this.$gettext("Cancel"), icon: "times" } }); }, moveMapToStretch(stretch) { this.$store.commit("map/setLayerVisible", LAYERS.STRETCHES); this.$store.commit("map/moveToExtent", { feature: stretch, zoom: 17, preventZoomOut: true }); }, loadStretches() { return new Promise((resolve, reject) => { this.$store .dispatch("imports/loadStretches") .then(response => { resolve(response); }) .catch(error => { reject(error); }); }); }, clean() { this.id = ""; this.edit = false; this.editExistingStretch = false; this.funktion = ""; this.startrhm = ""; this.tolerance = 5; this.endrhm = ""; this.objbn = ""; this.nobjbn = ""; this.countryCode = ""; this.date_info = new Date().toISOString().split("T")[0]; this.source = ""; this.pipetteStart = false; this.pipetteEnd = false; this.idError = false; this.funktionError = false; this.startrhmError = false; this.endrhmError = false; this.toleranceError = false; this.objbnError = false; this.nobjbnError = false; this.date_infoError = false; this.sourceError = false; this.countryCodeError = false; }, startEdit() { this.clean(); this.edit = true; }, togglePipette(t) { this.$store.commit("map/setLayerVisible", LAYERS.DISTANCEMARKSAXIS); if (t === "start") { this.pipetteStart = !this.pipetteStart; this.pipetteEnd = false; } else { this.pipetteEnd = !this.pipetteEnd; this.pipetteStart = false; } }, validate() { const fields = [ "id", "funktion", "startrhm", "tolerance", "endrhm", "objbn", "nobjbn", "countryCode", "date_info", "source" ]; fields.forEach(field => { if (!this[field]) { this[field + "Error"] = true; } else { this[field + "Error"] = false; } }); }, save() { this.validate(); if (!this.pointsValid) return; if ( !this.id || !this.startrhm || !this.endrhm || (!this.tolerance && this.editExistingStretch) || !this.source || !this.date_info || !this.objbn || !this.countryCode ) return; const data = { name: this.id, from: this.startrhm, to: this.endrhm, "source-organization": this.source, "date-info": this.date_info, objnam: this.objbn, nobjnam: this.nobjbn, countries: this.countryCode.split(",").map(x => { return x.trim(); }) }; if (!this.editExistingStretch) { data["tolerance"] = this.tolerance; } this.$store .dispatch("imports/saveStretch", data) .then(() => { displayInfo({ title: this.$gettext("Import"), message: this.$gettext("Starting import of stretch") }); this.clean(); this.loadStretches().then(() => { this.edit = false; }); }) .catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); } }, watch: { identifiedFeatures() { const filterDistanceMarks = x => { return /^distance_marks/.test(x["id_"]); }; const distanceMark = this.identifiedFeatures.filter(filterDistanceMarks); if (distanceMark.length > 0) { const value = distanceMark[0].getProperties()["location"]; this.startrhm = this.pipetteStart ? value : this.startrhm; this.endrhm = this.pipetteEnd ? value : this.endrhm; this.pipetteStart = false; this.pipetteEnd = false; } } }, computed: { ...mapState("map", ["identifiedFeatures", "currentMeasurement"]), ...mapGetters("user", ["isSysAdmin"]), ...mapState("imports", ["stretches", "staging"]), stretchesInStaging() { const result = []; for (let stretch of this.stretches) { for (let s of this.staging) { if (s.kind == "st" && s.summary.stretch == stretch.properties.name) { result.push({ name: s.summary.stretch, id: s.id }); } } } return result; }, pointsValid() { if (!this.startrhm || !this.endrhm) return true; const start = this.startrhm.replace(/\D+/g, "") * 1; const end = this.endrhm.replace(/\D+/g, "") * 1; const result = start < end; return result; } } }; </script> <style lang="scss" scoped> .linkto { cursor: pointer; } </style>