view client/src/components/ImportSoundingresults.vue @ 1558:0ded4c56978e

refac: component filestructure. remove admin/map hierarchy
author Thomas Junk <thomas.junk@intevation.de>
date Wed, 12 Dec 2018 09:22:20 +0100
parents client/src/components/map/contextbox/ImportSoundingresults.vue@4af7eaca44a1
children 38f91897ca69
line wrap: on
line source

<template>
  <div>
    <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center">
      <font-awesome-icon icon="upload" class="mr-2"></font-awesome-icon>
      <translate>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>&nbsp;(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"
        >
          <translate>Download Meta.json</translate>
        </a>
        <button
          v-if="editState"
          @click="deleteTempData"
          class="btn btn-danger"
          type="button"
        >
          <translate>Cancel Upload</translate>
        </button>
        <button
          :disabled="disableUploadButton"
          @click="submit"
          class="btn btn-info"
          type="button"
        >
          {{ uploadState ? Upload : Confirm }}
        </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 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";

const IMPORTSTATE = { UPLOAD: "UPLOAD", EDIT: "EDIT" };

export default {
  name: "imports",
  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>
.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>