Mercurial > gemma
view client/src/components/importschedule/Importscheduledetail.vue @ 2037:11cb57f85c60 unify_imports
Merged default into branch.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Fri, 25 Jan 2019 11:53:28 +0100 |
parents | 2f6cadcb3558 |
children | 4a0d4e50768d |
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" > {{ dialogLabel }} <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 > <option :value="$options.IMPORTTYPES.WATERWAYAREA" ><translate>Waterwayarea</translate></option > <option :value="$options.IMPORTTYPES.FAIRWAYDIMENSION" ><translate>Fairwaydimension</translate></option > <option :value="$options.IMPORTTYPES.WATERWAYGAUGES" ><translate>Waterway gauges</translate></option > <option :value="$options.IMPORTTYPES.DISTANCEMARKSVIRTUAL" ><translate>Distance Marks Virtual</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> <Availablefairwaydepth v-if="import_ == $options.IMPORTTYPES.FAIRWAYAVAILABILITY" @urlChanged="setUrl" :url="url" ></Availablefairwaydepth> <Bottleneck v-if="import_ == $options.IMPORTTYPES.BOTTLENECK" @urlChanged="setUrl" :url="url" ></Bottleneck> <Distancemarksvirtual v-if="import_ == $options.IMPORTTYPES.DISTANCEMARKSVIRTUAL" @urlChanged="setUrl" @usernameChanged="setUsername" @passwordChanged="setPassword" :url="url" :username="username" :password="password" ></Distancemarksvirtual> <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" ></Faiwaydimensions> <Gaugemeasurement v-if="import_ == $options.IMPORTTYPES.GAUGEMEASUREMENT" @urlChanged="setUrl" :url="url" ></Gaugemeasurement> <Waterwayarea v-if="import_ == $options.IMPORTTYPES.WATERWAYAREA" @urlChanged="setUrl" @featureTypeChanged="setFeatureType" @sortByChanged="setSortBy" :url="url" :featureType="featureType" :sortBy="sortBy" ></Waterwayarea> <Waterwaygauges v-if="import_ == $options.IMPORTTYPES.WATERWAYGAUGES" @urlChanged="setUrl" @usernameChanged="setUsername" @passwordChanged="setPassword" :url="url" :username="username" :password="password" ></Waterwaygauges> <Waterwayaxis v-if="import_ == $options.IMPORTTYPES.WATERWAYAXIS" @urlChanged="setUrl" @featureTypeChanged="setFeatureType" @sortByChanged="setSortBy" :url="url" :featureType="featureType" :sortBy="sortBy" ></Waterwayaxis> <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, initializeCurrentSchedule } from "@/store/importschedule"; import { mapState } from "vuex"; import { displayInfo, displayError } from "@/lib/errors.js"; import app from "@/main.js"; export default { name: "importscheduledetail", components: { Availablefairwaydepth: () => import("@/components/importschedule/importtypes/Availablefairwaydepth"), Bottleneck: () => import("@/components/importschedule/importtypes/Bottleneck"), Distancemarksvirtual: () => import("@/components/importschedule/importtypes/Distancemarksvirtual"), Faiwaydimensions: () => import("@/components/importschedule/importtypes/Fairwaydimensions"), Gaugemeasurement: () => import("@/components/importschedule/importtypes/Gaugemeasurement"), Waterwayarea: () => import("@/components/importschedule/importtypes/Waterwayarea"), Waterwaygauges: () => import("@/components/importschedule/importtypes/Waterwaygauges"), Waterwayaxis: () => import("@/components/importschedule/importtypes/Waterwayaxis") }, data() { return { passwordVisible: 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"; } } }, computed: { ...mapState("importschedule", [ "importScheduleDetailVisible", "currentSchedule" ]), dialogLabel() { if (this.id) return this.$gettext("Import") + " " + this.id; return this.$gettext("New Import"); }, 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: return true; default: return false; } }, isFeatureTypeRequired() { switch (this.import_) { case this.$options.IMPORTTYPES.WATERWAYAXIS: case this.$options.IMPORTTYPES.WATERWAYAREA: case this.$options.IMPORTTYPES.FAIRWAYDIMENSION: return true; default: return false; } }, isSortbyRequired() { switch (this.import_) { case this.$options.IMPORTTYPES.WATERWAYAXIS: case this.$options.IMPORTTYPES.WATERWAYAREA: case this.$options.IMPORTTYPES.FAIRWAYDIMENSION: return true; default: return false; } } }, methods: { setUrl(value) { this.url = value; }, setFeatureType(value) { this.featureType = value; }, setSortBy(value) { this.sortBy = 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] ? 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; 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; }, 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; } if (this.isCredentialsRequired) { if (!this.username || !this.password) return; data["username"] = 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; } this.triggerActive = false; this.$store .dispatch("importschedule/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.isCredentialsRequired) { if (!this.username || !this.password) return; addAttribute(data, { username: this.username, password: this.password }); } if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) { if ( !this.LOS || !this.minWidth || !this.maxWidth || !this.depth || !this.sourceOrganization ) return; const values = { los: this.LOS + "", depth: this.depth + "" }; values["min-width"] = this.minWidth + ""; values["max-width"] = this.maxWidth + ""; values["source-organization"] = this.sourceOrganization; addAttribute(data, values); } if (this.scheduled) data["cron"] = cron; data["kind"] = IMPORTTYPEKIND[this.import_]; data["send-email"] = this.eMailNotification; if (!this.id) { 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: 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("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/setImportScheduleDetailInvisible"); } }, IMPORTTYPES: IMPORTTYPES, on: "on", off: "off", 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; } .trigger { position: absolute; left: $large-offset; bottom: $offset; } .submit-button { position: absolute; right: $large-offset; bottom: $offset; } </style>