changeset 2880:c40540889b53

client: code cleanup, slight style improvements
author Markus Kottlaender <markus@intevation.de>
date Mon, 01 Apr 2019 17:37:22 +0200
parents c71b0c93e1a6
children 44c6551511c1
files client/src/components/Bottlenecks.vue client/src/components/importoverview/AdditionalLog.vue client/src/components/importoverview/ApprovedGaugeMeasurementDetail.vue client/src/components/importoverview/BottleneckDetail.vue client/src/components/importoverview/Filters.vue client/src/components/importoverview/ImportOverview.vue client/src/components/importoverview/LogEntry.vue client/src/components/importschedule/Importschedule.vue client/src/components/ui/UITableBody.vue client/src/components/usermanagement/Usermanagement.vue client/src/store/imports.js
diffstat 11 files changed, 158 insertions(+), 183 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/Bottlenecks.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/Bottlenecks.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -24,7 +24,7 @@
     <UITableBody
       :data="filteredBottlenecks() | sortTable(sortColumn, sortDirection)"
       :maxHeight="(showSplitscreen ? 18 : 35) + 'rem'"
-      :active="openBottleneck"
+      :isActive="item => item === this.openBottleneck"
     >
       <template v-slot:row="{ item: bottleneck }">
         <div class="table-cell truncate text-left" style="width: 230px">
--- a/client/src/components/importoverview/AdditionalLog.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/importoverview/AdditionalLog.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -6,8 +6,8 @@
       'flex-column',
       'text-left',
       {
-        full: showAdditional === $options.NODETAILS,
-        split: showAdditional !== $options.NODETAILS
+        full: !showAdditional,
+        split: showAdditional
       }
     ]"
   >
@@ -73,8 +73,7 @@
   name: "additionallogs",
   computed: {
     ...mapState("imports", ["showAdditional", "details"])
-  },
-  NODETAILS: -1
+  }
 };
 </script>
 
--- a/client/src/components/importoverview/ApprovedGaugeMeasurementDetail.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/importoverview/ApprovedGaugeMeasurementDetail.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -2,8 +2,8 @@
   <div
     :class="{
       diffs: true,
-      full: showLogs === $options.NODETAILS,
-      split: showLogs !== $options.NODETAILS
+      full: !showLogs,
+      split: showLogs
     }"
   >
     <div v-for="(result, index) in details.summary" :key="index">
@@ -108,14 +108,12 @@
  */
 import { mapState } from "vuex";
 
-const NODIFF = -1;
-
 export default {
   name: "agmdetails",
   props: ["entry"],
   data() {
     return {
-      showDiff: NODIFF
+      showDiff: false
     };
   },
   computed: {
@@ -123,14 +121,13 @@
   },
   methods: {
     toggleDiff(number) {
-      if (this.showDiff !== number || this.showDiff == NODIFF) {
+      if (this.showDiff !== number) {
         this.showDiff = number;
       } else {
-        this.showDiff = NODIFF;
+        this.showDiff = false;
       }
     }
-  },
-  NODETAILS: -1
+  }
 };
 </script>
 
--- a/client/src/components/importoverview/BottleneckDetail.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/importoverview/BottleneckDetail.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -2,8 +2,8 @@
   <div
     :class="{
       bottleneckdetails: true,
-      full: showLogs === $options.NODETAILS,
-      split: showLogs !== $options.NODETAILS
+      full: !showLogs,
+      split: showLogs
     }"
   >
     <div
@@ -30,9 +30,9 @@
               fixed-width
             ></font-awesome-icon>
           </div>
-          <a @click="moveToBottleneck(index)" class="" href="#">{{
-            bottleneck.properties.objnam
-          }}</a>
+          <a @click="moveToBottleneck(index)" href="#">
+            {{ bottleneck.properties.objnam }}
+          </a>
         </div>
 
         <div class="ml-3 d-flex flex-row" v-if="showBottleneckDetail === index">
@@ -149,13 +149,12 @@
     },
     showBottleneckDetails(index) {
       if (index == this.showBottleneckDetail) {
-        this.showBottleneckDetail = NO_BOTTLENECK;
+        this.showBottleneckDetail = false;
         return;
       }
       this.showBottleneckDetail = index;
     }
-  },
-  NODETAILS: -1
+  }
 };
 </script>
 
