Mercurial > gemma
diff client/src/application/Search.vue @ 1196:a397b52981b8
html cleanup
got rid of Topbar.vue to avoid unnecessary component nesting
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Mon, 19 Nov 2018 08:24:47 +0100 |
parents | |
children | 37889ae85133 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/application/Search.vue Mon Nov 19 08:24:47 2018 +0100 @@ -0,0 +1,197 @@ +<template> + <div :class="searchbarContainerStyle"> + <div class="input-group-prepend shadow"> + <span @click="toggleSearchbar" :class="searchButtonStyle" for="search"> + <i class="fa fa-search d-print-none"></i> + </span> + </div> + <div class="searchgroup flex-fill"> + <input + @keyup.enter="takeFirstSearchresult" + v-if="showSearchbar" + id="search" + v-model="searchQuery" + type="text" + class="form-control ui-element search searchbar d-print-none" + > + <ul v-if="showSearchbar && searchResults !== null " class="list-group d-print-none"> + <li v-for="entry of searchResults" :key="entry.name" class="list-group-item"> + <a href="#" @click.prevent="moveToSearchResult(entry)">{{entry.name}}</a> + </li> + </ul> + </div> + </div> +</template> + +<style lang="sass" scoped> + .searchcontainer + height: $icon-height + border-radius: 0.25rem + + .searchbar-expanded + margin-left: auto + margin-right: auto + padding-left: $offset + width: $searchbar-width !important + .searchbar + border-top-left-radius: 0 !important + border-bottom-left-radius: 0 !important + + + .searchbar-collapsed + margin-left: auto + width: $icon-width !important + transition: $transition-fast + + .searchbar + margin-left: auto + margin-right: auto + height: $icon-height !important + + .searchlabel + background-color: white !important + + .input-group-text + height: $icon-height + width: $icon-width + + .list-group + pointer-events: auto +</style> + +<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 debounce from "lodash.debounce"; +import { mapState } from "vuex"; + +import { displayError } from "../application/lib/errors.js"; +import { HTTP } from "../application/lib/http"; + +const setFocus = () => document.querySelector("#search").focus(); + +export default { + name: "search", + data() { + return { + searchQuery: "", + searchQueryIsDirty: false, + searchResults: null, + isSearching: false + }; + }, + computed: { + ...mapState("application", ["showSearchbar"]), + searchIndicator: function() { + if (this.isSearching) { + return "⟳"; + } else if (this.searchQueryIsDirty) { + return ""; + } else { + return "✓"; + } + }, + searchbarContainerStyle() { + return [ + "d-flex input-group searchcontainer", + { + "searchbar-collapsed": !this.showSearchbar, + "searchbar-expanded": this.showSearchbar + } + ]; + }, + searchButtonStyle() { + return [ + "ui-element input-group-text p-0 d-flex justify-content-center searchlabel d-print-none", + { + rounded: !this.showSearchbar, + "rounded-left": this.showSearchbar + } + ]; + } + }, + watch: { + searchQuery: function() { + this.searchQueryIsDirty = true; + this.triggerSearch(); + } + }, + methods: { + takeFirstSearchresult() { + if (!this.searchResults || this.searchResults.length != 1) return; + this.moveToSearchResult(this.searchResults[0]); + }, + triggerSearch: debounce(function() { + this.doSearch(); + }, 500), + doSearch() { + this.isCalculating = true; + this.searchResults = null; + + if (this.searchQuery == "") { + return; + } + + HTTP.post( + "/search", + { string: this.searchQuery }, + { + headers: { + "X-Gemma-Auth": localStorage.getItem("token"), + "Content-type": "text/xml; charset=UTF-8" + } + } + ) + .then(response => { + // console.log("got:", response.data); + this.searchResults = response.data; + }) + .catch(error => { + const { status, data } = error.response; + displayError({ + title: "Backend Error", + message: `${status}: ${data.message || data}` + }); + }); + + this.isCalculating = false; + this.searchQueryIsDirty = false; + }, + moveToSearchResult(resultEntry) { + // DEBUG console.log("Moving to", resultEntry); + if (resultEntry.geom.type == "Point") { + let zoom = 11; + if (resultEntry.type === "bottleneck") zoom = 17; + if (resultEntry.type === "rhm") zoom = 15; + if (resultEntry.type === "city") zoom = 13; + + this.$store.commit("map/moveMap", { + coordinates: resultEntry.geom.coordinates, + zoom, + preventZoomOut: true + }); + } + // this.searchQuery = ""; // clear search query again + this.toggleSearchbar(); + }, + toggleSearchbar() { + if (!this.showSearchbar) { + setTimeout(setFocus, 300); + } + this.$store.commit("application/showSearchbar", !this.showSearchbar); + } + } +}; +</script>