changeset 2972:6f351e00e579 unified_import

unified_imports: initial layout etd
author Thomas Junk <thomas.junk@intevation.de>
date Mon, 08 Apr 2019 15:50:23 +0200
parents 7a51fdfead2d
children de6e5b9eae84
files client/src/components/Contextbox.vue client/src/components/Sidebar.vue client/src/components/importconfiguration/Import.vue client/src/components/importconfiguration/ImportDetails.vue client/src/store/importschedule.js
diffstat 5 files changed, 353 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Contextbox.vue	Mon Apr 08 09:18:58 2019 +0200
+++ b/client/src/components/Contextbox.vue	Mon Apr 08 15:50:23 2019 +0200
@@ -6,7 +6,9 @@
     <ImportOverview
       v-if="contextBoxContent === 'importoverview'"
     ></ImportOverview>
-    <Stretches v-if="contextBoxContent === 'importconfiguration'"></Stretches>
+    <ImportConfiguration
+      v-if="contextBoxContent === 'importconfiguration'"
+    ></ImportConfiguration>
   </div>
 </template>
 
--- a/client/src/components/Sidebar.vue	Mon Apr 08 09:18:58 2019 +0200
+++ b/client/src/components/Sidebar.vue	Mon Apr 08 15:50:23 2019 +0200
@@ -63,6 +63,10 @@
             <font-awesome-icon class="fa-fw mr-2" fixed-width icon="clock" />
             <translate class="fix-trans-space">Imports</translate>
           </router-link>
+          <router-link to="/imports/configuration">
+            <font-awesome-icon class="fa-fw mr-2" fixed-width icon="clock" />
+            <translate class="fix-trans-space">Imports (New)</translate>
+          </router-link>
           <small class="text-muted pl-3">
             <translate>Systemadministration</translate>
           </small>
--- a/client/src/components/importconfiguration/Import.vue	Mon Apr 08 09:18:58 2019 +0200
+++ b/client/src/components/importconfiguration/Import.vue	Mon Apr 08 15:50:23 2019 +0200
@@ -1,9 +1,245 @@
 <template>
-  <h1>Hello</h1>
+  <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-reverse w-100 mb-3">
+      <button
+        :key="1"
+        v-if="mode === $options.MODES.EDIT"
+        @click="mode = $options.MODES.LIST"
+        class="btn btn-warning mr-3"
+      >
+        Back
+      </button>
+      <button
+        :key="2"
+        v-if="mode === $options.MODES.EDIT"
+        type="submit"
+        class="shadow-sm btn btn-info submit-button  mr-3"
+      >
+        <translate>Submit</translate>
+      </button>
+      <button
+        :key="3"
+        v-if="mode === $options.MODES.LIST"
+        @click="newConfiguration()"
+        class="btn btn-info mr-3"
+      >
+        <translate>New import</translate>
+      </button>
+      <button
+        v-if="mode === $options.MODES.EDIT && !isOnetime"
+        @click="triggerManualImport"
+        type="button"
+        class="shadow-sm btn btn-outline-info trigger mr-auto ml-3"
+      >
+        <font-awesome-icon class="fa-fw mr-2" fixed-width icon="play" />
+        <translate>Trigger import</translate>
+      </button>
+    </div>
+  </div>
 </template>
 
 <style></style>
 
 <script>
-export default {};
+/* 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
+  // IMPORTTYPEKIND,
+  // initializeCurrentSchedule
+} from "@/store/importschedule";
+
+export default {
+  components: {
+    ImportDetails: () => import("./ImportDetails.vue")
+  },
+  data() {
+    return {
+      loading: false,
+      sortColumn: "",
+      sortDirection: "",
+      mode: this.$options.MODES.LIST
+    };
+  },
+  methods: {
+    newConfiguration() {
+      this.mode = this.$options.MODES.EDIT;
+    },
+    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/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}`
+          });
+        });
+    }
+  },
+  computed: {
+    ...mapState("application", ["searchQuery"]),
+    ...mapState("importschedule", [
+      "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.getSchedules();
+  },
+  MODES: {
+    LIST: "list",
+    EDIT: "edit"
+  },
+  IMPORTTYPES: IMPORTTYPES
+};
 </script>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/components/importconfiguration/ImportDetails.vue	Mon Apr 08 15:50:23 2019 +0200
@@ -0,0 +1,101 @@
+<template>
+  <div>
+    <div class="mb-3">
+      <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>
+    </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
+  // 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 {
+  data() {
+    return {};
+  },
+  computed: {
+    ...mapState("importschedule", ["currentSchedule"]),
+    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: {},
+  IMPORTTYPES: IMPORTTYPES
+};
+</script>
--- a/client/src/store/importschedule.js	Mon Apr 08 09:18:58 2019 +0200
+++ b/client/src/store/importschedule.js	Mon Apr 08 15:50:23 2019 +0200
@@ -27,7 +27,10 @@
   FAIRWAYDIMENSION: "fairwaydimension",
   WATERWAYGAUGES: "waterwaygauges",
   DISTANCEMARKSVIRTUAL: "distancemarksvirtual",
-  DISTANCEMARKSASHORE: "distancemarksashore"
+  DISTANCEMARKSASHORE: "distancemarksashore",
+  SOUNDINGRESULTS: "soundingresults",
+  APPROVEDGAUGEMEASUREMENTS: "approvedgaugemeasurements",
+  WATERWAYPROFILES: "waterwayprofiles"
 };
 
 const KINDIMPORTTYPE = {
@@ -102,6 +105,9 @@
   namespaced: true,
   state: init(),
   mutations: {
+    setImportType: (state, type) => {
+      Vue.set(state.currentSchedule, "importType", type);
+    },
     clearCurrentSchedule: state => {
       state.currentSchedule = initializeCurrentSchedule();
     },