changeset 2578:3ad81357a57c

overview2 WIP
author Thomas Junk <thomas.junk@intevation.de>
date Mon, 11 Mar 2019 15:35:13 +0100
parents fcb139bfa56b
children 5295a182b4a4
files client/src/components/importoverview/ImportOverviewAlt.vue client/src/store/imports.js
diffstat 2 files changed, 68 insertions(+), 409 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/importoverview/ImportOverviewAlt.vue	Mon Mar 11 15:09:49 2019 +0100
+++ b/client/src/components/importoverview/ImportOverviewAlt.vue	Mon Mar 11 15:35:13 2019 +0100
@@ -5,350 +5,57 @@
       title="Staging Area"
       :closeCallback="$parent.close"
     />
-    <div class="imports text-left ml-1 mr-1">
-      <div class="mt-3 d-flex flex-row border-bottom">
-        <div class="icons small condensed">&nbsp;</div>
-        <div class="id small condensed">Id</div>
-        <div class="kind small condensed">Kind</div>
-        <div class="date small condensed">
-          Date
-        </div>
-        <div class="enqueued small condensed">
-          Imported
-        </div>
-        <div class="user small condensed">User</div>
-        <div class="actions small condensed">&nbsp;</div>
-      </div>
-      <div class="d-flex flex-row" v-for="entry in importQueue" :key="entry.id">
-        <div class="d-flex flex-column w-100">
-          <div class="d-flex flex-row">
-            <div class="icons">
-              <font-awesome-icon
-                @click="toggleDetails(entry.id)"
-                class="pointer text-info"
-                v-if="show != entry.id"
-                icon="angle-right"
-                fixed-width
-              ></font-awesome-icon>
-              <font-awesome-icon
-                @click="toggleDetails(entry.id)"
-                class="pointer  text-info"
-                v-if="show == entry.id"
-                icon="angle-down"
-                fixed-width
-              ></font-awesome-icon>
-            </div>
-            <div class="id small condensed">{{ entry.id }}</div>
-            <div class="kind small condensed">
-              {{ entry.kind.toUpperCase() }}
-            </div>
-            <div class="date small condensed">
-              {{ entry.summary.date | surveyDate }}
-            </div>
-            <div class="enqueued small condensed">
-              {{ entry.enqueued.split("T")[0] | surveyDate }}
-            </div>
-            <div class="user small condensed">{{ entry.user }}</div>
-            <div class="actions small condensed">
-              <font-awesome-icon
-                v-if="entry.warnings"
-                class="ml-1 text-warning text-info"
-                icon="exclamation-triangle"
-                fixed-width
-              ></font-awesome-icon>
-            </div>
-          </div>
-          <div class="d-flex flex-row" v-if="show == entry.id">
-            <div class="ml-1 details d-flex flex-column">
-              <div
-                v-if="isApprovedGaugeMeasurement(entry.kind.toUpperCase())"
-                class="d-flex flex-row"
-              >
-                <font-awesome-icon
-                  @click="toggleAdditional(entry.id)"
-                  class="pointer text-info"
-                  v-if="showAdditional != entry.id"
-                  icon="angle-right"
-                  fixed-width
-                ></font-awesome-icon>
-                <font-awesome-icon
-                  @click="toggleAdditional(entry.id)"
-                  class="pointer text-info"
-                  v-if="showAdditional == entry.id"
-                  icon="angle-down"
-                  fixed-width
-                ></font-awesome-icon>
-                <small class="condensed">Additional Info</small>
-              </div>
-              <div
-                v-if="showAdditional == entry.id"
-                class="additionalinfo ml-4"
-              >
-                <div v-for="(result, index) in entry.summary" :key="index">
-                  <font-awesome-icon
-                    @click="toggleDiff(index)"
-                    class="pointer text-info"
-                    v-if="showDiff != index"
-                    icon="angle-right"
-                    fixed-width
-                  ></font-awesome-icon>
-                  <font-awesome-icon
-                    @click="toggleDiff(index)"
-                    class="pointer text-info"
-                    v-if="showDiff == index"
-                    icon="angle-down"
-                    fixed-width
-                  ></font-awesome-icon>
-                  <span
-                    v-if="result.versions.length == 1"
-                    class="agmcode text-left"
-                    ><small
-                      >{{ result["fk-gauge-id"] }}
-                      <translate class="mr-1">( New )</translate></small
-                    ></span
-                  >
-                  <span
-                    v-if="result.versions.length == 2"
-                    class="agmcode text-left"
-                    ><small>{{ result["fk-gauge-id"] }}</small></span
-                  >
-                  <span class="agmdetail text-left"
-                    ><small>{{
-                      result["measure-date"] | datetime
-                    }}</small></span
-                  >
-                  <div v-if="showDiff == index" class="ml-1">
-                    <div>
-                      <div class="d-flex flex-row pl-3 text-left">
-                        <div class="header border-bottom agmdetailskeys">
-                          <small><translate>Value</translate></small>
-                        </div>
-                        <div
-                          v-if="result.versions.length == 2"
-                          class="header border-bottom agmdetailsvalues"
-                        >
-                          <small><translate>Old</translate></small>
-                        </div>
-                        <div class="header border-bottom agmdetailsvalues">
-                          <small><translate>New</translate></small>
-                        </div>
-                      </div>
-                      <div
-                        class="d-flex flex-row pl-3 text-left"
-                        v-for="(entry, index) in Object.keys(
-                          result.versions[0]
-                        )"
-                        :key="index"
-                      >
-                        <div
-                          v-if="
-                            result.versions.length == 1 ||
-                              result.versions[0][entry] !=
-                                result.versions[1][entry]
-                          "
-                          class="agmdetailskeys"
-                        >
-                          <small>{{ entry }}</small>
-                        </div>
-                        <div
-                          v-if="
-                            result.versions.length == 1 ||
-                              result.versions[0][entry] !=
-                                result.versions[1][entry]
-                          "
-                          class="agmdetailsvalues"
-                        >
-                          <small>{{ result.versions[0][entry] }}</small>
-                        </div>
-                        <div
-                          v-if="
-                            result.versions.length == 2 &&
-                              result.versions[0][entry] !=
-                                result.versions[1][entry]
-                          "
-                          class="agmdetailsvalues"
-                        >
-                          <small>{{ result.versions[1][entry] }}</small>
-                        </div>
-                      </div>
-                    </div>
-                  </div>
-                </div>
-              </div>
-              <div class="d-flex flex-row">
-                <div class="d-flex flex-column">
-                  <div class="d-flex flex-row">
-                    <font-awesome-icon
-                      @click="toggleLogs(entry.id)"
-                      class="pointer text-info"
-                      v-if="showLogs != entry.id"
-                      icon="angle-right"
-                      fixed-width
-                    ></font-awesome-icon>
-                    <font-awesome-icon
-                      @click="toggleLogs(entry.id)"
-                      class="pointer text-info"
-                      v-if="showLogs == entry.id"
-                      icon="angle-down"
-                      fixed-width
-                    ></font-awesome-icon>
-                    <small class="condensed">Logs</small>
-                  </div>
-                  <div v-if="showLogs == entry.id" class="ml-4 logentries">
-                    <div
-                      v-for="(logentry, index) in logEntries"
-                      :key="index"
-                      class="d-flex flex-row"
-                    >
-                      <small
-                        :class="[
-                          'condensed type',
-                          {
-                            'text-danger':
-                              logentry.kind.toUpperCase() == 'ERROR',
-                            'text-warning':
-                              logentry.kind.toUpperCase() == 'WARN'
-                          }
-                        ]"
-                        >{{ logentry.kind.toUpperCase() }}</small
-                      >
-                      <small
-                        :class="[
-                          'condensed type',
-                          {
-                            'text-danger':
-                              logentry.kind.toUpperCase() == 'ERROR',
-                            'text-warning':
-                              logentry.kind.toUpperCase() == 'WARN'
-                          }
-                        ]"
-                        >{{ logentry.time }}</small
-                      >
-                      <small
-                        :class="[
-                          'condensed type',
-                          {
-                            'text-danger':
-                              logentry.kind.toUpperCase() == 'ERROR',
-                            'text-warning':
-                              logentry.kind.toUpperCase() == 'WARN'
-                          }
-                        ]"
-                        >{{ logentry.message }}</small
-                      >
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
+    <div
+      class="ml-2 mt-2 d-flex flex-row flex-fill justify-content-between mr-2"
+    >
+      <Filters></Filters>
+      <div>
+        <button :class="commitStyle">
+          <translate>Commit</translate> {{ toCommit.length }}
+        </button>
       </div>
     </div>
