Mercurial > gemma
changeset 1230:957907eaaa72
implemented context sensitive box below search bar (see: issue224)
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Tue, 20 Nov 2018 08:47:53 +0100 |
parents | d395b2940a82 |
children | 315e618a29fd |
files | client/src/App.vue client/src/application/Contextbox.vue client/src/application/Search.vue client/src/application/Sidebar.vue client/src/bottlenecks/Bottlenecks.vue client/src/imports/Imports.vue client/src/staging/Staging.vue client/src/store/application.js |
diffstat | 8 files changed, 199 insertions(+), 247 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/App.vue Tue Nov 20 00:51:33 2018 +0100 +++ b/client/src/App.vue Tue Nov 20 08:47:53 2018 +0100 @@ -6,9 +6,7 @@ <Sidebar :routeName="routeName"></Sidebar> <div class="d-flex flex-column" style="max-width: 600px;"> <Search v-if="routeName == 'mainview'"></Search> - <Bottlenecks v-if="routeName == 'mainview'"></Bottlenecks> - <Imports v-if="routeName == 'mainview'"></Imports> - <Staging v-if="routeName == 'mainview'"></Staging> + <Contextbox v-if="routeName == 'mainview'"></Contextbox> </div> </div> <div class="ml-auto d-flex"> @@ -90,9 +88,7 @@ Layers: () => import("./layers/Layers"), Sidebar: () => import("./application/Sidebar"), Search: () => import("./application/Search"), - Bottlenecks: () => import("./bottlenecks/Bottlenecks"), - Imports: () => import("./imports/Imports.vue"), - Staging: () => import("./staging/Staging.vue") + Contextbox: () => import("./application/Contextbox") } }; </script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/application/Contextbox.vue Tue Nov 20 08:47:53 2018 +0100 @@ -0,0 +1,88 @@ +<template> + <div :class="style"> + <div @click="close" class="ui-element close-contextbox"> + <i class="fa fa-close"></i> + </div> + <Bottlenecks v-if="showInContextBox === 'bottlenecks'"></Bottlenecks> + <Imports v-if="showInContextBox === 'imports'"></Imports> + <Staging v-if="showInContextBox === 'staging'"></Staging> + </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 } from "vuex"; + +export default { + name: "contextbox", + components: { + Bottlenecks: () => import("../bottlenecks/Bottlenecks"), + Imports: () => import("../imports/Imports.vue"), + Staging: () => import("../staging/Staging.vue") + }, + computed: { + ...mapState("application", ["showSearchbarLastState", "showInContextBox"]), + style() { + return [ + "ui-element shadow contextbox pt-3 ml-3 rounded-bottom border-top", + { + contextboxcollapsed: !this.showInContextBox, + contextboxextended: this.showInContextBox + } + ]; + } + }, + methods: { + close() { + this.$store.commit("application/showInContextBox", null); + this.$store.commit( + "application/showSearchbar", + this.showSearchbarLastState + ); + } + } +}; +</script> + +<style lang="sass" scoped> +.contextbox + position: relative + background-color: #ffffff + opacity: $slight-transparent + transition: left 0.3s ease + overflow: hidden + background: #fff + +.contextboxcollapsed + width: 0 + height: 0 + transition: $transition-fast + +.contextboxextended + min-width: 600px + +.close-contextbox + position: absolute + z-index: 2 + right: 0 + top: 7px + height: $icon-width + width: $icon-height + display: none + +.contextboxextended .close-contextbox + display: block +</style>
--- a/client/src/application/Search.vue Tue Nov 20 00:51:33 2018 +0100 +++ b/client/src/application/Search.vue Tue Nov 20 08:47:53 2018 +0100 @@ -14,7 +14,7 @@ type="text" :class="searchInputStyle" > - <ul v-if="showSearchbar && searchResults !== null && !showBottlenecks" class="list-group d-print-none"> + <ul v-if="showSearchbar && searchResults !== null && !showInContextBox" 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> @@ -92,11 +92,7 @@ }; }, computed: { - ...mapState("application", [ - "showSearchbar", - "showBottlenecks", - "showImportSoundingResults" - ]), + ...mapState("application", ["showSearchbar", "showInContextBox"]), searchQuery: { get() { return this.$store.state.application.searchQuery; @@ -120,15 +116,15 @@ { "searchbar-collapsed": !this.showSearchbar, "searchbar-expanded": this.showSearchbar, - "d-flex": !this.showImportSoundingResults, - "d-none": this.showImportSoundingResults + "d-flex": this.showInContextBox !== "imports", + "d-none": this.showInContextBox === "imports" } ]; }, searchInputStyle() { return [ "form-control ui-element search searchbar d-print-none border-0", - { "rounded-top-right": this.showSearchbar && this.showBottlenecks } + { "rounded-top-right": this.showInContextBox } ]; }, searchButtonStyle() { @@ -137,7 +133,7 @@ { rounded: !this.showSearchbar, "rounded-left": this.showSearchbar, - "rounded-top-left": this.showSearchbar && this.showBottlenecks + "rounded-top-left": this.showSearchbar && this.showInContextBox } ]; } @@ -207,7 +203,7 @@ this.toggleSearchbar(); }, toggleSearchbar() { - if (!this.showBottlenecks) { + if (!this.showInContextBox) { if (!this.showSearchbar) { setTimeout(setFocus, 300); }
--- a/client/src/application/Sidebar.vue Tue Nov 20 00:51:33 2018 +0100 +++ b/client/src/application/Sidebar.vue Tue Nov 20 08:47:53 2018 +0100 @@ -17,7 +17,7 @@ class="text-body d-flex flex-row" v-if="routeName == 'mainview'" href="#" - @click="toggleBottlenecks" + @click="toggleContextBox('bottlenecks')" >Bottlenecks</a> </div> <div v-if="isSysAdmin"> @@ -30,7 +30,7 @@ <a href="#" class="text-body" - @click="toggleImportSoundingResults" + @click="toggleContextBox('imports')" >Import soundingresults</a> </div> <div v-if="routeName == 'mainview'" class="d-flex flex-row nav-link"> @@ -38,7 +38,7 @@ <a href="#" class="text-body" - @click="$store.commit('application/showStagingArea', !showStagingArea);" + @click="toggleContextBox('staging')" >Staging area</a> </div> <router-link class="text-body d-flex flex-row nav-link" to="usermanagement"> @@ -96,10 +96,8 @@ ...mapState("user", ["user"]), ...mapState("application", [ "showSidebar", - "showBottlenecks", - "showImportSoundingResults", - "showStagingArea", - "showSearchbarLastState" + "showSearchbarLastState", + "showInContextBox" ]), menuStyle() { return { @@ -126,10 +124,12 @@ this.$store.commit("application/showSplitscreen", false); this.$router.push("/login"); }, - toggleBottlenecks() { - this.$store.commit("application/showBottlenecks", !this.showBottlenecks); - this.$store.commit("application/showImportSoundingResults", false); - if (this.showBottlenecks) { + toggleContextBox(context) { + this.$store.commit( + "application/showInContextBox", + this.showInContextBox === context ? null : context + ); + if (this.showInContextBox === context) { this.$store.commit("application/showSearchbar", true); } else { this.$store.commit( @@ -137,13 +137,6 @@ this.showSearchbarLastState ); } - }, - toggleImportSoundingResults() { - this.$store.commit( - "application/showImportSoundingResults", - !this.showImportSoundingResults - ); - this.$store.commit("application/showBottlenecks", false); } } };
--- a/client/src/bottlenecks/Bottlenecks.vue Tue Nov 20 00:51:33 2018 +0100 +++ b/client/src/bottlenecks/Bottlenecks.vue Tue Nov 20 08:47:53 2018 +0100 @@ -1,8 +1,5 @@ <template> - <div :class="bottlenecksStyle"> - <div @click="closeBottlenecks" class="ui-element close-bottlenecks"> - <i class="fa fa-close"></i> - </div> + <div> <h4>Bottlenecks</h4> <hr class="mb-0"> <div class="row p-2 text-left small"> @@ -96,23 +93,8 @@ }; }, computed: { - ...mapState("application", [ - "showBottlenecks", - "showSidebar", - "searchQuery", - "showSearchbarLastState" - ]), + ...mapState("application", ["searchQuery", "showSearchbarLastState"]), ...mapState("bottlenecks", ["bottlenecks"]), - ...mapState("map", ["openLayersMap"]), - bottlenecksStyle() { - return [ - "ui-element shadow bottlenecks pt-3 ml-3 rounded-bottom border-top", - { - bottleneckscollapsed: !this.showBottlenecks, - bottlenecksextended: this.showBottlenecks - } - ]; - }, sortClass() { return [ "fa ml-1", @@ -214,13 +196,6 @@ }); } }, - closeBottlenecks() { - this.$store.commit("application/showBottlenecks", false); - this.$store.commit( - "application/showSearchbar", - this.showSearchbarLastState - ); - }, displayCurrentSurvey(current) { return current ? current.substr(0, current.length - 1) : ""; }, @@ -235,34 +210,6 @@ </script> <style lang="sass" scoped> -.bottlenecks - position: relative - background-color: #ffffff - opacity: $slight-transparent - transition: left 0.3s ease - overflow: hidden - background: #fff - -.bottleneckscollapsed - width: 0 - height: 0 - transition: $transition-fast - -.bottlenecksextended - min-width: 600px - -.close-bottlenecks - position: absolute - z-index: 2 - right: 0 - top: 7px - height: $icon-width - width: $icon-height - display: none - -.bottlenecksextended .close-bottlenecks - display: block - .bottleneck-list overflow-y: auto max-height: 500px
--- a/client/src/imports/Imports.vue Tue Nov 20 00:51:33 2018 +0100 +++ b/client/src/imports/Imports.vue Tue Nov 20 08:47:53 2018 +0100 @@ -1,11 +1,5 @@ <template> - <div :class="importStyle"> - <div - @click="$store.commit('application/showImportSoundingResults', false);" - class="ui-element close-imports" - > - <i class="fa fa-close"></i> - </div> + <div> <h4>Import soundingresults</h4> <hr class="mr-auto ml-auto mb-0 w-90"> <div v-if="editState" class="p-3"> @@ -82,7 +76,6 @@ <script> import { HTTP } from "../application/lib/http"; import { displayError, displayInfo } from "../application/lib/errors.js"; -import { mapState } from "vuex"; const defaultLabel = "Choose .zip-file"; const IMPORTSTATE = { UPLOAD: "UPLOAD", EDIT: "EDIT" }; @@ -132,22 +125,12 @@ } }, computed: { - ...mapState("application", ["showImportSoundingResults"]), editState() { return this.importState === IMPORTSTATE.EDIT; }, uploadState() { return this.importState === IMPORTSTATE.UPLOAD; }, - importStyle() { - return [ - "ui-element shadow imports ml-3 pt-3 rounded", - { - importscollapsed: !this.showImportSoundingResults, - importsextended: this.showImportSoundingResults - } - ]; - }, dataLink() { return ( "data:text/json;charset=utf-8," + @@ -191,36 +174,6 @@ .uploadsection width: 90% -.imports - position: relative - background-color: #ffffff - opacity: $slight-transparent - transition: left 0.3s ease - overflow: hidden - background: #fff - margin-top: -$offset - width: 90% - -.importscollapsed - width: 0 - height: 0 - transition: $transition-fast - -.importsextended - min-width: 600px - -.close-imports - position: absolute - z-index: 2 - right: 0 - top: 7px - height: $icon-width - width: $icon-height - display: none - -.importsextended .close-imports - display: block - .label-text width: 10rem text-align: left
--- a/client/src/staging/Staging.vue Tue Nov 20 00:51:33 2018 +0100 +++ b/client/src/staging/Staging.vue Tue Nov 20 08:47:53 2018 +0100 @@ -1,55 +1,43 @@ <template> - <div v-if="showStagingArea" :class="stagingAreaStyle"> - <div class="p-3"> - <div - @click="$store.commit('application/showStagingArea', !showStagingArea);" - class="ui-element close-showStagingArea position-absolute" - > - <i class="fa fa-close"></i> - </div> - <div class="card-title mb-4 headline"> - <h4>Staging area</h4> - <hr> - </div> - <div class="d-flex flex-row input-group mb-5"> - <table class="table mb-4"> - <thead> - <tr> - <th>Name</th> - <th>Datatype</th> - <th>Importdate</th> - <th>ImportID</th> - <th> </th> - <th> </th> - </tr> - </thead> - <tbody> - <tr v-for="data in filteredData" :key="data.id"> - <td> - <a @click="zoomTo(data.location)" href="#">{{data.name}}</a> - </td> - <td>{{data.type}}</td> - <td>{{data.date}}</td> - <td>{{data.importID}}</td> - <td> - <button class="btn btn-outline-info"> - <i class="fa fa-thumbs-o-up"></i> - </button> - </td> - <td> - <button class="btn btn-outline-info"> - <i class="fa fa-thumbs-o-down"></i> - </button> - </td> - </tr> - </tbody> - </table> - </div> - <div class="confirmbutton"> - <button class="btn btn-info">Confirm</button> - </div> - </div> - </div> + <div> + <h4>Staging area</h4> + <hr> + <table class="table mb-0"> + <thead> + <tr> + <th>Name</th> + <th>Location</th> + <th>Datatype</th> + <th>Importdate</th> + <th>ImportID</th> + <th> </th> + </tr> + </thead> + <tbody> + <tr v-for="data in filteredData" :key="data.id"> + <td>{{ data.name }}</td> + <td> + <a + @click="zoomTo(data.location)" + href="#" + >{{ data.location[0] }}, {{ data.location[1] }}</a> + </td> + <td>{{ data.type }}</td> + <td>{{ data.date }}</td> + <td>{{ data.importID }}</td> + <td> + <input + type="checkbox" + aria-label="Checkbox for following text input" + > + </td> + </tr> + </tbody> + </table> + <div class="p-3"> + <button class="btn btn-info">Confirm</button> + </div> + </div> </template> <script> @@ -105,60 +93,59 @@ } }, computed: { - ...mapState("application", ["showStagingArea"]), + ...mapState("application", ["searchQuery"]), filteredData() { - return demodata; - }, - stagingAreaStyle() { - return [ - "ui-element staging-card bg-white ml-3 pt-3 mx-auto rounded border-top position-relative", - { - stagingcollapsed: !this.showStagingArea, - stagingextended: this.showStagingArea - } - ]; + return demodata.filter(data => { + const nameFound = data.name + .toLowerCase() + .includes(this.searchQuery.toLowerCase()); + const dateFound = data.date + .toLowerCase() + .includes(this.searchQuery.toLowerCase()); + const locationFound = data.location.find(coord => { + return coord + .toString() + .toLowerCase() + .includes(this.searchQuery.toLowerCase()); + }) + const statusFound = data.status + .toLowerCase() + .includes(this.searchQuery.toLowerCase()); + const importIDFound = data.importID + .toLowerCase() + .includes(this.searchQuery.toLowerCase()); + const typeFound = data.type + .toLowerCase() + .includes(this.searchQuery.toLowerCase()); + + return ( + nameFound || + dateFound || + locationFound || + statusFound || + importIDFound || + typeFound + ); + }); } - } + }, + methods: { + zoomTo(coordinates) { + this.$store.commit("map/moveMap", { + coordinates: coordinates, + zoom: 17, + preventZoomOut: true + }); + } + }, }; </script> <style lang="sass" scoped> -.close-showStagingArea - z-index: 2 - right: 0 - top: 7px - height: $icon-width - width: $icon-height - -.stagingcollapsed - width: 0 - height: 0 - transition: $transition-fast - -.stagingextended - min-width: 600px - -.staging-card - position: relative - background-color: #ffffff - padding-top: $offset - opacity: $slight-transparent - transition: left 0.3s ease - overflow: hidden - background: #fff - margin-left: $offset !important - margin-top: -$offset !important - width: 90% - .table th, td font-size: 0.9rem border-top: 0px !important text-align: left padding: 0.5rem !important - -.confirmbutton - position: absolute - bottom: $offset - right: $large-offset </style>
--- a/client/src/store/application.js Tue Nov 20 00:51:33 2018 +0100 +++ b/client/src/store/application.js Tue Nov 20 08:47:53 2018 +0100 @@ -23,15 +23,13 @@ secondaryLogo: process.env.VUE_APP_SECONDARY_LOGO_URL, showSidebar: false, showUsermenu: false, - showBottlenecks: false, showSplitscreen: false, showSearchbar: false, showSearchbarLastState: false, showIdentify: false, showLayers: true, showPdfTool: false, - showImportSoundingResults: false, - showStagingArea: false, + showInContextBox: null, // bottlenecks, imports, staging countries: ["AT", "SK", "HU", "HR", "RS", "BiH", "BG", "RO", "UA"], searchQuery: "", version @@ -57,12 +55,6 @@ showSidebar: (state, show) => { state.showSidebar = show; }, - showBottlenecks: (state, show) => { - state.showBottlenecks = show; - if (show) { - state.showSearchbarLastState = state.showSearchbar; - } - }, showSplitscreen: (state, show) => { state.showSplitscreen = show; }, @@ -81,11 +73,11 @@ showPdfTool: (state, show) => { state.showPdfTool = show; }, - showImportSoundingResults: (state, show) => { - state.showImportSoundingResults = show; - }, - showStagingArea: (state, show) => { - state.showStagingArea = show; + showInContextBox: (state, context) => { + state.showInContextBox = context; + if (context) { + state.showSearchbarLastState = state.showSearchbar; + } }, searchQuery: (state, searchQuery) => { state.searchQuery = searchQuery;