Mercurial > gemma
comparison client/src/components/Search.vue @ 1558:0ded4c56978e
refac: component filestructure. remove admin/map hierarchy
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Wed, 12 Dec 2018 09:22:20 +0100 |
parents | client/src/components/map/Search.vue@9b81ac91a43e |
children | f2d24dceecc7 |
comparison
equal
deleted
inserted
replaced
1557:62171cd9a42b | 1558:0ded4c56978e |
---|---|
1 <template> | |
2 <div :class="searchbarContainerStyle"> | |
3 <div class="input-group-prepend m-0 d-print-none"> | |
4 <span @click="toggleSearchbar" :class="searchButtonStyle" for="search"> | |
5 <font-awesome-icon icon="search"></font-awesome-icon> | |
6 </span> | |
7 </div> | |
8 <div | |
9 :class="[ | |
10 'searchgroup', | |
11 { | |
12 'searchgroup-collapsed': !showSearchbar, | |
13 big: | |
14 showContextBox && | |
15 ['bottlenecks', 'staging'].indexOf(contextBoxContent) !== -1 | |
16 } | |
17 ]" | |
18 > | |
19 <input | |
20 @keyup.enter="takeFirstSearchresult" | |
21 id="search" | |
22 v-model="searchQuery" | |
23 type="text" | |
24 :class="searchInputStyle" | |
25 /> | |
26 </div> | |
27 <div | |
28 v-if="showSearchbar && searchResults !== null && !showContextBox" | |
29 class="searchresults border-top ui-element bg-white rounded-bottom d-print-none position-absolute" | |
30 > | |
31 <div | |
32 v-for="entry of searchResults" | |
33 :key="entry.name" | |
34 class="border-top text-left" | |
35 > | |
36 <a | |
37 href="#" | |
38 @click.prevent="moveToSearchResult(entry)" | |
39 class="p-2 d-block text-nowrap" | |
40 > | |
41 <font-awesome-icon | |
42 icon="ship" | |
43 v-if="entry.type === 'bottleneck'" | |
44 class="mr-1" | |
45 fixed-width | |
46 /> | |
47 <font-awesome-icon | |
48 icon="water" | |
49 v-if="entry.type === 'rhm'" | |
50 class="mr-1" | |
51 fixed-width | |
52 /> | |
53 <font-awesome-icon | |
54 icon="city" | |
55 v-if="entry.type === 'city'" | |
56 class="mr-1" | |
57 fixed-width | |
58 /> | |
59 {{ entry.name }} | |
60 </a> | |
61 </div> | |
62 </div> | |
63 </div> | |
64 </template> | |
65 | |
66 <style lang="scss" scoped> | |
67 .searchcontainer { | |
68 opacity: 0.96; | |
69 } | |
70 | |
71 .searchcontainer .searchbar { | |
72 border-top-left-radius: 0 !important; | |
73 border-bottom-left-radius: 0 !important; | |
74 } | |
75 | |
76 .searchgroup { | |
77 margin-left: -3px; | |
78 transition: width 0.3s; | |
79 width: 300px; | |
80 overflow: hidden; | |
81 } | |
82 | |
83 .searchgroup.big { | |
84 width: 571px; | |
85 } | |
86 | |
87 .searchgroup-collapsed { | |
88 width: 0; | |
89 } | |
90 | |
91 .searchbar { | |
92 height: 2rem !important; | |
93 box-shadow: none !important; | |
94 } | |
95 | |
96 .searchbar.rounded-top-right { | |
97 border-radius: 0 !important; | |
98 border-top-right-radius: 0.25rem !important; | |
99 } | |
100 | |
101 .searchlabel.rounded-top-left { | |
102 border-radius: 0 !important; | |
103 border-top-left-radius: 0.25rem !important; | |
104 } | |
105 | |
106 .input-group-text { | |
107 height: 2rem; | |
108 width: 2rem; | |
109 } | |
110 | |
111 .input-group-prepend svg path { | |
112 fill: #666; | |
113 } | |
114 | |
115 .searchresults { | |
116 box-shadow: 0 0.1rem 0.5rem rgba(0, 0, 0, 0.2); | |
117 top: 2rem; | |
118 left: 0; | |
119 right: 0; | |
120 max-height: 24rem; | |
121 overflow: auto; | |
122 } | |
123 | |
124 .searchresults > div:first-child { | |
125 border-top: 0 !important; | |
126 } | |
127 | |
128 .searchresults a { | |
129 text-decoration: none; | |
130 } | |
131 | |
132 .searchresults a:hover { | |
133 background: #f8f8f8; | |
134 } | |
135 </style> | |
136 | |
137 <script> | |
138 /* This is Free Software under GNU Affero General Public License v >= 3.0 | |
139 * without warranty, see README.md and license for details. | |
140 * | |
141 * SPDX-License-Identifier: AGPL-3.0-or-later | |
142 * License-Filename: LICENSES/AGPL-3.0.txt | |
143 * | |
144 * Copyright (C) 2018 by via donau | |
145 * – Österreichische Wasserstraßen-Gesellschaft mbH | |
146 * Software engineering by Intevation GmbH | |
147 * | |
148 * Author(s): | |
149 * Markus Kottländer <markus.kottlaender@intevation.de> | |
150 */ | |
151 import debounce from "lodash.debounce"; | |
152 import { mapState } from "vuex"; | |
153 | |
154 import { displayError } from "../lib/errors.js"; | |
155 import { HTTP } from "../lib/http"; | |
156 | |
157 const setFocus = () => document.querySelector("#search").focus(); | |
158 | |
159 export default { | |
160 name: "search", | |
161 data() { | |
162 return { | |
163 searchQueryIsDirty: false, | |
164 searchResults: null, | |
165 isSearching: false | |
166 }; | |
167 }, | |
168 computed: { | |
169 ...mapState("application", [ | |
170 "showSearchbar", | |
171 "showContextBox", | |
172 "contextBoxContent" | |
173 ]), | |
174 searchQuery: { | |
175 get() { | |
176 return this.$store.state.application.searchQuery; | |
177 }, | |
178 set(value) { | |
179 this.$store.commit("application/searchQuery", value); | |
180 } | |
181 }, | |
182 searchIndicator: function() { | |
183 if (this.isSearching) { | |
184 return "⟳"; | |
185 } else if (this.searchQueryIsDirty) { | |
186 return ""; | |
187 } else { | |
188 return "✓"; | |
189 } | |
190 }, | |
191 searchbarContainerStyle() { | |
192 return [ | |
193 "input-group searchcontainer shadow-xs", | |
194 { | |
195 "d-flex": this.contextBoxContent !== "imports", | |
196 "d-none": this.contextBoxContent === "imports" && this.showContextBox | |
197 } | |
198 ]; | |
199 }, | |
200 searchInputStyle() { | |
201 return [ | |
202 "form-control ui-element search searchbar d-print-none border-0", | |
203 { "rounded-top-right": this.showContextBox || this.searchResults } | |
204 ]; | |
205 }, | |
206 searchButtonStyle() { | |
207 return [ | |
208 "ui-element input-group-text p-0 d-flex border-0 justify-content-center searchlabel bg-white d-print-none", | |
209 { | |
210 rounded: !this.showSearchbar, | |
211 "rounded-left": this.showSearchbar, | |
212 "rounded-top-left": | |
213 this.showSearchbar && (this.showContextBox || this.searchResults) | |
214 } | |
215 ]; | |
216 } | |
217 }, | |
218 watch: { | |
219 searchQuery: function() { | |
220 this.searchQueryIsDirty = true; | |
221 this.triggerSearch(); | |
222 } | |
223 }, | |
224 methods: { | |
225 takeFirstSearchresult() { | |
226 if (!this.searchResults || this.searchResults.length != 1) return; | |
227 this.moveToSearchResult(this.searchResults[0]); | |
228 }, | |
229 triggerSearch: debounce(function() { | |
230 this.doSearch(); | |
231 }, 500), | |
232 doSearch() { | |
233 this.isCalculating = true; | |
234 this.searchResults = null; | |
235 | |
236 if (this.searchQuery == "") { | |
237 return; | |
238 } | |
239 | |
240 HTTP.post( | |
241 "/search", | |
242 { string: this.searchQuery }, | |
243 { | |
244 headers: { | |
245 "X-Gemma-Auth": localStorage.getItem("token"), | |
246 "Content-type": "text/xml; charset=UTF-8" | |
247 } | |
248 } | |
249 ) | |
250 .then(response => { | |
251 // console.log("got:", response.data); | |
252 this.searchResults = response.data; | |
253 }) | |
254 .catch(error => { | |
255 const { status, data } = error.response; | |
256 displayError({ | |
257 title: this.$gettext("Backend Error"), | |
258 message: `${status}: ${data.message || data}` | |
259 }); | |
260 }); | |
261 | |
262 this.isCalculating = false; | |
263 this.searchQueryIsDirty = false; | |
264 }, | |
265 moveToSearchResult(resultEntry) { | |
266 // DEBUG console.log("Moving to", resultEntry); | |
267 if (resultEntry.geom.type == "Point") { | |
268 let zoom = 11; | |
269 if (resultEntry.type === "bottleneck") zoom = 17; | |
270 if (resultEntry.type === "rhm") zoom = 15; | |
271 if (resultEntry.type === "city") zoom = 13; | |
272 | |
273 this.$store.commit("map/moveMap", { | |
274 coordinates: resultEntry.geom.coordinates, | |
275 zoom, | |
276 preventZoomOut: true | |
277 }); | |
278 } | |
279 // this.searchQuery = ""; // clear search query again | |
280 this.toggleSearchbar(); | |
281 }, | |
282 toggleSearchbar() { | |
283 if (!this.showContextBox) { | |
284 if (!this.showSearchbar) { | |
285 setTimeout(setFocus, 300); | |
286 } | |
287 this.$store.commit("application/showSearchbar", !this.showSearchbar); | |
288 } | |
289 } | |
290 } | |
291 }; | |
292 </script> |