Mercurial > gemma
view client/src/components/map/Search.vue @ 1441:a4554e942954
Client: add a set of marked translations
* add a number of marked translatios in javascript part of some .vue files
* generate the corresponding .po files and translation.json file
* add some examples translations for ImportSoundingresults.vue
author | Fadi Abbud <fadi.abbud@intevation.de> |
---|---|
date | Fri, 30 Nov 2018 13:09:40 +0100 |
parents | c8fe86d1c270 |
children | bb47531bdd22 |
line wrap: on
line source
<template> <div :class="searchbarContainerStyle"> <div class="input-group-prepend m-0 d-print-none"> <span @click="toggleSearchbar" :class="searchButtonStyle" for="search"> <font-awesome-icon icon="search"></font-awesome-icon> </span> </div> <div :class="['searchgroup', {'searchgroup-collapsed': !showSearchbar, big: showContextBox && ['bottlenecks', 'staging'].indexOf(contextBoxContent) !== -1 }]"> <input @keyup.enter="takeFirstSearchresult" id="search" v-model="searchQuery" type="text" :class="searchInputStyle" > </div> <div v-if="showSearchbar && searchResults !== null && !showContextBox" class="searchresults border-top ui-element bg-white rounded-bottom d-print-none position-absolute" > <div v-for="entry of searchResults" :key="entry.name" class="border-top text-left"> <a href="#" @click.prevent="moveToSearchResult(entry)" class="p-2 d-block text-nowrap"> <font-awesome-icon icon="ship" v-if="entry.type === 'bottleneck'" class="mr-1" fixed-width /> <font-awesome-icon icon="water" v-if="entry.type === 'rhm'" class="mr-1" fixed-width/> <font-awesome-icon icon="city" v-if="entry.type === 'city'" class="mr-1" fixed-width/> {{ entry.name }} </a> </div> </div> </div> </template> <style lang="sass" scoped> .searchcontainer opacity: $slight-transparent .searchbar border-top-left-radius: 0 !important border-bottom-left-radius: 0 !important .searchgroup margin-left: -3px transition: width 0.3s width: 300px overflow: hidden &.big width: 571px .searchgroup-collapsed width: 0 .searchbar height: $icon-height !important box-shadow: none !important &.rounded-top-right border-radius: 0 !important border-top-right-radius: $border-radius !important .searchlabel &.rounded-top-left border-radius: 0 !important border-top-left-radius: $border-radius !important .input-group-text height: $icon-height width: $icon-width .input-group-prepend svg path fill: #666 .searchresults box-shadow: $shadow-xs top: $icon-height left: 0 right: 0 max-height: 24rem overflow: auto > div:first-child border-top: 0 !important a text-decoration: none &:hover background: #f8f8f8 </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 "../../lib/errors.js"; import { HTTP } from "../../lib/http"; const setFocus = () => document.querySelector("#search").focus(); export default { name: "search", data() { return { searchQueryIsDirty: false, searchResults: null, isSearching: false }; }, computed: { ...mapState("application", [ "showSearchbar", "showContextBox", "contextBoxContent" ]), searchQuery: { get() { return this.$store.state.application.searchQuery; }, set(value) { this.$store.commit("application/searchQuery", value); } }, searchIndicator: function() { if (this.isSearching) { return "⟳"; } else if (this.searchQueryIsDirty) { return ""; } else { return "✓"; } }, searchbarContainerStyle() { return [ "input-group searchcontainer shadow-xs", { "d-flex": this.contextBoxContent !== "imports", "d-none": this.contextBoxContent === "imports" && this.showContextBox } ]; }, searchInputStyle() { return [ "form-control ui-element search searchbar d-print-none border-0", { "rounded-top-right": this.showContextBox || this.searchResults } ]; }, searchButtonStyle() { return [ "ui-element input-group-text p-0 d-flex border-0 justify-content-center searchlabel bg-white d-print-none", { rounded: !this.showSearchbar, "rounded-left": this.showSearchbar, "rounded-top-left": this.showSearchbar && (this.showContextBox || this.searchResults) } ]; } }, 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: this.$gettext("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.showContextBox) { if (!this.showSearchbar) { setTimeout(setFocus, 300); } this.$store.commit("application/showSearchbar", !this.showSearchbar); } } } }; </script>