view client/src/components/admin/Importqueue.vue @ 1460:3d5aea677345

merge
author Fadi Abbud <fadi.abbud@intevation.de>
date Mon, 03 Dec 2018 16:05:47 +0100
parents 33dda08d67be
children 9b81ac91a43e
line wrap: on
line source

<template>
  <div class="d-flex flex-row">
    <div :class="spacerStyle"></div>
    <div class="mt-3">
      <div class="card importqueuecard shadow-xs">
        <h6 class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center">
          <font-awesome-icon icon="tasks" class="mr-2"></font-awesome-icon>
          <translate class="headline">Importqueue</translate>
        </h6>
        <div class="card-body importcardbody">
          <div class="card-body importcardbody">
            <div class="searchandfilter d-flex flex-row">
              <div class="searchgroup input-group">
                <div class="input-group-prepend">
                  <span class="input-group-text" id="search">
                    <font-awesome-icon icon="search"></font-awesome-icon>
                  </span>
                </div>
                <input
                  v-model="searchQuery"
                  type="text"
                  class="form-control"
                  placeholder
                  aria-label="Search"
                  aria-describedby="search"
                >
              </div>
              <div class="filters">
                <button @click="setFilter('successful')" :class="successfulStyle">
                  <translate>Successful</translate>
                </button>
                <button @click="setFilter('failed')" :class="failedStyle">
                  <translate>Failed</translate>
                </button>
                <button @click="setFilter('pending')" :class="pendingStyle">
                  <translate>Pending</translate>
                </button>
                <button @click="setFilter('rejected')" :class="rejectedStyle">
                  <translate>Rejected</translate>
                </button>
                <button @click="setFilter('accepted')" :class="acceptedStyle">
                  <translate>Accepted</translate>
                </button>
              </div>
            </div>
            <table class="table">
              <thead>
                <tr>
                  <th>
                    <translate>Enqueued</translate>
                  </th>
                  <th>
                    <translate>Kind</translate>
                  </th>
                  <th>
                    <translate>User</translate>
                  </th>
                  <th>
                    <translate>State</translate>
                  </th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="job in filteredImports" :key="job.id">
                  <td>{{job.enqueued}}</td>
                  <td>{{job.kind}}</td>
                  <td>{{job.user}}</td>
                  <td>{{job.state}}</td>
                </tr>
              </tbody>
            </table>
            <div>
              <button @click="refresh" class="btn btn-info refresh">
                <translate>Refresh</translate>
              </button>
            </div>
          </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):
 * Markus Kottländer <markus@intevation.de>
 */
import { displayError } from "../../lib/errors.js";
import { mapState } from "vuex";

export default {
  name: "importqueue",
  data() {
    return {
      searchQuery: "",
      successful: false,
      failed: false,
      pending: false,
      rejected: false,
      accepted: false
    };
  },
  mounted() {
    this.loadQueue();
  },
  methods: {
    setFilter(name) {
      this[name] = !this[name];
      const allSet =
        this.successful &&
        this.failed &&
        this.pending &&
        this.accepted &&
        this.rejected;
      if (allSet) {
        this.successful = false;
        this.failed = false;
        this.pending = false;
        this.accepted = false;
        this.rejected = false;
      }
    },
    loadQueue() {
      this.$store.dispatch("imports/getImports").catch(error => {
        const { status, data } = error.response;
        displayError({
          title: this.$gettext("Backend Error"),
          message: `${status}: ${data.message || data}`
        });
      });
    },
    refresh() {
      this.loadQueue();
    }
  },
  computed: {
    ...mapState("imports", ["imports"]),
    ...mapState("application", ["showSidebar"]),
    filteredImports() {
      const filtered = this.imports
        .filter(element => {
          if (!this.searchQuery) return true;
          return [(element.kind, element.user, element.enqueued)].some(x => {
            return x.toLowerCase().includes(this.searchQuery.toLowerCase());
          });
        })
        .filter(y => {
          if (
            !this.successful &&
            !this.failed &&
            !this.pending &&
            !this.accepted &&
            !this.rejected
          )
            return true;
          let filterCriteria = [];
          if (this.successful) filterCriteria.push("successful");
          if (this.failed) filterCriteria.push("failed");
          if (this.pending) filterCriteria.push("pending");
          if (this.accepted) filterCriteria.push("accepted");
          if (this.rejected) filterCriteria.push("rejected");
          const result = filterCriteria.map(selectedState => {
            return y.state === selectedState;
          });
          return result.some(x => x);
        });
      return filtered;
    },
    spacerStyle() {
      return [
        "spacer ml-3",
        {
          "spacer-expanded": this.showSidebar,
          "spacer-collapsed": !this.showSidebar
        }
      ];
    },
    successfulStyle() {
      return {
        btn: true,
        "btn-light": !this.successful,
        "btn-dark": this.successful
      };
    },
    pendingStyle() {
      return {
        btn: true,
        "btn-light": !this.pending,
        "btn-dark": this.pending
      };
    },
    failedStyle() {
      return {
        btn: true,
        "btn-light": !this.failed,
        "btn-dark": this.failed
      };
    },
    rejectedStyle() {
      return {
        btn: true,
        "btn-light": !this.rejected,
        "btn-dark": this.rejected
      };
    },
    acceptedStyle() {
      return {
        btn: true,
        "btn-light": !this.accepted,
        "btn-dark": this.accepted
      };
    }
  }
};
</script>

<style lang="scss" scoped>
.refresh {
  position: absolute;
  right: $offset;
  bottom: $offset;
}

.spacer {
  height: 100vh;
}

.spacer-collapsed {
  min-width: $icon-width + $offset;
  transition: $transition-fast;
}

.spacer-expanded {
  min-width: $sidebar-width + $offset;
}

.importqueuecard {
  width: 80vw;
  min-height: 20rem;
}

.card-body {
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.searchandfilter {
  position: relative;
  margin-bottom: $xx-large-offset;
}

.filters {
  position: absolute;
  right: 0;
}

.filters button {
  margin-right: $small-offset;
}

.table td,
.table th {
  border-top: 0 !important;
  text-align: left;
  padding: $small-offset !important;
}

.searchgroup {
  position: absolute;
  left: 0;
  width: 50%;
}
</style>