Mercurial > gemma
view client/src/components/importoverview/ImportOverview.vue @ 3333:d5dbfba9faae
clinet: pdf-template: fix positioning of diagramlegend (FairwayAvailability,AvailableFairwayDepth)
author | Fadi Abbud <fadi.abbud@intevation.de> |
---|---|
date | Mon, 20 May 2019 16:54:52 +0200 |
parents | 5a3ac4d3dbbb |
children | c0f5f62343c9 |
line wrap: on
line source
<template> <div class="overview"> <UIBoxHeader icon="clipboard-check" :title="importReviewLabel" :closeCallback="$parent.close" :actions="[{ callback: loadUpdatedLogs, icon: 'sync' }]" /> <div class="position-relative"> <UISpinnerOverlay v-if="loading" /> <div class="border-bottom p-2 d-flex justify-content-between"> <Filters></Filters> <button class="btn btn-xs btn-info" :disabled="!reviewed.length" @click="save" > <translate>Commit</translate> {{ reviewed.length }} </button> </div> <div class="p-2 d-flex align-items-center justify-content-between border-bottom" > <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(selectedInterval !== $options.LAST_HOUR) }} <template v-if="selectedInterval !== $options.TODAY"> <span class="mx-2">–</span> {{ interval[1] | dateTime(selectedInterval !== $options.LAST_HOUR) }} </template> <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.TODAY"><translate>Day</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="[ { id: 'id', title: `${idLabel}`, width: '79px' }, { id: 'kind', title: `${kindLabel}`, width: '53px' }, { id: 'enqueued', title: `${enqueuedLabel}`, width: '138px' }, { id: 'user', title: `${userLabel}`, width: '105px' }, { id: 'signer', title: `${signerLabel}`, width: '105px' }, { id: 'state', title: `${statusLabel}`, width: '72px' }, { id: 'warnings', icon: 'exclamation-triangle', width: '44px' } ]" /> <!-- For server-side sorting, etc simply don't use the sortTable filter. Instead you could just pass a function that loads the imports, like: :data="loadImports(sortColumn, sortDirection)" --> <UITableBody :data="filteredImports() | sortTable(sortColumn, sortDirection)" :isActive="item => item.id === this.show" maxHeight="70vh" > <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> </template> <style lang="sass" scoped> .spinner-overlay top: 110px </style> <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, mapGetters } from "vuex"; import { displayError, displayInfo } from "@/lib/errors"; import { STATES } from "@/store/imports"; import { sortTable } from "@/lib/mixins"; import { HTTP } from "@/lib/http"; import { startOfDay, startOfHour, endOfHour, endOfDay, addDays, subDays, format } from "date-fns"; export default { components: { Filters: () => import("./Filters"), LogEntry: () => import("./LogEntry"), LogDetail: () => import("./LogDetail") }, mixins: [sortTable], LAST_HOUR: "lasthour", TODAY: "today", LAST_7_DAYS: "lastsevendays", LAST_30_DAYS: "lastthirtydays", data() { return { loading: false, selectedInterval: this.$options.LAST_HOUR }; }, computed: { ...mapState("application", ["searchQuery"]), ...mapState("imports", [ "show", "imports", "reviewed", "startDate", "endDate", "prev", "next" ]), ...mapGetters("imports", ["filters"]), importReviewLabel() { return this.$gettext("Import review"); }, idLabel() { return this.$gettext("Id"); }, kindLabel() { return this.$gettext("Kind"); }, enqueuedLabel() { return this.$gettext("Enqueued"); }, userLabel() { return this.$gettext("User"); }, signerLabel() { return this.$gettext("Signer"); }, statusLabel() { return this.$gettext("Status"); }, interval() { return [this.startDate, this.endDate]; } }, watch: { $route() { const { id } = this.$route.params; if (id) this.showSingleRessource(id); }, selectedInterval() { this.loadUpdatedLogs(); }, imports() { if (this.imports.length == 0) { if (this.next) { const [start, end] = this.determineInterval(this.next); this.$store.commit("imports/setStartDate", start); this.$store.commit("imports/setEndDate", end); this.loadLogs(); } else if (this.prev) { const [start, end] = this.determineInterval(this.prev); this.$store.commit("imports/setStartDate", start); this.$store.commit("imports/setEndDate", end); this.loadLogs(); } } }, filters() { this.loadLogs(); } }, methods: { showSingleRessource(id) { id = id * 1; this.loadDetails(id) .then(response => { this.$store.commit("imports/setCurrentDetails", response.data); const { enqueued } = response.data; this.$store.commit("imports/setStartDate", startOfHour(enqueued)); this.$store.commit("imports/setEndDate", endOfHour(enqueued)); this.$store.commit("imports/showDetailsFor", id); this.loadLogs(); }) .catch(error => { this.loading = false; this.$store.commit("imports/setCurrentDetails", {}); const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); }, loadDetails(id) { return new Promise((resolve, reject) => { HTTP.get("/imports/" + id, { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }) .then(response => { resolve(response); }) .catch(error => { reject(error); }); }); }, determineInterval(pointInTime) { let start, end; switch (this.selectedInterval) { case this.$options.LAST_HOUR: start = startOfHour(pointInTime); end = endOfHour(pointInTime); break; case this.$options.TODAY: start = startOfDay(pointInTime); end = endOfDay(pointInTime); break; case this.$options.LAST_7_DAYS: start = startOfDay(pointInTime); end = endOfDay(addDays(start, 7)); break; case this.$options.LAST_30_DAYS: start = startOfDay(pointInTime); end = endOfDay(addDays(start, 30)); break; } return [start, end]; }, earlier() { if (!this.prev) return; const [start, end] = this.determineInterval(this.prev); this.$store.commit("imports/setStartDate", start); this.$store.commit("imports/setEndDate", end); this.loadLogs(); }, later() { if (!this.next) return; const [start, end] = this.determineInterval(this.next); this.$store.commit("imports/setStartDate", start); this.$store.commit("imports/setEndDate", end); this.loadLogs(); }, filteredImports() { return this.imports; }, loadUpdatedLogs() { const now = new Date(); switch (this.selectedInterval) { case this.$options.LAST_HOUR: this.$store.commit("imports/setStartDate", startOfHour(now)); this.$store.commit("imports/setEndDate", now); break; case this.$options.TODAY: this.$store.commit("imports/setStartDate", startOfDay(now)); this.$store.commit("imports/setEndDate", now); break; case this.$options.LAST_7_DAYS: this.$store.commit( "imports/setStartDate", subDays(startOfDay(now), 7) ); this.$store.commit("imports/setEndDate", now); break; case this.$options.LAST_30_DAYS: this.$store.commit( "imports/setStartDate", subDays(startOfDay(now), 30) ); this.$store.commit("imports/setEndDate", now); break; } this.loadLogs(); }, loadLogs() { this.loading = true; this.$store .dispatch("imports/getImports", { filter: this.filters, from: format(this.startDate, "YYYY-MM-DDTHH:mm:ss.SSS"), to: format(this.endDate, "YYYY-MM-DDTHH:mm:ss.SSS"), query: this.searchQuery }) .then(() => { if (this.show) { this.loadDetails(this.show) .then(response => { this.$store.commit("imports/setCurrentDetails", response.data); this.loading = false; }) .catch(error => { this.loading = false; this.$store.commit("imports/setCurrentDetails", {}); const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); } else { this.loading = false; } }) .catch(error => { const { status, data } = error.response; this.loading = false; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); }, save() { if (!this.reviewed.length) return; let popupContent = `<table class="table table-sm small mb-0 border-0" style="margin-top: -1px;">`; this.reviewed.forEach(r => { let imp = this.imports.find(i => i.id === r.id); let approved = STATES.APPROVED === r.status; popupContent += `<tr> <td>${imp.id}</td> <td>${imp.kind.toUpperCase()}</td> <td>${this.$options.filters.dateTime(imp.enqueued)}</td> <td class="text-${approved ? "success" : "danger"}"> ${this.$gettext(approved ? "approved" : "declined")} </td> </tr>`; }); popupContent += "</table>"; this.$store.commit("application/popup", { icon: "clipboard-check", title: this.$gettext("Finish Review"), padding: false, big: true, content: popupContent, confirm: { icon: "check", callback: () => { let data = this.reviewed.map(r => ({ id: r.id, state: r.status })); this.$store .dispatch("imports/confirmReview", data) .then(response => { this.loadLogs(); this.$store.commit("imports/setReviewed", []); const messages = response.data .map(x => { if (x.message) return x.message; if (x.error) return x.error; }) .join("\n\n"); displayInfo({ title: "Staging Area", message: messages, options: { timeout: 0, buttons: [{ text: "Ok", action: null, bold: true }] } }); }) .catch(error => { const { status, data } = error.response; displayError({ title: "Backend Error", message: `${status}: ${data.message || data}` }); }); } }, cancel: { label: this.$gettext("Cancel"), icon: "times" } }); } }, mounted() { const { id } = this.$route.params; if (id) { this.showSingleRessource(id); } else { this.$store.commit("application/searchQuery", ""); this.loadLogs(); } } }; </script>