Mercurial > gemma
view client/src/components/ImportStretches.vue @ 2704:84145179ec72
import_overview: open logs and details in parallel
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Mon, 18 Mar 2019 15:56:54 +0100 |
parents | 9f3856337f55 |
children | add2d47c2567 |
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-1 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-1 col-2"> {{ stretch.properties["date_info"] | surveyDate }} </div> <div class="py-1 col-3"> {{ stretch.properties["source_organization"] }} </div> <div class="py-1 col text-right"> <button class="btn btn-xs btn-dark mr-1" @click="editStretch(stretch)" > <font-awesome-icon icon="pencil-alt" fixed-width /> </button> <button class="btn btn-xs 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"; import { HTTP } from "@/lib/http"; export default { name: "importstretches", data() { return { staging: [], 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) => { HTTP.get("/imports?states=pending", { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }) .then(response => { const { imports } = response.data; this.staging = imports; 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"]), 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>