Mercurial > gemma
view client/src/components/ImportSoundingresults.vue @ 2068:5a898da60b87
dma added
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Wed, 30 Jan 2019 15:43:08 +0100 |
parents | f2d24dceecc7 |
children | a08e0f532304 |
line wrap: on
line source
<template> <div class="main d-flex flex-column"> <div class="d-flex flex-row"> <Spacer></Spacer> <div class="card shadow-xs mt-3 mr-3 w-100 importsoundingresultscard"> <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center" > <font-awesome-icon icon="upload" class="mr-2"></font-awesome-icon> <translate class="headline">Import Soundingresults</translate> </h6> <div v-if="editState" class="ml-auto mr-auto mt-4 w-95"> <div class="d-flex flex-column"> <div class="d-flex flex-row"> <div class="mt-1 text-left w-50 ml-2 mr-4"> <small class="text-muted"> <translate>Bottleneck</translate> </small> <select v-model="bottleneck" class="custom-select"> <option v-for="bottleneck in availableBottlenecks" :key="bottleneck" >{{ bottleneck }}</option > </select> <span class="text-danger"> <small v-if="!bottleneck"> <translate>Please select a bottleneck</translate> </small> </span> </div> <div class="d-flex flex-column mt-1 text-left w-50 mr-2"> <small class="text-muted"> <translate>Projection</translate> (EPSG) </small> <input class="form-control" v-model="projection" value="4326" placeholder="e.g. 4326" type="number" /> <span class="text-left text-danger"> <small v-if="!projection"> <translate>Please enter a projection</translate> </small> </span> </div> </div> <div class="d-flex flex-row"> <div class="mt-1 text-left w-50 ml-2 mr-4"> <small class="text-muted"> <translate>Depthreference</translate> </small> <select v-model="depthReference" class="custom-select" id="depthreference" > <option v-for="option in this.$options.depthReferenceOptions" :key="option" >{{ option }}</option > </select> <span class="text-left text-danger"> <small v-if="!depthReference"> <translate>Please enter a reference</translate> </small> </span> </div> <div class="mt-1 text-left w-50 mr-2"> <small class="text-muted"> <translate>Date</translate> </small> <input id="importdate" type="date" class="form-control" placeholder="Date of import" aria-label="bottleneck" aria-describedby="bottlenecklabel" v-model="importDate" /> <span class="text-left text-danger"> <small v-if="!importDate"> <translate>Please enter a date</translate> </small> </span> </div> </div> </div> <div class="ml-2 mt-2 text-left"> <small v-for="(message, index) in messages" :key="index"> {{ message }} </small> </div> </div> <div class="w-95 ml-auto mr-auto mt-4 mb-4"> <div v-if="uploadState" class="d-flex flex-row input-group mb-4"> <div class="custom-file"> <input accept=".zip" type="file" @change="fileSelected" class="custom-file-input" id="uploadFile" /> <label class="custom-file-label" for="uploadFile"> {{ uploadLabel }} </label> </div> </div> <div class="buttons text-right"> <a v-if="editState" download="meta.json" :href="dataLink" class="btn btn-outline-info pull-left mt-4" > <translate>Download Meta.json</translate> </a> <button v-if="editState" @click="deleteTempData" class="btn btn-danger mt-4" type="button" > <translate>Cancel Upload</translate> </button> <button :disabled="disableUploadButton" @click="submit" class="btn btn-info mt-4" type="button" > {{ uploadState ? Upload : Confirm }} </button> </div> </div> </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 by via donau * – Österreichische Wasserstraßen-Gesellschaft mbH * Software engineering by Intevation GmbH * * Author(s): * Thomas Junk <thomas.junk@intevation.de> * Markus Kottländer <markus.kottlaender@intevation.de> */ import { HTTP } from "@/lib/http"; import { displayError, displayInfo } from "@/lib/errors.js"; import { mapState } from "vuex"; import Spacer from "./Spacer"; const IMPORTSTATE = { UPLOAD: "UPLOAD", EDIT: "EDIT" }; export default { name: "imports", components: { Spacer }, data() { return { importState: IMPORTSTATE.UPLOAD, depthReference: "", bottleneck: "", projection: "", importDate: "", uploadLabel: this.$gettext("choose .zip- file"), uploadFile: null, disableUpload: false, token: null, messages: [] }; }, methods: { initialState() { this.importState = IMPORTSTATE.UPLOAD; this.depthReference = ""; this.bottleneck = ""; this.projection = ""; this.importDate = ""; this.uploadLabel = this.$gettext("choose .zip- file"); this.uploadFile = null; this.disableUpload = false; this.token = null; this.messages = []; }, fileSelected(e) { const files = e.target.files || e.dataTransfer.files; if (!files) return; this.uploadLabel = files[0].name; this.uploadFile = files[0]; }, deleteTempData() { HTTP.delete("/imports/soundingresult-upload/" + this.token, { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }) .then(() => { this.initialState(); }) .catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); }, submit() { if (!this.uploadFile || this.disableUpload) return; if (this.importState === IMPORTSTATE.UPLOAD) { this.upload(); } else { this.confirm(); } }, upload() { let formData = new FormData(); formData.append("soundingresult", this.uploadFile); HTTP.post("/imports/soundingresult-upload", formData, { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-Type": "multipart/form-data" } }) .then(response => { if (response.data.meta) { const { bottleneck, date, epsg } = response.data.meta; const depthReference = response.data.meta["depth-reference"]; this.bottleneck = bottleneck; this.depthReference = depthReference; this.importDate = new Date(date).toISOString().split("T")[0]; this.projection = epsg; } this.importState = IMPORTSTATE.EDIT; this.token = response.data.token; this.messages = response.data.messages; }) .catch(error => { const { status, data } = error.response; const messages = data.messages ? data.messages.join(", ") : ""; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${messages}` }); }); }, confirm() { let formData = new FormData(); formData.append("token", this.token); if (this.bottleneck) formData.append("bottleneck", this.bottleneck); if (this.importDate) formData.append("date", this.importDate.split("T")[0]); if (this.depthReference) formData.append("depth-reference", this.depthReference); if (this.projection) formData.append("", this.projection); HTTP.post("/imports/soundingresult", formData, { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-Type": "multipart/form-data" } }) .then(() => { displayInfo({ title: this.$gettext("Import"), message: this.$gettext("Starting import for ") + this.bottleneck }); this.initialState(); }) .catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); } }, mounted() { this.$store.dispatch("bottlenecks/loadBottlenecks"); }, watch: { showContextBox() { if (!this.showContextBox && this.token) this.deleteTempData(); } }, computed: { ...mapState("application", ["showContextBox"]), ...mapState("bottlenecks", ["bottlenecks"]), disableUploadButton() { if (this.importState === IMPORTSTATE.UPLOAD) return this.disableUpload; if ( !this.bottleneck || !this.importDate || !this.depthReference || !this.projection ) return true; return this.disableUpload; }, availableBottlenecks() { return this.bottlenecks.map(x => x.properties.name); }, editState() { return this.importState === IMPORTSTATE.EDIT; }, uploadState() { return this.importState === IMPORTSTATE.UPLOAD; }, Upload() { return this.$gettext("Upload"); }, Confirm() { return this.$gettext("Confirm"); }, dataLink() { return ( "data:text/json;charset=utf-8," + encodeURIComponent( JSON.stringify({ depthReference: this.depthReference, bottleneck: this.bottleneck, date: this.importDate }) ) ); } }, depthReferenceOptions: [ "", // "NAP", // "KP", // "FZP", // "ADR", // "TAW", // "PUL", // "NGM", // "ETRS", // "POT", // "LDC", // "HDC", // "ZPG", // "GLW", // "HSW", // "LNW", // "HNW", // "IGN", // "WGS", "RN" //, // "HBO" ] }; </script> <style lang="scss" scoped> .importsoundingresultscard { height: 100%; } .projectionLabel { margin-left: $small-offset; } .depthreferencelabel { margin-left: $small-offset; } .offset-r { margin-right: $small-offset; } .buttons button { margin-left: $offset !important; } .label-text { width: 5rem; text-align: left; line-height: 2.25rem; } </style>