Mercurial > gemma
view client/src/components/staging/StagingDetail.vue @ 2037:11cb57f85c60 unify_imports
Merged default into branch.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Fri, 25 Jan 2019 11:53:28 +0100 |
parents | a8d8e855cb26 |
children | e9879eb7e965 |
line wrap: on
line source
<template> <div :class="detail"> <div class="d-flex flex-row"> <div class="mt-auto d-flex flex-row mb-auto small name text-left"> <a v-if="isSoundingResult(data.kind.toUpperCase())" @click="zoomTo()" href="#" >{{ data.summary.bottleneck }}</a > <span v-if="isBottleneck(data.kind.toUpperCase())" class="text-left" ><translate>Bottlenecks</translate> ({{ data.summary.bottlenecks.length }})</span > <span v-if="isFairwayDimension(data.kind.toUpperCase())" >{{ data.summary["source-organization"] }} (LOS: {{ data.summary.los }})</span > </div> <div class="mt-auto mb-auto small text-left type"> {{ data.kind.toUpperCase() }} </div> <div v-if="data.summary" class="mt-auto mb-auto small text-left date"> {{ formatSurveyDate(data.summary.date) }} </div> <div v-else class="mt-auto mb-auto small text-left date">-</div> <div class="mt-auto mb-auto small text-left imported"> {{ formatSurveyDate(data.enqueued.split("T")[0]) }} </div> <div class="mt-auto mb-auto small text-left username"> {{ data.user }} </div> <div class="controls d-flex flex-row justify-content-end"> <div> <button :class="{ 'ml-3': true, 'mr-3': true, btn: true, 'btn-sm': true, 'btn-outline-success': needsApproval(data) || isRejected(data), 'btn-success': isApproved(data) }" @click="toggleApproval(data.id, $options.STATES.APPROVED)" > <font-awesome-icon icon="check"></font-awesome-icon> </button> </div> <div> <button :class="{ 'mr-3': true, btn: true, 'btn-sm': true, 'btn-outline-danger': needsApproval(data) || isApproved(data), 'btn-danger': isRejected(data) }" @click="toggleApproval(data.id, $options.STATES.REJECTED)" > <font-awesome-icon icon="times"></font-awesome-icon> </button> </div> <div v-if="isBottleneck(data.kind.toUpperCase())"> <div @click="showDetails()" class="mt-auto mb-auto text-info text-left" > <font-awesome-icon v-if="show" icon="angle-up" fixed-width ></font-awesome-icon> <font-awesome-icon v-if="loading" icon="spinner" fixed-width ></font-awesome-icon> <font-awesome-icon v-if="!show && !loading" icon="angle-down" fixed-width ></font-awesome-icon> </div> </div> <div v-else class="empty"></div> </div> </div> <div v-for="(bottleneck, index) in bottlenecks" :key="index" class="d-flex flex-row" v-if="show && bottlenecks.length > 0" > <div class="d-flex flex-column"> <div class="d-flex flex-row"> <a @click="moveToBottleneck(index)" class="small" href="#">{{ bottleneck.properties.objnam }}</a> <div @click="showFull = !showFull" class="small mt-auto mb-auto text-info text-left" > <font-awesome-icon v-if="showFull" icon="angle-up" fixed-width ></font-awesome-icon> <font-awesome-icon v-if="!showFull" icon="angle-down" fixed-width ></font-awesome-icon> </div> </div> <div class="d-flex flex-row" v-if="showFull"> <table> <tr v-for="(info, index) in Object.keys(bottleneck.properties)" :key="index" class="mr-1 small text-muted" > <td class="condensed text-left">{{ info }}</td> <td class="condensed pl-3 text-left"> {{ bottleneck.properties[info] }} </td> </tr> </table> </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 { formatSurveyDate } from "@/lib/date.js"; import { STATES } from "@/store/imports.js"; import { HTTP } from "@/lib/http"; import { WFS } from "ol/format.js"; import { or as orFilter, equalTo as equalToFilter } from "ol/format/filter.js"; import { displayError } from "@/lib/errors.js"; import { mapState } from "vuex"; import center from "@turf/center"; export default { name: "stagingdetail", props: ["data"], data() { return { showFull: false, show: false, loading: false, bottlenecks: [] }; }, mounted() { this.bottlenecks = []; if (this.open) this.showDetails(); }, computed: { ...mapState("imports", ["importToReview"]), open() { return this.importToReview == this.data.id; }, detail() { return [ "pb-2", "pt-2", "d-flex", "flex-column", "w-100", { highlight: this.open && this.needsApproval(this.data) } ]; } }, watch: { open() { const { review } = this.$route.query; if (review) { this.showDetails(); } } }, methods: { showDetails() { if (this.data.kind.toUpperCase() !== "BN") return; if (this.show) { this.show = false; return; } if (this.bottlenecks.length > 0) { this.show = true; return; } this.loading = true; const generateFilter = () => { const { bottlenecks } = this.data.summary; if (bottlenecks.length === 1) return equalToFilter("bottleneck_id", bottlenecks[0]); const orExpressions = bottlenecks.map(x => { equalToFilter("bottleneck_id", x); }); return orFilter(...orExpressions); }; const filterExpression = generateFilter(); const bottleneckFeatureCollectionRequest = new WFS().writeGetFeature({ srsName: "EPSG:4326", featureNS: "gemma", featurePrefix: "gemma", featureTypes: ["bottlenecks"], outputFormat: "application/json", filter: filterExpression }); HTTP.post( "/internal/wfs", new XMLSerializer().serializeToString( bottleneckFeatureCollectionRequest ), { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } } ) .then(response => { this.bottlenecks = response.data.features; this.show = true; this.loading = false; }) .catch(error => { const { status, data } = error.response; displayError({ title: this.$gettext("Backend Error"), message: `${status}: ${data.message || data}` }); }); }, isFairwayDimension(kind) { return kind === "FD"; }, isBottleneck(kind) { return kind === "BN"; }, isSoundingResult(kind) { return kind === "SR"; }, formatSurveyDate(date) { return formatSurveyDate(date); }, needsApproval(item) { return item.status === STATES.NEEDSAPPROVAL; }, isRejected(item) { return item.status === STATES.REJECTED; }, isApproved(item) { return item.status === STATES.APPROVED; }, moveToBottleneck(index) { const { coordinates } = center(this.bottlenecks[index]).geometry; this.moveMap(coordinates); }, moveMap(coordinates) { this.$store.commit("map/moveMap", { coordinates: coordinates, zoom: 17, preventZoomOut: true }); }, zoomTo() { const { lat, lon, bottleneck, date } = this.data.summary; const coordinates = [lat, lon]; this.moveMap(coordinates); this.$store .dispatch("bottlenecks/setSelectedBottleneck", bottleneck) .then(() => { this.$store.commit("bottlenecks/setSelectedSurveyByDate", date); }); }, toggleApproval(id, newStatus) { this.$store.commit("imports/toggleApproval", { id: id, newStatus: newStatus }); } }, STATES: STATES }; </script> <style lang="scss" scoped> .highlight { background-color: #f9f9f9; } .condensed { font-stretch: condensed; } .empty { margin-right: 20px; } .name { width: 180px; } .date { width: 90px; } .type { width: 40px; } .imported { width: 90px; } .username { width: 150px; } .controls { width: 60px; } </style>