view client/src/components/importconfiguration/ScheduledImports.vue @ 5661:216366f1067b fix_wait-retry_check

linting
author Thomas Junk <thomas.junk@intevation.de>
date Thu, 02 Nov 2023 16:10:03 +0100
parents dd20ee7cc9d8
children
line wrap: on
line source

<template>
  <form @submit.prevent="save" class="w-100">
    <div class="d-flex px-2">
      <div :key="1" class="flex-column">
        <small class="text-muted">
          <translate>Email Notification</translate>
        </small>
        <div class="flex-flex-row text-left">
          <toggle-button
            :value="eMailNotification"
            v-model="eMailNotification"
            :sync="true"
            class="mt-2"
            :speed="100"
            :labels="{
              checked: this.$options.on,
              unchecked: this.$options.off
            }"
            :width="60"
            :height="30"
          />
        </div>
      </div>
      <div
        :key="2"
        v-if="directImportAvailable"
        class="flex-column text-left ml-3"
      >
        <small class="text-muted">
          <translate>Import via</translate>
        </small>
        <div>
          <!-- '#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>
    </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"
    />
    <DQLReport
      v-if="import_ == $options.IMPORTTYPES.REPORT"
      @reportNameChanged="setReportName"
      :reportName="reportName"
      :availableReports="availableReports"
    />
    <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"
    />
    <Fairwaymarks
      v-if="import_ == $options.IMPORTTYPES.FAIRWAYMARKS"
      @urlChanged="setUrl"
      @featureTypeChanged="setFeatureType"
      @sortByChanged="setSortBy"
      @selectedMarkChanged="setSelectedMark"
      :isUpdate="!this.id"
      :url="url"
      :featureType="featureType"
      :sortBy="sortBy"
      :mark="selectedMark"
    />
    <Gaugemeasurement
      v-if="import_ == $options.IMPORTTYPES.GAUGEMEASUREMENT && !directImport"
      @urlChanged="setUrl"
      :url="url"
    />
    <Statsupdate
      v-if="import_ == $options.IMPORTTYPES.STATSUPDATE && !directImport"
      @statsUpdateChanged="setStatsUpdate"
      :statsUpdate="statsUpdate"
    />
    <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 p-2">
        <div class="flex-column w-50">
          <div class="d-flex flex-row">
            <div class="flex-column mr-4">
              <div class="flex-row text-left">
                <small class="text-muted">
                  <translate>Scheduled</translate>?
                </small>
              </div>
              <div class="flex-row text-left">
                <toggle-button
                  :value="scheduled"
                  v-model="scheduled"
                  :sync="true"
                  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</translate>
                </small>
              </div>
              <div class="flex-flex-row text-left">
                <toggle-button
                  :disabled="!scheduled"
                  :value="easyCron"
                  v-model="easyCron"
                  :sync="true"
                  class="mt-2"
                  :speed="100"
                  :labels="{
                    checked: this.$options.on,
                    unchecked: this.$options.off
                  }"
                  :width="60"
                  :height="30"
                />
              </div>
            </div>
          </div>
        </div>
        <div class="flex-column ml-2">
          <div class="ml-auto flex-column">
            <div class="flex-row text-left">
              <small class="text-muted">
                <translate>Retry on failure</translate>
              </small>
            </div>
            <div class="flex-row text-left">
              <toggle-button
                :value="retry"
                v-model="retry"
                :sync="true"
                class="mt-2"
                :speed="100"
                :labels="{
                  checked: this.$options.on,
                  unchecked: this.$options.off
                }"
                v-tooltip.bottom="ttRetry"
                :width="60"
                :height="30"
              />
            </div>
          </div>
        </div>
      </div>
    </template>
    <template v-if="!directImport || !directImportAvailable">
      <div class="d-flex flex-row">
        <div class="flex-column w-50 px-2 pb-3">
          <div class="flex-row text-left">
            <small class="text-muted">
              <translate>Schedule</translate>
            </small>
          </div>
          <div v-if="easyCron" class="text-left w-100">
            <select
              :disabled="!scheduled"
              v-model="simple"
              class="form-control form-control-sm"
            >
              <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">
              <div class="my-auto mr-2">{{ $options.EVERY }}</div>
              <select
                :disabled="!scheduled"
                style="width: 130px;"
                v-model="cronMode"
                class="form-control form-control-sm"
                @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">
                <div class="mt-auto mb-auto">{{ $options.ON }}</div>
                <input
                  :disabled="!scheduled"
                  v-model="minutes"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
                <div class="mt-auto mb-auto">{{ $options.MINUTESPAST }}</div>
              </div>
              <div v-if="cronMode == 'day'" class="ml-1 d-flex flex-row">
                <div class="mt-auto mb-auto">{{ $options.AT }}</div>
                <input
                  :disabled="!scheduled"
                  v-model="hour"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
                <input
                  :disabled="!scheduled"
                  v-model="minutes"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
                <div class="mt-auto mb-auto">{{ $options.OCLOCK }}</div>
              </div>
              <div v-if="cronMode == 'week'" class="ml-1 d-flex flex-row">
                <div class="ml-1 mr-1 mt-auto mb-auto">{{ $options.ON }}</div>
                <select
                  :disabled="!scheduled"
                  v-model="day"
                  class="form-control form-control-sm"
                >
                  <option
                    v-for="(option, key) in $options.DAYSOFWEEK"
                    :key="key"
                    :value="key"
                    >{{ option }}</option
                  >
                </select>
                <div class="ml-1 mt-auto mb-auto">{{ $options.AT }}</div>
                <input
                  :disabled="!scheduled"
                  v-model="hour"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
                <input
                  :disabled="!scheduled"
                  v-model="minutes"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
              </div>
              <div v-if="cronMode == 'month'" class="ml-1 d-flex flex-row">
                <div class="ml-1 mt-auto mb-auto">{{ $options.ON }}</div>
                <input
                  :disabled="!scheduled"
                  v-model="dayOfMonth"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
                <div class="mt-auto mb-auto">{{ $options.AT }}</div>
                <input
                  :disabled="!scheduled"
                  v-model="hour"
                  class="cronfield ml-1 mr-2 form-control form-control-sm"
                  type="number"
                />
                <input
                  :disabled="!scheduled"
                  v-model="minutes"
                  class="cronfield ml-1 mr-2 form-control form-control-sm"
                  type="number"
                />
                <div class="mt-auto mb-auto">{{ $options.OCLOCK }}</div>
              </div>
              <div v-if="cronMode == 'year'" class="ml-1 d-flex flex-row">
                <div class="ml-1 mt-auto mb-auto">{{ $options.ON }}</div>
                <input
                  :disabled="!scheduled"
                  v-model="dayOfMonth"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
                <div class="mt-auto mb-auto">{{ $options.OF }}</div>
                <select
                  :disabled="!scheduled"
                  v-model="month"
                  class="ml-1 mr-1 form-control form-control-sm"
                >
                  <option
                    v-for="(option, key) in $options.MONTHS"
                    :value="key"
                    :key="key"
                    >{{ option }}</option
                  >
                </select>
                <div class="mt-auto mb-auto">{{ $options.ON }}</div>
                <input
                  :disabled="!scheduled"
                  v-model="hour"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
                <input
                  :disabled="!scheduled"
                  v-model="minutes"
                  class="cronfield ml-1 mr-1 form-control form-control-sm"
                  type="number"
                />
              </div>
            </div>
            <div class="mt-3 w-50 d-flex">
              <div class="my-auto mr-2">
                <translate>Cronstring</translate>
              </div>
              <input
                :disabled="!scheduled"
                class="form-control form-control-sm"
                v-model="cronString"
                type="text"
              />
            </div>
          </div>
        </div>
        <div class="d-flex flex-column ml-2">
          <div class="d-flex flex-row ">
            <div class="ml-1 flex-column">
              <div class="flex-row text-left">
                <small class="text-muted">
                  <translate>Tries</translate>
                </small>
              </div>
              <div>
                <input
                  :disabled="!retry"
                  style="width:120px;"
                  v-model="trys"
                  class="mr-1 form-control form-control-sm"
                  v-tooltip.bottom="ttRetries"
                  type="number"
                  max="200"
                  min="0"
                />
              </div>
            </div>
            <div class="flex-column">
              <div class="flex-row text-left">
                <small class="text-muted">
                  <translate>Wait to retry</translate>
                </small>
              </div>
              <div>
                <input
                  :disabled="!retry"
                  v-on:change="checkMinimum"
                  style="width:120px;"
                  v-model="waitRetry"
                  v-tooltip.bottom="ttWaitRetry"
                  class="ml-1 form-control form-control-sm"
                />
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>
    <div v-else class="d-flex text-left px-2 pb-3">
      <div class="flex-column w-100">
        <div class="custom-file">
          <input
            accept=".xml"
            type="file"
            @change="fileSelected"
            class="custom-file-input custom-file-input-sm"
            id="uploadFile"
          />
          <label class="pointer custom-file-label" for="uploadFile">
            {{ uploadLabel }}
          </label>
        </div>
      </div>
    </div>
    <div class="d-flex justify-content-between p-2 border-top">
      <button :key="1" @click="back()" class="btn btn-sm btn-warning">
        Back
      </button>
      <div>
        <button
          @click="triggerManualImport"
          type="button"
          class="btn btn-sm btn-outline-info"
          :disabled="!triggerActive || !isValid"
        >
          <font-awesome-icon fixed-width icon="play" />
          <translate>Trigger import</translate>
        </button>
        <button
          v-if="!directImport || !directImportAvailable"
          :disabled="!isValid"
          type="submit"
          class="btn btn-sm btn-info ml-3"
        >
          <translate>Save</translate>
        </button>
      </div>
    </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, 2020 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"),
    DQLReport: () => import("./types/DQLReport"),
    Faiwaydimensions: () => import("./types/Fairwaydimensions"),
    Fairwaymarks: () => import("./types/Fairwaymarks"),
    Gaugemeasurement: () => import("./types/Gaugemeasurement"),
    Statsupdate: () => import("./types/Statsupdate"),
    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,
      retry: false,
      ...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";
      }
    },
    retry() {
      if (!this.retry) {
        this.trys = null;
        this.waitRetry = "";
      }
    }
  },
  computed: {
    ...mapState("importschedule", [
      "availableReports",
      "importScheduleDetailVisible",
      "currentSchedule"
    ]),
    import_() {
      return this.currentSchedule.importType;
    },
    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.FAIRWAYMARKS:
        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.FAIRWAYMARKS:
        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;
      }
    },
    usernamePasswordFilled() {
      if (
        this.isCredentialsRequired &&
        this.currentSchedule.id &&
        this.username
      )
        return true;
      if (
        this.isCredentialsRequired &&
        !this.currentSchedule.id &&
        this.username &&
        this.password
      )
        return true;
      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.isFeatureTypeRequired && !this.featureType) return false;
        if (this.isCredentialsRequired && !this.usernamePasswordFilled)
          return false;
        if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) {
          if (
            !this.LOS ||
            !this.minWidth ||
            !this.maxWidth ||
            !this.depth ||
            !this.sourceOrganization
          )
            return false;
        }
      }
      return true;
    },
    ttWaitRetry() {
      return `${this.$gettext(
        "Time between retries. Valid units are 's' , 'm' and 'h' "
      )}<div style="text-align:left;">${this.$gettext(
        "Examples:"
      )}<ul><li>${this.$gettext("60s for 60 Seconds ")}
      </li><li> ${this.$gettext("30m for 30 Minutes")}</li><li> ${this.$gettext(
        "2h45m for for two hours and 45 Minutes"
      )}</li><li>${this.$gettext("At least 5 Seconds ")}
      </li></ul></div>`;
    },
    ttRetries() {
      return ` ${this.$gettext("Maximum retry count")}<br> ${this.$gettext(
        "If there is no error during import, there will be no retry"
      )}
        <br><div style="margin-left:45px;text-align:left;"<ul>
        <li> ${this.$gettext("0 means no retry")}</li><li> ${this.$gettext(
        "Positive values are the upper limit for retries"
      )}
        </li><li>${this.$gettext("Maximum of 200")}
      </li></ul></div>`;
    },
    ttRetry() {
      return this.$gettext("retryDescription");
    }
  },
  methods: {
    checkMinimum() {
      let m = /^((\d+)h)?((\d+)m)?((\d+)s)?$/.exec(this.waitRetry);
      if (m) {
        let s = 0;
        if (m[2]) {
          s += m[2] * 3600;
        }
        if (m[4]) {
          s += m[4] * 60;
        }
        if (m[6]) {
          s += m[6];
        }
        if (s < 5) this.waitRetry = "5s";
      }
    },
    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];
    },
    setReportName(value) {
      this.reportName = value;
    },
    setStatsUpdate(value) {
      this.statsUpdate = value;
    },
    setUrl(value) {
      this.url = value;
    },
    setFeatureType(value) {
      this.featureType = value;
    },
    setSortBy(value) {
      this.sortBy = value;
    },
    setSelectedMark(value) {
      this.selectedMark = 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 = parseInt(value * 100);
    },
    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;
      this.trys = this.currentSchedule.trys;
      this.waitRetry = this.currentSchedule.waitRetry;
      this.selectedMark = this.currentSchedule.selectedMark;
      this.statsUpdate = this.currentSchedule.statsUpdate;
      this.reportName = this.currentSchedule.reportName;
      this.retry =
        this.currentSchedule.trys === null ||
        this.currentSchedule.trys === undefined ||
        this.currentSchedule === 0
          ? false
          : true;
    },
    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);
      if (this.eMailNotification) {
        formData.append("send-email", this.eMailNotification);
      }
      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 => {
            let message = "Backend not reachable";
            if (error.response) {
              const { status, data } = error.response;
              message = `${status}: ${data.message || data}`;
            }
            displayError({
              title: this.$gettext("Backend Error"),
              message: message
            });
          });
        })
        .catch(error => {
          let message = "Backend not reachable";
          if (error.response) {
            const { status, data } = error.response;
            message = `${status}: ${data.message || data}`;
          }
          displayError({
            title: this.$gettext("Backend Error"),
            message: message
          });
        });
    },
    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.sortBy) {
        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;
      }
      if (this.waitRetry) data["wait-retry"] = this.waitRetry;
      if (this.trys) data["trys"] = Number(this.trys);
      if (this.import_ === this.$options.IMPORTTYPES.STATSUPDATE) {
        if (!this.statsUpdate) return;
        data["name"] = this.statsUpdate;
      }
      if (this.import_ === this.$options.IMPORTTYPES.REPORT) {
        if (!this.reportName) return;
        data["name"] = this.reportName;
      }
      data["send-email"] = this.eMailNotification;
      this.triggerActive = false;
      const type =
        this.import_ === "fairwaymarks"
          ? `fm_${this.selectedMark.toLowerCase()}`
          : IMPORTTYPEKIND[this.import_];
      this.$store
        .dispatch("importschedule/triggerImport", {
          type: type,
          data
        })
        .then(response => {
          const { id } = response.data;
          displayInfo({
            title: this.$gettext("Import"),
            message: this.$gettext("Manually triggered import: #") + id
          });
        })
        .catch(error => {
          let message = "Backend not reachable";
          if (error.response) {
            const { status, data } = error.response;
            message = `${status}: ${data.message || data}`;
          }
          displayError({
            title: this.$gettext("Backend Error"),
            message: message
          });
        })
        .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"] =
        this.import_ === "fairwaymarks"
          ? `fm_${this.selectedMark.toLowerCase()}`
          : IMPORTTYPEKIND[this.import_];
      if (this.isURLRequired) {
        if (!this.url) return;
        config["url"] = this.url;
        config["insecure"] = this.insecure;
      }
      if (this.sortBy) {
        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.usernamePasswordFilled) return;
        config = {
          ...config,
          user: this.username
        };
        if (this.password) {
          config["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;
      }
      if (this.waitRetry) config["wait-retry"] = this.waitRetry;
      if (this.trys) config["trys"] = Number(this.trys);
      if (this.import_ === this.$options.IMPORTTYPES.REPORT) {
        if (!this.reportName) return;
        config["name"] = this.reportName;
      }
      if (this.import_ === this.$options.IMPORTTYPES.STATSUPDATE) {
        if (!this.statsUpdate) return;
        config["name"] = this.statsUpdate;
      }
      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 => {
                let message = "Backend not reachable";
                if (error.response) {
                  const { status, data } = error.response;
                  message = `${status}: ${data.message || data}`;
                }
                displayError({
                  title: this.$gettext("Backend Error"),
                  message: message
                });
              });
          })
          .catch(error => {
            let message = "Backend not reachable";
            if (error.response) {
              const { status, data } = error.response;
              message = `${status}: ${data.message || data}`;
            }
            displayError({
              title: this.$gettext("Backend Error"),
              message: message
            });
          });
      } 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 => {
                let message = "Backend not reachable";
                if (error.response) {
                  const { status, data } = error.response;
                  message = `${status}: ${data.message || data}`;
                }
                displayError({
                  title: this.$gettext("Backend Error"),
                  message: message
                });
              });
          })
          .catch(error => {
            let message = "Backend not reachable";
            if (error.response) {
              const { status, data } = error.response;
              message = `${status}: ${data.message || data}`;
            }
            displayError({
              title: this.$gettext("Backend Error"),
              message: message
            });
          });
      }
    },
    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 scoped>
.cronfield {
  width: 55px;
}

.importscheduledetailscard {
  min-height: 550px;
}

.importscheduledetails {
  width: 100%;
  margin-top: var(--offset);
  margin-right: var(--offset);
}
</style>