Mercurial > gemma
view client/src/components/importschedule/Importscheduledetail.vue @ 1771:88b8da513944
deactivate delete and edit action during editing
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Fri, 11 Jan 2019 11:33:34 +0100 |
parents | e84f78cd0d2f |
children | bd72d1a7ffe6 |
line wrap: on
line source
<template> <div class="importscheduledetails fadeIn animated" v-if="importScheduleDetailVisible" > <div class="card shadow-xs importscheduledetailscard pb-5"> <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center" > <translate>New import</translate> <span @click="closeDetailview" class="closebutton"> <font-awesome-icon icon="times"></font-awesome-icon> </span> </h6> <div class="card-body"> <form @submit.prevent="save" class="ml-2 mr-2"> <div class="d-flex flex-row"> <div class="flex-column w-50 mr-3"> <div class="flex-row text-left"> <small class="text-muted"> <translate>Imports</translate> </small> </div> <select v-model="import_" class="custom-select" id="importtype"> <option :value="$options.IMPORTTYPES.BOTTLENECK" ><translate>Bottlenecks</translate></option > <option :value="$options.IMPORTTYPES.WATERWAYAXIS" ><translate>Waterway axis</translate></option > <option :value="$options.IMPORTTYPES.GAUGEMEASUREMENT" ><translate>Gauge measurement</translate></option > <option :value="$options.IMPORTTYPES.FAIRWAYAVAILABILITY" ><translate>Available Fairway Depths</translate></option > </select> </div> <div class="flex-column ml-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> <div v-if="isURLRequired"> <div class="d-flex flex-row"> <div class="flex-column mt-3 mr-3 w-100"> <div class="flex-row text-left"> <small class="text-muted"> <translate>URL</translate> </small> </div> <div class="w-100"> <input v-model="url" class="form-control" type="url" /> </div> </div> <div v-if="false" class="flex-column mt-3 text-left"> <div class="d-flex flex-row"> <small class="text-muted mr-2" ><translate>Insecure</translate> </small> </div> <div class="d-flex flex-row"> <toggle-button v-model="insecure" class="mt-2" :speed="100" :color="{ checked: '#FF0000', unchecked: '#E9ECEF', disabled: '#CCCCCC' }" :labels="{ checked: this.$options.on, unchecked: this.$options.off }" :width="60" :height="30" /> </div> </div> </div> <div v-if="!url" class="d-flex flex-row"> <small ><translate class="text-danger" >Please enter a URL</translate ></small > </div> </div> <div v-if="isFeatureTypeRequired"> <div class="d-flex flex-row"> <div class="flex-column mt-3 mr-3 w-50"> <div class="flex-row text-left"> <small class="text-muted"> <translate>Featuretype</translate> </small> </div> <div class="w-100"> <input v-model="featureType" class="form-control" type="text" /> </div> <div v-if="!featureType" class="d-flex flex-row"> <small ><translate class="text-danger" >Please enter a Featuretype</translate ></small > </div> </div> <div class="flex-column mt-3 w-50"> <div class="flex-row text-left"> <small class="text-muted"> <translate>SortBy</translate> </small> </div> <div class="w-100"> <input v-model="sortBy" class="form-control" type="text" /> </div> <div v-if="!sortBy" class="d-flex flex-row"> <small ><translate class="text-danger" >Please enter SortBy</translate ></small > </div> </div> </div> </div> <div class="d-flex flex-row"> <div class="flex-column mt-3 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 mt-3 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 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> <button type="submit" class="shadow-sm btn btn-info submit-button"> <translate>Submit</translate> </button> <button @click="triggerManualImport" type="button" class="shadow-sm btn btn-outline-info trigger" :disabled="!triggerActive" > <font-awesome-icon class="fa-fw mr-2" fixed-width icon="play" ></font-awesome-icon ><translate>Trigger import</translate> </button> </form> </div> </div> </div> </template> <script> /* This is Free Software under GNU Affero General Public License v >= 3.0 * without warranty, see README.md and license for details. * * SPDX-License-Identifier: AGPL-3.0-or-later * License-Filename: LICENSES/AGPL-3.0.txt * * Copyright (C) 2018 by via donau * – Österreichische Wasserstraßen-Gesellschaft mbH * Software engineering by Intevation GmbH * * Author(s): * Thomas Junk <thomas.junk@intevation.de> */ import { IMPORTTYPES, IMPORTTYPEKIND } from "@/store/imports.js"; import { mapState } from "vuex"; import { displayInfo, displayError } from "@/lib/errors.js"; import app from "@/main.js"; export default { name: "importscheduledetail", data() { return { id: null, importType: null, schedule: null, import_: null, importSource: null, eMailNotification: false, scheduled: false, easyCron: true, cronMode: "", minutes: null, month: null, hour: null, day: null, dayOfMonth: null, simple: null, url: null, insecure: false, triggerActive: true, cronString: "* * * * ", featureType: null, sortBy: null }; }, IMPORTTYPES: IMPORTTYPES, 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") }, 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("imports", ["importScheduleDetailVisible", "currentSchedule"]), isURLRequired() { switch (this.import_) { case this.$options.IMPORTTYPES.BOTTLENECK: case this.$options.IMPORTTYPES.WATERWAYAXIS: case this.$options.IMPORTTYPES.GAUGEMEASUREMENT: case this.$options.IMPORTTYPES.FAIRWAYAVAILABILITY: return true; default: return false; } }, isFeatureTypeRequired() { switch (this.import_) { case this.$options.IMPORTTYPES.WATERWAYAXIS: return true; default: return false; } }, isSortbyRequired() { switch (this.import_) { case this.$options.IMPORTTYPES.WATERWAYAXIS: return true; default: return false; } }, fixedSource() { if (this.import_ === this.$options.IMPORTTYPES.BOTTLENECK) return true; return false; } }, methods: { calcCronString() { let getValue = value => { return this[value] ? this[value] : "*"; }; if (this.cronMode === "15minutes") return "0 */15 * * * *"; const min = getValue("minutes"); const h = getValue("hour"); const dm = getValue("dayOfMonth"); const m = getValue("month"); const wd = getValue("day"); return `0 ${min} ${h} ${dm} ${m} ${wd}`; }, 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.import_ = this.currentSchedule.import_; 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; }, 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 = null; this.month = null; this.hour = null; this.day = null; this.dayOfMonth = null; }, triggerManualImport() { if (!this.triggerActive) return; if (!this.import_) 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; } this.triggerActive = false; this.$store .dispatch("imports/triggerImport", { type: 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() { const addAttribute = (data, attribute) => { if (!data["attributes"]) data.attributes = {}; data["attributes"] = { ...data["attributes"], ...attribute }; }; 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 = {}; if (this.isURLRequired) { if (!this.url) return; data["url"] = this.url; addAttribute(data, { insecure: this.insecure + "" }); } if (this.isSortbyRequired) { if (!this.sortBy) return; addAttribute(data, { "sort-by": this.sortBy }); } if (this.isFeatureTypeRequired) { if (!this.featureType) return; addAttribute(data, { "feature-type": this.featureType }); } if (this.scheduled) data["cron"] = cron; data["kind"] = IMPORTTYPEKIND[this.import_]; data["send-email"] = this.eMailNotification; if (!this.id) { this.$store .dispatch("imports/saveCurrentSchedule", data) .then(response => { const { id } = response.data; displayInfo({ title: this.$gettext("Import"), message: this.$gettext("Saved import: #") + id }); this.closeDetailview(); this.$store.dispatch("imports/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("imports/updateCurrentSchedule", { data: data, 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("imports/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("imports/clearCurrentSchedule"); this.$store.commit("imports/setImportScheduleDetailInvisible"); } }, imports: [], on: "on", off: "off", periods: { DAILY: "daily", MONTHLY: "monthly" } }; </script> <style lang="scss" scoped> .cronfield { width: 55px; } .importscheduledetailscard { min-height: 550px; } .importscheduledetails { width: 100%; margin-top: $offset; margin-right: $offset; } .trigger { position: absolute; left: $large-offset; bottom: $offset; } .submit-button { position: absolute; right: $large-offset; bottom: $offset; } </style>