changeset 2993:ec3196e2d579

imports: moved scheduled imports component in filesystem
author Thomas Junk <thomas.junk@intevation.de>
date Wed, 10 Apr 2019 14:28:45 +0200
parents 5f617f25e646
children 5124644494df
files client/src/components/importconfiguration/ImportDetails.vue client/src/components/importconfiguration/ScheduledImports.vue client/src/components/importconfiguration/types/ScheduledImports.vue
diffstat 3 files changed, 958 insertions(+), 958 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/importconfiguration/ImportDetails.vue	Wed Apr 10 12:02:45 2019 +0200
+++ b/client/src/components/importconfiguration/ImportDetails.vue	Wed Apr 10 14:28:45 2019 +0200
@@ -93,7 +93,7 @@
     ApprovedGaugeMeasurement: () => import("./types/ApprovedGaugeMeasurement"),
     WaterwayProfiles: () => import("./types/WaterwayProfiles"),
     SoundingResults: () => import("./types/Soundingresults"),
-    ScheduledImports: () => import("./types/ScheduledImports")
+    ScheduledImports: () => import("./ScheduledImports")
   },
   data() {
     return {};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/importconfiguration/ScheduledImports.vue	Wed Apr 10 14:28:45 2019 +0200
@@ -0,0 +1,957 @@
+<template>
+  <form @submit.prevent="save" class="w-100">
+    <div v-if="directImportAvailable" class="flex-column">
+      <div class="flex-row text-left">
+        <small class="text-muted">
+          <translate>Import via</translate>
+        </small>
+      </div>
+      <div class="flex-flex-row text-left">
+        <!-- '#75c791' is the DEFAULT_COLOR_CHECKED
+                  from vue-js-toggle-button as here both states are active -->
+        <toggle-button
+          :color="{ unchecked: '#75c791' }"
+          v-model="directImport"
+          class="mt-2"
+          :speed="100"
+          :labels="{
+            checked: this.$options.FILE,
+            unchecked: this.$options.URL
+          }"
+          :width="60"
+          :height="30"
+        />
+      </div>
+    </div>
+    <Availablefairwaydepth
+      v-if="
+        import_ == $options.IMPORTTYPES.FAIRWAYAVAILABILITY && !directImport
+      "
+      @urlChanged="setUrl"
+      :url="url"
+    />
+    <Bottleneck
+      v-if="import_ == $options.IMPORTTYPES.BOTTLENECK"
+      @urlChanged="setUrl"
+      @toleranceChanged="setTolerance"
+      :url="url"
+      :tolerance="tolerance"
+      :directImport="directImport"
+    />
+    <Distancemarksvirtual
+      v-if="import_ == $options.IMPORTTYPES.DISTANCEMARKSVIRTUAL"
+      @urlChanged="setUrl"
+      @usernameChanged="setUsername"
+      @passwordChanged="setPassword"
+      :url="url"
+      :username="username"
+      :password="password"
+    />
+    <Distancemarksashore
+      v-if="import_ == $options.IMPORTTYPES.DISTANCEMARKSASHORE"
+      @urlChanged="setUrl"
+      @featureTypeChanged="setFeatureType"
+      @sortByChanged="setSortBy"
+      :url="url"
+      :featureType="featureType"
+      :sortBy="sortBy"
+    />
+    <Faiwaydimensions
+      v-if="import_ == $options.IMPORTTYPES.FAIRWAYDIMENSION"
+      @urlChanged="setUrl"
+      @featureTypeChanged="setFeatureType"
+      @sortByChanged="setSortBy"
+      @LOSChanged="setLOS"
+      @depthChanged="setDepth"
+      @minWidthChanged="setMinWidth"
+      @maxWidthChanged="setMaxWidth"
+      @sourceOrganizationChanged="setSourceOrganization"
+      :url="url"
+      :featureType="featureType"
+      :sortBy="sortBy"
+      :LOS="LOS"
+      :minWidth="minWidth"
+      :maxWidth="maxWidth"
+      :sourceOrganization="sourceOrganization"
+      :depth="depth"
+    />
+    <Gaugemeasurement
+      v-if="import_ == $options.IMPORTTYPES.GAUGEMEASUREMENT && !directImport"
+      @urlChanged="setUrl"
+      :url="url"
+    />
+    <Waterwayarea
+      v-if="import_ == $options.IMPORTTYPES.WATERWAYAREA"
+      @urlChanged="setUrl"
+      @featureTypeChanged="setFeatureType"
+      @sortByChanged="setSortBy"
+      :url="url"
+      :featureType="featureType"
+      :sortBy="sortBy"
+    />
+    <Waterwaygauges
+      v-if="import_ == $options.IMPORTTYPES.WATERWAYGAUGES"
+      @urlChanged="setUrl"
+      @usernameChanged="setUsername"
+      @passwordChanged="setPassword"
+      :url="url"
+      :username="username"
+      :password="password"
+    />
+    <Waterwayaxis
+      v-if="import_ == $options.IMPORTTYPES.WATERWAYAXIS"
+      @urlChanged="setUrl"
+      @featureTypeChanged="setFeatureType"
+      @sortByChanged="setSortBy"
+      :url="url"
+      :featureType="featureType"
+      :sortBy="sortBy"
+    />
+
+    <template v-if="!directImport || !directImportAvailable">
+      <div class="d-flex flex-row mt-3">
+        <div class="flex-column mr-4">
+          <div class="flex-row text-left">
+            <small class="text-muted">
+              <translate>Email Notification</translate>
+            </small>
+          </div>
+          <div class="flex-flex-row text-left">
+            <toggle-button
+              v-model="eMailNotification"
+              class="mt-2"
+              :speed="100"
+              :labels="{
+                checked: this.$options.on,
+                unchecked: this.$options.off
+              }"
+              :width="60"
+              :height="30"
+            />
+          </div>
+        </div>
+
+        <div class="flex-column mr-4">
+          <div class="flex-row text-left">
+            <small class="text-muted">
+              <translate>Scheduled</translate>?
+            </small>
+          </div>
+          <div class="flex-flex-row text-left">
+            <toggle-button
+              v-model="scheduled"
+              class="mt-2"
+              :speed="100"
+              :labels="{
+                checked: this.$options.on,
+                unchecked: this.$options.off
+              }"
+              :width="60"
+              :height="30"
+            />
+          </div>
+        </div>
+        <div class="flex-column mr-2">
+          <div class="flex-row text-left">
+            <small class="text-muted">
+              <translate>Simple schedule</translate>
+            </small>
+          </div>
+          <div class="flex-flex-row text-left">
+            <toggle-button
+              :disabled="!scheduled"
+              v-model="easyCron"
+              class="mt-2"
+              :speed="100"
+              :labels="{
+                checked: this.$options.on,
+                unchecked: this.$options.off
+              }"
+              :width="60"
+              :height="30"
+            />
+          </div>
+        </div>
+      </div>
+      <div class="flex-column w-100 mr-2">
+        <div class="flex-row text-left">
+          <small class="text-muted">
+            <translate>Schedule</translate>
+          </small>
+        </div>
+        <div v-if="easyCron" class="text-left w-50">
+          <select :disabled="!scheduled" v-model="simple" class="form-control"
+            ><option value="weekly"><translate>Weekly</translate></option>
+            <option value="monthly"><translate>Monthly</translate> </option>
+          </select>
+        </div>
+        <div v-if="!easyCron" class="text-left w-100">
+          <div class="d-flex flex-row">
+            <h4 class="mt-auto mb-auto mr-2">{{ $options.EVERY }}</h4>
+            <select
+              :disabled="!scheduled"
+              style="width: 130px;"
+              v-model="cronMode"
+              class="form-control"
+              @change="clearInputs"
+            >
+              <option :value="null"></option>
+              <option
+                v-for="(option, key) in $options.CRONMODE"
+                :value="key"
+                :key="key"
+                >{{ option }}</option
+              >
+            </select>
+            <div v-if="cronMode == 'hour'" class="ml-1 d-flex flex-row">
+              <h4 class="mt-auto mb-auto">{{ $options.ON }}</h4>
+              <input
+                :disabled="!scheduled"
+                v-model="minutes"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+              <h4 class="mt-auto mb-auto">{{ $options.MINUTESPAST }}</h4>
+            </div>
+            <div v-if="cronMode == 'day'" class="ml-1 d-flex flex-row">
+              <h4 class="mt-auto mb-auto">{{ $options.AT }}</h4>
+              <input
+                :disabled="!scheduled"
+                v-model="hour"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+              <input
+                :disabled="!scheduled"
+                v-model="minutes"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+              <h4 class="mt-auto mb-auto">{{ $options.OCLOCK }}</h4>
+            </div>
+            <div v-if="cronMode == 'week'" class="ml-1 d-flex flex-row">
+              <h4 class="ml-1 mr-1 mt-auto mb-auto">{{ $options.ON }}</h4>
+              <select :disabled="!scheduled" v-model="day" class="form-control">
+                <option
+                  v-for="(option, key) in $options.DAYSOFWEEK"
+                  :key="key"
+                  :value="key"
+                  >{{ option }}</option
+                >
+              </select>
+              <h4 class="ml-1 mt-auto mb-auto">{{ $options.AT }}</h4>
+              <input
+                :disabled="!scheduled"
+                v-model="hour"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+              <input
+                :disabled="!scheduled"
+                v-model="minutes"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+            </div>
+            <div v-if="cronMode == 'month'" class="ml-1 d-flex flex-row">
+              <h4 class="ml-1 mt-auto mb-auto">{{ $options.ON }}</h4>
+              <input
+                :disabled="!scheduled"
+                v-model="dayOfMonth"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+              <h4 class="mt-auto mb-auto">{{ $options.AT }}</h4>
+              <input
+                :disabled="!scheduled"
+                v-model="hour"
+                class="cronfield ml-1 mr-2 form-control"
+                type="number"
+              />
+              <input
+                :disabled="!scheduled"
+                v-model="minutes"
+                class="cronfield ml-1 mr-2 form-control"
+                type="number"
+              />
+              <h4 class="mt-auto mb-auto">{{ $options.OCLOCK }}</h4>
+            </div>
+            <div v-if="cronMode == 'year'" class="ml-1 d-flex flex-row">
+              <h4 class="ml-1 mt-auto mb-auto">{{ $options.ON }}</h4>
+              <input
+                :disabled="!scheduled"
+                v-model="dayOfMonth"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+              <h4 class="mt-auto mb-auto">{{ $options.OF }}</h4>
+              <select
+                :disabled="!scheduled"
+                v-model="month"
+                class="ml-1 mr-1 form-control"
+              >
+                <option
+                  v-for="(option, key) in $options.MONTHS"
+                  :value="key"
+                  :key="key"
+                  >{{ option }}</option
+                >
+              </select>
+              <h4 class="mt-auto mb-auto">{{ $options.ON }}</h4>
+              <input
+                :disabled="!scheduled"
+                v-model="hour"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+              <input
+                :disabled="!scheduled"
+                v-model="minutes"
+                class="cronfield ml-1 mr-1 form-control"
+                type="number"
+              />
+            </div>
+          </div>
+          <div class="mt-3 w-50 d-flex flex-row">
+            <h5 class="mt-auto mb-auto mr-2">
+              <translate>Cronstring</translate>
+            </h5>
+            <input
+              :disabled="!scheduled"
+              class="form-control"
+              v-model="cronString"
+              type="text"
+            />
+          </div>
+        </div>
+      </div>
+    </template>
+    <div v-else class="d-flex flex-row text-left">
+      <div class="mt-3 mb-3 flex-column w-100">
+        <div class="custom-file">
+          <input
+            accept=".xml"
+            type="file"
+            @change="fileSelected"
+            class="custom-file-input"
+            id="uploadFile"
+          />
+          <label class="pointer custom-file-label" for="uploadFile">
+            {{ uploadLabel }}
+          </label>
+        </div>
+      </div>
+    </div>
+    <div class="w-100 d-flex flex-row mt-3">
+      <button
+        @click="triggerManualImport"
+        type="button"
+        class="shadow-sm btn btn-outline-info"
+        :disabled="!triggerActive || !isValid"
+      >
+        <font-awesome-icon class="fa-fw mr-2" fixed-width icon="play" />
+        <translate>Trigger import</translate>
+      </button>
+      <button
+        :disabled="!isValid"
+        type="submit"
+        class="ml-auto shadow-sm btn btn-info mr-3"
+      >
+        <translate>Save</translate>
+      </button>
+      <button :key="1" @click="back()" class="btn btn-warning">
+        Back
+      </button>
+    </div>
+  </form>
+</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 {
+  IMPORTTYPES,
+  IMPORTTYPEKIND,
+  initializeCurrentSchedule
+} from "@/store/importschedule";
+import { mapState } from "vuex";
+import { displayInfo, displayError } from "@/lib/errors";
+import app from "@/main";
+import { HTTP } from "@/lib/http";
+
+export default {
+  name: "importscheduledetail",
+  components: {
+    Availablefairwaydepth: () => import("./types/Availablefairwaydepth"),
+    Bottleneck: () => import("./types/Bottleneck"),
+    Distancemarksvirtual: () => import("./types/Distancemarksvirtual"),
+    Distancemarksashore: () => import("./types/Distancemarksashore"),
+    Faiwaydimensions: () => import("./types/Fairwaydimensions"),
+    Gaugemeasurement: () => import("./types/Gaugemeasurement"),
+    Waterwayarea: () => import("./types/Waterwayarea"),
+    Waterwaygauges: () => import("./types/Waterwaygauges"),
+    Waterwayaxis: () => import("./types/Waterwayaxis")
+  },
+  data() {
+    return {
+      directImport: false,
+      passwordVisible: false,
+      uploadLabel: this.$gettext("choose file to upload"),
+      uploadFile: null,
+      ...initializeCurrentSchedule()
+    };
+  },
+  mounted() {
+    this.initialize();
+  },
+  watch: {
+    cronMode() {
+      this.cronString = this.calcCronString();
+    },
+    minutes() {
+      this.cronString = this.calcCronString();
+    },
+    hour() {
+      this.cronString = this.calcCronString();
+    },
+    month() {
+      this.cronString = this.calcCronString();
+    },
+    day() {
+      this.cronString = this.calcCronString();
+    },
+    dayOfMonth() {
+      this.cronString = this.calcCronString();
+    },
+    importScheduleDetailVisible() {
+      this.initialize();
+    },
+    cronString() {
+      if (this.isWeekly(this.cronString)) {
+        this.simple = "weekly";
+      }
+      if (this.isMonthly(this.cronString)) {
+        this.simple = "monthly";
+      }
+    }
+  },
+  computed: {
+    ...mapState("importschedule", [
+      "importScheduleDetailVisible",
+      "currentSchedule"
+    ]),
+    import_() {
+      return this.currentSchedule.importType;
+    },
+    dialogLabel() {
+      if (this.id) return this.$gettext("Import") + " " + this.id;
+      return this.$gettext("New Import");
+    },
+    directImportAvailable() {
+      switch (this.import_) {
+        case this.$options.IMPORTTYPES.BOTTLENECK:
+        case this.$options.IMPORTTYPES.FAIRWAYAVAILABILITY:
+        case this.$options.IMPORTTYPES.GAUGEMEASUREMENT:
+          return true;
+        default:
+          return false;
+      }
+    },
+    isCredentialsRequired() {
+      switch (this.import_) {
+        case this.$options.IMPORTTYPES.WATERWAYGAUGES:
+        case this.$options.IMPORTTYPES.DISTANCEMARKSVIRTUAL:
+          return true;
+        default:
+          return false;
+      }
+    },
+    isURLRequired() {
+      switch (this.import_) {
+        case this.$options.IMPORTTYPES.BOTTLENECK:
+        case this.$options.IMPORTTYPES.WATERWAYAXIS:
+        case this.$options.IMPORTTYPES.GAUGEMEASUREMENT:
+        case this.$options.IMPORTTYPES.FAIRWAYAVAILABILITY:
+        case this.$options.IMPORTTYPES.WATERWAYAREA:
+        case this.$options.IMPORTTYPES.FAIRWAYDIMENSION:
+        case this.$options.IMPORTTYPES.WATERWAYGAUGES:
+        case this.$options.IMPORTTYPES.DISTANCEMARKSVIRTUAL:
+        case this.$options.IMPORTTYPES.DISTANCEMARKSASHORE:
+          return true;
+        default:
+          return false;
+      }
+    },
+    isFeatureTypeRequired() {
+      switch (this.import_) {
+        case this.$options.IMPORTTYPES.WATERWAYAXIS:
+        case this.$options.IMPORTTYPES.WATERWAYAREA:
+        case this.$options.IMPORTTYPES.FAIRWAYDIMENSION:
+        case this.$options.IMPORTTYPES.DISTANCEMARKSASHORE:
+          return true;
+        default:
+          return false;
+      }
+    },
+    isSortbyRequired() {
+      switch (this.import_) {
+        case this.$options.IMPORTTYPES.WATERWAYAXIS:
+        case this.$options.IMPORTTYPES.WATERWAYAREA:
+        case this.$options.IMPORTTYPES.FAIRWAYDIMENSION:
+        case this.$options.IMPORTTYPES.DISTANCEMARKSASHORE:
+          return true;
+        default:
+          return false;
+      }
+    },
+    isToleranceRequired() {
+      switch (this.import_) {
+        case this.$options.IMPORTTYPES.BOTTLENECK:
+          return true;
+        default:
+          return false;
+      }
+    },
+    isValid() {
+      if (!this.import_) return false;
+      if (this.isToleranceRequired && !this.tolerance) return false;
+      if (this.directImport && !this.uploadFile) return false;
+      else if (!this.directImport) {
+        if (this.isURLRequired && !this.url) return false;
+        if (this.isSortbyRequired && !this.sortBy) return false;
+        if (this.isFeatureTypeRequired && !this.featureType) return false;
+        if (this.isCredentialsRequired && (!this.username || !this.password))
+          return false;
+        if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) {
+          if (
+            !this.LOS ||
+            !this.minWidth ||
+            !this.maxWidth ||
+            !this.depth ||
+            !this.sourceOrganization
+          )
+            return false;
+        }
+      }
+      return true;
+    }
+  },
+  methods: {
+    back() {
+      this.$store.commit("importschedule/setListMode");
+    },
+    fileSelected(e) {
+      const files = e.target.files || e.dataTransfer.files;
+      if (!files) return;
+      this.uploadLabel = files[0].name;
+      this.uploadFile = files[0];
+    },
+    setUrl(value) {
+      this.url = value;
+    },
+    setFeatureType(value) {
+      this.featureType = value;
+    },
+    setSortBy(value) {
+      this.sortBy = value;
+    },
+    setTolerance(value) {
+      this.tolerance = value;
+    },
+    setUsername(value) {
+      this.username = value;
+    },
+    setPassword(value) {
+      this.password = value;
+    },
+    setLOS(value) {
+      this.LOS = value;
+    },
+    setMinWidth(value) {
+      this.minWidth = value;
+    },
+    setMaxWidth(value) {
+      this.maxWidth = value;
+    },
+    setDepth(value) {
+      this.depth = value;
+    },
+    setSourceOrganization(value) {
+      this.sourceOrganization = value;
+    },
+    calcCronString() {
+      let getValue = value => {
+        return this[value] !== null ? this[value] : "*";
+      };
+
+      const min = getValue("minutes");
+      const h = getValue("hour");
+      const dm = getValue("dayOfMonth");
+      const m = getValue("month");
+      const wd = getValue("day");
+
+      if (this.cronMode === "15minutes") return "0 */15 * * * *";
+      if (this.cronMode === "hour") return `0 ${min} * * * *`;
+      if (this.cronMode === "day") return `0 ${min} ${h} * * *`;
+      if (this.cronMode === "week") return `0 ${min} ${h} * * ${wd}`;
+      if (this.cronMode === "month") return `0 ${min} ${h} ${dm} * *`;
+      if (this.cronMode === "year") return `0 ${min} ${h} ${dm} ${m} *`;
+      return this.cronString;
+    },
+    validateBottleneckfields() {
+      return !!this.url;
+    },
+    initialize() {
+      this.id = this.currentSchedule.id;
+      this.importType = this.currentSchedule.importType;
+      this.schedule = this.currentSchedule.schedule;
+      this.scheduled = this.currentSchedule.scheduled;
+      this.importSource = this.currentSchedule.importSource;
+      this.eMailNotification = this.currentSchedule.eMailNotification;
+      this.easyCron = this.currentSchedule.easyCron;
+      this.cronMode = this.currentSchedule.cronMode;
+      this.minutes = this.currentSchedule.minutes;
+      this.month = this.currentSchedule.month;
+      this.hour = this.currentSchedule.hour;
+      this.day = this.currentSchedule.day;
+      this.dayOfMonth = this.currentSchedule.dayOfMonth;
+      this.simple = this.currentSchedule.simple;
+      this.url = this.currentSchedule.url;
+      this.insecure = this.currentSchedule.insecure;
+      this.cronString = this.currentSchedule.cronString;
+      this.featureType = this.currentSchedule.featureType;
+      this.sortBy = this.currentSchedule.sortBy;
+      this.tolerance = this.currentSchedule.tolerance;
+      this.username = this.currentSchedule.username;
+      this.password = this.currentSchedule.password;
+      this.LOS = this.currentSchedule.LOS;
+      this.minWidth = this.currentSchedule.minWidth;
+      this.maxWidth = this.currentSchedule.maxWidth;
+      this.depth = this.currentSchedule.depth;
+      this.sourceOrganization = this.currentSchedule.sourceOrganization;
+      this.directImport = false;
+    },
+    isWeekly(cron) {
+      return /0 \d{1,2} \d{1,2} \* \* \d{1}/.test(cron);
+    },
+    isMonthly(cron) {
+      return /0 \d{1,2} \d{1,2} \d{1,2} \* \*/.test(cron);
+    },
+    clearInputs() {
+      this.minutes = this.currentSchedule.minutes;
+      this.month = this.currentSchedule.month;
+      this.hour = this.currentSchedule.hour;
+      this.day = this.currentSchedule.day;
+      this.dayOfMonth = this.currentSchedule.dayOfMonth;
+    },
+    triggerFileUpload() {
+      if (!this.uploadFile) return;
+      let formData = new FormData();
+      let routeParam = "";
+      switch (this.import_) {
+        case this.$options.IMPORTTYPES.BOTTLENECK:
+          formData.append("tolerance", this.tolerance);
+          routeParam = "ubn";
+          break;
+        case this.$options.IMPORTTYPES.FAIRWAYAVAILABILITY:
+          routeParam = "ufa";
+          break;
+        case this.$options.IMPORTTYPES.GAUGEMEASUREMENT:
+          routeParam = "ugm";
+          break;
+        default:
+          throw new Error("invalid importroute");
+      }
+
+      formData.append(routeParam, this.uploadFile);
+      HTTP.post("/imports/" + routeParam, formData, {
+        headers: {
+          "X-Gemma-Auth": localStorage.getItem("token"),
+          "Content-Type": "multipart/form-data"
+        }
+      })
+        .then(response => {
+          const { id } = response.data;
+          displayInfo({
+            title: this.$gettext("File Import"),
+            message: this.$gettext("Import import: #") + id
+          });
+          this.closeDetailview();
+          this.$store.dispatch("importschedule/loadSchedules").catch(error => {
+            const { status, data } = error.response;
+            displayError({
+              title: this.gettext("Backend Error"),
+              message: `${status}: ${data.message || data}`
+            });
+          });
+        })
+        .catch(error => {
+          const { status, data } = error.response;
+          displayError({
+            title: this.$gettext("Backend Error"),
+            message: `${status}: ${data.message || data}`
+          });
+        });
+    },
+    triggerManualImport() {
+      if (!this.triggerActive) return;
+      if (!this.import_) return;
+      if (this.directImport) {
+        if (!this.uploadFile) return;
+        this.triggerFileUpload();
+        return;
+      }
+      let data = {};
+      if (this.isURLRequired) {
+        if (!this.url) return;
+        data["url"] = this.url;
+        data["insecure"] = this.insecure;
+      }
+      if (this.isFeatureTypeRequired) {
+        if (!this.featureType) return;
+        data["feature-type"] = this.featureType;
+      }
+      if (this.isSortbyRequired) {
+        if (!this.sortBy) return;
+        data["sort-by"] = this.sortBy;
+      }
+      if (this.isToleranceRequired) {
+        if (!this.tolerance) return;
+        data["tolerance"] = parseFloat(this.tolerance);
+      }
+      if (this.isCredentialsRequired) {
+        if (!this.username || !this.password) return;
+        data["user"] = this.username;
+        data["password"] = this.password;
+      }
+      if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) {
+        if (
+          !this.LOS ||
+          !this.minWidth ||
+          !this.maxWidth ||
+          !this.depth ||
+          !this.sourceOrganization
+        )
+          return;
+        data["feature-type"] = this.featureType;
+        data["sort-by"] = this.sortBy;
+        data["los"] = this.LOS * 1;
+        data["min-width"] = this.minWidth * 1;
+        data["max-width"] = this.maxWidth * 1;
+        data["depth"] = this.depth * 1;
+        data["source-organization"] = this.sourceOrganization;
+      }
+      data["send-email"] = this.eMailNotification;
+      this.triggerActive = false;
+      this.$store
+        .dispatch("importschedule/triggerImport", {
+          type: IMPORTTYPEKIND[this.import_],
+          data
+        })
+        .then(response => {
+          const { id } = response.data;
+          displayInfo({
+            title: this.$gettext("Import"),
+            message: this.$gettext("Manually triggered import: #") + id
+          });
+        })
+        .catch(error => {
+          const { status, data } = error.response;
+          displayError({
+            title: this.$gettext("Backend Error"),
+            message: `${status}: ${data.message || data}`
+          });
+        })
+        .finally(() => {
+          this.triggerActive = true;
+        });
+    },
+    save() {
+      if (!this.import_) return;
+      let cron = this.cronString;
+      if (this.easyCron) {
+        if (this.simple === "weekly") cron = "0 0 0 * * 0";
+        if (this.simple === "monthly") cron = "0 0 0 1 * *";
+      }
+      let data = {};
+      let config = {};
+      data["kind"] = IMPORTTYPEKIND[this.import_];
+
+      if (this.isURLRequired) {
+        if (!this.url) return;
+        config["url"] = this.url;
+        config["insecure"] = this.insecure;
+      }
+      if (this.isSortbyRequired) {
+        if (!this.sortBy) return;
+        config["sort-by"] = this.sortBy;
+      }
+      if (this.isFeatureTypeRequired) {
+        if (!this.featureType) return;
+        config["feature-type"] = this.featureType;
+      }
+      if (this.isToleranceRequired) {
+        if (!this.tolerance) return;
+        config["tolerance"] = parseFloat(this.tolerance);
+      }
+      if (this.isCredentialsRequired) {
+        if (!this.username || !this.password) return;
+        config = {
+          ...config,
+          user: this.username,
+          password: this.password
+        };
+      }
+      if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) {
+        if (
+          !this.LOS ||
+          !this.minWidth ||
+          !this.maxWidth ||
+          !this.depth ||
+          !this.sourceOrganization
+        )
+          return;
+        config = { ...config, los: this.LOS, depth: this.depth };
+        config["min-width"] = this.minWidth;
+        config["max-width"] = this.maxWidth;
+        config["source-organization"] = this.sourceOrganization;
+      }
+      if (this.scheduled) config["cron"] = cron;
+      config["send-email"] = this.eMailNotification;
+      if (!this.id) {
+        data["config"] = config;
+        this.$store
+          .dispatch("importschedule/saveCurrentSchedule", data)
+          .then(response => {
+            const { id } = response.data;
+            displayInfo({
+              title: this.$gettext("Import"),
+              message: this.$gettext("Saved import: #") + id
+            });
+            this.closeDetailview();
+            this.$store
+              .dispatch("importschedule/loadSchedules")
+              .catch(error => {
+                const { status, data } = error.response;
+                displayError({
+                  title: this.gettext("Backend Error"),
+                  message: `${status}: ${data.message || data}`
+                });
+              });
+          })
+          .catch(error => {
+            const { status, data } = error.response;
+            displayError({
+              title: this.$gettext("Backend Error"),
+              message: `${status}: ${data.message || data}`
+            });
+          });
+      } else {
+        this.$store
+          .dispatch("importschedule/updateCurrentSchedule", {
+            data: config,
+            id: this.id
+          })
+          .then(response => {
+            const { id } = response.data;
+            displayInfo({
+              title: this.$gettext("Import"),
+              message: this.$gettext("update import: #") + id
+            });
+            this.closeDetailview();
+            this.$store
+              .dispatch("importschedule/loadSchedules")
+              .catch(error => {
+                const { status, data } = error.response;
+                displayError({
+                  title: this.gettext("Backend Error"),
+                  message: `${status}: ${data.message || data}`
+                });
+              });
+          })
+          .catch(error => {
+            const { status, data } = error.response;
+            displayError({
+              title: this.$gettext("Backend Error"),
+              message: `${status}: ${data.message || data}`
+            });
+          });
+      }
+    },
+    closeDetailview() {
+      this.$store.commit("importschedule/clearCurrentSchedule");
+      this.$store.commit("importschedule/setListMode");
+    }
+  },
+  IMPORTTYPES: IMPORTTYPES,
+  on: "on",
+  off: "off",
+  FILE: app.$gettext("File"),
+  URL: app.$gettext("URL"),
+  EVERY: app.$gettext("Every"),
+  MINUTESPAST: app.$gettext("minutes past"),
+  ON: app.$gettext("on"),
+  OF: app.$gettext("of"),
+  AT: app.$gettext("at"),
+  OCLOCK: app.$gettext("o' clock"),
+  CRONMODE: {
+    "15minutes": app.$gettext("15 minutes"),
+    hour: app.$gettext("hour"),
+    day: app.$gettext("day"),
+    week: app.$gettext("week"),
+    month: app.$gettext("month"),
+    year: app.$gettext("year")
+  },
+  DAYSOFWEEK: {
+    1: app.$gettext("Monday"),
+    2: app.$gettext("Tuesday"),
+    3: app.$gettext("Wednesday"),
+    4: app.$gettext("Thursday"),
+    5: app.$gettext("Friday"),
+    6: app.$gettext("Saturday"),
+    0: app.$gettext("Sunday")
+  },
+  MONTHS: {
+    1: app.$gettext("January"),
+    2: app.$gettext("February"),
+    3: app.$gettext("March"),
+    4: app.$gettext("April"),
+    5: app.$gettext("May"),
+    6: app.$gettext("June"),
+    7: app.$gettext("July"),
+    8: app.$gettext("August"),
+    9: app.$gettext("September"),
+    10: app.$gettext("October"),
+    11: app.$gettext("November"),
+    12: app.$gettext("December")
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.cronfield {
+  width: 55px;
+}
+
+.importscheduledetailscard {
+  min-height: 550px;
+}
+
+.importscheduledetails {
+  width: 100%;
+  margin-top: $offset;
+  margin-right: $offset;
+}
+</style>
--- a/client/src/components/importconfiguration/types/ScheduledImports.vue	Wed Apr 10 12:02:45 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,957 +0,0 @@
-<template>
-  <form @submit.prevent="save" class="w-100">
-    <div v-if="directImportAvailable" class="flex-column">
-      <div class="flex-row text-left">
-        <small class="text-muted">
-          <translate>Import via</translate>
-        </small>
-      </div>
-      <div class="flex-flex-row text-left">
-        <!-- '#75c791' is the DEFAULT_COLOR_CHECKED
-                  from vue-js-toggle-button as here both states are active -->
-        <toggle-button
-          :color="{ unchecked: '#75c791' }"
-          v-model="directImport"
-          class="mt-2"
-          :speed="100"
-          :labels="{
-            checked: this.$options.FILE,
-            unchecked: this.$options.URL
-          }"
-          :width="60"
-          :height="30"
-        />
-      </div>
-    </div>
-    <Availablefairwaydepth
-      v-if="
-        import_ == $options.IMPORTTYPES.FAIRWAYAVAILABILITY && !directImport
-      "
-      @urlChanged="setUrl"
-      :url="url"
-    />
-    <Bottleneck
-      v-if="import_ == $options.IMPORTTYPES.BOTTLENECK"
-      @urlChanged="setUrl"
-      @toleranceChanged="setTolerance"
-      :url="url"
-      :tolerance="tolerance"
-      :directImport="directImport"
-    />
-    <Distancemarksvirtual
-      v-if="import_ == $options.IMPORTTYPES.DISTANCEMARKSVIRTUAL"
-      @urlChanged="setUrl"
-      @usernameChanged="setUsername"
-      @passwordChanged="setPassword"
-      :url="url"
-      :username="username"
-      :password="password"
-    />
-    <Distancemarksashore
-      v-if="import_ == $options.IMPORTTYPES.DISTANCEMARKSASHORE"
-      @urlChanged="setUrl"
-      @featureTypeChanged="setFeatureType"
-      @sortByChanged="setSortBy"
-      :url="url"
-      :featureType="featureType"
-      :sortBy="sortBy"
-    />
-    <Faiwaydimensions
-      v-if="import_ == $options.IMPORTTYPES.FAIRWAYDIMENSION"
-      @urlChanged="setUrl"
-      @featureTypeChanged="setFeatureType"
-      @sortByChanged="setSortBy"
-      @LOSChanged="setLOS"
-      @depthChanged="setDepth"
-      @minWidthChanged="setMinWidth"
-      @maxWidthChanged="setMaxWidth"
-      @sourceOrganizationChanged="setSourceOrganization"
-      :url="url"
-      :featureType="featureType"
-      :sortBy="sortBy"
-      :LOS="LOS"
-      :minWidth="minWidth"
-      :maxWidth="maxWidth"
-      :sourceOrganization="sourceOrganization"
-      :depth="depth"
-    />
-    <Gaugemeasurement
-      v-if="import_ == $options.IMPORTTYPES.GAUGEMEASUREMENT && !directImport"
-      @urlChanged="setUrl"
-      :url="url"
-    />
-    <Waterwayarea
-      v-if="import_ == $options.IMPORTTYPES.WATERWAYAREA"
-      @urlChanged="setUrl"
-      @featureTypeChanged="setFeatureType"
-      @sortByChanged="setSortBy"
-      :url="url"
-      :featureType="featureType"
-      :sortBy="sortBy"
-    />
-    <Waterwaygauges
-      v-if="import_ == $options.IMPORTTYPES.WATERWAYGAUGES"
-      @urlChanged="setUrl"
-      @usernameChanged="setUsername"
-      @passwordChanged="setPassword"
-      :url="url"
-      :username="username"
-      :password="password"
-    />
-    <Waterwayaxis
-      v-if="import_ == $options.IMPORTTYPES.WATERWAYAXIS"
-      @urlChanged="setUrl"
-      @featureTypeChanged="setFeatureType"
-      @sortByChanged="setSortBy"
-      :url="url"
-      :featureType="featureType"
-      :sortBy="sortBy"
-    />
-
-    <template v-if="!directImport || !directImportAvailable">
-      <div class="d-flex flex-row mt-3">
-        <div class="flex-column mr-4">
-          <div class="flex-row text-left">
-            <small class="text-muted">
-              <translate>Email Notification</translate>
-            </small>
-          </div>
-          <div class="flex-flex-row text-left">
-            <toggle-button
-              v-model="eMailNotification"
-              class="mt-2"
-              :speed="100"
-              :labels="{
-                checked: this.$options.on,
-                unchecked: this.$options.off
-              }"
-              :width="60"
-              :height="30"
-            />
-          </div>
-        </div>
-
-        <div class="flex-column mr-4">
-          <div class="flex-row text-left">
-            <small class="text-muted">
-              <translate>Scheduled</translate>?
-            </small>
-          </div>
-          <div class="flex-flex-row text-left">
-            <toggle-button
-              v-model="scheduled"
-              class="mt-2"
-              :speed="100"
-              :labels="{
-                checked: this.$options.on,
-                unchecked: this.$options.off
-              }"
-              :width="60"
-              :height="30"
-            />
-          </div>
-        </div>
-        <div class="flex-column mr-2">
-          <div class="flex-row text-left">
-            <small class="text-muted">
-              <translate>Simple schedule</translate>
-            </small>
-          </div>
-          <div class="flex-flex-row text-left">
-            <toggle-button
-              :disabled="!scheduled"
-              v-model="easyCron"
-              class="mt-2"
-              :speed="100"
-              :labels="{
-                checked: this.$options.on,
-                unchecked: this.$options.off
-              }"
-              :width="60"
-              :height="30"
-            />
-          </div>
-        </div>
-      </div>
-      <div class="flex-column w-100 mr-2">
-        <div class="flex-row text-left">
-          <small class="text-muted">
-            <translate>Schedule</translate>
-          </small>
-        </div>
-        <div v-if="easyCron" class="text-left w-50">
-          <select :disabled="!scheduled" v-model="simple" class="form-control"
-            ><option value="weekly"><translate>Weekly</translate></option>
-            <option value="monthly"><translate>Monthly</translate> </option>
-          </select>
-        </div>
-        <div v-if="!easyCron" class="text-left w-100">
-          <div class="d-flex flex-row">
-            <h4 class="mt-auto mb-auto mr-2">{{ $options.EVERY }}</h4>
-            <select
-              :disabled="!scheduled"
-              style="width: 130px;"
-              v-model="cronMode"
-              class="form-control"
-              @change="clearInputs"
-            >
-              <option :value="null"></option>
-              <option
-                v-for="(option, key) in $options.CRONMODE"
-                :value="key"
-                :key="key"
-                >{{ option }}</option
-              >
-            </select>
-            <div v-if="cronMode == 'hour'" class="ml-1 d-flex flex-row">
-              <h4 class="mt-auto mb-auto">{{ $options.ON }}</h4>
-              <input
-                :disabled="!scheduled"
-                v-model="minutes"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-              <h4 class="mt-auto mb-auto">{{ $options.MINUTESPAST }}</h4>
-            </div>
-            <div v-if="cronMode == 'day'" class="ml-1 d-flex flex-row">
-              <h4 class="mt-auto mb-auto">{{ $options.AT }}</h4>
-              <input
-                :disabled="!scheduled"
-                v-model="hour"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-              <input
-                :disabled="!scheduled"
-                v-model="minutes"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-              <h4 class="mt-auto mb-auto">{{ $options.OCLOCK }}</h4>
-            </div>
-            <div v-if="cronMode == 'week'" class="ml-1 d-flex flex-row">
-              <h4 class="ml-1 mr-1 mt-auto mb-auto">{{ $options.ON }}</h4>
-              <select :disabled="!scheduled" v-model="day" class="form-control">
-                <option
-                  v-for="(option, key) in $options.DAYSOFWEEK"
-                  :key="key"
-                  :value="key"
-                  >{{ option }}</option
-                >
-              </select>
-              <h4 class="ml-1 mt-auto mb-auto">{{ $options.AT }}</h4>
-              <input
-                :disabled="!scheduled"
-                v-model="hour"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-              <input
-                :disabled="!scheduled"
-                v-model="minutes"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-            </div>
-            <div v-if="cronMode == 'month'" class="ml-1 d-flex flex-row">
-              <h4 class="ml-1 mt-auto mb-auto">{{ $options.ON }}</h4>
-              <input
-                :disabled="!scheduled"
-                v-model="dayOfMonth"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-              <h4 class="mt-auto mb-auto">{{ $options.AT }}</h4>
-              <input
-                :disabled="!scheduled"
-                v-model="hour"
-                class="cronfield ml-1 mr-2 form-control"
-                type="number"
-              />
-              <input
-                :disabled="!scheduled"
-                v-model="minutes"
-                class="cronfield ml-1 mr-2 form-control"
-                type="number"
-              />
-              <h4 class="mt-auto mb-auto">{{ $options.OCLOCK }}</h4>
-            </div>
-            <div v-if="cronMode == 'year'" class="ml-1 d-flex flex-row">
-              <h4 class="ml-1 mt-auto mb-auto">{{ $options.ON }}</h4>
-              <input
-                :disabled="!scheduled"
-                v-model="dayOfMonth"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-              <h4 class="mt-auto mb-auto">{{ $options.OF }}</h4>
-              <select
-                :disabled="!scheduled"
-                v-model="month"
-                class="ml-1 mr-1 form-control"
-              >
-                <option
-                  v-for="(option, key) in $options.MONTHS"
-                  :value="key"
-                  :key="key"
-                  >{{ option }}</option
-                >
-              </select>
-              <h4 class="mt-auto mb-auto">{{ $options.ON }}</h4>
-              <input
-                :disabled="!scheduled"
-                v-model="hour"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-              <input
-                :disabled="!scheduled"
-                v-model="minutes"
-                class="cronfield ml-1 mr-1 form-control"
-                type="number"
-              />
-            </div>
-          </div>
-          <div class="mt-3 w-50 d-flex flex-row">
-            <h5 class="mt-auto mb-auto mr-2">
-              <translate>Cronstring</translate>
-            </h5>
-            <input
-              :disabled="!scheduled"
-              class="form-control"
-              v-model="cronString"
-              type="text"
-            />
-          </div>
-        </div>
-      </div>
-    </template>
-    <div v-else class="d-flex flex-row text-left">
-      <div class="mt-3 mb-3 flex-column w-100">
-        <div class="custom-file">
-          <input
-            accept=".xml"
-            type="file"
-            @change="fileSelected"
-            class="custom-file-input"
-            id="uploadFile"
-          />
-          <label class="pointer custom-file-label" for="uploadFile">
-            {{ uploadLabel }}
-          </label>
-        </div>
-      </div>
-    </div>
-    <div class="w-100 d-flex flex-row mt-3">
-      <button
-        @click="triggerManualImport"
-        type="button"
-        class="shadow-sm btn btn-outline-info"
-        :disabled="!triggerActive || !isValid"
-      >
-        <font-awesome-icon class="fa-fw mr-2" fixed-width icon="play" />
-        <translate>Trigger import</translate>
-      </button>
-      <button
-        :disabled="!isValid"
-        type="submit"
-        class="ml-auto shadow-sm btn btn-info mr-3"
-      >
-        <translate>Save</translate>
-      </button>
-      <button :key="1" @click="back()" class="btn btn-warning">
-        Back
-      </button>
-    </div>
-  </form>
-</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 {
-  IMPORTTYPES,
-  IMPORTTYPEKIND,
-  initializeCurrentSchedule
-} from "@/store/importschedule";
-import { mapState } from "vuex";
-import { displayInfo, displayError } from "@/lib/errors";
-import app from "@/main";
-import { HTTP } from "@/lib/http";
-
-export default {
-  name: "importscheduledetail",
-  components: {
-    Availablefairwaydepth: () => import("./Availablefairwaydepth"),
-    Bottleneck: () => import("./Bottleneck"),
-    Distancemarksvirtual: () => import("./Distancemarksvirtual"),
-    Distancemarksashore: () => import("./Distancemarksashore"),
-    Faiwaydimensions: () => import("./Fairwaydimensions"),
-    Gaugemeasurement: () => import("./Gaugemeasurement"),
-    Waterwayarea: () => import("./Waterwayarea"),
-    Waterwaygauges: () => import("./Waterwaygauges"),
-    Waterwayaxis: () => import("./Waterwayaxis")
-  },
-  data() {
-    return {
-      directImport: false,
-      passwordVisible: false,
-      uploadLabel: this.$gettext("choose file to upload"),
-      uploadFile: null,
-      ...initializeCurrentSchedule()
-    };
-  },
-  mounted() {
-    this.initialize();
-  },
-  watch: {
-    cronMode() {
-      this.cronString = this.calcCronString();
-    },
-    minutes() {
-      this.cronString = this.calcCronString();
-    },
-    hour() {
-      this.cronString = this.calcCronString();
-    },
-    month() {
-      this.cronString = this.calcCronString();
-    },
-    day() {
-      this.cronString = this.calcCronString();
-    },
-    dayOfMonth() {
-      this.cronString = this.calcCronString();
-    },
-    importScheduleDetailVisible() {
-      this.initialize();
-    },
-    cronString() {
-      if (this.isWeekly(this.cronString)) {
-        this.simple = "weekly";
-      }
-      if (this.isMonthly(this.cronString)) {
-        this.simple = "monthly";
-      }
-    }
-  },
-  computed: {
-    ...mapState("importschedule", [
-      "importScheduleDetailVisible",
-      "currentSchedule"
-    ]),
-    import_() {
-      return this.currentSchedule.importType;
-    },
-    dialogLabel() {
-      if (this.id) return this.$gettext("Import") + " " + this.id;
-      return this.$gettext("New Import");
-    },
-    directImportAvailable() {
-      switch (this.import_) {
-        case this.$options.IMPORTTYPES.BOTTLENECK:
-        case this.$options.IMPORTTYPES.FAIRWAYAVAILABILITY:
-        case this.$options.IMPORTTYPES.GAUGEMEASUREMENT:
-          return true;
-        default:
-          return false;
-      }
-    },
-    isCredentialsRequired() {
-      switch (this.import_) {
-        case this.$options.IMPORTTYPES.WATERWAYGAUGES:
-        case this.$options.IMPORTTYPES.DISTANCEMARKSVIRTUAL:
-          return true;
-        default:
-          return false;
-      }
-    },
-    isURLRequired() {
-      switch (this.import_) {
-        case this.$options.IMPORTTYPES.BOTTLENECK:
-        case this.$options.IMPORTTYPES.WATERWAYAXIS:
-        case this.$options.IMPORTTYPES.GAUGEMEASUREMENT:
-        case this.$options.IMPORTTYPES.FAIRWAYAVAILABILITY:
-        case this.$options.IMPORTTYPES.WATERWAYAREA:
-        case this.$options.IMPORTTYPES.FAIRWAYDIMENSION:
-        case this.$options.IMPORTTYPES.WATERWAYGAUGES:
-        case this.$options.IMPORTTYPES.DISTANCEMARKSVIRTUAL:
-        case this.$options.IMPORTTYPES.DISTANCEMARKSASHORE:
-          return true;
-        default:
-          return false;
-      }
-    },
-    isFeatureTypeRequired() {
-      switch (this.import_) {
-        case this.$options.IMPORTTYPES.WATERWAYAXIS:
-        case this.$options.IMPORTTYPES.WATERWAYAREA:
-        case this.$options.IMPORTTYPES.FAIRWAYDIMENSION:
-        case this.$options.IMPORTTYPES.DISTANCEMARKSASHORE:
-          return true;
-        default:
-          return false;
-      }
-    },
-    isSortbyRequired() {
-      switch (this.import_) {
-        case this.$options.IMPORTTYPES.WATERWAYAXIS:
-        case this.$options.IMPORTTYPES.WATERWAYAREA:
-        case this.$options.IMPORTTYPES.FAIRWAYDIMENSION:
-        case this.$options.IMPORTTYPES.DISTANCEMARKSASHORE:
-          return true;
-        default:
-          return false;
-      }
-    },
-    isToleranceRequired() {
-      switch (this.import_) {
-        case this.$options.IMPORTTYPES.BOTTLENECK:
-          return true;
-        default:
-          return false;
-      }
-    },
-    isValid() {
-      if (!this.import_) return false;
-      if (this.isToleranceRequired && !this.tolerance) return false;
-      if (this.directImport && !this.uploadFile) return false;
-      else if (!this.directImport) {
-        if (this.isURLRequired && !this.url) return false;
-        if (this.isSortbyRequired && !this.sortBy) return false;
-        if (this.isFeatureTypeRequired && !this.featureType) return false;
-        if (this.isCredentialsRequired && (!this.username || !this.password))
-          return false;
-        if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) {
-          if (
-            !this.LOS ||
-            !this.minWidth ||
-            !this.maxWidth ||
-            !this.depth ||
-            !this.sourceOrganization
-          )
-            return false;
-        }
-      }
-      return true;
-    }
-  },
-  methods: {
-    back() {
-      this.$store.commit("importschedule/setListMode");
-    },
-    fileSelected(e) {
-      const files = e.target.files || e.dataTransfer.files;
-      if (!files) return;
-      this.uploadLabel = files[0].name;
-      this.uploadFile = files[0];
-    },
-    setUrl(value) {
-      this.url = value;
-    },
-    setFeatureType(value) {
-      this.featureType = value;
-    },
-    setSortBy(value) {
-      this.sortBy = value;
-    },
-    setTolerance(value) {
-      this.tolerance = value;
-    },
-    setUsername(value) {
-      this.username = value;
-    },
-    setPassword(value) {
-      this.password = value;
-    },
-    setLOS(value) {
-      this.LOS = value;
-    },
-    setMinWidth(value) {
-      this.minWidth = value;
-    },
-    setMaxWidth(value) {
-      this.maxWidth = value;
-    },
-    setDepth(value) {
-      this.depth = value;
-    },
-    setSourceOrganization(value) {
-      this.sourceOrganization = value;
-    },
-    calcCronString() {
-      let getValue = value => {
-        return this[value] !== null ? this[value] : "*";
-      };
-
-      const min = getValue("minutes");
-      const h = getValue("hour");
-      const dm = getValue("dayOfMonth");
-      const m = getValue("month");
-      const wd = getValue("day");
-
-      if (this.cronMode === "15minutes") return "0 */15 * * * *";
-      if (this.cronMode === "hour") return `0 ${min} * * * *`;
-      if (this.cronMode === "day") return `0 ${min} ${h} * * *`;
-      if (this.cronMode === "week") return `0 ${min} ${h} * * ${wd}`;
-      if (this.cronMode === "month") return `0 ${min} ${h} ${dm} * *`;
-      if (this.cronMode === "year") return `0 ${min} ${h} ${dm} ${m} *`;
-      return this.cronString;
-    },
-    validateBottleneckfields() {
-      return !!this.url;
-    },
-    initialize() {
-      this.id = this.currentSchedule.id;
-      this.importType = this.currentSchedule.importType;
-      this.schedule = this.currentSchedule.schedule;
-      this.scheduled = this.currentSchedule.scheduled;
-      this.importSource = this.currentSchedule.importSource;
-      this.eMailNotification = this.currentSchedule.eMailNotification;
-      this.easyCron = this.currentSchedule.easyCron;
-      this.cronMode = this.currentSchedule.cronMode;
-      this.minutes = this.currentSchedule.minutes;
-      this.month = this.currentSchedule.month;
-      this.hour = this.currentSchedule.hour;
-      this.day = this.currentSchedule.day;
-      this.dayOfMonth = this.currentSchedule.dayOfMonth;
-      this.simple = this.currentSchedule.simple;
-      this.url = this.currentSchedule.url;
-      this.insecure = this.currentSchedule.insecure;
-      this.cronString = this.currentSchedule.cronString;
-      this.featureType = this.currentSchedule.featureType;
-      this.sortBy = this.currentSchedule.sortBy;
-      this.tolerance = this.currentSchedule.tolerance;
-      this.username = this.currentSchedule.username;
-      this.password = this.currentSchedule.password;
-      this.LOS = this.currentSchedule.LOS;
-      this.minWidth = this.currentSchedule.minWidth;
-      this.maxWidth = this.currentSchedule.maxWidth;
-      this.depth = this.currentSchedule.depth;
-      this.sourceOrganization = this.currentSchedule.sourceOrganization;
-      this.directImport = false;
-    },
-    isWeekly(cron) {
-      return /0 \d{1,2} \d{1,2} \* \* \d{1}/.test(cron);
-    },
-    isMonthly(cron) {
-      return /0 \d{1,2} \d{1,2} \d{1,2} \* \*/.test(cron);
-    },
-    clearInputs() {
-      this.minutes = this.currentSchedule.minutes;
-      this.month = this.currentSchedule.month;
-      this.hour = this.currentSchedule.hour;
-      this.day = this.currentSchedule.day;
-      this.dayOfMonth = this.currentSchedule.dayOfMonth;
-    },
-    triggerFileUpload() {
-      if (!this.uploadFile) return;
-      let formData = new FormData();
-      let routeParam = "";
-      switch (this.import_) {
-        case this.$options.IMPORTTYPES.BOTTLENECK:
-          formData.append("tolerance", this.tolerance);
-          routeParam = "ubn";
-          break;
-        case this.$options.IMPORTTYPES.FAIRWAYAVAILABILITY:
-          routeParam = "ufa";
-          break;
-        case this.$options.IMPORTTYPES.GAUGEMEASUREMENT:
-          routeParam = "ugm";
-          break;
-        default:
-          throw new Error("invalid importroute");
-      }
-
-      formData.append(routeParam, this.uploadFile);
-      HTTP.post("/imports/" + routeParam, formData, {
-        headers: {
-          "X-Gemma-Auth": localStorage.getItem("token"),
-          "Content-Type": "multipart/form-data"
-        }
-      })
-        .then(response => {
-          const { id } = response.data;
-          displayInfo({
-            title: this.$gettext("File Import"),
-            message: this.$gettext("Import import: #") + id
-          });
-          this.closeDetailview();
-          this.$store.dispatch("importschedule/loadSchedules").catch(error => {
-            const { status, data } = error.response;
-            displayError({
-              title: this.gettext("Backend Error"),
-              message: `${status}: ${data.message || data}`
-            });
-          });
-        })
-        .catch(error => {
-          const { status, data } = error.response;
-          displayError({
-            title: this.$gettext("Backend Error"),
-            message: `${status}: ${data.message || data}`
-          });
-        });
-    },
-    triggerManualImport() {
-      if (!this.triggerActive) return;
-      if (!this.import_) return;
-      if (this.directImport) {
-        if (!this.uploadFile) return;
-        this.triggerFileUpload();
-        return;
-      }
-      let data = {};
-      if (this.isURLRequired) {
-        if (!this.url) return;
-        data["url"] = this.url;
-        data["insecure"] = this.insecure;
-      }
-      if (this.isFeatureTypeRequired) {
-        if (!this.featureType) return;
-        data["feature-type"] = this.featureType;
-      }
-      if (this.isSortbyRequired) {
-        if (!this.sortBy) return;
-        data["sort-by"] = this.sortBy;
-      }
-      if (this.isToleranceRequired) {
-        if (!this.tolerance) return;
-        data["tolerance"] = parseFloat(this.tolerance);
-      }
-      if (this.isCredentialsRequired) {
-        if (!this.username || !this.password) return;
-        data["user"] = this.username;
-        data["password"] = this.password;
-      }
-      if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) {
-        if (
-          !this.LOS ||
-          !this.minWidth ||
-          !this.maxWidth ||
-          !this.depth ||
-          !this.sourceOrganization
-        )
-          return;
-        data["feature-type"] = this.featureType;
-        data["sort-by"] = this.sortBy;
-        data["los"] = this.LOS * 1;
-        data["min-width"] = this.minWidth * 1;
-        data["max-width"] = this.maxWidth * 1;
-        data["depth"] = this.depth * 1;
-        data["source-organization"] = this.sourceOrganization;
-      }
-      data["send-email"] = this.eMailNotification;
-      this.triggerActive = false;
-      this.$store
-        .dispatch("importschedule/triggerImport", {
-          type: IMPORTTYPEKIND[this.import_],
-          data
-        })
-        .then(response => {
-          const { id } = response.data;
-          displayInfo({
-            title: this.$gettext("Import"),
-            message: this.$gettext("Manually triggered import: #") + id
-          });
-        })
-        .catch(error => {
-          const { status, data } = error.response;
-          displayError({
-            title: this.$gettext("Backend Error"),
-            message: `${status}: ${data.message || data}`
-          });
-        })
-        .finally(() => {
-          this.triggerActive = true;
-        });
-    },
-    save() {
-      if (!this.import_) return;
-      let cron = this.cronString;
-      if (this.easyCron) {
-        if (this.simple === "weekly") cron = "0 0 0 * * 0";
-        if (this.simple === "monthly") cron = "0 0 0 1 * *";
-      }
-      let data = {};
-      let config = {};
-      data["kind"] = IMPORTTYPEKIND[this.import_];
-
-      if (this.isURLRequired) {
-        if (!this.url) return;
-        config["url"] = this.url;
-        config["insecure"] = this.insecure;
-      }
-      if (this.isSortbyRequired) {
-        if (!this.sortBy) return;
-        config["sort-by"] = this.sortBy;
-      }
-      if (this.isFeatureTypeRequired) {
-        if (!this.featureType) return;
-        config["feature-type"] = this.featureType;
-      }
-      if (this.isToleranceRequired) {
-        if (!this.tolerance) return;
-        config["tolerance"] = parseFloat(this.tolerance);
-      }
-      if (this.isCredentialsRequired) {
-        if (!this.username || !this.password) return;
-        config = {
-          ...config,
-          user: this.username,
-          password: this.password
-        };
-      }
-      if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) {
-        if (
-          !this.LOS ||
-          !this.minWidth ||
-          !this.maxWidth ||
-          !this.depth ||
-          !this.sourceOrganization
-        )
-          return;
-        config = { ...config, los: this.LOS, depth: this.depth };
-        config["min-width"] = this.minWidth;
-        config["max-width"] = this.maxWidth;
-        config["source-organization"] = this.sourceOrganization;
-      }
-      if (this.scheduled) config["cron"] = cron;
-      config["send-email"] = this.eMailNotification;
-      if (!this.id) {
-        data["config"] = config;
-        this.$store
-          .dispatch("importschedule/saveCurrentSchedule", data)
-          .then(response => {
-            const { id } = response.data;
-            displayInfo({
-              title: this.$gettext("Import"),
-              message: this.$gettext("Saved import: #") + id
-            });
-            this.closeDetailview();
-            this.$store
-              .dispatch("importschedule/loadSchedules")
-              .catch(error => {
-                const { status, data } = error.response;
-                displayError({
-                  title: this.gettext("Backend Error"),
-                  message: `${status}: ${data.message || data}`
-                });
-              });
-          })
-          .catch(error => {
-            const { status, data } = error.response;
-            displayError({
-              title: this.$gettext("Backend Error"),
-              message: `${status}: ${data.message || data}`
-            });
-          });
-      } else {
-        this.$store
-          .dispatch("importschedule/updateCurrentSchedule", {
-            data: config,
-            id: this.id
-          })
-          .then(response => {
-            const { id } = response.data;
-            displayInfo({
-              title: this.$gettext("Import"),
-              message: this.$gettext("update import: #") + id
-            });
-            this.closeDetailview();
-            this.$store
-              .dispatch("importschedule/loadSchedules")
-              .catch(error => {
-                const { status, data } = error.response;
-                displayError({
-                  title: this.gettext("Backend Error"),
-                  message: `${status}: ${data.message || data}`
-                });
-              });
-          })
-          .catch(error => {
-            const { status, data } = error.response;
-            displayError({
-              title: this.$gettext("Backend Error"),
-              message: `${status}: ${data.message || data}`
-            });
-          });
-      }
-    },
-    closeDetailview() {
-      this.$store.commit("importschedule/clearCurrentSchedule");
-      this.$store.commit("importschedule/setListMode");
-    }
-  },
-  IMPORTTYPES: IMPORTTYPES,
-  on: "on",
-  off: "off",
-  FILE: app.$gettext("File"),
-  URL: app.$gettext("URL"),
-  EVERY: app.$gettext("Every"),
-  MINUTESPAST: app.$gettext("minutes past"),
-  ON: app.$gettext("on"),
-  OF: app.$gettext("of"),
-  AT: app.$gettext("at"),
-  OCLOCK: app.$gettext("o' clock"),
-  CRONMODE: {
-    "15minutes": app.$gettext("15 minutes"),
-    hour: app.$gettext("hour"),
-    day: app.$gettext("day"),
-    week: app.$gettext("week"),
-    month: app.$gettext("month"),
-    year: app.$gettext("year")
-  },
-  DAYSOFWEEK: {
-    1: app.$gettext("Monday"),
-    2: app.$gettext("Tuesday"),
-    3: app.$gettext("Wednesday"),
-    4: app.$gettext("Thursday"),
-    5: app.$gettext("Friday"),
-    6: app.$gettext("Saturday"),
-    0: app.$gettext("Sunday")
-  },
-  MONTHS: {
-    1: app.$gettext("January"),
-    2: app.$gettext("February"),
-    3: app.$gettext("March"),
-    4: app.$gettext("April"),
-    5: app.$gettext("May"),
-    6: app.$gettext("June"),
-    7: app.$gettext("July"),
-    8: app.$gettext("August"),
-    9: app.$gettext("September"),
-    10: app.$gettext("October"),
-    11: app.$gettext("November"),
-    12: app.$gettext("December")
-  }
-};
-</script>
-
-<style lang="scss" scoped>
-.cronfield {
-  width: 55px;
-}
-
-.importscheduledetailscard {
-  min-height: 550px;
-}
-
-.importscheduledetails {
-  width: 100%;
-  margin-top: $offset;
-  margin-right: $offset;
-}
-</style>