Mercurial > gemma
changeset 1077:c58608084c11
finished bottleneck list (search, sort, sounding data)
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Fri, 26 Oct 2018 14:04:37 +0200 |
parents | 12312fb1cda2 |
children | 2ed3b4eaaab4 |
files | client/src/bottlenecks/Bottlenecks.vue |
diffstat | 1 files changed, 115 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/bottlenecks/Bottlenecks.vue Fri Oct 26 10:05:20 2018 +0200 +++ b/client/src/bottlenecks/Bottlenecks.vue Fri Oct 26 14:04:37 2018 +0200 @@ -1,23 +1,45 @@ <template> - <div :class="bottlenecksStyle"> + <div :class="bottlenecksStyle" style="overflow: hidden; background: #fff;"> <div @click="$store.commit('application/toggleBottlenecks');" class="ui-element close-bottlenecks"> <i class="fa fa-close"></i> </div> - <div v-if="!this.bottlenecksCollapsed"> - <h4>Bottlenecks</h4> - <hr class="mb-0"> - <div style="max-height: 500px; overflow-y: scroll"> - <table class="table text-left mb-0" style="margin-top: -1px;"> - <tr v-for="(bottleneck) in bottlenecks" - :key="bottleneck.name"> - <td> + <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="bottleneck-table d-flex flex-column"> + <div class="d-flex flex-row p-2 border-top"> + <div> + <a href="#" @click="sortBy('name')" class="sort-link">Name</a> + <i :class="sortClass" v-if="sortColumn === 'name'"></i> + </div> + <!--<div> + <a href="#" @click="sortBy('latestMeasurement')">Latest Measurement</a> + <i :class="sortClass" v-if="sortColumn === 'latestMeasurement'"></i> + </div>--> + <div></div> + </div> + <div class="d-flex flex-column"> + <div v-for="bottleneck in filteredAndSortedBottlenecks" :key="bottleneck.name" class="border-top"> + <div class="d-flex flex-row justify-content-between p-2"> + <div> <a href="#" class="d-block" @click="moveToBottleneck(bottleneck)"> {{ bottleneck.name }} </a> - </td> - </tr> - </table> + </div> + <!--<td>2018-10-25</td>--> + <div class="text-right"> + <button type="button" class="btn btn-sm btn-outline-secondary" @click="queryBottleneck(bottleneck)"> + <i class="fa fa-angle-down"></i> + </button> + </div> + </div> + <div :class="['surveys', {open: selectedBottleneck === bottleneck}]"> + <a href="#" class="d-block p-2 border-top" v-for="(survey, index) in surveys[bottleneck.name]" :key="index" @click="selectSurvey(survey)"> + {{ survey.date_info }} + </a> + </div> + </div> </div> </div> </div> @@ -40,9 +62,20 @@ */ import { mapState } 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", + selectedBottleneck: null, + surveys: {} + }; + }, computed: { ...mapState("application", ["bottlenecksCollapsed"]), ...mapState("bottlenecks", ["bottlenecks"]), @@ -56,11 +89,41 @@ bottlenecksextended: !this.bottlenecksCollapsed, shadow: true }; + }, + filteredAndSortedBottlenecks() { + return this.bottlenecks + .filter(bn => { + return bn.name.toLowerCase().includes(this.search.toLowerCase()); + }) + .sort((bnA, bnB) => { + switch (this.sortColumn) { + case "name": + if (bnA.name.toLowerCase() < bnB.name.toLowerCase()) + return this.sortDirection === "ASC" ? -1 : 1; + if (bnA.name.toLowerCase() > bnB.name.toLowerCase()) + return this.sortDirection === "ASC" ? 1 : -1; + return 0; + default: + return 0; + } + }); + }, + sortClass() { + return { + fa: true, + "fa-sort-amount-asc": this.sortDirection === "ASC", + "fa-sort-amount-desc": this.sortDirection === "DESC", + "ml-1": true + }; } }, methods: { - // TODO: make this central, duplicates code from application/Topbar.vue + selectSurvey(survey) { + this.$store.commit("fairwayprofile/setSelectedMorph", survey); + this.moveToBottleneck(this.selectedBottleneck); + }, moveToBottleneck(bottleneck) { + // TODO: make this central, duplicates code from application/Topbar.vue if (bottleneck.geom.type == "Point") { let view = this.openLayersMap.getView(); const currentZoom = view.getZoom(); @@ -77,6 +140,30 @@ ); } this.$store.commit("application/toggleBottlenecks"); + }, + sortBy(column) { + this.sortColumn = column; + this.sortDirection = this.sortDirection === "ASC" ? "DESC" : "ASC"; + }, + queryBottleneck(bottleneck) { + HTTP.get("/surveys/" + bottleneck.name, { + headers: { + "X-Gemma-Auth": localStorage.getItem("token"), + "Content-type": "text/xml; charset=UTF-8" + } + }) + .then(response => { + this.surveys[bottleneck.name] = response.data.surveys; + this.selectedBottleneck = + this.selectedBottleneck === bottleneck ? null : bottleneck; + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: "Backend Error", + message: `${status}: ${data.message || data}` + }); + }); } }, mounted() { @@ -104,7 +191,6 @@ } .bottlenecksextended { - min-height: $sidebar-height; width: 500px; } @@ -122,4 +208,19 @@ .bottlenecksextended .close-bottlenecks { display: block; } + +.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>