Mercurial > gemma
view client/src/components/importoverview/importlogs/LogDetail.vue @ 2625:fd93babdf8e6
client: popup: made content padding optional (for full-width tables)
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Wed, 13 Mar 2019 16:24:35 +0100 |
parents | 9b7138751f5b |
children |
line wrap: on
line source
<template> <div class="entry d-flex flex-column py-1 border-bottom"> <div class="d-flex flex-row position-relative"> <small @click="showDetails(job.id)" class="jobid ml-2 mt-1 mr-2"> {{ job.id }} </small> <small @click="showDetails(job.id)" class="enqueued mt-1 mr-2"> {{ formatDateTime(job.enqueued) }} </small> <small @click="showDetails(job.id)" class="kind mt-1 mr-2"> {{ job.kind.toUpperCase() }} </small> <small @click="showDetails(job.id)" class="user mt-1 mr-2"> {{ job.user }} </small> <small @click="showDetails(job.id)" class="signer mt-1 mr-2"> {{ job.signer }} </small> <small @click="showDetails(job.id)" class="state mt-1 mr-2"> <span :class="{ 'text-danger': job.state.toUpperCase() == 'FAILED' }" >{{ job.state }}<font-awesome-icon v-if="job.warnings" class="ml-1 text-warning" icon="exclamation-triangle" fixed-width ></font-awesome-icon> </span> <span v-if="!job.warnings" style="margin-right: 1.6em;"></span> </small> <div @click="showDetails(job.id)" class="mt-1 text-info detailsbutton"> <font-awesome-icon class="pointer" v-if="show" icon="angle-up" fixed-width ></font-awesome-icon> <font-awesome-icon class="pointer" v-if="loading" icon="spinner" fixed-width ></font-awesome-icon> <font-awesome-icon class="pointer" v-if="!show && !loading" icon="angle-down" fixed-width ></font-awesome-icon> </div> </div> <div class="detailstable d-flex flex-row"> <div :class="collapse"> <div class="text-left"> <small style="margin-right:10px" class="type condensed" ><translate>Kind</translate></small > <a href="#" @click="sortAsc = !sortAsc" style="margin-right:58px" class="datetime sort-link" ><small class="condensed"><translate>Date</translate></small> <small class="message condensed" ><font-awesome-icon :icon="sortIcon" class="ml-1" ></font-awesome-icon></small ></a> <small class="condensed"><translate>Message</translate></small> </div> <div class="logentries"> <div v-for="(entry, index) in sortedEntries" :key="index" class="detailsrow text-left" > <small :class="[ 'condensed type', { 'text-danger': entry.kind.toUpperCase() == 'ERROR', 'text-warning': entry.kind.toUpperCase() == 'WARN' } ]" >{{ entry.kind.toUpperCase() }}</small > <small :class="[ 'condensed datetime', { 'text-danger': entry.kind.toUpperCase() == 'ERROR', 'text-warning': entry.kind.toUpperCase() == 'WARN' } ]" >{{ formatDateTime(entry.time) }}</small > <small :class="[ 'condensed message', { 'text-danger': entry.kind.toUpperCase() == 'ERROR', 'text-warning': entry.kind.toUpperCase() == 'WARN' } ]" >{{ entry.message }}</small > </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): * Thomas Junk <thomas.junk@intevation.de> */ import { HTTP } from "@/lib/http.js"; import { displayError } from "@/lib/errors.js"; import locale2 from "locale2"; export default { name: "importqueuedetail", props: ["job", "reload"], data() { return { loading: false, show: false, entries: [], sortAsc: true }; }, mounted() { this.openSpecificDetail(); }, watch: { $route() { this.openSpecificDetail(); }, reload() { if (this.reload) { this.entries = []; this.show = false; } } }, methods: { openSpecificDetail() { const { id } = this.$route.params; if (id == this.job.id) { this.showDetails(id); } else { this.show = false; } }, formatDate(date) { return date ? new Date(date).toLocaleDateString(locale2, { day: "2-digit", month: "2-digit", year: "numeric" }) : ""; }, formatDateTime(date) { if (!date) return ""; const d = new Date(date); return ( d.toLocaleDateString(locale2, { day: "2-digit", month: "2-digit", year: "numeric" }) + " - " + d.toLocaleTimeString(locale2, { hour12: false }) ); }, showDetails(id) { if (this.show) { this.show = false; return; } if (this.entries.length === 0) { this.loading = true; HTTP.get("/imports/" + id, { headers: { "X-Gemma-Auth": localStorage.getItem("token") } }) .then(response => { const { entries } = response.data; this.entries = entries; this.show = true; this.loading = false; }) .catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); } else { this.show = true; } } }, computed: { sortedEntries() { let sorted = this.entries.slice(); sorted.sort((r1, r2) => { let d1 = new Date(r1.time); let d2 = new Date(r2.time); if (d2 < d1) { return !this.sortAsc ? -1 : 1; } if (d2 > d1) { return !this.sortAsc ? 1 : -1; } return 0; }); return sorted; }, sortIcon() { return this.sortAsc ? "sort-amount-down" : "sort-amount-up"; }, icon() { return { "angle-up": !this.show, "angle-down": this.show }; }, collapse() { return { details: true, collapse: true, show: this.show, "w-100": true }; } } }; </script> <style lang="scss" scoped> .logentries { overflow: auto; } .condensed { font-stretch: condensed; } .entry { background-color: white; cursor: pointer; width: 100%; } .entry:hover { background-color: #efefef; transition: 1.6s; } .detailstable { margin-left: $offset; margin-right: $large-offset; } .detailsbutton { position: absolute; top: 0; right: 0; height: 100%; } .jobid { width: 5%; } .user { width: 15%; } .signer { width: 15%; } .kind { width: 10%; } .state { width: 15%; } .details { width: 50%; } .detailsrow { line-height: 0.7rem; } .type { white-space: nowrap; } .datetime { white-space: nowrap; padding-left: 10px; padding-right: 10px; } .message { white-space: nowrap; } </style>