Mercurial > gemma
changeset 2578:3ad81357a57c
overview2 WIP
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Mon, 11 Mar 2019 15:35:13 +0100 |
parents | fcb139bfa56b |
children | 5295a182b4a4 |
files | client/src/components/importoverview/ImportOverviewAlt.vue client/src/store/imports.js |
diffstat | 2 files changed, 68 insertions(+), 409 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/importoverview/ImportOverviewAlt.vue Mon Mar 11 15:09:49 2019 +0100 +++ b/client/src/components/importoverview/ImportOverviewAlt.vue Mon Mar 11 15:35:13 2019 +0100 @@ -5,350 +5,57 @@ 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"> </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="actions small condensed"> </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="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> - </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 + class="ml-2 mt-2 d-flex flex-row flex-fill justify-content-between mr-2" + > + <Filters></Filters> + <div> + <button :class="commitStyle"> + <translate>Commit</translate> {{ toCommit.length }} + </button> </div> </div> + <LogEntry v-for="entry in imports" :key="entry.id"></LogEntry> </div> </template> <script> -import { displayError } from "@/lib/errors.js"; -import { HTTP } from "@/lib/http"; +/* 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 { mapState } from "vuex"; - -const NODETAILS = -1; -const NODIFF = -1; +import { displayError } from "@/lib/errors.js"; +import { mapState, mapGetters } from "vuex"; export default { name: "importoverviewalt", - data() { - return { - showDiff: NODIFF, - importQueue: [], - logEntries: [], - show: NODETAILS, - showAdditional: NODETAILS, - showLogs: NODETAILS - }; + components: { + Filters: () => import("./Filters.vue"), + LogEntry: () => import("./LogEntry.vue") + }, + computed: { + ...mapState("imports", ["imports"]), + ...mapGetters("imports", ["toCommit"]), + commitStyle() { + return { + btn: true, + "btn-sm": true, + "btn-light": this.toCommit.length == 0, + "btn-info": this.toCommit.length > 0 + }; + } }, 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") @@ -365,81 +72,9 @@ } }, mounted() { - this.refresh(); - }, - NODETAILS: NODETAILS + this.loadLogs(); + } }; </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: 200px; - overflow-y: auto; -} - -.additionalinfo > div:hover { - background: #eee; -} - -.logentries > div:hover { - background: #eee; -} - -.details { - width: 100%; - padding: 5px; - cursor: pointer; -} - -.imports { - line-height: 0.8rem; -} - -.icons { - width: 4%; -} - -.id { - width: 10%; -} - -.kind { - width: 10%; -} - -.date { - width: 20%; -} - -.enqueued { - width: 20%; -} - -.user { - width: 10%; -} -.actions { - width: 16%; -} -</style> +<style lang="scss" scoped></style>
--- a/client/src/store/imports.js Mon Mar 11 15:09:49 2019 +0100 +++ b/client/src/store/imports.js Mon Mar 11 15:35:13 2019 +0100 @@ -24,15 +24,23 @@ REJECTED: "declined" }; +const NODETAILS = -1; +const NODIFF = -1; + // initial state const init = () => { return { + filters: [], stretches: [], imports: [], staging: [], importToReview: null, stagingVisible: true, - logsVisible: true + logsVisible: true, + show: NODETAILS, + showAdditional: NODETAILS, + showLogs: NODETAILS, + showDiff: NODIFF }; }; @@ -70,6 +78,11 @@ namespaced: true, state: init(), getters: { + toCommit: state => { + return state.imports.filter(x => { + return x.status && x.status !== STATES.NEEDSAPPROVAL; + }); + }, processedReviews: state => { return state.staging .filter(x => x.status !== STATES.NEEDSAPPROVAL) @@ -82,10 +95,20 @@ } }, mutations: { + setFilters: (state, filters) => { + state.filters = filters; + }, + clearFilters: state => { + state.filters = []; + }, setStretches: (state, stretches) => { state.stretches = stretches; }, setImports: (state, imports) => { + imports = imports.map(x => { + if (x.state === "pending") x["status"] = STATES.NEEDSAPPROVAL; + return x; + }); state.imports = imports; }, setStagingVisibility: (state, visibility) => { @@ -167,7 +190,8 @@ headers: { "X-Gemma-Auth": localStorage.getItem("token") } }) .then(response => { - commit("setImports", response.data.imports); + const { imports } = response.data; + commit("setImports", imports); resolve(response); }) .catch(error => {