Mercurial > gemma
changeset 2982:ef79b635857b
merge with unified_import
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Tue, 09 Apr 2019 16:31:55 +0200 |
parents | 7c301ff449bc (current diff) e47e440ab921 (diff) |
children | 2e7c0f9cff24 |
files | client/src/components/ImportApprovedGaugeMeasurement.vue client/src/components/ImportSoundingresults.vue client/src/components/ImportWaterwayProfiles.vue client/src/components/importschedule/Importschedule.vue client/src/components/importschedule/Importscheduledetail.vue client/src/components/importschedule/importtypes/Availablefairwaydepth.vue client/src/components/importschedule/importtypes/Bottleneck.vue client/src/components/importschedule/importtypes/Distancemarksashore.vue client/src/components/importschedule/importtypes/Distancemarksvirtual.vue client/src/components/importschedule/importtypes/Fairwaydimensions.vue client/src/components/importschedule/importtypes/Gaugemeasurement.vue client/src/components/importschedule/importtypes/Waterwayarea.vue client/src/components/importschedule/importtypes/Waterwayaxis.vue client/src/components/importschedule/importtypes/Waterwaygauges.vue |
diffstat | 34 files changed, 3039 insertions(+), 3048 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/App.vue Mon Apr 08 18:54:13 2019 +0200 +++ b/client/src/components/App.vue Tue Apr 09 16:31:55 2019 +0200 @@ -79,7 +79,7 @@ ...mapState("user", ["isAuthenticated"]), ...mapState("application", ["contextBoxContent", "showSearchbar"]), isMapVisible() { - return /importoverview|stretches|review|bottlenecks|mainview/.test( + return /importconfiguration|importoverview|stretches|review|bottlenecks|mainview/.test( this.routeName ); },
--- a/client/src/components/Contextbox.vue Mon Apr 08 18:54:13 2019 +0200 +++ b/client/src/components/Contextbox.vue Tue Apr 09 16:31:55 2019 +0200 @@ -6,6 +6,9 @@ <ImportOverview v-if="contextBoxContent === 'importoverview'" ></ImportOverview> + <ImportConfiguration + v-if="contextBoxContent === 'importconfiguration'" + ></ImportConfiguration> </div> </template> @@ -31,7 +34,9 @@ Bottlenecks: () => import("@/components/Bottlenecks"), Stretches: () => import("@/components/ImportStretches.vue"), ImportOverview: () => - import("@/components/importoverview/ImportOverview.vue") + import("@/components/importoverview/ImportOverview.vue"), + ImportConfiguration: () => + import("@/components/importconfiguration/Import.vue") }, computed: { ...mapState("application", [
--- a/client/src/components/ImportApprovedGaugeMeasurement.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -<template> - <div class="d-flex flex-row"> - <Spacer /> - <div class="card sysconfig mt-2 shadow-xs w-100 h-100 mr-2"> - <UIBoxHeader icon="upload" :title="importGaugmeasurmentLabel" /> - <div class="card-body stretches-card"> - <div class="w-95 ml-auto mr-auto mt-4 mb-4"> - <div class="d-flex flex-column text-left w-25"> - <label class="text-nowrap" for="originator"> - <small class="text-muted" - >{{ $options.ORIGINATOR }} / {{ $options.FROM }}</small - > - </label> - <input - type="text" - v-model="originator" - class="form-control" - id="originator" - /> - <span class="text-left text-danger"> - <small v-if="!originator"> - <translate>Please enter an originator</translate> - </small> - </span> - </div> - <div class="mt-4 flex-column w-100"> - <div class="custom-file"> - <input - accept=".csv" - 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="buttons text-right"> - <button - :disabled="disableUploadButton" - @click="submit" - class="btn btn-info mt-4" - type="button" - > - <font-awesome-icon class="fa-fw mr-2" fixed-width icon="play" /> - <translate>Trigger import</translate> - </button> - </div> - </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 { HTTP } from "@/lib/http"; -import { displayError, displayInfo } from "@/lib/errors.js"; -import app from "@/main"; - -export default { - name: "importapprovedgaugemeasurements", - data() { - return { - disableUploadButton: false, - uploadLabel: this.$gettext("choose file to upload"), - uploadFile: null, - originator: "viadonau" - }; - }, - computed: { - importGaugmeasurmentLabel() { - return this.$gettext("Import approved gaugemeasurements"); - } - }, - methods: { - initialState() { - this.uploadLabel = this.$gettext("choose file to upload"); - this.uploadFile = null; - this.originator = "viadonau"; - }, - fileSelected(e) { - const files = e.target.files || e.dataTransfer.files; - if (!files) return; - this.uploadLabel = files[0].name; - this.uploadFile = files[0]; - }, - submit() { - if (!this.originator || !this.uploadFile) return; - let formData = new FormData(); - formData.append("agm", this.uploadFile); - formData.append("originator", this.originator); - HTTP.post("/imports/agm", formData, { - headers: { - "X-Gemma-Auth": localStorage.getItem("token"), - "Content-Type": "multipart/form-data" - } - }) - .then(() => { - displayInfo({ - title: this.$gettext("Import"), - message: this.$gettext( - "Starting import of Approved Gauge Measurements" - ) - }); - this.initialState(); - }) - .catch(error => { - const { status, data } = error.response; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${data.message || data}` - }); - }); - } - }, - components: { - Spacer: () => import("./Spacer") - }, - ORIGINATOR: app.$gettext("originator"), - FROM: app.$gettext("from") -}; -</script> - -<style lang="scss" scoped></style>
--- a/client/src/components/ImportSoundingresults.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,357 +0,0 @@ -<template> - <div class="main d-flex flex-column"> - <div class="d-flex flex-row"> - <Spacer /> - <div class="card shadow-xs mt-2 mr-2 w-100 h-100"> - <UIBoxHeader icon="upload" :title="importSoundingresultsLabel" /> - <div v-if="editState"> - <div - v-for="(message, index) in messages" - :key="index" - class="alert alert-warning small rounded-0" - > - {{ message }} - </div> - <div class="container"> - <div class="row"> - <div class="col-5"> - <small class="text-muted"> - <translate>Bottleneck</translate> - </small> - <select v-model="bottleneck" class="custom-select"> - <option - v-for="bottleneck in availableBottlenecks" - :value="bottleneck" - :key="bottleneck.properties.objnam" - > - {{ bottleneck.properties.objnam }} - </option> - </select> - <span class="text-danger"> - <small v-if="!bottleneck"> - <translate>Please select a bottleneck</translate> - </small> - </span> - </div> - <div class="col-2"> - <small class="text-muted"> - <translate>Projection</translate> (EPSG) - </small> - <input - class="form-control" - v-model="projection" - value="4326" - placeholder="e.g. 4326" - type="number" - /> - <span class="text-left text-danger"> - <small v-if="!projection"> - <translate>Please enter a projection</translate> - </small> - </span> - </div> - <div class="col-2"> - <small class="text-muted"> - <translate>Depthreference</translate> - </small> - <select - v-model="depthReference" - class="custom-select" - id="depthreference" - > - <option - v-for="option in this.depthReferenceOptions" - :key="option" - >{{ option }}</option - > - </select> - <span class="text-left text-danger"> - <small v-if="!depthReference"> - <translate>Please enter a reference</translate> - </small> - </span> - </div> - <div class="col-3"> - <small class="text-muted"> <translate>Date</translate> </small> - <input - id="importdate" - type="date" - class="form-control" - placeholder="Date of import" - aria-label="bottleneck" - aria-describedby="bottlenecklabel" - v-model="importDate" - /> - <span class="text-left text-danger"> - <small v-if="!importDate"> - <translate>Please enter a date</translate> - </small> - </span> - </div> - </div> - <div class="row"></div> - </div> - </div> - <div class="container py-5"> - <div v-if="uploadState" class="input-group"> - <div class="custom-file"> - <input - accept=".zip" - type="file" - @change="fileSelected" - class="custom-file-input" - id="uploadFile" - /> - <label class="pointer custom-file-label" for="uploadFile"> - {{ uploadLabel }} - </label> - </div> - </div> - <div class="d-flex justify-content-between" v-if="editState"> - <a - download="meta.json" - :href="dataLink" - :class="[ - 'btn btn-outline-info', - { disabled: !bottleneck || !importDate || !depthReference } - ]" - > - <translate>Download Meta.json</translate> - </a> - <span> - <button - @click="deleteTempData" - class="btn btn-danger" - type="button" - > - <translate>Cancel Upload</translate> - </button> - <button - :disabled="disableUploadButton" - @click="confirm" - class="btn btn-info ml-2" - type="button" - > - <translate>Confirm</translate> - </button> - </span> - </div> - </div> - </div> - </div> - </div> -</template> - -<script> -/* This is Free Software under GNU Affero General Public License v >= 3.0 - * without warranty, see README.md and license for details. - * - * SPDX-License-Identifier: AGPL-3.0-or-later - * License-Filename: LICENSES/AGPL-3.0.txt - * - * Copyright (C) 2018 by via donau - * – Österreichische Wasserstraßen-Gesellschaft mbH - * Software engineering by Intevation GmbH - * - * Author(s): - * Thomas Junk <thomas.junk@intevation.de> - * Markus Kottländer <markus.kottlaender@intevation.de> - */ -import { HTTP } from "@/lib/http"; -import { displayError, displayInfo } from "@/lib/errors.js"; -import { mapState } from "vuex"; - -const IMPORTSTATE = { UPLOAD: "UPLOAD", EDIT: "EDIT" }; - -export default { - name: "imports", - components: { - Spacer: () => import("@/components/Spacer") - }, - data() { - return { - importState: IMPORTSTATE.UPLOAD, - depthReference: "", - bottleneck: "", - projection: "", - importDate: "", - uploadLabel: this.$gettext("choose .zip- file"), - uploadFile: null, - disableUpload: false, - token: null, - messages: [] - }; - }, - methods: { - initialState() { - this.importState = IMPORTSTATE.UPLOAD; - this.depthReference = ""; - this.bottleneck = null; - this.projection = ""; - this.importDate = ""; - this.uploadLabel = this.$gettext("choose .zip- file"); - this.uploadFile = null; - this.disableUpload = false; - this.token = null; - this.messages = []; - }, - fileSelected(e) { - const files = e.target.files || e.dataTransfer.files; - if (!files) return; - this.uploadLabel = files[0].name; - this.uploadFile = files[0]; - this.upload(); - }, - deleteTempData() { - HTTP.delete("/imports/sr-upload/" + this.token, { - headers: { - "X-Gemma-Auth": localStorage.getItem("token") - } - }) - .then(() => { - this.initialState(); - }) - .catch(error => { - const { status, data } = error.response; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${data.message || data}` - }); - }); - }, - upload() { - let formData = new FormData(); - formData.append("soundingresult", this.uploadFile); - HTTP.post("/imports/sr-upload", formData, { - headers: { - "X-Gemma-Auth": localStorage.getItem("token"), - "Content-Type": "multipart/form-data" - } - }) - .then(response => { - if (response.data.meta) { - const { bottleneck, date, epsg } = response.data.meta; - const depthReference = response.data.meta["depth-reference"]; - this.bottleneck = this.bottlenecks.find( - bn => bn.properties.objnam === bottleneck - ); - this.depthReference = depthReference; - this.importDate = new Date(date).toISOString().split("T")[0]; - this.projection = epsg; - } - this.importState = IMPORTSTATE.EDIT; - this.token = response.data.token; - this.messages = response.data.messages; - }) - .catch(error => { - const { status, data } = error.response; - const messages = data.messages ? data.messages.join(", ") : ""; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${messages}` - }); - }); - }, - confirm() { - let formData = new FormData(); - formData.append("token", this.token); - if (this.bottleneck) - formData.append("bottleneck", this.bottleneck.properties.objnam); - if (this.importDate) - formData.append("date", this.importDate.split("T")[0]); - if (this.depthReference) - formData.append("depth-reference", this.depthReference); - if (this.projection) formData.append("", this.projection); - - HTTP.post("/imports/sr", formData, { - headers: { - "X-Gemma-Auth": localStorage.getItem("token"), - "Content-Type": "multipart/form-data" - } - }) - .then(() => { - displayInfo({ - title: this.$gettext("Import"), - message: - this.$gettext("Starting import for ") + - this.bottleneck.properties.objnam - }); - this.initialState(); - }) - .catch(error => { - const { status, data } = error.response; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${data.message || data}` - }); - }); - } - }, - mounted() { - this.$store.dispatch("bottlenecks/loadBottlenecks"); - }, - watch: { - showContextBox() { - if (!this.showContextBox && this.token) this.deleteTempData(); - } - }, - computed: { - ...mapState("application", ["showContextBox"]), - ...mapState("bottlenecks", ["bottlenecks"]), - importSoundingresultsLabel() { - return this.$gettext("Import Soundingresults"); - }, - disableUploadButton() { - if (this.importState === IMPORTSTATE.UPLOAD) return this.disableUpload; - if ( - !this.bottleneck || - !this.importDate || - !this.depthReference || - !this.projection - ) - return true; - return this.disableUpload; - }, - availableBottlenecks() { - return this.bottlenecks; - }, - editState() { - return this.importState === IMPORTSTATE.EDIT; - }, - uploadState() { - return this.importState === IMPORTSTATE.UPLOAD; - }, - Upload() { - return this.$gettext("Upload"); - }, - Confirm() { - return this.$gettext("Confirm"); - }, - dataLink() { - if (this.bottleneck && this.depthReference && this.import) { - return ( - "data:text/json;charset=utf-8," + - encodeURIComponent( - JSON.stringify({ - depthReference: this.depthReference, - bottleneck: this.bottleneck.properties.objnam, - date: this.importDate - }) - ) - ); - } - }, - depthReferenceOptions() { - if ( - this.bottleneck && - this.bottleneck.properties.reference_water_levels - ) { - return Object.keys( - JSON.parse(this.bottleneck.properties.reference_water_levels) - ); - } - return []; - } - } -}; -</script>
--- a/client/src/components/ImportWaterwayProfiles.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -<template> - <div class="d-flex flex-row"> - <Spacer /> - <div class="card sysconfig mt-2 shadow-xs w-100 h-100 mr-2"> - <UIBoxHeader icon="upload" :title="importWaterwayProfilesLabel" /> - <div class="card-body stretches-card"> - <div class="w-95 ml-auto mr-auto mt-4 mb-4"> - <div class="mb-4"> - <div class="d-flex flex-row"> - <div class="flex-column w-100"> - <div class="flex-row text-left"> - <small class="text-muted"> <translate>URL</translate> </small> - </div> - <div class="w-100"> - <input class="form-control" type="url" v-model="url" /> - </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 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 - class="form-control" - type="text" - v-model="featureType" - /> - </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 class="form-control" type="text" v-model="sortBy" /> - </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 text-left"> - <div class="mt-3 mb-3 flex-column w-100"> - <div class="custom-file"> - <input - accept=".csv" - 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="buttons text-right"> - <button - :disabled="disableUploadButton" - @click="submit" - class="btn btn-info mt-4" - type="button" - > - <font-awesome-icon class="fa-fw mr-2" fixed-width icon="play" /> - <translate>Trigger import</translate> - </button> - </div> - </div> - </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 { displayError, displayInfo } from "@/lib/errors.js"; -import { HTTP } from "@/lib/http"; - -export default { - name: "importwaterwayprofiles", - components: { - Spacer: () => import("./Spacer") - }, - data() { - return { - url: "https://service.d4d-portal.info/wamos/wfs/", - sortBy: "hydro_scamin", - featureType: "ws-wamos:ienc_wtwprf", - disableUploadButton: false, - uploadLabel: this.$gettext("choose file to upload"), - uploadFile: null - }; - }, - computed: { - importWaterwayProfilesLabel() { - return this.$gettext("Import Waterway Profiles"); - } - }, - methods: { - fileSelected(e) { - const files = e.target.files || e.dataTransfer.files; - if (!files) return; - this.uploadLabel = files[0].name; - this.uploadFile = files[0]; - }, - submit() { - if (!this.url || !this.featureType || !this.sortBy || !this.uploadFile) - return; - let formData = new FormData(); - formData.append("wp", this.uploadFile); - formData.append("url", this.url); - formData.append("feature-type", this.featureType); - formData.append("sort-by", this.sortBy); - HTTP.post("/imports/wp", formData, { - headers: { - "X-Gemma-Auth": localStorage.getItem("token"), - "Content-Type": "multipart/form-data" - } - }) - .then(() => { - displayInfo({ - title: this.$gettext("Import"), - message: - this.uploadLabel + this.$gettext(" was successfully uploaded.") - }); - this.url = "https://service.d4d-portal.info/wamos/wfs/"; - this.uploadFile = null; - this.uploadLabel = this.$gettext("choose file to upload"); - }) - .catch(error => { - const { status, data } = error.response; - const messages = data.messages ? data.messages.join(", ") : ""; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${messages}` - }); - }); - } - } -}; -</script> - -<style lang="scss" scoped></style>
--- a/client/src/components/Sidebar.vue Mon Apr 08 18:54:13 2019 +0200 +++ b/client/src/components/Sidebar.vue Tue Apr 09 16:31:55 2019 +0200 @@ -43,23 +43,7 @@ </router-link> </div> <div v-if="isWaterwayAdmin"> - <small class="text-muted pl-3"> <translate>Import</translate> </small> - <hr class="m-0" /> - <router-link to="/importsoundingresults"> - <font-awesome-icon class="fa-fw mr-2" fixed-width icon="upload" /> - <span class="fix-trans-space" v-translate>Soundingresults</span> - </router-link> - <router-link to="/importapprovedgaugemeasurement"> - <font-awesome-icon class="fa-fw mr-2" fixed-width icon="upload" /> - <span class="fix-trans-space" v-translate - >Approved Gaugemeasurements</span - > - </router-link> - <router-link to="/importwaterwayprofiles"> - <font-awesome-icon class="fa-fw mr-2" fixed-width icon="upload" /> - <span class="fix-trans-space" v-translate>Waterway Profiles</span> - </router-link> - <router-link to="/importschedule"> + <router-link to="/imports/configuration"> <font-awesome-icon class="fa-fw mr-2" fixed-width icon="clock" /> <translate class="fix-trans-space">Imports</translate> </router-link>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/Import.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,261 @@ +<template> + <div> + <UIBoxHeader icon="clock" :title="title" /> + <div v-if="mode === $options.MODES.LIST" class="mb-3"> + <UISpinnerOverlay v-if="loading" /> + <UITableHeader + :columns="[ + { id: 'id', title: `${idLabel}`, class: 'col-1' }, + { id: 'kind', title: `${typeLabel}`, class: 'col-2' }, + { id: 'user', title: `${authorLabel}`, class: 'col-2' }, + { id: 'config.cron', title: `${scheduleLabel}`, class: 'col-2' }, + { id: 'config.send-email', title: `${emailLabel}`, class: 'col-2' } + ]" + /> + <UITableBody + :data="filteredSchedules | sortTable(sortColumn, sortDirection)" + :isActive="item => currentSchedule && item.id === currentSchedule.id" + > + <template v-slot:row="{ item: schedule }"> + <div class="table-cell col-1">{{ schedule.id }}</div> + <div class="table-cell col-2"> + {{ schedule.kind.toUpperCase() }} + </div> + <div class="table-cell col-2">{{ schedule.user }}</div> + <div class="table-cell col-2">{{ schedule.config.cron }}</div> + <div class="table-cell col-2"> + <font-awesome-icon + v-if="schedule.config['send-email']" + class="fa-fw mr-2" + fixed-width + icon="check" + /> + </div> + <div class="table-cell col justify-content-end"> + <button + @click="triggerManualImport(schedule.id)" + class="btn btn-xs btn-dark mr-1" + :disabled="importScheduleDetailVisible" + > + <font-awesome-icon icon="play" fixed-width /> + </button> + <button + @click="editSchedule(schedule.id)" + class="btn btn-xs btn-dark mr-1" + :disabled="importScheduleDetailVisible" + > + <font-awesome-icon icon="pencil-alt" fixed-width /> + </button> + <button + @click="deleteSchedule(schedule)" + class="btn btn-xs btn-dark" + :disabled="importScheduleDetailVisible" + > + <font-awesome-icon icon="trash" fixed-width /> + </button> + </div> + </template> + </UITableBody> + </div> + <ImportDetails v-if="mode === $options.MODES.EDIT"></ImportDetails> + <div class="d-flex flex-row w-100 mb-3"> + <button + :key="3" + v-if="mode === $options.MODES.LIST && !isOnetime" + @click="newConfiguration()" + class="ml-auto btn btn-info mr-3" + > + <translate>New import</translate> + </button> + </div> + </div> +</template> + +<style></style> + +<script> +/* This is Free Software under GNU Affero General Public License v >= 3.0 + * without warranty, see README.md and license for details. + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * License-Filename: LICENSES/AGPL-3.0.txt + * + * Copyright (C) 2018 by via donau + * – Österreichische Wasserstraßen-Gesellschaft mbH + * Software engineering by Intevation GmbH + * + * Author(s): + * Thomas Junk <thomas.junk@intevation.de> + * Markus Kottländer <markus.kottlaender@intevation.de> + */ +import { mapState } from "vuex"; +import { displayInfo, displayError } from "@/lib/errors"; +import { HTTP } from "@/lib/http"; +import { + IMPORTTYPES, + MODES + // IMPORTTYPEKIND, + // initializeCurrentSchedule +} from "@/store/importschedule"; + +export default { + components: { + ImportDetails: () => import("./ImportDetails.vue") + }, + data() { + return { + loading: false, + sortColumn: "", + sortDirection: "" + }; + }, + methods: { + back() { + this.$store.commit("importschedule/setListMode"); + }, + newConfiguration() { + this.$store.commit("importschedule/setEditMode"); + }, + getSchedules() { + this.loading = true; + this.$store + .dispatch("importschedule/loadSchedules") + .catch(error => { + const { status, data } = error.response; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${data.message || data}` + }); + }) + .finally(() => { + this.loading = false; + }); + }, + editSchedule(id) { + this.$store + .dispatch("importschedule/loadSchedule", id) + .then(() => { + this.$store.commit("importschedule/setEditMode"); + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${data.message || data}` + }); + }); + }, + triggerManualImport(id) { + HTTP.get("/imports/config/" + id + "/run", { + headers: { "X-Gemma-Auth": localStorage.getItem("token") } + }) + .then(response => { + const { id } = response.data; + displayInfo({ + title: this.$gettext("Imports"), + 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}` + }); + }); + }, + deleteSchedule(schedule) { + console.log(schedule); + this.$store.commit("application/popup", { + icon: "trash", + title: this.$gettext("Delete Import"), + content: + this.$gettext("Do you really want to delete the import with ID") + + `<b>${schedule.id}</b>` + + this.$gettext("of type") + + `<b>${schedule.kind.toUpperCase()}</b>?`, + confirm: { + label: this.$gettext("Delete"), + icon: "trash", + callback: () => { + this.$store + .dispatch("importschedule/deleteSchedule", schedule.id) + .then(() => { + this.getSchedules(); + displayInfo({ + title: this.$gettext("Imports"), + message: this.$gettext("Deleted import: #") + schedule.id + }); + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${data.message || data}` + }); + }); + } + }, + cancel: { + label: this.$gettext("Cancel"), + icon: "times" + } + }); + } + }, + computed: { + ...mapState("application", ["searchQuery"]), + ...mapState("importschedule", [ + "mode", + "schedules", + "currentSchedule", + "importScheduleDetailVisible" + ]), + isOnetime() { + for (let kind of [ + this.$options.IMPORTTYPES.SOUNDINGRESULTS, + this.$options.IMPORTTYPES.APPROVEDGAUGEMEASUREMENTS, + this.$options.IMPORTTYPES.WATERWAYPROFILES + ]) { + if (kind === this.currentSchedule.importType) return true; + } + return false; + }, + title() { + return this.$gettext("Imports"); + }, + filteredSchedules() { + return this.schedules.filter(s => { + return (s.id + s.kind) + .toLowerCase() + .includes(this.searchQuery.toLowerCase()); + }); + }, + importScheduleLabel() { + return this.$gettext("Import Schedule"); + }, + idLabel() { + return this.$gettext("ID"); + }, + typeLabel() { + return this.$gettext("Type"); + }, + authorLabel() { + return this.$gettext("Author"); + }, + scheduleLabel() { + return this.$gettext("Schedule"); + }, + emailLabel() { + return this.$gettext("Email"); + } + }, + mounted() { + this.$store.commit("importschedule/setListMode"); + this.$store.commit("importschedule/clearCurrentSchedule"); + this.getSchedules(); + }, + IMPORTTYPES: IMPORTTYPES, + MODES: MODES +}; +</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/ImportDetails.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,136 @@ +<template> + <div class="mt-3 mb-3 mr-3 ml-3 text-left"> + <small class="text-muted"> + <translate>Import type</translate> + </small> + <select v-model="Import" class="custom-select" id="importtype"> + <optgroup :label="regularLabel"> + <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>Waterway area</translate> + </option> + <option :value="$options.IMPORTTYPES.FAIRWAYDIMENSION"> + <translate>Fairway dimension</translate> + </option> + <option :value="$options.IMPORTTYPES.WATERWAYGAUGES"> + <translate>Waterway gauges</translate> + </option> + <option :value="$options.IMPORTTYPES.DISTANCEMARKSVIRTUAL"> + <translate>Distance marks virtual</translate> + </option> + <option :value="$options.IMPORTTYPES.DISTANCEMARKSASHORE"> + <translate>Distance marks ashore</translate> + </option> + </optgroup> + <optgroup :label="onetimeLabel"> + <option :value="$options.IMPORTTYPES.SOUNDINGRESULTS"> + <translate>Soundingresults</translate> + </option> + <option :value="$options.IMPORTTYPES.APPROVEDGAUGEMEASUREMENTS"> + <translate>Approved Gaugemeasurements</translate> + </option> + <option :value="$options.IMPORTTYPES.WATERWAYPROFILES"> + <translate>Waterway Profiles</translate> + </option> + </optgroup> + </select> + <ApprovedGaugeMeasurement + v-if="Import === $options.IMPORTTYPES.APPROVEDGAUGEMEASUREMENTS" + class="mt-3" + /> + <WaterwayProfiles + class="mt-3" + v-if="Import === $options.IMPORTTYPES.WATERWAYPROFILES" + /> + <SoundingResults + class="mt-3" + v-if="Import === $options.IMPORTTYPES.SOUNDINGRESULTS" + /> + <ScheduledImports + class="mt-3" + v-if="Import && !isOnetime" + ></ScheduledImports> + <div v-if="!Import" class="d-flex flex-row w-100 mt-3"> + <button :key="1" @click="back()" class="ml-auto btn btn-warning"> + Back + </button> + </div> + </div> +</template> + +<style lang="scss" scoped></style> + +<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 } from "@/store/importschedule"; +import { mapState } from "vuex"; +export default { + components: { + ApprovedGaugeMeasurement: () => + import("./types/ApprovedGaugeMeasurement.vue"), + WaterwayProfiles: () => import("./types/WaterwayProfiles"), + SoundingResults: () => import("./types/Soundingresults.vue"), + ScheduledImports: () => import("./types/ScheduledImports.vue") + }, + data() { + return {}; + }, + computed: { + ...mapState("importschedule", ["currentSchedule"]), + isOnetime() { + for (let kind of [ + this.$options.IMPORTTYPES.SOUNDINGRESULTS, + this.$options.IMPORTTYPES.APPROVEDGAUGEMEASUREMENTS, + this.$options.IMPORTTYPES.WATERWAYPROFILES + ]) { + if (kind === this.currentSchedule.importType) return true; + } + return false; + }, + Import: { + get() { + return this.currentSchedule.importType; + }, + set(value) { + this.$store.commit("importschedule/setImportType", value); + } + }, + onetimeLabel() { + return this.$gettext("Onetime Imports"); + }, + regularLabel() { + return this.$gettext("Regular Imports"); + } + }, + methods: { + back() { + this.$store.commit("importschedule/setListMode"); + } + }, + IMPORTTYPES: IMPORTTYPES +}; +</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/ApprovedGaugeMeasurement.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,132 @@ +<template> + <div> + <div class="d-flex flex-column text-left w-25"> + <label class="text-nowrap" for="originator"> + <small class="text-muted" + >{{ $options.ORIGINATOR }} / {{ $options.FROM }}</small + > + </label> + <input + type="text" + v-model="originator" + class="form-control" + id="originator" + /> + <span class="text-left text-danger"> + <small v-if="!originator"> + <translate>Please enter an originator</translate> + </small> + </span> + </div> + <div class="mt-4 flex-column w-100"> + <div class="custom-file"> + <input + accept=".csv" + type="file" + @change="fileSelected" + class="custom-file-input" + id="uploadFile" + /> + <label class="pointer custom-file-label" for="uploadFile"> + {{ uploadLabel }} + </label> + </div> + </div> + <div class="d-flex flex-row-reverse w-100 mt-3"> + <button :key="1" @click="back()" class="btn btn-warning"> + Back + </button> + <button + :key="2" + type="submit" + @click="submit" + class="shadow-sm btn btn-info submit-button mr-3" + > + <translate>Submit</translate> + </button> + </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 { HTTP } from "@/lib/http"; +import { displayError, displayInfo } from "@/lib/errors.js"; +import app from "@/main"; + +export default { + name: "importapprovedgaugemeasurements", + data() { + return { + disableUploadButton: false, + uploadLabel: this.$gettext("choose file to upload"), + uploadFile: null, + originator: "viadonau" + }; + }, + computed: { + importGaugmeasurmentLabel() { + return this.$gettext("Import approved gaugemeasurements"); + } + }, + methods: { + back() { + this.uploadLabel = this.$gettext("choose file to upload"); + this.uploadFile = null; + this.originator = "viadonau"; + 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]; + }, + submit() { + if (!this.originator || !this.uploadFile) return; + let formData = new FormData(); + formData.append("agm", this.uploadFile); + formData.append("originator", this.originator); + HTTP.post("/imports/agm", formData, { + headers: { + "X-Gemma-Auth": localStorage.getItem("token"), + "Content-Type": "multipart/form-data" + } + }) + .then(() => { + displayInfo({ + title: this.$gettext("Import"), + message: this.$gettext( + "Starting import of Approved Gauge Measurements" + ) + }); + this.back(); + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${data.message || data}` + }); + }); + } + }, + ORIGINATOR: app.$gettext("originator"), + FROM: app.$gettext("from") +}; +</script> + +<style lang="scss" scoped></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Availablefairwaydepth.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,51 @@ +<template> + <div> + <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 + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </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> +</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> + */ +export default { + name: "availablefairwaydepth", + props: ["url"], + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + } + } +}; +</script> + +<style></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Bottleneck.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,107 @@ +<template> + <div> + <div class="d-flex flex-row"> + <div class="flex-column mt-3 mr-3 w-100"> + <template v-if="!directImport"> + <div class="flex-row text-left"> + <small class="text-muted"> <translate>URL</translate> </small> + </div> + <div class="w-100"> + <input + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </div> + </template> + </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 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>Tolerance for snapping of waterway axis [m]</translate> + </small> + </div> + <div class="w-100"> + <input + @input="toleranceChanged" + class="tolerance form-control" + type="number" + min="0" + :value="tolerance" + /> + </div> + <div v-if="!tolerance" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a tolerance value</translate + ></small + > + </div> + </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, 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> + */ +export default { + name: "bottleneckimport", + props: ["url", "tolerance", "directImport"], + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + }, + toleranceChanged(e) { + this.$emit("toleranceChanged", e.target.value); + } + } +}; +</script> + +<style></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Distancemarksashore.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,99 @@ +<template> + <div> + <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 + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </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 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 + @input="featureTypeChanged" + class="featuretype form-control" + type="text" + :value="featureType" + /> + </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 + @input="sortByChanged" + class="sortby form-control" + type="text" + :value="sortBy" + /> + </div> + <div v-if="!sortBy" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter SortBy</translate + ></small + > + </div> + </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> + */ +export default { + name: "distancemarksashore", + props: ["url", "featureType", "sortBy"], + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + }, + featureTypeChanged(e) { + this.$emit("featureTypeChanged", e.target.value); + }, + sortByChanged(e) { + this.$emit("sortByChanged", e.target.value); + } + } +}; +</script> + +<style></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Distancemarksvirtual.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,116 @@ +<template> + <div> + <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 + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </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 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>Username</translate> </small> + </div> + <div class="w-100"> + <input + @input="usernameChanged" + class="username form-control" + type="text" + :value="username" + /> + </div> + <div v-if="!username" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a Username</translate + ></small + > + </div> + </div> + <div class="flex-column mt-3 w-50"> + <div class="flex-row text-left"> + <small class="text-muted"> <translate>Password</translate> </small> + </div> + <div class="w-100 d-flex flex-row"> + <input + @input="passwordChanged" + class="pasword form-control" + :type="showPassword" + :value="password" + /> + <span + class="input-group-text ml-2" + @click="passwordVisible = !passwordVisible" + > + <font-awesome-icon :icon="passwordVisible ? 'eye-slash' : 'eye'" /> + </span> + </div> + <div v-if="!password" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a Password</translate + ></small + > + </div> + </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> + */ +export default { + name: "distancemarksvirtual", + props: ["url", "username", "password"], + data() { + return { + passwordVisible: false + }; + }, + computed: { + showPassword() { + if (this.passwordVisible) return "text"; + return "password"; + } + }, + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + }, + usernameChanged(e) { + this.$emit("usernameChanged", e.target.value); + }, + passwordChanged(e) { + this.$emit("passwordChanged", e.target.value); + } + } +}; +</script> + +<style></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Fairwaydimensions.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,243 @@ +<template> + <div> + <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 + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </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 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 + @input="featureTypeChanged" + class="featuretype form-control" + type="text" + :value="featureType" + /> + </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 + @input="sortByChanged" + class="sortby form-control" + type="text" + :value="sortBy" + /> + </div> + <div v-if="!sortBy" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter SortBy</translate + ></small + > + </div> + </div> + </div> + <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>LOS</translate> </small> + </div> + <div class="w-100"> + <select v-model="los" class="form-control"> + <option>1</option> + <option>2</option> + <option>3</option> + </select> + </div> + <div v-if="!LOS" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a level of service</translate + ></small + > + </div> + </div> + <div class="flex-column mt-3 w-50"> + <div class="flex-row text-left"> + <small class="text-muted"> <translate>Depth</translate> </small> + </div> + <div class="d-flex flex-row"> + <input + @input="depthChanged" + class="depth form-control" + type="number" + :value="depth" + /> + <div class="ml-2 my-auto">cm</div> + </div> + <div v-if="!depth" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a depth</translate + ></small + > + </div> + </div> + </div> + <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>MinWidth</translate> </small> + </div> + <div class="d-flex flex-row"> + <input + @input="minWidthChanged" + class="minwidth form-control" + type="number" + :value="minWidth" + /> + <div class="ml-2 my-auto"> m</div> + </div> + <div v-if="!minWidth" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a minimum width</translate + ></small + > + </div> + </div> + <div class="flex-column mt-3 w-50"> + <div class="flex-row text-left"> + <small class="text-muted"> <translate>MaxWidth</translate> </small> + </div> + <div class="d-flex flex-row"> + <input + @input="maxWidthChanged" + class="maxwidth form-control" + type="number" + :value="maxWidth" + /> + <div class="ml-2 my-auto"> m</div> + </div> + <div v-if="!maxWidth" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a maximum width</translate + ></small + > + </div> + </div> + </div> + <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>Source orgranization</translate> + </small> + </div> + <div class="w-100"> + <input + @input="sourceOrganizationChanged" + class="sourceorganization form-control" + type="text" + :value="sourceOrganization" + /> + </div> + <div v-if="!sourceOrganization" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a source orgranization</translate + ></small + > + </div> + </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> + */ +export default { + name: "fairwaydimensions", + props: [ + "url", + "featureType", + "sortBy", + "depth", + "LOS", + "minWidth", + "maxWidth", + "sourceOrganization" + ], + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + }, + featureTypeChanged(e) { + this.$emit("featureTypeChanged", e.target.value); + }, + sortByChanged(e) { + this.$emit("sortByChanged", e.target.value); + }, + depthChanged(e) { + this.$emit("depthChanged", e.target.value * 1); + }, + LOSChanged(e) { + this.$emit("LOSChanged", e.target.value * 1); + }, + minWidthChanged(e) { + this.$emit("minWidthChanged", e.target.value * 1); + }, + maxWidthChanged(e) { + this.$emit("maxWidthChanged", e.target.value * 1); + }, + sourceOrganizationChanged(e) { + this.$emit("sourceOrganizationChanged", e.target.value); + } + }, + computed: { + los: { + get() { + return this.LOS; + }, + set(value) { + this.$emit("LOSChanged", value * 1); + } + } + } +}; +</script> + +<style></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Gaugemeasurement.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,51 @@ +<template> + <div> + <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 + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </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> +</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> + */ +export default { + name: "gaugemeasurement", + props: ["url"], + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + } + } +}; +</script> + +<style></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/ScheduledImports.vue Tue Apr 09 16:31:55 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.js"; +import app from "@/main.js"; +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>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Soundingresults.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,350 @@ +<template> + <div> + <div v-if="editState" class="mb-3"> + <div + v-for="(message, index) in messages" + :key="index" + class="alert alert-warning small rounded-0" + > + {{ message }} + </div> + <div class="d-flex flex-row w-100"> + <div class="w-50 mr-2 text-left"> + <small class="text-muted"> + <translate>Bottleneck</translate> + </small> + <select v-model="bottleneck" class="custom-select"> + <option + v-for="bottleneck in availableBottlenecks" + :value="bottleneck" + :key="bottleneck.properties.objnam" + > + {{ bottleneck.properties.objnam }} + </option> + </select> + <span class="text-danger"> + <small v-if="!bottleneck"> + <translate>Please select a bottleneck</translate> + </small> + </span> + </div> + <div class="w-50 ml-3 text-left"> + <small class="text-muted"> + <translate>Projection</translate> (EPSG) + </small> + <input + class="form-control" + v-model="projection" + value="4326" + placeholder="e.g. 4326" + type="number" + /> + <span class="text-left text-danger"> + <small v-if="!projection"> + <translate>Please enter a projection</translate> + </small> + </span> + </div> + </div> + <div class="d-flex flex-row w-100 mt-3"> + <div class="w-50 mr-2 text-left"> + <small class="text-muted"> + <translate>Depthreference</translate> + </small> + <select + v-model="depthReference" + class="custom-select" + id="depthreference" + > + <option + v-for="option in this.depthReferenceOptions" + :key="option" + >{{ option }}</option + > + </select> + <span class="text-left text-danger"> + <small v-if="!depthReference"> + <translate>Please enter a reference</translate> + </small> + </span> + </div> + <div class="w-50 ml-3 text-left"> + <small class="text-muted"> <translate>Date</translate> </small> + <input + id="importdate" + type="date" + class="form-control" + placeholder="Date of import" + aria-label="bottleneck" + aria-describedby="bottlenecklabel" + v-model="importDate" + /> + <span class="text-left text-danger"> + <small v-if="!importDate"> + <translate>Please enter a date</translate> + </small> + </span> + </div> + </div> + </div> + <div class="mt-3"> + <div v-if="uploadState" class="input-group"> + <div class="custom-file"> + <input + accept=".zip" + type="file" + @change="fileSelected" + class="custom-file-input" + id="uploadFile" + /> + <label class="pointer custom-file-label" for="uploadFile"> + {{ uploadLabel }} + </label> + </div> + </div> + <div class="d-flex justify-content-between mt-3" v-if="editState"> + <a + download="meta.json" + :href="dataLink" + :class="[ + 'btn btn-outline-info', + { disabled: !bottleneck || !importDate || !depthReference } + ]" + > + <translate>Download Meta.json</translate> + </a> + <span> + <button + :disabled="disableUploadButton" + @click="confirm" + class="btn btn-info mr-2" + type="button" + > + <translate>Confirm</translate> + </button> + <button :key="1" @click="deleteTempData()" class="btn btn-warning"> + Back + </button> + </span> + </div> + <div v-if="uploadState" class="d-flex flex-row-100 mt-3"> + <button :key="2" @click="back()" class="ml-auto btn btn-warning"> + Back + </button> + </div> + </div> + </div> +</template> + +<script> +/* This is Free Software under GNU Affero General Public License v >= 3.0 + * without warranty, see README.md and license for details. + * + * SPDX-License-Identifier: AGPL-3.0-or-later + * License-Filename: LICENSES/AGPL-3.0.txt + * + * Copyright (C) 2018 by via donau + * – Österreichische Wasserstraßen-Gesellschaft mbH + * Software engineering by Intevation GmbH + * + * Author(s): + * Thomas Junk <thomas.junk@intevation.de> + * Markus Kottländer <markus.kottlaender@intevation.de> + */ +import { HTTP } from "@/lib/http"; +import { displayError, displayInfo } from "@/lib/errors.js"; +import { mapState } from "vuex"; + +const IMPORTSTATE = { UPLOAD: "UPLOAD", EDIT: "EDIT" }; + +export default { + data() { + return { + importState: IMPORTSTATE.UPLOAD, + depthReference: "", + bottleneck: "", + projection: "", + importDate: "", + uploadLabel: this.$gettext("choose .zip- file"), + uploadFile: null, + disableUpload: false, + token: null, + messages: [] + }; + }, + methods: { + back() { + this.$store.commit("importschedule/setListMode"); + }, + initialState() { + this.importState = IMPORTSTATE.UPLOAD; + this.depthReference = ""; + this.bottleneck = null; + this.projection = ""; + this.importDate = ""; + this.uploadLabel = this.$gettext("choose .zip- file"); + this.uploadFile = null; + this.disableUpload = false; + this.token = null; + this.messages = []; + }, + fileSelected(e) { + const files = e.target.files || e.dataTransfer.files; + if (!files) return; + this.uploadLabel = files[0].name; + this.uploadFile = files[0]; + this.upload(); + }, + deleteTempData() { + HTTP.delete("/imports/sr-upload/" + this.token, { + headers: { + "X-Gemma-Auth": localStorage.getItem("token") + } + }) + .then(() => { + this.initialState(); + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${data.message || data}` + }); + }); + }, + upload() { + let formData = new FormData(); + formData.append("soundingresult", this.uploadFile); + HTTP.post("/imports/sr-upload", formData, { + headers: { + "X-Gemma-Auth": localStorage.getItem("token"), + "Content-Type": "multipart/form-data" + } + }) + .then(response => { + if (response.data.meta) { + const { bottleneck, date, epsg } = response.data.meta; + const depthReference = response.data.meta["depth-reference"]; + this.bottleneck = this.bottlenecks.find( + bn => bn.properties.objnam === bottleneck + ); + this.depthReference = depthReference; + this.importDate = new Date(date).toISOString().split("T")[0]; + this.projection = epsg; + } + this.importState = IMPORTSTATE.EDIT; + this.token = response.data.token; + this.messages = response.data.messages; + }) + .catch(error => { + const { status, data } = error.response; + const messages = data.messages ? data.messages.join(", ") : ""; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${messages}` + }); + }); + }, + confirm() { + let formData = new FormData(); + formData.append("token", this.token); + if (this.bottleneck) + formData.append("bottleneck", this.bottleneck.properties.objnam); + if (this.importDate) + formData.append("date", this.importDate.split("T")[0]); + if (this.depthReference) + formData.append("depth-reference", this.depthReference); + if (this.projection) formData.append("", this.projection); + + HTTP.post("/imports/sr", formData, { + headers: { + "X-Gemma-Auth": localStorage.getItem("token"), + "Content-Type": "multipart/form-data" + } + }) + .then(() => { + displayInfo({ + title: this.$gettext("Import"), + message: + this.$gettext("Starting import for ") + + this.bottleneck.properties.objnam + }); + this.initialState(); + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${data.message || data}` + }); + }); + } + }, + mounted() { + this.$store.dispatch("bottlenecks/loadBottlenecks"); + }, + watch: { + showContextBox() { + if (!this.showContextBox && this.token) this.deleteTempData(); + } + }, + computed: { + ...mapState("application", ["showContextBox"]), + ...mapState("bottlenecks", ["bottlenecks"]), + importSoundingresultsLabel() { + return this.$gettext("Import Soundingresults"); + }, + disableUploadButton() { + if (this.importState === IMPORTSTATE.UPLOAD) return this.disableUpload; + if ( + !this.bottleneck || + !this.importDate || + !this.depthReference || + !this.projection + ) + return true; + return this.disableUpload; + }, + availableBottlenecks() { + return this.bottlenecks; + }, + editState() { + return this.importState === IMPORTSTATE.EDIT; + }, + uploadState() { + return this.importState === IMPORTSTATE.UPLOAD; + }, + Upload() { + return this.$gettext("Upload"); + }, + Confirm() { + return this.$gettext("Confirm"); + }, + dataLink() { + if (this.bottleneck && this.depthReference && this.import) { + return ( + "data:text/json;charset=utf-8," + + encodeURIComponent( + JSON.stringify({ + depthReference: this.depthReference, + bottleneck: this.bottleneck.properties.objnam, + date: this.importDate + }) + ) + ); + } + }, + depthReferenceOptions() { + if ( + this.bottleneck && + this.bottleneck.properties.reference_water_levels + ) { + return Object.keys( + JSON.parse(this.bottleneck.properties.reference_water_levels) + ); + } + return []; + } + } +}; +</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/WaterwayProfiles.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,170 @@ +<template> + <div> + <div class="mb-4"> + <div class="d-flex flex-row"> + <div class="flex-column w-100"> + <div class="flex-row text-left"> + <small class="text-muted"> <translate>URL</translate> </small> + </div> + <div class="w-100"> + <input class="form-control" type="url" v-model="url" /> + </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 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 class="form-control" type="text" v-model="featureType" /> + </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 class="form-control" type="text" v-model="sortBy" /> + </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 text-left"> + <div class="mt-3 mb-3 flex-column w-100"> + <div class="custom-file"> + <input + accept=".csv" + 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="d-flex flex-row-reverse w-100 mt-3"> + <button :key="1" @click="back()" class="btn btn-warning"> + Back + </button> + <button + :key="2" + type="submit" + @click="submit" + class="shadow-sm btn btn-info submit-button mr-3" + > + <translate>Submit</translate> + </button> + </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 { displayError, displayInfo } from "@/lib/errors.js"; +import { HTTP } from "@/lib/http"; + +export default { + data() { + return { + url: "https://service.d4d-portal.info/wamos/wfs/", + sortBy: "hydro_scamin", + featureType: "ws-wamos:ienc_wtwprf", + disableUploadButton: false, + uploadLabel: this.$gettext("choose file to upload"), + uploadFile: null + }; + }, + computed: { + importWaterwayProfilesLabel() { + return this.$gettext("Import Waterway Profiles"); + } + }, + methods: { + back() { + this.url = "https://service.d4d-portal.info/wamos/wfs/"; + this.uploadFile = null; + this.uploadLabel = this.$gettext("choose file to upload"); + 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]; + }, + submit() { + if (!this.url || !this.featureType || !this.sortBy || !this.uploadFile) + return; + let formData = new FormData(); + formData.append("wp", this.uploadFile); + formData.append("url", this.url); + formData.append("feature-type", this.featureType); + formData.append("sort-by", this.sortBy); + HTTP.post("/imports/wp", formData, { + headers: { + "X-Gemma-Auth": localStorage.getItem("token"), + "Content-Type": "multipart/form-data" + } + }) + .then(() => { + displayInfo({ + title: this.$gettext("Import"), + message: + this.uploadLabel + this.$gettext(" was successfully uploaded.") + }); + this.back(); + }) + .catch(error => { + const { status, data } = error.response; + const messages = data.messages ? data.messages.join(", ") : ""; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${messages}` + }); + }); + } + } +}; +</script> + +<style lang="scss" scoped></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Waterwayarea.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,99 @@ +<template> + <div> + <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 + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </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 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 + @input="featureTypeChanged" + class="featuretype form-control" + type="text" + :value="featureType" + /> + </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 + @input="sortByChanged" + class="sortby form-control" + type="text" + :value="sortBy" + /> + </div> + <div v-if="!sortBy" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter SortBy</translate + ></small + > + </div> + </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> + */ +export default { + name: "waterwayarea", + props: ["url", "featureType", "sortBy"], + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + }, + featureTypeChanged(e) { + this.$emit("featureTypeChanged", e.target.value); + }, + sortByChanged(e) { + this.$emit("sortByChanged", e.target.value); + } + } +}; +</script> + +<style></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Waterwayaxis.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,99 @@ +<template> + <div> + <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 + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </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 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 + @input="featureTypeChanged" + class="featuretype form-control" + type="text" + :value="featureType" + /> + </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 + @input="sortByChanged" + class="sortby form-control" + type="text" + :value="sortBy" + /> + </div> + <div v-if="!sortBy" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter SortBy</translate + ></small + > + </div> + </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> + */ +export default { + name: "waterwayaxis", + props: ["url", "featureType", "sortBy"], + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + }, + featureTypeChanged(e) { + this.$emit("featureTypeChanged", e.target.value); + }, + sortByChanged(e) { + this.$emit("sortByChanged", e.target.value); + } + } +}; +</script> + +<style></style>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/importconfiguration/types/Waterwaygauges.vue Tue Apr 09 16:31:55 2019 +0200 @@ -0,0 +1,116 @@ +<template> + <div> + <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 + @input="urlChanged" + class="url form-control" + type="url" + :value="url" + /> + </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 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>Username</translate> </small> + </div> + <div class="w-100"> + <input + @input="usernameChanged" + class="username form-control" + type="text" + :value="username" + /> + </div> + <div v-if="!username" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a Username</translate + ></small + > + </div> + </div> + <div class="flex-column mt-3 w-50"> + <div class="flex-row text-left"> + <small class="text-muted"> <translate>Password</translate> </small> + </div> + <div class="w-100 d-flex flex-row"> + <input + @input="passwordChanged" + class="password form-control" + :type="showPassword" + :value="password" + /> + <span + class="input-group-text ml-2" + @click="passwordVisible = !passwordVisible" + > + <font-awesome-icon :icon="passwordVisible ? 'eye-slash' : 'eye'" /> + </span> + </div> + <div v-if="!password" class="d-flex flex-row"> + <small + ><translate class="text-danger" + >Please enter a Password</translate + ></small + > + </div> + </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> + */ +export default { + name: "waterwaygauges", + props: ["username", "password", "url"], + data() { + return { + passwordVisible: false + }; + }, + computed: { + showPassword() { + if (this.passwordVisible) return "text"; + return "password"; + } + }, + methods: { + urlChanged(e) { + this.$emit("urlChanged", e.target.value); + }, + usernameChanged(e) { + this.$emit("usernameChanged", e.target.value); + }, + passwordChanged(e) { + this.$emit("passwordChanged", e.target.value); + } + } +}; +</script> + +<style></style>
--- a/client/src/components/importschedule/Importschedule.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,273 +0,0 @@ -<template> - <div class="d-flex flex-row"> - <Spacer /> - <div class="mt-2 w-100"> - <div class="card flex-grow-1 schedulecard shadow-xs"> - <UIBoxHeader icon="clock" :title="importScheduleLabel" /> - <div class="searchandfilter p-3 w-50 mx-auto"> - <div class="searchgroup input-group"> - <div class="input-group-prepend"> - <span class="input-group-text" id="search"> - <font-awesome-icon icon="search" /> - </span> - </div> - <input - v-model="searchQuery" - type="text" - class="form-control" - placeholder - aria-label="Search" - aria-describedby="search" - /> - </div> - </div> - <UITableHeader - :columns="[ - { id: 'id', title: `${idLabel}`, class: 'col-1' }, - { id: 'kind', title: `${typeLabel}`, class: 'col-2' }, - { id: 'user', title: `${authorLabel}`, class: 'col-2' }, - { id: 'config.cron', title: `${scheduleLabel}`, class: 'col-2' }, - { id: 'config.send-email', title: `${emailLabel}`, class: 'col-2' } - ]" - /> - <UITableBody - :data="filteredSchedules() | sortTable(sortColumn, sortDirection)" - :isActive="item => currentSchedule && item.id === currentSchedule.id" - > - <template v-slot:row="{ item: schedule }"> - <div class="table-cell col-1">{{ schedule.id }}</div> - <div class="table-cell col-2"> - {{ schedule.kind.toUpperCase() }} - </div> - <div class="table-cell col-2">{{ schedule.user }}</div> - <div class="table-cell col-2">{{ schedule.config.cron }}</div> - <div class="table-cell col-2 text-center"> - <font-awesome-icon - v-if="schedule.config['send-email']" - class="fa-fw mr-2" - fixed-width - icon="check" - /> - </div> - <div class="table-cell col justify-content-end"> - <button - @click="editSchedule(schedule.id)" - class="btn btn-xs btn-dark mr-1" - :disabled="importScheduleDetailVisible" - > - <font-awesome-icon icon="pencil-alt" fixed-width /> - </button> - <button - @click="deleteSchedule(schedule)" - class="btn btn-xs btn-dark mr-1" - :disabled="importScheduleDetailVisible" - > - <font-awesome-icon icon="trash" fixed-width /> - </button> - <button - @click="triggerManualImport(schedule.id)" - class="btn btn-xs btn-dark" - :disabled="importScheduleDetailVisible" - > - <font-awesome-icon icon="play" fixed-width /> - </button> - </div> - </template> - </UITableBody> - <div class="p-3 text-right"> - <button - :disabled="importScheduleDetailVisible" - @click="newImport" - class="btn btn-info newbutton" - > - <translate>New Import</translate> - </button> - </div> - </div> - </div> - <Importscheduledetail /> - </div> -</template> - -<style lang="sass" scoped> -th - border-top: 0px - -.card-body - padding-bottom: $small-offset - -.schedulecard - margin-right: $small-offset - min-height: 20rem - -.schedulecard-body - width: 100% - margin-left: auto - margin-right: auto -</style> - -<script> -/* This is Free Software under GNU Affero General Public License v >= 3.0 - * without warranty, see README.md and license for details. - * - * SPDX-License-Identifier: AGPL-3.0-or-later - * License-Filename: LICENSES/AGPL-3.0.txt - * - * Copyright (C) 2018 by via donau - * – Österreichische Wasserstraßen-Gesellschaft mbH - * Software engineering by Intevation GmbH - * - * Author(s): - * Thomas Junk <thomas.junk@intevation.de> - * Markus Kottländer <markus.kottlaender@intevation.de> - */ - -import { mapState } from "vuex"; -import { HTTP } from "@/lib/http"; -import { displayInfo, displayError } from "@/lib/errors"; -import { sortTable } from "@/lib/mixins"; - -export default { - name: "importschedule", - mixins: [sortTable], - components: { - Importscheduledetail: () => import("./Importscheduledetail"), - Spacer: () => import("@/components/Spacer") - }, - data() { - return { - searchQuery: "" - }; - }, - computed: { - ...mapState("application", ["showSidebar"]), - ...mapState("importschedule", [ - "schedules", - "currentSchedule", - "importScheduleDetailVisible" - ]), - importScheduleLabel() { - return this.$gettext("Import Schedule"); - }, - idLabel() { - return this.$gettext("ID"); - }, - typeLabel() { - return this.$gettext("Type"); - }, - authorLabel() { - return this.$gettext("Author"); - }, - scheduleLabel() { - return this.$gettext("Schedule"); - }, - emailLabel() { - return this.$gettext("Email"); - }, - spacerStyle() { - return [ - "spacer ml-3", - { - "spacer-expanded": this.showSidebar, - "spacer-collapsed": !this.showSidebar - } - ]; - } - }, - methods: { - filteredSchedules() { - return this.schedules.filter(s => { - return (s.id + s.kind) - .toLowerCase() - .includes(this.searchQuery.toLowerCase()); - }); - }, - editSchedule(id) { - this.$store - .dispatch("importschedule/loadSchedule", id) - .then(() => { - this.$store.commit("importschedule/setImportScheduleDetailVisible"); - }) - .catch(error => { - const { status, data } = error.response; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${data.message || data}` - }); - }); - }, - triggerManualImport(id) { - HTTP.get("/imports/config/" + id + "/run", { - headers: { "X-Gemma-Auth": localStorage.getItem("token") } - }) - .then(response => { - const { id } = response.data; - displayInfo({ - title: this.$gettext("Imports"), - 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}` - }); - }); - }, - getSchedules() { - this.$store.dispatch("importschedule/loadSchedules").catch(error => { - const { status, data } = error.response; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${data.message || data}` - }); - }); - }, - newImport() { - this.$store.commit("importschedule/setImportScheduleDetailVisible"); - }, - deleteSchedule(schedule) { - console.log(schedule); - this.$store.commit("application/popup", { - icon: "trash", - title: this.$gettext("Delete Import"), - content: - this.$gettext("Do you really want to delete the import with ID") + - `<b>${schedule.id}</b>` + - this.$gettext("of type") + - `<b>${schedule.kind.toUpperCase()}</b>?`, - confirm: { - label: this.$gettext("Delete"), - icon: "trash", - callback: () => { - this.$store - .dispatch("importschedule/deleteSchedule", schedule.id) - .then(() => { - this.getSchedules(); - displayInfo({ - title: this.$gettext("Imports"), - message: this.$gettext("Deleted import: #") + schedule.id - }); - }) - .catch(error => { - const { status, data } = error.response; - displayError({ - title: this.$gettext("Backend Error"), - message: `${status}: ${data.message || data}` - }); - }); - } - }, - cancel: { - label: this.$gettext("Cancel"), - icon: "times" - } - }); - } - }, - mounted() { - this.getSchedules(); - } -}; -</script>
--- a/client/src/components/importschedule/Importscheduledetail.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1027 +0,0 @@ -<template> - <div - class="importscheduledetails fadeIn animated" - v-if="importScheduleDetailVisible" - > - <div class="card shadow-xs importscheduledetailscard pb-5"> - <UIBoxHeader :title="dialogLabel" :closeCallback="closeDetailview" /> - <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>Waterway area</translate> - </option> - <option :value="$options.IMPORTTYPES.FAIRWAYDIMENSION"> - <translate>Fairway dimension</translate> - </option> - <option :value="$options.IMPORTTYPES.WATERWAYGAUGES"> - <translate>Waterway gauges</translate> - </option> - <option :value="$options.IMPORTTYPES.DISTANCEMARKSVIRTUAL"> - <translate>Distance marks virtual</translate> - </option> - <option :value="$options.IMPORTTYPES.DISTANCEMARKSASHORE"> - <translate>Distance marks ashore</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="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"> - <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 :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> - <button - :disabled="!isValid" - type="submit" - class="shadow-sm btn btn-info submit-button" - > - <translate>Save</translate> - </button> - </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> - <button - @click="triggerManualImport" - type="button" - class="shadow-sm btn btn-outline-info trigger" - :disabled="!triggerActive || !isValid" - > - <font-awesome-icon class="fa-fw mr-2" fixed-width icon="play" /> - <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, 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.js"; -import app from "@/main.js"; -import { HTTP } from "@/lib/http"; - -export default { - name: "importscheduledetail", - components: { - Availablefairwaydepth: () => - import("@/components/importschedule/importtypes/Availablefairwaydepth"), - Bottleneck: () => - import("@/components/importschedule/importtypes/Bottleneck"), - Distancemarksvirtual: () => - import("@/components/importschedule/importtypes/Distancemarksvirtual"), - Distancemarksashore: () => - import("@/components/importschedule/importtypes/Distancemarksashore"), - 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 { - 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" - ]), - 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: { - 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.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.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/setImportScheduleDetailInvisible"); - } - }, - 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; -} - -.trigger { - position: absolute; - left: $large-offset; - bottom: $offset; -} - -.submit-button { - position: absolute; - right: $large-offset; - bottom: $offset; -} -</style>
--- a/client/src/components/importschedule/importtypes/Availablefairwaydepth.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -<template> - <div> - <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 - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </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> -</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> - */ -export default { - name: "availablefairwaydepth", - props: ["url"], - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - } - } -}; -</script> - -<style></style>
--- a/client/src/components/importschedule/importtypes/Bottleneck.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -<template> - <div> - <div class="d-flex flex-row"> - <div class="flex-column mt-3 mr-3 w-100"> - <template v-if="!directImport"> - <div class="flex-row text-left"> - <small class="text-muted"> <translate>URL</translate> </small> - </div> - <div class="w-100"> - <input - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </div> - </template> - </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 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>Tolerance for snapping of waterway axis [m]</translate> - </small> - </div> - <div class="w-100"> - <input - @input="toleranceChanged" - class="tolerance form-control" - type="number" - min="0" - :value="tolerance" - /> - </div> - <div v-if="!tolerance" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a tolerance value</translate - ></small - > - </div> - </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, 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> - */ -export default { - name: "bottleneckimport", - props: ["url", "tolerance", "directImport"], - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - }, - toleranceChanged(e) { - this.$emit("toleranceChanged", e.target.value); - } - } -}; -</script> - -<style></style>
--- a/client/src/components/importschedule/importtypes/Distancemarksashore.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -<template> - <div> - <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 - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </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 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 - @input="featureTypeChanged" - class="featuretype form-control" - type="text" - :value="featureType" - /> - </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 - @input="sortByChanged" - class="sortby form-control" - type="text" - :value="sortBy" - /> - </div> - <div v-if="!sortBy" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter SortBy</translate - ></small - > - </div> - </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> - */ -export default { - name: "distancemarksashore", - props: ["url", "featureType", "sortBy"], - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - }, - featureTypeChanged(e) { - this.$emit("featureTypeChanged", e.target.value); - }, - sortByChanged(e) { - this.$emit("sortByChanged", e.target.value); - } - } -}; -</script> - -<style></style>
--- a/client/src/components/importschedule/importtypes/Distancemarksvirtual.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -<template> - <div> - <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 - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </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 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>Username</translate> </small> - </div> - <div class="w-100"> - <input - @input="usernameChanged" - class="username form-control" - type="text" - :value="username" - /> - </div> - <div v-if="!username" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a Username</translate - ></small - > - </div> - </div> - <div class="flex-column mt-3 w-50"> - <div class="flex-row text-left"> - <small class="text-muted"> <translate>Password</translate> </small> - </div> - <div class="w-100 d-flex flex-row"> - <input - @input="passwordChanged" - class="pasword form-control" - :type="showPassword" - :value="password" - /> - <span - class="input-group-text ml-2" - @click="passwordVisible = !passwordVisible" - > - <font-awesome-icon :icon="passwordVisible ? 'eye-slash' : 'eye'" /> - </span> - </div> - <div v-if="!password" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a Password</translate - ></small - > - </div> - </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> - */ -export default { - name: "distancemarksvirtual", - props: ["url", "username", "password"], - data() { - return { - passwordVisible: false - }; - }, - computed: { - showPassword() { - if (this.passwordVisible) return "text"; - return "password"; - } - }, - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - }, - usernameChanged(e) { - this.$emit("usernameChanged", e.target.value); - }, - passwordChanged(e) { - this.$emit("passwordChanged", e.target.value); - } - } -}; -</script> - -<style></style>
--- a/client/src/components/importschedule/importtypes/Fairwaydimensions.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,243 +0,0 @@ -<template> - <div> - <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 - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </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 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 - @input="featureTypeChanged" - class="featuretype form-control" - type="text" - :value="featureType" - /> - </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 - @input="sortByChanged" - class="sortby form-control" - type="text" - :value="sortBy" - /> - </div> - <div v-if="!sortBy" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter SortBy</translate - ></small - > - </div> - </div> - </div> - <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>LOS</translate> </small> - </div> - <div class="w-100"> - <select v-model="los" class="form-control"> - <option>1</option> - <option>2</option> - <option>3</option> - </select> - </div> - <div v-if="!LOS" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a level of service</translate - ></small - > - </div> - </div> - <div class="flex-column mt-3 w-50"> - <div class="flex-row text-left"> - <small class="text-muted"> <translate>Depth</translate> </small> - </div> - <div class="d-flex flex-row"> - <input - @input="depthChanged" - class="depth form-control" - type="number" - :value="depth" - /> - <div class="ml-2 my-auto">cm</div> - </div> - <div v-if="!depth" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a depth</translate - ></small - > - </div> - </div> - </div> - <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>MinWidth</translate> </small> - </div> - <div class="d-flex flex-row"> - <input - @input="minWidthChanged" - class="minwidth form-control" - type="number" - :value="minWidth" - /> - <div class="ml-2 my-auto"> m</div> - </div> - <div v-if="!minWidth" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a minimum width</translate - ></small - > - </div> - </div> - <div class="flex-column mt-3 w-50"> - <div class="flex-row text-left"> - <small class="text-muted"> <translate>MaxWidth</translate> </small> - </div> - <div class="d-flex flex-row"> - <input - @input="maxWidthChanged" - class="maxwidth form-control" - type="number" - :value="maxWidth" - /> - <div class="ml-2 my-auto"> m</div> - </div> - <div v-if="!maxWidth" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a maximum width</translate - ></small - > - </div> - </div> - </div> - <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>Source orgranization</translate> - </small> - </div> - <div class="w-100"> - <input - @input="sourceOrganizationChanged" - class="sourceorganization form-control" - type="text" - :value="sourceOrganization" - /> - </div> - <div v-if="!sourceOrganization" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a source orgranization</translate - ></small - > - </div> - </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> - */ -export default { - name: "fairwaydimensions", - props: [ - "url", - "featureType", - "sortBy", - "depth", - "LOS", - "minWidth", - "maxWidth", - "sourceOrganization" - ], - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - }, - featureTypeChanged(e) { - this.$emit("featureTypeChanged", e.target.value); - }, - sortByChanged(e) { - this.$emit("sortByChanged", e.target.value); - }, - depthChanged(e) { - this.$emit("depthChanged", e.target.value * 1); - }, - LOSChanged(e) { - this.$emit("LOSChanged", e.target.value * 1); - }, - minWidthChanged(e) { - this.$emit("minWidthChanged", e.target.value * 1); - }, - maxWidthChanged(e) { - this.$emit("maxWidthChanged", e.target.value * 1); - }, - sourceOrganizationChanged(e) { - this.$emit("sourceOrganizationChanged", e.target.value); - } - }, - computed: { - los: { - get() { - return this.LOS; - }, - set(value) { - this.$emit("LOSChanged", value * 1); - } - } - } -}; -</script> - -<style></style>
--- a/client/src/components/importschedule/importtypes/Gaugemeasurement.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -<template> - <div> - <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 - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </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> -</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> - */ -export default { - name: "gaugemeasurement", - props: ["url"], - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - } - } -}; -</script> - -<style></style>
--- a/client/src/components/importschedule/importtypes/Waterwayarea.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -<template> - <div> - <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 - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </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 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 - @input="featureTypeChanged" - class="featuretype form-control" - type="text" - :value="featureType" - /> - </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 - @input="sortByChanged" - class="sortby form-control" - type="text" - :value="sortBy" - /> - </div> - <div v-if="!sortBy" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter SortBy</translate - ></small - > - </div> - </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> - */ -export default { - name: "waterwayarea", - props: ["url", "featureType", "sortBy"], - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - }, - featureTypeChanged(e) { - this.$emit("featureTypeChanged", e.target.value); - }, - sortByChanged(e) { - this.$emit("sortByChanged", e.target.value); - } - } -}; -</script> - -<style></style>
--- a/client/src/components/importschedule/importtypes/Waterwayaxis.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -<template> - <div> - <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 - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </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 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 - @input="featureTypeChanged" - class="featuretype form-control" - type="text" - :value="featureType" - /> - </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 - @input="sortByChanged" - class="sortby form-control" - type="text" - :value="sortBy" - /> - </div> - <div v-if="!sortBy" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter SortBy</translate - ></small - > - </div> - </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> - */ -export default { - name: "waterwayaxis", - props: ["url", "featureType", "sortBy"], - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - }, - featureTypeChanged(e) { - this.$emit("featureTypeChanged", e.target.value); - }, - sortByChanged(e) { - this.$emit("sortByChanged", e.target.value); - } - } -}; -</script> - -<style></style>
--- a/client/src/components/importschedule/importtypes/Waterwaygauges.vue Mon Apr 08 18:54:13 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -<template> - <div> - <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 - @input="urlChanged" - class="url form-control" - type="url" - :value="url" - /> - </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 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>Username</translate> </small> - </div> - <div class="w-100"> - <input - @input="usernameChanged" - class="username form-control" - type="text" - :value="username" - /> - </div> - <div v-if="!username" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a Username</translate - ></small - > - </div> - </div> - <div class="flex-column mt-3 w-50"> - <div class="flex-row text-left"> - <small class="text-muted"> <translate>Password</translate> </small> - </div> - <div class="w-100 d-flex flex-row"> - <input - @input="passwordChanged" - class="password form-control" - :type="showPassword" - :value="password" - /> - <span - class="input-group-text ml-2" - @click="passwordVisible = !passwordVisible" - > - <font-awesome-icon :icon="passwordVisible ? 'eye-slash' : 'eye'" /> - </span> - </div> - <div v-if="!password" class="d-flex flex-row"> - <small - ><translate class="text-danger" - >Please enter a Password</translate - ></small - > - </div> - </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> - */ -export default { - name: "waterwaygauges", - props: ["username", "password", "url"], - data() { - return { - passwordVisible: false - }; - }, - computed: { - showPassword() { - if (this.passwordVisible) return "text"; - return "password"; - } - }, - methods: { - urlChanged(e) { - this.$emit("urlChanged", e.target.value); - }, - usernameChanged(e) { - this.$emit("usernameChanged", e.target.value); - }, - passwordChanged(e) { - this.$emit("passwordChanged", e.target.value); - } - } -}; -</script> - -<style></style>
--- a/client/src/router.js Mon Apr 08 18:54:13 2019 +0200 +++ b/client/src/router.js Tue Apr 09 16:31:55 2019 +0200 @@ -81,70 +81,6 @@ } }, { - path: "/importsoundingresults", - name: "importsoundingresults", - component: () => import("./components/ImportSoundingresults.vue"), - meta: { - requiresAuth: true - }, - beforeEnter: (to, from, next) => { - const isWaterwayAdmin = store.getters["user/isWaterwayAdmin"]; - if (!isWaterwayAdmin) { - next("/login"); - } else { - next(); - } - } - }, - { - path: "/importwaterwayprofiles", - name: "waterwayprofiles", - component: () => import("./components/ImportWaterwayProfiles"), - meta: { - requiresAuth: true - }, - beforeEnter: (to, from, next) => { - const isWaterwayAdmin = store.getters["user/isWaterwayAdmin"]; - if (!isWaterwayAdmin) { - next("/login"); - } else { - next(); - } - } - }, - { - path: "/importapprovedgaugemeasurement", - name: "approvedgaugemeasurement", - component: () => import("./components/ImportApprovedGaugeMeasurement"), - meta: { - requiresAuth: true - }, - beforeEnter: (to, from, next) => { - const isWaterwayAdmin = store.getters["user/isWaterwayAdmin"]; - if (!isWaterwayAdmin) { - next("/login"); - } else { - next(); - } - } - }, - { - path: "/importschedule", - name: "importschedule", - component: () => import("./components/importschedule/Importschedule.vue"), - meta: { - requiresAuth: true - }, - beforeEnter: (to, from, next) => { - const isWaterwayAdmin = store.getters["user/isWaterwayAdmin"]; - if (!isWaterwayAdmin) { - next("/login"); - } else { - next(); - } - } - }, - { path: "/", name: "mainview", component: Maplayer, @@ -175,6 +111,26 @@ } }, { + path: "/imports/configuration", + name: "importconfiguration", + component: Maplayer, + meta: { + requiresAuth: true + }, + beforeEnter: (to, from, next) => { + const isWaterwayAdmin = store.getters["user/isWaterwayAdmin"]; + if (!isWaterwayAdmin) { + next("/login"); + } else { + store.commit("application/searchQuery", ""); + store.commit("application/showContextBox", true); + store.commit("application/contextBoxContent", "importconfiguration"); + store.commit("application/showSearchbar", true); + next(); + } + } + }, + { path: "/imports/overview/:id?", name: "importoverview", component: Maplayer,
--- a/client/src/store/importschedule.js Mon Apr 08 18:54:13 2019 +0200 +++ b/client/src/store/importschedule.js Tue Apr 09 16:31:55 2019 +0200 @@ -27,7 +27,10 @@ FAIRWAYDIMENSION: "fairwaydimension", WATERWAYGAUGES: "waterwaygauges", DISTANCEMARKSVIRTUAL: "distancemarksvirtual", - DISTANCEMARKSASHORE: "distancemarksashore" + DISTANCEMARKSASHORE: "distancemarksashore", + SOUNDINGRESULTS: "soundingresults", + APPROVEDGAUGEMEASUREMENTS: "approvedgaugemeasurements", + WATERWAYPROFILES: "waterwayprofiles" }; const KINDIMPORTTYPE = { @@ -59,7 +62,6 @@ id: null, importType: null, schedule: null, - import_: null, importSource: null, eMailNotification: false, scheduled: false, @@ -88,12 +90,18 @@ }; }; +const MODES = { + LIST: "list", + EDIT: "edit" +}; + // initial state const init = () => { return { schedules: [], importScheduleDetailVisible: false, - currentSchedule: initializeCurrentSchedule() + currentSchedule: initializeCurrentSchedule(), + mode: MODES.LIST }; }; @@ -102,6 +110,16 @@ namespaced: true, state: init(), mutations: { + setEditMode: state => { + state.mode = MODES.EDIT; + }, + setListMode: state => { + state.currentSchedule = initializeCurrentSchedule(); + state.mode = MODES.LIST; + }, + setImportType: (state, type) => { + Vue.set(state.currentSchedule, "importType", type); + }, clearCurrentSchedule: state => { state.currentSchedule = initializeCurrentSchedule(); }, @@ -118,7 +136,7 @@ const { kind, config, id } = payload; const eMailNotification = config["send-email"]; const { cron, url } = config; - Vue.set(state.currentSchedule, "import_", KINDIMPORTTYPE[kind]); + Vue.set(state.currentSchedule, "importType", KINDIMPORTTYPE[kind]); Vue.set(state.currentSchedule, "id", id); if (cron) { Vue.set(state.currentSchedule, "scheduled", true); @@ -320,5 +338,6 @@ importschedule, initializeCurrentSchedule, IMPORTTYPES, - IMPORTTYPEKIND + IMPORTTYPEKIND, + MODES };