Mercurial > gemma
view client/src/components/ImportStretches.vue @ 3044:c71373594719
client: map: prepared store to hold multiple map objects
This will be necessary to sync maps, toggle layers per map, etc. Therefore the methods to move the map
(moveToExtent, etc.) became actions instead of mutations.
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Sat, 13 Apr 2019 16:02:06 +0200 |
parents | 4b9e83cf82ea |
children | 1ef2f4179d30 |
line wrap: on
line source
<template> <div class="d-flex flex-column mb-3"> <UIBoxHeader icon="road" :title="defineStretchesLabel" :closeCallback="$parent.close" /> <div class="position-relative"> <UISpinnerOverlay v-if="loading" /> <div v-if="!edit" class="mb-3"> <UITableHeader :columns="[ { id: 'properties.name', title: `${nameLabel}`, class: 'col-4' }, { id: 'properties.date_info', title: `${dateLabel}`, class: 'col-2' }, { id: 'properties.source_organization', title: `${sourceorganizationLabel}`, class: 'col-3' } ]" /> <UITableBody :data="filteredStretches() | sortTable(sortColumn, sortDirection)" > <template v-slot:row="{ item: stretch }"> <div class="py-1 col-4 "> <a class="pointer 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> </template> </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" /> </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" /> </span> </div> <span class="text-left text-danger"> <small v-if="endrhmError && !endrhm"> <translate>Please enter an end point</translate> </small> </span> </div> </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> </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"; import { HTTP } from "@/lib/http"; import { sortTable } from "@/lib/mixins"; export default { name: "importstretches", mixins: [sortTable], 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, loading: false }; }, computed: { ...mapState("application", ["searchQuery"]), ...mapState("map", ["identifiedFeatures", "currentMeasurement"]), ...mapGetters("map", ["openLayersMap"]), ...mapGetters("user", ["isSysAdmin"]), ...mapState("imports", ["stretches"]), defineStretchesLabel() { return this.$gettext("Define Stretches"); }, nameLabel() { return this.$gettext("Name"); }, dateLabel() { return this.$gettext("Date"); }, sourceorganizationLabel() { return this.$gettext("Source organization"); }, 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; } }, 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; } } }, methods: { filteredStretches() { return this.stretches.filter(s => { return (s.properties.name + s.properties.source_organization) .toLowerCase() .includes(this.searchQuery.toLowerCase()); }); }, 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("imports/selectedStretchId", stretch.id); this.openLayersMap.getLayer("STRETCHES").setVisible(true); this.$store.dispatch("map/moveToExtent", { feature: stretch, zoom: 17, preventZoomOut: true }); }, 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.openLayersMap.getLayer("DISTANCEMARKSAXIS").setVisible(true); 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.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.$store.dispatch("imports/loadStretches").then(() => { this.edit = false; }); }) .catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); } }, mounted() { this.edit = false; this.loading = true; this.$store .dispatch("imports/loadStretches") .catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }) .finally(() => (this.loading = false)); this.loadStagingData().catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); } }; </script>