view client/src/components/importoverview/ImportOverview.vue @ 2557:91c68153e7b6

staging: switch route to new design per default
author Thomas Junk <thomas.junk@intevation.de>
date Fri, 08 Mar 2019 12:24:42 +0100
parents client/src/components/importoverview/ImportOverviewAlt.vue@ebaa0e93b05a
children d9e1db955d49
line wrap: on
line source

<template>
  <div class="overview">
    <UIBoxHeader
      icon="clipboard-check"
      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="state small condensed">State</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="state small condensed">
              {{ entry.state }}
            </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>
              <font-awesome-icon
                v-if="!entry.warnings"
                class="ml-1 text-white"
                icon="exclamation-triangle"
                fixed-width
              ></font-awesome-icon>
              <font-awesome-icon
                class="ml-1 text-mute"
                icon="check"
                fixed-width
              ></font-awesome-icon>
              <font-awesome-icon
                class="ml-1 text-mute"
                icon="times"
                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>
    </div>
  </div>
</template>

<script>
import { displayError } from "@/lib/errors.js";
import { HTTP } from "@/lib/http";

//import { mapState } from "vuex";

const NODETAILS = -1;
const NODIFF = -1;

export default {
  name: "importoverviewalt",
  data() {
    return {
      showDiff: NODIFF,
      importQueue: [],
      logEntries: [],
      show: NODETAILS,
      showAdditional: NODETAILS,
      showLogs: NODETAILS
    };
  },
  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")
        .then(() => {
          this.reload = false;
        })
        .catch(error => {
          const { status, data } = error.response;
          displayError({
            title: this.$gettext("Backend Error"),
            message: `${status}: ${data.message || data}`
          });
        });
    }
  },
  mounted() {
    this.refresh();
  },
  NODETAILS: NODETAILS
};
</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: 350px;
  overflow-y: auto;
}

.additionalinfo > div:hover {
  background: #eee;
}

.logentries > div:hover {
  background: #eee;
}

.details {
  width: 100%;
  padding: 5px;
  cursor: pointer;
}

.imports {
  line-height: 1.5rem;
}

.icons {
  width: 4%;
}

.id {
  width: 10%;
}

.kind {
  width: 10%;
}

.date {
  width: 20%;
}

.enqueued {
  width: 20%;
}

.user {
  width: 10%;
}

.state {
  width: 10%;
}

.actions {
  width: 16%;
}
</style>