Mercurial > gemma
changeset 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 | 486d66a9565c |
children | 49740dcba52c |
files | client/src/App.vue client/src/application/Search.vue client/src/application/Topbar.vue |
diffstat | 3 files changed, 217 insertions(+), 245 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/App.vue Sun Nov 18 18:44:22 2018 +0100 +++ b/client/src/App.vue Mon Nov 19 08:24:47 2018 +0100 @@ -2,7 +2,14 @@ <div id="app" class="main"> <div v-if="isAuthenticated" class="d-flex flex-column userinterface"> <div class="topcontainer"> - <Topbar :routeName="routeName"></Topbar> + <div class="topbar d-flex flex-row"> + <Sidebar :routeName="routeName"></Sidebar> + <Bottlenecks v-if="routeName == 'mainview'"></Bottlenecks> + <Imports v-if="routeName == 'mainview'"></Imports> + <Search v-if="routeName == 'mainview'"></Search> + <Layers v-if="routeName == 'mainview'"></Layers> + <Identify v-if="routeName == 'mainview'"></Identify> + </div> </div> <div class="flex-fill"></div> <div class="bottomcontainer d-flex flex-row align-items-end"> @@ -34,6 +41,11 @@ z-index: 4 pointer-events: none +.topbar + padding-top: $offset + margin-left: $offset + margin-right: $offset + #app height: 100vh width: 100vw @@ -72,11 +84,16 @@ } }, components: { - Topbar: () => import("./application/Topbar"), Drawtool: () => import("./drawtool/Drawtool"), Morphtool: () => import("./morphtool/Morphtool"), Pdftool: () => import("./pdftool/Pdftool"), - Zoom: () => import("./zoom/zoom") + Zoom: () => import("./zoom/zoom"), + Identify: () => import("./identify/Identify"), + Layers: () => import("./layers/Layers"), + Sidebar: () => import("./application/Sidebar"), + Search: () => import("./application/Search"), + Bottlenecks: () => import("./bottlenecks/Bottlenecks"), + Imports: () => import("./imports/Imports.vue") } }; </script>
--- /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>
--- a/client/src/application/Topbar.vue Sun Nov 18 18:44:22 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,242 +0,0 @@ -<template> - <div class="topbar d-flex flex-row"> - <Sidebar :routeName="routeName"></Sidebar> - <Bottlenecks v-if="routeName == 'mainview'"></Bottlenecks> - <Imports v-if="routeName == 'mainview'"></Imports> - <div v-if="routeName == 'mainview'" :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> - <div class=""> - <Layers v-if="routeName == 'mainview'"></Layers> - </div> - <div class=""> - <Identify v-if="routeName == 'mainview'"></Identify> - </div> - </div> -</template> - -<style lang="sass" scoped> -.splitbutton - height: $icon-height - -.list-group - pointer-events: auto - -.splitscreen - background-color: white - padding: $small-offset - margin-right: $small-offset - margin-left: $offset - border-radius: $border-radius - height: $icon-height - width: $icon-width - -.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 - -.topbar - padding-top: $offset - margin-left: $offset - margin-right: $offset - -.logout - font-size: x-large -</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): - * Thomas Junk <thomas.junk@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: "topbar", - components: { - Identify: () => import("../identify/Identify"), - Layers: () => import("../layers/Layers"), - Sidebar: () => import("./Sidebar"), - Bottlenecks: () => import("../bottlenecks/Bottlenecks"), - Imports: () => import("../imports/Imports.vue") - }, - data() { - return { - searchQuery: "", - searchQueryIsDirty: false, - searchResults: null, - isSearching: false - }; - }, - computed: { - ...mapState("application", [ - "showSidebar", - "showSplitscreen", - "showSearchbar" - ]), - ...mapState("map", ["openLayersMap"]), - ...mapState("fairwayprofile", ["currentProfile"]), - 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 - } - ]; - } - }, - props: ["routeName"], - 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>