--- a/client/src/components/importoverview/Filters.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/importoverview/Filters.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -53,7 +53,7 @@
     pendingStyle() {
       return {
         btn: true,
-        "btn-sm": true,
+        "btn-xs": true,
         "btn-light": !this.pending,
         "btn-secondary": this.pending
       };
@@ -62,7 +62,7 @@
       return {
         "ml-2": true,
         btn: true,
-        "btn-sm": true,
+        "btn-xs": true,
         "btn-light": !this.failed,
         "btn-secondary": this.failed
       };
@@ -71,7 +71,7 @@
       return {
         "ml-2": true,
         btn: true,
-        "btn-sm": true,
+        "btn-xs": true,
         "btn-light": !this.declined,
         "btn-secondary": this.declined
       };
@@ -80,7 +80,7 @@
       return {
         "ml-2": true,
         btn: true,
-        "btn-sm": true,
+        "btn-xs": true,
         "btn-light": !this.accepted,
         "btn-secondary": this.accepted
       };
@@ -89,7 +89,7 @@
       return {
         "ml-2": true,
         btn: true,
-        "btn-sm": true,
+        "btn-xs": true,
         "btn-light": !this.warning,
         "btn-secondary": this.warning
       };
--- a/client/src/components/importoverview/ImportOverview.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/importoverview/ImportOverview.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -8,64 +8,56 @@
     />
     <div class="position-relative">
       <SpinnerOverlay v-if="loading" />
-      <div class="p-2 mb-1 d-flex flex-row flex-fill justify-content-between">
+      <div class="border-bottom p-2 d-flex justify-content-between">
         <Filters></Filters>
-        <div>
-          <button
-            class="btn btn-sm btn-info"
-            :disabled="!reviewed.length"
-            @click="save"
-          >
-            <translate>Commit</translate> {{ reviewed.length }}
-          </button>
-        </div>
+        <button
+          class="btn btn-xs btn-info"
+          :disabled="!reviewed.length"
+          @click="save"
+        >
+          <translate>Commit</translate> {{ reviewed.length }}
+        </button>
       </div>
       <div
-        class="ml-2 mr-2 mb-2 datefilter d-flex flex-row justify-content-between"
+        class="p-2 d-flex align-items-center justify-content-between border-bottom"
       >
-        <div class="mr-3 my-auto pointer">
-          <button
-            :disabled="!this.prev"
-            @click="earlier"
-            class="btn btn-sm btn-outline-light text-dark"
-          >
-            <translate>Earlier</translate>
-            <font-awesome-icon class="ml-2" icon="angle-left" />
-          </button>
-        </div>
-        <div class="selected-interval my-auto">
-          <span class="date">{{ interval[0] | dateTime }}</span>
-          <span class="ml-3 mr-3">-</span>
-          <span class="date">{{ interval[1] | dateTime }}</span>
-        </div>
-        <div class="ml-3 my-auto pointer">
-          <button
-            :disabled="!this.next"
-            @click="later"
-            class="btn btn-sm btn-outline-light text-dark"
-          >
-            <font-awesome-icon class="mr-2" icon="angle-right" /><translate
-              >Later</translate
-            >
-          </button>
-        </div>
-        <div class="d-flex flex-row">
+        <button
+          :disabled="!this.prev"
+          @click="earlier"
+          class="btn btn-xs btn-outline-secondary"
+        >
+          <font-awesome-icon icon="angle-left" fixed-width />
+          <translate>Earlier</translate>
+        </button>
+        <div class="d-flex align-items-center small">
+          {{ interval[0] | dateTime }}
+          <span class="mx-2">&ndash;</span>
+          {{ interval[1] | dateTime }}
           <select
-            class="my-auto btn btn-outline-light text-dark form-control interval-select"
+            style="width: 75px; height: 24px"
+            class="form-control form-control-sm small ml-2"
             v-model="selectedInterval"
           >
-            <option :value="$options.LAST_HOUR"
-              ><translate>Hour</translate></option
-            >
+            <option :value="$options.LAST_HOUR">
+              <translate>Hour</translate>
+            </option>
             <option :value="$options.TODAY"><translate>Day</translate></option>
-            <option :value="$options.LAST_7_DAYS"
-              ><translate>7 days</translate></option
-            >
+            <option :value="$options.LAST_7_DAYS">
+              <translate>7 days</translate>
+            </option>
             <option :value="$options.LAST_30_DAYS">
               <translate>30 Days</translate>
             </option>
           </select>
         </div>
+        <button
+          :disabled="!this.next"
+          @click="later"
+          class="btn btn-xs btn-outline-secondary"
+        >
+          <translate>Later</translate>
+          <font-awesome-icon icon="angle-right" fixed-width />
+        </button>
       </div>
       <UITableHeader
         :columns="[
@@ -85,11 +77,15 @@
      -->
       <UITableBody
         :data="filteredImports() | sortTable(sortColumn, sortDirection)"
+        :isActive="item => item.id === this.show"
         maxHeight="73vh"
       >
         <template v-slot:row="{ item: entry }">
           <LogEntry :entry="entry"></LogEntry>
         </template>
+        <template v-slot:expand="{ item: entry }">
+          <LogDetail :entry="entry"></LogDetail>
+        </template>
       </UITableBody>
     </div>
   </div>
@@ -129,7 +125,8 @@
 export default {
   components: {
     Filters: () => import("./Filters.vue"),
-    LogEntry: () => import("./LogEntry.vue")
+    LogEntry: () => import("./LogEntry.vue"),
+    LogDetail: () => import("./LogDetail.vue")
   },
   mixins: [sortTable],
   LAST_HOUR: "lasthour",
@@ -321,7 +318,7 @@
           query: this.searchQuery
         })
         .then(() => {
-          if (this.show != -1) {
+          if (this.show) {
             this.loadDetails(this.show)
               .then(response => {
                 this.$store.commit("imports/setCurrentDetails", response.data);
@@ -418,23 +415,12 @@
   },
   mounted() {
     const { id } = this.$route.params;
-    if (!id) {
+    if (id) {
+      this.showSingleRessource(id);
+    } else {
       this.$store.commit("application/searchQuery", "");
       this.loadLogs();
-    } else {
-      this.showSingleRessource(id);
     }
   }
 };
 </script>
-
-<style lang="scss" scoped>
-.date {
-  font-stretch: condensed;
-}
-.interval-select {
-  padding: 0px;
-  margin: 0px;
-  font-size: 80%;
-}
-</style>
--- a/client/src/components/importoverview/LogEntry.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/importoverview/LogEntry.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -1,81 +1,71 @@
 <template>
-  <div>
-    <div class="row no-gutters text-left">
-      <div
-        style="width: 79px;"
-        class="table-cell d-flex justify-content-between"
+  <div class="row w-100 no-gutters text-left">
+    <div style="width: 79px;" class="table-cell d-flex justify-content-between">
+      <font-awesome-icon
+        @click="toggleDetails"
+        :class="'pointer ' + (entry.id === show ? 'text-white' : 'text-info')"
+        :icon="entry.id === show ? 'angle-down' : 'angle-right'"
+        fixed-width
+      ></font-awesome-icon>
+      {{ entry.id }}
+    </div>
+    <div style="width: 53px;" class="table-cell center">
+      {{ entry.kind.toUpperCase() }}
+    </div>
+    <div style="width: 138px;" class="table-cell center">
+      {{ entry.enqueued | dateTime }}
+    </div>
+    <div style="width: 105px;" class="table-cell truncate">
+      {{ entry.user }}
+    </div>
+    <div style="width: 105px;" class="table-cell truncate">
+      {{ entry.signer }}
+    </div>
+    <div style="width: 72px;" class="table-cell center">
+      <span v-if="entry.state === 'failed'" class="text-danger">
+        {{ entry.state }}
+      </span>
+      <span v-else>{{ entry.state }}</span>
+    </div>
+    <div style="width: 44px;" class="table-cell center">
+      <font-awesome-icon
+        v-if="entry.warnings"
+        class="text-warning"
+        icon="exclamation-triangle"
+        fixed-width
+      ></font-awesome-icon>
+    </div>
+    <div style="flex-grow: 1; padding: 0;" class="table-cell text-right">
+      <button
+        :class="['action approved', { active: isApproved }]"
+        @click="toggleApproval($options.STATES.APPROVED)"
+        v-if="entry.state === 'pending'"
       >
         <font-awesome-icon
-          @click="toggleDetails"
-          class="my-auto text-info pointer"
-          :icon="entry.id === show ? 'angle-down' : 'angle-right'"
-          fixed-width
+          class="small pointer"
+          icon="check"
         ></font-awesome-icon>
-        {{ entry.id }}
-      </div>
-      <div style="width: 53px;" class="table-cell text-center">
-        {{ entry.kind.toUpperCase() }}
-      </div>
-      <div style="width: 138px;" class="table-cell text-center">
-        {{ entry.enqueued | dateTime }}
-      </div>
-      <div style="width: 105px;" class="table-cell truncate">
-        {{ entry.user }}
-      </div>
-      <div style="width: 105px;" class="table-cell truncate">
-        {{ entry.signer }}
-      </div>
-      <div style="width: 72px;" class="table-cell text-center">
-        <span v-if="entry.state === 'failed'" class="text-danger">{{
-          entry.state
-        }}</span>
-        <span v-else>{{ entry.state }}</span>
-      </div>
-      <div style="width: 44px;" class="table-cell text-center">
+      </button>
+      <button
+        :class="['action rejected', { active: isRejected }]"
+        @click="toggleApproval($options.STATES.REJECTED)"
+        v-if="entry.state === 'pending'"
+      >
         <font-awesome-icon
-          v-if="entry.warnings"
-          class="text-warning"
-          icon="exclamation-triangle"
-          fixed-width
+          icon="times"
+          class="small pointer"
         ></font-awesome-icon>
-      </div>
-      <div style="flex-grow: 1; padding: 0;" class="table-cell text-right">
-        <div v-if="entry.state === 'pending'">
-          <button
-            :class="['actions approved', { active: isApproved }]"
-            @click="toggleApproval($options.STATES.APPROVED)"
-          >
-            <font-awesome-icon
-              class="small pointer"
-              icon="check"
-            ></font-awesome-icon>
-          </button>
-          <button
-            :class="['actions rejected', { active: isRejected }]"
-            @click="toggleApproval($options.STATES.REJECTED)"
-          >
-            <font-awesome-icon
-              icon="times"
-              class="small pointer"
-            ></font-awesome-icon>
-          </button>
-        </div>
-      </div>
+      </button>
     </div>
-    <LogDetail
-      :entry="entry"
-      :details="details"
-      v-if="show === entry.id"
-    ></LogDetail>
   </div>
 </template>
 
 <style lang="sass" scoped>
-.actions
+.action
   height: 100%
   width: 50%
   border: 0
-  background: transparent
+  background: white
   outline: none
   &.approved
     color: green
@@ -90,6 +80,11 @@
     &:hover
       color: white
       background: red
+.active
+  .action
+    background-color: #d2eaee
+    &.rejected
+      border-left: solid 1px rgba(255, 255, 255, 0.3)
 </style>
 
 <script>
@@ -112,9 +107,6 @@
 import { HTTP } from "@/lib/http.js";
 
 export default {
-  components: {
-    LogDetail: () => import("./LogDetail.vue")
-  },
   props: ["entry"],
   computed: {
     ...mapState("imports", ["show"]),
--- a/client/src/components/importschedule/Importschedule.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/importschedule/Importschedule.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -32,13 +32,16 @@
         />
         <UITableBody
           :data="filteredSchedules() | sortTable(sortColumn, sortDirection)"
+          :isActive="item => currentSchedule && item.id === currentSchedule.id"
         >
           <template v-slot:row="{ item: schedule }">
-            <div class="py-1 col-1">{{ schedule.id }}</div>
-            <div class="py-1 col-2">{{ schedule.kind.toUpperCase() }}</div>
-            <div class="py-1 col-2">{{ schedule.user }}</div>
-            <div class="py-1 col-2">{{ schedule.config.cron }}</div>
-            <div class="py-1 col-2 text-center">
+            <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"
@@ -46,7 +49,7 @@
                 icon="check"
               ></font-awesome-icon>
             </div>
-            <div class="py-1 col text-right">
+            <div class="table-cell col justify-content-end">
               <button
                 @click="editSchedule(schedule.id)"
                 class="btn btn-xs btn-dark mr-1"
@@ -141,7 +144,11 @@
   },
   computed: {
     ...mapState("application", ["showSidebar"]),
-    ...mapState("importschedule", ["schedules", "importScheduleDetailVisible"]),
+    ...mapState("importschedule", [
+      "schedules",
+      "currentSchedule",
+      "importScheduleDetailVisible"
+    ]),
     importScheduleLabel() {
       return this.$gettext("Import Schedule");
     },
--- a/client/src/components/ui/UITableBody.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/ui/UITableBody.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -7,12 +7,12 @@
     <div
       v-for="(item, index) in data"
       :key="key(index)"
-      :class="['row-container border-top', { active: active === item }]"
+      :class="['row-container border-top', { active: isActive(item) }]"
     >
       <div class="row mx-0">
         <slot :item="item" :index="index" name="row"></slot>
       </div>
-      <div class="expand" v-if="active === item">
+      <div class="expand" v-if="isActive(item)">
         <slot :item="item" :index="index" name="expand"></slot>
       </div>
     </div>
@@ -27,14 +27,12 @@
   .row-container
     > .row
       &:hover
-        background-color: #fafafa
+        background-color: #fcfcfc
       .table-cell
         display: flex
         align-items: center
         padding: 1.5px 3px
         border-right: solid 1px #dee2e6
-        &:hover
-          background-color: #f2f2f2
         &:last-child
           border-right: none
         &.center
@@ -77,8 +75,9 @@
       type: String,
       default: "18rem"
     },
-    active: {
-      type: [Object, Array]
+    isActive: {
+      type: Function,
+      default: () => false
     }
   },
   methods: {
--- a/client/src/components/usermanagement/Usermanagement.vue	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/components/usermanagement/Usermanagement.vue	Mon Apr 01 17:37:22 2019 +0200
@@ -15,8 +15,8 @@
           />
           <UITableBody
             :data="users | sortTable(sortColumn, sortDirection, page, pageSize)"
+            :isActive="item => item === currentUser"
             maxHeight="47rem"
-            :active="currentUser"
           >
             <template v-slot:row="{ item: user }">
               <div
--- a/client/src/store/imports.js	Mon Apr 01 17:33:08 2019 +0200
+++ b/client/src/store/imports.js	Mon Apr 01 17:37:22 2019 +0200
@@ -17,16 +17,12 @@
 import { equalTo as equalToFilter } from "ol/format/filter.js";
 import { startOfHour, endOfHour } from "date-fns";
 
-/* eslint-disable no-unused-vars */
-/* eslint-disable no-unreachable */
 const STATES = {
   NEEDSAPPROVAL: "pending",
   APPROVED: "accepted",
   REJECTED: "declined"
 };
 
-const NODETAILS = -1;
-
 // initial state
 const init = () => {
   return {
@@ -38,9 +34,9 @@
     stretches: [],
     imports: [],
     reviewed: [],
-    show: NODETAILS,
-    showAdditional: NODETAILS,
-    showLogs: NODETAILS,
+    show: null,
+    showAdditional: null,
+    showLogs: null,
     details: [],
     startDate: startOfHour(new Date()),
     endDate: endOfHour(new Date()),
@@ -158,19 +154,19 @@
       state.show = id;
     },
     hideDetails: state => {
-      state.show = NODETAILS;
+      state.show = null;
     },
     showAdditionalInfoFor: (state, id) => {
       state.showAdditional = id;
     },
     hideAdditionalInfo: state => {
-      state.showAdditional = NODETAILS;
+      state.showAdditional = false;
     },
     showAdditionalLogsFor: (state, id) => {
       state.showLogs = id;
     },
     hideAdditionalLogs: state => {
-      state.showLogs = NODETAILS;
+      state.showLogs = false;
     },
     toggleApprove: (state, change) => {
       const { id, newStatus } = change;
@@ -192,7 +188,7 @@
     }
   },
   actions: {
-    loadStretch({ commit }, name) {
+    loadStretch(context, name) {
       return new Promise((resolve, reject) => {
         getStretchFromWFS(equalToFilter("name", name))
           .then(response => {
@@ -219,7 +215,7 @@
           });
       });
     },
-    saveStretch({ commit }, stretch) {
+    saveStretch(context, stretch) {
       return new Promise((resolve, reject) => {
         HTTP.post("/imports/st", stretch, {
           headers: { "X-Gemma-Auth": localStorage.getItem("token") }
@@ -271,7 +267,7 @@
           });
       });
     },
-    confirmReview({ state }, reviewResults) {
+    confirmReview(context, reviewResults) {
       return new Promise((resolve, reject) => {
         HTTP.patch("/imports", reviewResults, {
           headers: {