view client/src/components/importschedule/Importschedule.vue @ 2384:c06b001dc26b

client: improved popup implementation For deleting users and templates there was a more or less quick n' dirty implementation of a confirmation dialog/popup. Since we need this kind of dialog in several more places I generalized the implementation a bit and made it more robust.
author Markus Kottlaender <markus@intevation.de>
date Mon, 25 Feb 2019 13:11:30 +0100
parents f04d33fec01e
children f185503ef35a
line wrap: on
line source

<template>
  <div class="d-flex flex-row">
    <Spacer></Spacer>
    <div class="mt-3 w-100">
      <div class="card flex-grow-1 schedulecard shadow-xs">
        <h6
          class="mb-0 py-2 px-3 border-bottom d-flex text-info align-items-center"
        >
          <font-awesome-icon icon="clock" class="mr-2"></font-awesome-icon>
          <translate class="headline">Imports</translate>
        </h6>
        <div class="card-body schedulecardbody">
          <div class="card-body schedulecardbody">
            <div class="searchandfilter mb-3  w-50 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>
            <transition name="fade">
              <table v-if="schedules.length" class="table table-hover">
                <thead>
                  <tr>
                    <th><translate>ID</translate></th>
                    <th><translate>Type</translate></th>
                    <th><translate>Author</translate></th>
                    <th><translate>Schedule</translate></th>
                    <th><translate>Email</translate></th>
                    <th style="width: 140px"></th>
                  </tr>
                </thead>
                <transition-group name="fade" tag="tbody">
                  <tr v-for="schedule in schedules" :key="schedule.id">
                    <td>{{ schedule.id }}</td>
                    <td>{{ schedule.kind.toUpperCase() }}</td>
                    <td>{{ schedule.user }}</td>
                    <td>{{ schedule.config.cron }}</td>
                    <td>
                      <font-awesome-icon
                        v-if="schedule.config['send-email']"
                        class="fa-fw mr-2"
                        fixed-width
                        icon="check"
                      ></font-awesome-icon>
                    </td>
                    <td class="text-right">
                      <button
                        @click="editSchedule(schedule.id)"
                        class="btn btn-sm btn-dark mr-1"
                        :disabled="importScheduleDetailVisible"
                      >
                        <font-awesome-icon
                          icon="pencil-alt"
                          fixed-width
                        ></font-awesome-icon>
                      </button>
                      <button
                        @click="deleteSchedule(schedule)"
                        class="btn btn-sm btn-dark mr-1"
                        :disabled="importScheduleDetailVisible"
                      >
                        <font-awesome-icon
                          icon="trash"
                          fixed-width
                        ></font-awesome-icon>
                      </button>
                      <button
                        @click="triggerManualImport(schedule.id)"
                        class="btn btn-sm btn-dark"
                        :disabled="importScheduleDetailVisible"
                      >
                        <font-awesome-icon
                          icon="play"
                          fixed-width
                        ></font-awesome-icon>
                      </button>
                    </td>
                  </tr>
                </transition-group>
              </table>
              <div v-else class="mt-4 small text-center py-3">
                <translate>No scheduled imports</translate>
              </div>
            </transition>
            <div class="text-right">
              <button
                :disabled="importScheduleDetailVisible"
                @click="newImport"
                class="btn btn-info newbutton"
              >
                <translate>New Import</translate>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
    <Importscheduledetail></Importscheduledetail>
  </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):
 * Thomas Junk <thomas.junk@intevation.de>
 * Markus Kottländer <markus.kottlaender@intevation.de>
 */

import { mapState } from "vuex";
import { HTTP } from "@/lib/http";
import { displayInfo, displayError } from "@/lib/errors.js";

export default {
  name: "importschedule",
  components: {
    Importscheduledetail: () => import("./Importscheduledetail"),
    Spacer: () => import("@/components/Spacer")
  },
  data() {
    return {
      searchQuery: ""
    };
  },
  mounted() {
    this.getSchedules();
  },
  methods: {
    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}`
          });
        });
    },
    getSchedules() {
      this.$store.dispatch("importschedule/loadSchedules").catch(error => {
        const { status, data } = error.response;
        displayError({
          title: this.$gettext("Backend Error"),
          message: `${status}: ${data.message || data}`
        });
      });
    },
    newImport() {
      this.$store.commit("importschedule/setImportScheduleDetailVisible");
    },
    deleteSchedule(schedule) {
      console.log(schedule);
      this.$store.commit("application/popup", {
        icon: "trash",
        title: this.$gettext("Delete Import"),
        content: this.$gettext(
          `Do you really want to delete the import with ID <b>${
            schedule.id
          }</b> of type <b>${schedule.kind.toUpperCase()}</b>?`
        ),
        confirm: {
          label: this.$gettext("Delete"),
          icon: "trash",
          callback: () => {
            this.$store
              .dispatch("importschedule/deleteSchedule", schedule.id)
              .then(() => {
                this.getSchedules();
                displayInfo({
                  title: this.$gettext("Imports"),
                  message: this.$gettext("Deleted import: #") + schedule.id
                });
              })
              .catch(error => {
                const { status, data } = error.response;
                displayError({
                  title: this.$gettext("Backend Error"),
                  message: `${status}: ${data.message || data}`
                });
              });
          }
        },
        cancel: {
          label: this.$gettext("Cancel"),
          icon: "times"
        }
      });
    }
  },
  computed: {
    ...mapState("application", ["showSidebar"]),
    ...mapState("importschedule", ["schedules", "importScheduleDetailVisible"]),
    spacerStyle() {
      return [
        "spacer ml-3",
        {
          "spacer-expanded": this.showSidebar,
          "spacer-collapsed": !this.showSidebar
        }
      ];
    }
  }
};
</script>

<style lang="scss" scoped>
th {
  border-top: 0px;
}

.card-body {
  padding-bottom: $small-offset;
}

.schedulecard {
  margin-right: $offset;
  min-height: 20rem;
}

.schedulecard-body {
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}
</style>