view client/src/bottlenecks/Bottlenecks.vue @ 1207:70116d392387

close bottleneck list: made searchbar collapse only if it was collapsed before opening the bottleneck list will expand the searchbar, closing the bottleneck list was always collapsing the searchbar too. Now it stays open if it was open beforeopening the bottleneck list
author Markus Kottlaender <markus@intevation.de>
date Mon, 19 Nov 2018 13:02:48 +0100
parents ddfdf440da24
children 8df4ebbc5c3f
line wrap: on
line source

<template>
    <div :class="bottlenecksStyle">
        <div @click="closeBottlenecks" class="ui-element close-bottlenecks">
            <i class="fa fa-close"></i>
        </div>

        <h4>Bottlenecks</h4>
        <hr class="mb-0">
        <div class="row p-2 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 } from "vuex";
import { HTTP } from "../application/lib/http";
import { displayError } from "../application/lib/errors.js";

export default {
  name: "bottlenecks",
  data() {
    return {
      sortColumn: "name",
      sortDirection: "ASC",
      openBottleneck: null,
      openBottleneckSurveys: null
    };
  },
  computed: {
    ...mapState("application", [
      "showBottlenecks",
      "showSidebar",
      "searchQuery",
      "showSearchbarLastState"
    ]),
    ...mapState("bottlenecks", ["bottlenecks"]),
    ...mapState("map", ["openLayersMap"]),
    bottlenecksStyle() {
      return [
        "ui-element shadow bottlenecks border-top",
        {
          bottleneckscollapsed: !this.showBottlenecks,
          bottlenecksextended: this.showBottlenecks
        }
      ];
    },
    sortClass() {
      return [
        "fa ml-1",
        {
          "fa-sort-amount-asc": this.sortDirection === "ASC",
          "fa-sort-amount-desc": this.sortDirection === "DESC"
        }
      ];
    }
  },
  methods: {
    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
      );
      this.$store.commit("bottlenecks/setSelectedSurvey", survey);
      this.moveToBottleneck(bottleneck);
    },
    moveToBottleneck(bottleneck) {
      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";
    },
    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}`
            });
          });
      }
    },
    closeBottlenecks() {
      this.$store.commit("application/showBottlenecks", false);
      this.$store.commit("application/showSearchbar", this.showSearchbarLastState);
    },
    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="sass" scoped>
.bottlenecks
  position: relative
  background-color: #ffffff
  padding-top: $offset
  opacity: $slight-transparent
  border-bottom-left-radius: $border-radius
  border-bottom-right-radius: $border-radius
  transition: left 0.3s ease
  overflow: hidden
  background: #fff
  margin-left: $offset

.bottleneckscollapsed
  width: 0
  height: 0
  transition: $transition-fast

.bottlenecksextended
  min-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>