view client/src/bottlenecks/Bottlenecks.vue @ 1087:8ae18a8d000e

removed debug console.log
author Markus Kottlaender <markus@intevation.de>
date Mon, 29 Oct 2018 15:36:11 +0100
parents 9361f39c5f68
children dbf0221b1cf1
line wrap: on
line source

<template>
    <div :class="bottlenecksStyle" :style="'left: ' + (sidebarCollapsed ? '64px' : '17rem')">
        <div @click="$store.commit('application/toggleBottlenecks');" 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="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 bottleneck-list">
                <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>
                        </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>
</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",
      selectedBottleneck: null,
      surveys: {}
    };
  },
  computed: {
    ...mapState("application", ["bottlenecksCollapsed"]),
    ...mapState("bottlenecks", ["bottlenecks"]),
    ...mapState("mapstore", ["openLayersMap"]),
    ...mapGetters("application", ["sidebarCollapsed"]),
    bottlenecksStyle() {
      return {
        "ui-element": true,
        bottlenecks: true,
        overlay: true,
        bottleneckscollapsed: this.bottlenecksCollapsed,
        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: {
    selectSurvey(survey) {
      this.$store.commit("fairwayprofile/setSelectedMorph", survey);
      this.$store.commit("fairwayprofile/setAvailableSurveys", {surveys: this.surveys[this.selectedBottleneck.name] });
      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();
        const newZoom = Math.max(17, currentZoom);
        view.animate(
          {
            zoom: newZoom,
            center: fromLonLat(
              bottleneck.geom.coordinates,
              view.getProjection()
            )
          },
          700
        );
      }
    },
    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() {
    this.$store.dispatch("bottlenecks/loadBottlenecks");
  }
};
</script>

<style lang="scss">
.bottlenecks {
  position: absolute;
  z-index: -2;
  top: $offset;
  background-color: #ffffff;
  padding-top: $offset;
  opacity: $slight-transparent;
  border-radius: $border-radius;
  transition: left .3s ease;
  overflow: hidden;
  background: #fff;
}

.bottleneckscollapsed {
  width: 0;
  height: 0;
  transition: $transition-fast;
}

.bottlenecksextended {
  width: 500px;
}

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