+    <LogEntry v-for="entry in imports" :key="entry.id"></LogEntry>
   </div>
 </template>
 
 <script>
-import { displayError } from "@/lib/errors.js";
-import { HTTP } from "@/lib/http";
+/* 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 { mapState } from "vuex";
-
-const NODETAILS = -1;
-const NODIFF = -1;
+import { displayError } from "@/lib/errors.js";
+import { mapState, mapGetters } from "vuex";
 
 export default {
   name: "importoverviewalt",
-  data() {
-    return {
-      showDiff: NODIFF,
-      importQueue: [],
-      logEntries: [],
-      show: NODETAILS,
-      showAdditional: NODETAILS,
-      showLogs: NODETAILS
-    };
+  components: {
+    Filters: () => import("./Filters.vue"),
+    LogEntry: () => import("./LogEntry.vue")
+  },
+  computed: {
+    ...mapState("imports", ["imports"]),
+    ...mapGetters("imports", ["toCommit"]),
+    commitStyle() {
+      return {
+        btn: true,
+        "btn-sm": true,
+        "btn-light": this.toCommit.length == 0,
+        "btn-info": this.toCommit.length > 0
+      };
+    }
   },
   methods: {
-    isFairwayDimension(kind) {
-      return kind === "FD";
-    },
-    isApprovedGaugeMeasurement(kind) {
-      return kind === "AGM";
-    },
-    isBottleneck(kind) {
-      return kind === "BN" || kind === "UBN";
-    },
-    isStretch(kind) {
-      return kind === "ST";
-    },
-    toggleAdditional(id) {
-      if (id === this.showAdditional) {
-        this.showAdditional = NODETAILS;
-        return;
-      }
-      this.showAdditional = id;
-    },
-    toggleDiff(id) {
-      if (id === this.showDiff) {
-        this.showDiff = NODIFF;
-        return;
-      }
-      this.showDiff = id;
-    },
-    toggleLogs(id) {
-      if (id === this.showLogs) {
-        this.showLogs = NODETAILS;
-        return;
-      }
-      this.loadLogEntries(id);
-    },
-    toggleDetails(id) {
-      if (id === this.show) {
-        this.show = NODETAILS;
-        this.showAdditional = NODETAILS;
-        this.showLogs = NODETAILS;
-        return;
-      }
-      this.show = id;
-    },
-    refresh() {
-      this.reload = true;
-      this.loadImportQueue();
-      this.loadLogs();
-    },
-    loadLogEntries(id) {
-      HTTP.get("/imports/" + id, {
-        headers: { "X-Gemma-Auth": localStorage.getItem("token") }
-      })
-        .then(response => {
-          const { entries } = response.data;
-          this.logEntries = entries;
-          this.showLogs = id;
-        })
-        .catch(error => {
-          const { status, data } = error.response;
-          displayError({
-            title: this.$gettext("Backend Error"),
-            message: `${status}: ${data.message || data}`
-          });
-        });
-    },
-    loadImportQueue() {
-      HTTP.get("/imports?states=running,pending", {
-        headers: { "X-Gemma-Auth": localStorage.getItem("token") }
-      })
-        .then(response => {
-          this.importQueue = response.data.imports;
-        })
-        .catch(error => {
-          const { status, data } = error.response;
-          displayError({
-            title: "Backend Error",
-            message: `${status}: ${data.message || data}`
-          });
-        });
-    },
     loadLogs() {
       this.$store
         .dispatch("imports/getImports")
@@ -365,81 +72,9 @@
     }
   },
   mounted() {
-    this.refresh();
-  },
-  NODETAILS: NODETAILS
+    this.loadLogs();
+  }
 };
 </script>
 
-<style lang="scss" scoped>
-.agmdetailskeys {
-  width: 100px;
-}
-
-.agmdetailsvalues {
-  width: 200px;
-}
-
-.overview {
-  max-height: 800px;
-}
-.logentries {
-  max-height: 400px;
-  max-width: 600px;
-  font-size: smaller;
-  white-space: nowrap;
-  line-height: 1.1em;
-  overflow: auto;
-}
-
-.additionalinfo {
-  max-width: 650px;
-  max-height: 200px;
-  overflow-y: auto;
-}
-
-.additionalinfo > div:hover {
-  background: #eee;
-}
-
-.logentries > div:hover {
-  background: #eee;
-}
-
-.details {
-  width: 100%;
-  padding: 5px;
-  cursor: pointer;
-}
-
-.imports {
-  line-height: 0.8rem;
-}
-
-.icons {
-  width: 4%;
-}
-
-.id {
-  width: 10%;
-}
-
-.kind {
-  width: 10%;
-}
-
-.date {
-  width: 20%;
-}
-
-.enqueued {
-  width: 20%;
-}
-
-.user {
-  width: 10%;
-}
-.actions {
-  width: 16%;
-}
-</style>
+<style lang="scss" scoped></style>
--- a/client/src/store/imports.js	Mon Mar 11 15:09:49 2019 +0100
+++ b/client/src/store/imports.js	Mon Mar 11 15:35:13 2019 +0100
@@ -24,15 +24,23 @@
   REJECTED: "declined"
 };
 
+const NODETAILS = -1;
+const NODIFF = -1;
+
 // initial state
 const init = () => {
   return {
+    filters: [],
     stretches: [],
     imports: [],
     staging: [],
     importToReview: null,
     stagingVisible: true,
-    logsVisible: true
+    logsVisible: true,
+    show: NODETAILS,
+    showAdditional: NODETAILS,
+    showLogs: NODETAILS,
+    showDiff: NODIFF
   };
 };
 
@@ -70,6 +78,11 @@
   namespaced: true,
   state: init(),
   getters: {
+    toCommit: state => {
+      return state.imports.filter(x => {
+        return x.status && x.status !== STATES.NEEDSAPPROVAL;
+      });
+    },
     processedReviews: state => {
       return state.staging
         .filter(x => x.status !== STATES.NEEDSAPPROVAL)
@@ -82,10 +95,20 @@
     }
   },
   mutations: {
+    setFilters: (state, filters) => {
+      state.filters = filters;
+    },
+    clearFilters: state => {
+      state.filters = [];
+    },
     setStretches: (state, stretches) => {
       state.stretches = stretches;
     },
     setImports: (state, imports) => {
+      imports = imports.map(x => {
+        if (x.state === "pending") x["status"] = STATES.NEEDSAPPROVAL;
+        return x;
+      });
       state.imports = imports;
     },
     setStagingVisibility: (state, visibility) => {
@@ -167,7 +190,8 @@
           headers: { "X-Gemma-Auth": localStorage.getItem("token") }
         })
           .then(response => {
-            commit("setImports", response.data.imports);
+            const { imports } = response.data;
+            commit("setImports", imports);
             resolve(response);
           })
           .catch(error => {