Mercurial > gemma
view client/src/bottlenecks/Bottlenecks.vue @ 1143:846e336d8ee5
merge
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Mon, 12 Nov 2018 15:00:45 +0100 |
parents | dc3f0277628a 2fda33d55d81 |
children | 5f98d0c9d738 |
line wrap: on
line source
<template> <div :class="bottlenecksStyle" :style="'left: ' + (showSidebar ? '17rem' : '64px')"> <div @click="$store.commit('application/showBottlenecks', !showBottlenecks);" class="ui-element close-bottlenecks"> <i class="fa fa-close"></i> </div> <h4>Bottlenecks</h4> <hr class="mb-0"> <input type="text" v-model="search" placeholder="Search Bottleneck..." class="border-0 w-100 p-2" /> <div class="row p-2 border-top text-left small"> <div class="col-5"> <a href="#" @click="sortBy('name')" class="sort-link">Name</a> <i :class="sortClass" v-if="sortColumn === 'name'"></i> </div> <div class="col-2"> <a href="#" @click="sortBy('latestMeasurement')" class="sort-link">Latest Measurement</a> <i :class="sortClass" v-if="sortColumn === 'latestMeasurement'"></i> </div> <div class="col-3"> <a href="#" @click="sortBy('chainage')" class="sort-link">Chainage</a> <i :class="sortClass" v-if="sortColumn === 'chainage'"></i> </div> <div class="col-2"></div> </div> <div class="bottleneck-list small text-left"> <div v-for="bottleneck in filteredAndSortedBottlenecks()" :key="bottleneck.properties.name" class="border-top row mx-0 py-2"> <div class="col-5 text-left"> <a href="#" class="d-block" @click="moveToBottleneck(bottleneck)"> {{ bottleneck.properties.name }} </a> </div> <div class="col-2"> {{ displayCurrentSurvey(bottleneck.properties.current) }} </div> <div class="col-3"> {{ displayCurrentChainage(bottleneck.properties.from, bottleneck.properties.from) }} </div> <div class="col-2 text-right"> <button type="button" class="btn btn-sm btn-outline-secondary" @click="toggleBottleneck(bottleneck.properties.name)"> <i class="fa fa-angle-down"></i> </button> </div> <div :class="['col-12', 'surveys', {open: openBottleneck === bottleneck.properties.name}]"> <a href="#" class="d-block p-2" v-for="(survey, index) in openBottleneckSurveys" :key="index" @click="selectSurvey(survey, bottleneck)"> {{ survey.date_info }} </a> </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): * Markus Kottländer <markus.kottlaender@intevation.de> */ import { mapState, mapGetters } from "vuex"; import { fromLonLat } from "ol/proj"; import { HTTP } from "../application/lib/http"; import { displayError } from "../application/lib/errors.js"; export default { name: "bottlenecks", data() { return { search: "", sortColumn: "name", sortDirection: "ASC", openBottleneck: null, openBottleneckSurveys: null }; }, computed: { ...mapState("application", ["showBottlenecks", "showSidebar"]), ...mapState("bottlenecks", ["bottlenecks"]), ...mapState("map", ["openLayersMap"]), bottlenecksStyle() { return { "ui-element": true, bottlenecks: true, overlay: true, bottleneckscollapsed: !this.showBottlenecks, bottlenecksextended: this.showBottlenecks, shadow: true }; }, sortClass() { return { fa: true, "fa-sort-amount-asc": this.sortDirection === "ASC", "fa-sort-amount-desc": this.sortDirection === "DESC", "ml-1": true }; } }, methods: { filteredAndSortedBottlenecks() { return this.bottlenecks .filter(bn => { return bn.properties.name .toLowerCase() .includes(this.search.toLowerCase()); }) .sort((bnA, bnB) => { switch (this.sortColumn) { case "name": if ( bnA.properties.name.toLowerCase() < bnB.properties.name.toLowerCase() ) return this.sortDirection === "ASC" ? -1 : 1; if ( bnA.properties.name.toLowerCase() > bnB.properties.name.toLowerCase() ) return this.sortDirection === "ASC" ? 1 : -1; return 0; case "latestMeasurement": { if ( (bnA.properties.current || "") < (bnB.properties.current || "") ) return this.sortDirection === "ASC" ? -1 : 1; if ( (bnA.properties.current || "") > (bnB.properties.current || "") ) return this.sortDirection === "ASC" ? 1 : -1; return 0; } case "chainage": if (bnA.properties.from < bnB.properties.from) return this.sortDirection === "ASC" ? -1 : 1; if (bnA.properties.from > bnB.properties.from) return this.sortDirection === "ASC" ? 1 : -1; return 0; default: return 0; } }); }, selectSurvey(survey, bottleneck) { this.$store.dispatch( "bottlenecks/setSelectedBottleneck", bottleneck.properties.name ); this.$store.commit("bottlenecks/setSelectedSurvey", survey); this.moveToBottleneck(bottleneck); }, moveToBottleneck(bottleneck) { // TODO: make this central, duplicates code from application/Topbar.vue let view = this.openLayersMap.getView(); const currentZoom = view.getZoom(); const newZoom = Math.max(17, currentZoom); view.animate( { zoom: newZoom, center: fromLonLat( bottleneck.geometry.coordinates, view.getProjection() ) }, 700 ); }, sortBy(column) { this.sortColumn = column; this.sortDirection = this.sortDirection === "ASC" ? "DESC" : "ASC"; }, toggleBottleneck(name) { this.openBottleneckSurveys = null; if (name === this.openBottleneck) { this.openBottleneck = null; } else { this.openBottleneck = name; HTTP.get("/surveys/" + name, { headers: { "X-Gemma-Auth": localStorage.getItem("token"), "Content-type": "text/xml; charset=UTF-8" } }) .then(response => { this.openBottleneckSurveys = response.data.surveys; }) .catch(error => { const { status, data } = error.response; displayError({ title: "Backend Error", message: `${status}: ${data.message || data}` }); }); } }, displayCurrentSurvey(current) { return current ? current.substr(0, current.length - 1) : ""; }, displayCurrentChainage(from, to) { return from / 10 + " - " + to / 10; } }, mounted() { this.$store.dispatch("bottlenecks/loadBottlenecks"); } }; </script> <style lang="scss" scoped> .bottlenecks { position: absolute; z-index: -2; top: $offset; background-color: #ffffff; padding-top: $offset; opacity: $slight-transparent; border-radius: $border-radius; transition: left 0.3s ease; overflow: hidden; background: #fff; } .bottleneckscollapsed { width: 0; height: 0; transition: $transition-fast; } .bottlenecksextended { width: 600px; } .close-bottlenecks { position: absolute; z-index: 2; right: 0; top: 7px; border-radius: $border-radius; height: $icon-width; width: $icon-height; display: none; } .bottlenecksextended .close-bottlenecks { display: block; } .bottleneck-list { overflow-y: auto; max-height: 500px; } .surveys { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } .surveys.open { max-height: 999px; } .sort-link { color: #444; font-weight: bold; } </style>