Mercurial > gemma
diff client/src/components/Bottlenecks.vue @ 1558:0ded4c56978e
refac: component filestructure. remove admin/map hierarchy
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Wed, 12 Dec 2018 09:22:20 +0100 |
parents | client/src/components/map/contextbox/Bottlenecks.vue@276df8dadc14 |
children | 70421380142d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/Bottlenecks.vue Wed Dec 12 09:22:20 2018 +0100 @@ -0,0 +1,324 @@ +<template> + <div> + <h6 class="mb-0 py-2 px-3 border-bottom d-flex align-items-center"> + <font-awesome-icon icon="ship" class="mr-2"></font-awesome-icon> + <translate>Bottlenecks</translate> + </h6> + <div class="row p-2 text-left small"> + <div class="col-5"> + <a href="#" @click="sortBy('name')" class="sort-link"> + <translate>Name</translate> + </a> + <font-awesome-icon + :icon="sortIcon" + class="ml-1" + v-if="sortColumn === 'name'" + ></font-awesome-icon> + </div> + <div class="col-2"> + <a href="#" @click="sortBy('latestMeasurement')" class="sort-link"> + <translate>Latest</translate> <br /> + <translate>Measurement</translate> + </a> + <font-awesome-icon + :icon="sortIcon" + class="ml-1" + v-if="sortColumn === 'latestMeasurement'" + ></font-awesome-icon> + </div> + <div class="col-3"> + <a href="#" @click="sortBy('chainage')" class="sort-link"> + <translate>Chainage</translate> + </a> + <font-awesome-icon + :icon="sortIcon" + class="ml-1" + v-if="sortColumn === 'chainage'" + ></font-awesome-icon> + </div> + <div class="col-2"></div> + </div> + <div + class="bottleneck-list small text-left" + :style="'max-height: ' + (showSplitscreen ? 18 : 35) + 'rem'" + v-if="filteredAndSortedBottlenecks().length" + > + <div + v-for="bottleneck in filteredAndSortedBottlenecks()" + :key="bottleneck.properties.name" + class="border-top row bottleneck-row mx-0" + > + <div class="col-5 py-2 text-left"> + <a href="#" @click="selectBottleneck(bottleneck)">{{ + bottleneck.properties.name + }}</a> + </div> + <div class="col-2 py-2"> + {{ formatSurveyDate(bottleneck.properties.current) }} + </div> + <div class="col-3 py-2"> + {{ + displayCurrentChainage( + bottleneck.properties.from, + bottleneck.properties.to + ) + }} + </div> + <div class="col-2 pr-0 text-right"> + <button + type="button" + class="btn btn-sm btn-info rounded-0 h-100" + @click="loadSurveys(bottleneck.properties.name)" + v-if="bottleneck.properties.current" + > + <font-awesome-icon + icon="spinner" + fixed-width + spin + v-if="loading === bottleneck.properties.name" + ></font-awesome-icon> + <font-awesome-icon + icon="angle-down" + fixed-width + v-if=" + loading !== bottleneck.properties.name && + openBottleneck !== bottleneck.properties.name + " + ></font-awesome-icon> + <font-awesome-icon + icon="angle-up" + fixed-width + v-if=" + loading !== bottleneck.properties.name && + openBottleneck === bottleneck.properties.name + " + ></font-awesome-icon> + </button> + </div> + <div + :class="[ + 'col-12 p-0', + 'surveys', + { open: openBottleneck === bottleneck.properties.name } + ]" + > + <a + href="#" + class="d-block px-3 py-2" + v-for="(survey, index) in openBottleneckSurveys" + :key="index" + @click="selectSurvey(survey, bottleneck)" + >{{ formatSurveyDate(survey.date_info) }}</a + > + </div> + </div> + </div> + <div v-else class="small text-center py-3 border-top"> + <translate>No results.</translate> + </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 } from "vuex"; +import { HTTP } from "../lib/http"; +import { displayError } from "../lib/errors.js"; +import { formatSurveyDate } from "../lib/date.js"; + +export default { + name: "bottlenecks", + data() { + return { + sortColumn: "name", + sortDirection: "ASC", + openBottleneck: null, + openBottleneckSurveys: null, + loading: null + }; + }, + computed: { + ...mapState("application", [ + "searchQuery", + "showSearchbarLastState", + "showSplitscreen" + ]), + ...mapState("bottlenecks", ["bottlenecks"]), + sortIcon() { + return this.sortDirection === "ASC" + ? "sort-amount-down" + : "sort-amount-up"; + } + }, + methods: { + formatSurveyDate(date) { + return formatSurveyDate(date); + }, + filteredAndSortedBottlenecks() { + return this.bottlenecks + .filter(bn => { + return bn.properties.name + .toLowerCase() + .includes(this.searchQuery.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 + ) + .then(() => { + this.$store.commit("bottlenecks/selectedSurvey", survey); + }) + .then(() => { + this.$store.commit("map/moveMap", { + coordinates: bottleneck.geometry.coordinates, + zoom: 17, + preventZoomOut: true + }); + }); + }, + selectBottleneck(bottleneck) { + this.$store + .dispatch( + "bottlenecks/setSelectedBottleneck", + bottleneck.properties.name + ) + .then(() => { + this.$store.commit("bottlenecks/setFirstSurveySelected"); + }) + .then(() => { + this.$store.commit("map/moveMap", { + coordinates: bottleneck.geometry.coordinates, + zoom: 17, + preventZoomOut: true + }); + }); + }, + sortBy(column) { + this.sortColumn = column; + this.sortDirection = this.sortDirection === "ASC" ? "DESC" : "ASC"; + }, + loadSurveys(name) { + this.openBottleneckSurveys = null; + if (name === this.openBottleneck) { + this.openBottleneck = null; + } else { + this.openBottleneck = name; + this.loading = 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.sort((a, b) => { + return a.date_info < b.date_info ? 1 : -1; + }); + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: this.$gettext("Backend Error"), + message: `${status}: ${data.message || data}` + }); + }) + .finally(() => (this.loading = null)); + } + }, + displayCurrentChainage(from, to) { + return from / 10 + " - " + to / 10; + } + }, + mounted() { + this.$store.dispatch("bottlenecks/loadBottlenecks"); + } +}; +</script> + +<style lang="scss" scoped> +.bottleneck-list { + overflow-y: auto; +} + +.bottleneck-list .bottleneck-row a { + text-decoration: none; +} + +.bottleneck-list .bottleneck-row:hover { + background: #fbfbfb; +} + +.surveys { + max-height: 0; + min-height: 0; + overflow: hidden; +} + +.surveys a:hover { + background: #f3f3f3; +} + +.surveys.open { + max-height: 250px; + overflow: auto; +} + +.sort-link { + color: #444; + font-weight: bold; +} +</style>