Mercurial > gemma
changeset 2566:83b938bf4da9
client: prepared store and minimized splitscreens for multiple simultaneous diagrams
author | Markus Kottlaender <markus@intevation.de> |
---|---|
date | Mon, 11 Mar 2019 11:34:54 +0100 |
parents | 114979e97a6c |
children | 1cac2e58ef7d |
files | client/src/components/App.vue client/src/components/Splitscreen.vue client/src/components/Zoom.vue client/src/components/fairway/Fairwayprofile.vue client/src/components/fairway/Infobar.vue client/src/components/splitscreen/MinimizedSplitscreens.vue client/src/components/splitscreen/Splitscreen.vue client/src/components/ui/UIBoxHeader.vue client/src/main.js client/src/store/application.js client/src/store/bottlenecks.js client/src/store/fairway.js |
diffstat | 12 files changed, 261 insertions(+), 212 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/components/App.vue Mon Mar 11 11:14:44 2019 +0100 +++ b/client/src/components/App.vue Mon Mar 11 11:34:54 2019 +0100 @@ -1,7 +1,7 @@ <template> <div id="app" class="main"> <div v-if="isAuthenticated" class="d-flex flex-column userinterface"> - <div class="topbar d-flex pt-2 mx-2"> + <div class="d-flex p-2"> <div class="mr-auto d-flex"> <Sidebar :routeName="routeName"></Sidebar> <div :class="searchContainer"> @@ -21,12 +21,9 @@ <Toolbar v-if="isMapVisible"></Toolbar> </div> </div> - <div class="flex-fill"></div> - <div class="d-flex flex-row align-items-end"> - <Infobar v-if="isMapVisible"></Infobar> - </div> <Zoom v-if="isMapVisible"></Zoom> <Splitscreen v-if="isMapVisible" /> + <MinimizedSplitscreens v-if="isMapVisible" /> </div> <router-view /> <vue-snotify></vue-snotify> @@ -45,11 +42,6 @@ pointer-events: none; } -.topbar { - position: relative; - z-index: 2; -} - #app { height: 100%; width: 100%; @@ -103,7 +95,6 @@ }, components: { Profiles: () => import("./fairway/Profiles"), - Infobar: () => import("./fairway/Infobar"), Pdftool: () => import("./Pdftool"), Zoom: () => import("./Zoom"), Identify: () => import("./identify/Identify"), @@ -113,7 +104,8 @@ Contextbox: () => import("./Contextbox"), Toolbar: () => import("./toolbar/Toolbar"), Popup: () => import("./Popup"), - Splitscreen: () => import("./Splitscreen") + Splitscreen: () => import("./splitscreen/Splitscreen"), + MinimizedSplitscreens: () => import("./splitscreen/MinimizedSplitscreens") } }; </script>
--- a/client/src/components/Splitscreen.vue Mon Mar 11 11:14:44 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -<template> - <div - :class="[ - 'splitscreen bg-white d-flex flex-column ui-element', - { show: showSplitscreen } - ]" - > - <UIBoxHeader - :icon="config.icon" - :title="config.title" - :closeCallback="close" - :collapseCallback="collapse" - /> - <div class="d-flex flex-fill"> - <transition name="fade"> - <div - class="loading d-flex justify-content-center align-items-center" - v-if="splitscreenLoading" - > - <font-awesome-icon icon="spinner" spin /> - </div> - </transition> - <component :is="config.component" /> - </div> - </div> -</template> - -<style lang="sass" scoped> -.splitscreen - position: absolute - bottom: -50vh - left: 0 - right: 0 - height: 50vh - overflow: hidden - z-index: 1 - box-shadow: 0 -.125rem .25rem rgba(0, 0, 0, 0.075) - transition: bottom 0.3s - &.show - bottom: 0 - - .loading - background: rgba(255, 255, 255, 0.96) - position: absolute - z-index: 99 - top: 34px - right: 0 - bottom: 0 - left: 0 -</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 { mapState } from "vuex"; - -export default { - components: { - Fairwayprofile: () => import("@/components/fairway/Fairwayprofile") - }, - computed: { - ...mapState("application", [ - "splitscreen", - "showSplitscreen", - "splitscreenLoading" - ]), - config() { - return this.splitscreen || { title: "", icon: "", component: "" }; - } - }, - methods: { - collapse() { - this.$store.commit("application/showSplitscreen", false); - if (this.config.collapseCallback) this.config.collapseCallback(); - }, - close() { - this.$store.commit("application/showSplitscreen", false); - if (this.config.closeCallback) this.config.closeCallback(); - } - } -}; -</script>
--- a/client/src/components/Zoom.vue Mon Mar 11 11:14:44 2019 +0100 +++ b/client/src/components/Zoom.vue Mon Mar 11 11:34:54 2019 +0100 @@ -1,22 +1,19 @@ <template> - <div - class="d-flex buttoncontainer shadow-xs mb-2 position-absolute" - :style="showSplitscreen ? 'margin-bottom: 51vh !important' : ''" - > + <div :class="['zoom-buttons shadow-xs', { splitscreen: showSplitscreen }]"> <button - class="zoomButton border-0 bg-white rounded-left ui-element" + class="zoom-button border-0 bg-white rounded-left ui-element" @click="zoomOut" > <font-awesome-icon icon="minus"></font-awesome-icon> </button> <button - class="zoomButton border-0 bg-white ui-element border-right" + class="zoom-button border-0 bg-white ui-element border-right" @click="refreshMap" > <font-awesome-icon icon="redo"></font-awesome-icon> </button> <button - class="zoomButton border-0 bg-white rounded-right ui-element border-right" + class="zoom-button border-0 bg-white rounded-right ui-element border-right" @click="zoomIn" > <font-awesome-icon icon="plus"></font-awesome-icon> @@ -24,22 +21,25 @@ </div> </template> -<style lang="scss" scoped> -.buttoncontainer { - bottom: 0; - left: 50%; - margin-left: -$icon-width; - transition: margin-bottom 0.3s; -} +<style lang="sass" scoped> +.zoom-buttons + position: absolute + bottom: $small-offset + left: 50% + margin-left: -($icon-width * 1.5) + margin-bottom: 0 + transition: margin-bottom 0.3s + &.splitscreen + margin-bottom: 50vh -.zoomButton { - min-height: $icon-width; - min-width: $icon-width; - z-index: 1; - outline: none; - color: #666; -} + .zoom-button + min-height: $icon-width + min-width: $icon-width + z-index: 1 + outline: none + color: #666 </style> + <script> /* This is Free Software under GNU Affero General Public License v >= 3.0 * without warranty, see README.md and license for details.
--- a/client/src/components/fairway/Fairwayprofile.vue Mon Mar 11 11:14:44 2019 +0100 +++ b/client/src/components/fairway/Fairwayprofile.vue Mon Mar 11 11:34:54 2019 +0100 @@ -46,13 +46,12 @@ ...mapState("fairwayprofile", [ "additionalSurvey", "currentProfile", + "startPoint", "endPoint", "fairwayData", - "minAlt", "maxAlt", "referenceWaterLevel", "selectedWaterLevel", - "startPoint", "waterLevels" ]), ...mapState("bottlenecks", ["selectedSurvey"]),
--- a/client/src/components/fairway/Infobar.vue Mon Mar 11 11:14:44 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -<template> - <div - v-if="Object.keys(currentProfile).length" - class="ui-element shadow-xs infobar rounded bg-white ml-auto mb-2 mr-2" - > - <div class="d-flex flex-row justify-content-between h-100"> - <h6 class="my-auto px-2"> - {{ selectedBottleneck }} ({{ selectedSurvey.date_info }}) - </h6> - <span - class="p-2 border-left d-flex align-items-center" - @click="$store.commit('application/showSplitscreen', true)" - > - <font-awesome-icon class="pointer" icon="angle-up"></font-awesome-icon> - </span> - <span - class="p-2 border-left d-flex align-items-center" - @click="$store.dispatch('fairwayprofile/clearSelection')" - > - <font-awesome-icon icon="times" class="pointer"></font-awesome-icon> - </span> - </div> - </div> -</template> - -<style lang="scss" scoped> -.infobar { - height: 2.2rem; -} - -.infobar svg path { - fill: #666; -} -</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 { mapState } from "vuex"; - -export default { - name: "infobar", - computed: { - ...mapState("application", ["showSplitscreen"]), - ...mapState("fairwayprofile", ["currentProfile"]), - ...mapState("bottlenecks", ["selectedBottleneck", "selectedSurvey"]) - } -}; -</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/splitscreen/MinimizedSplitscreens.vue Mon Mar 11 11:34:54 2019 +0100 @@ -0,0 +1,61 @@ +<template> + <div class="minimizedSplitscreens ui-element"> + <transition name="fade"> + <UIBoxHeader + v-for="splitscreen in splitscreens" + :key="splitscreen.id" + :icon="splitscreen.icon" + :title="splitscreen.title" + :closeCallback="close(splitscreen)" + :expandCallback="expand(splitscreen)" + :collapsed="true" + /> + </transition> + </div> +</template> + +<style lang="sass" scoped> +.minimizedSplitscreens + position: absolute + bottom: $small-offset + right: $small-offset +</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@intevation.de> + */ + +import { mapState } from "vuex"; + +export default { + computed: { + ...mapState("application", ["splitscreens"]) + }, + methods: { + close(splitscreen) { + return () => { + if (splitscreen.closeCallback) splitscreen.closeCallback(); + this.$store.commit("application/removeSplitscreen", splitscreen.id); + }; + }, + expand(splitscreen) { + return () => { + if (splitscreen.expandCallback) splitscreen.expandCallback(); + this.$store.commit("application/activeSplitscreen", splitscreen.id); + this.$store.commit("application/showSplitscreen", true); + }; + } + } +}; +</script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/splitscreen/Splitscreen.vue Mon Mar 11 11:34:54 2019 +0100 @@ -0,0 +1,100 @@ +<template> + <div> + <div + :class="[ + 'splitscreen bg-white d-flex flex-column ui-element', + { show: showSplitscreen } + ]" + > + <UIBoxHeader + :icon="activeSplitscreen.icon" + :title="activeSplitscreen.title" + :closeCallback="close" + :collapseCallback="collapse" + v-if="activeSplitscreen" + /> + <div class="d-flex flex-fill"> + <transition name="fade"> + <div + class="loading d-flex justify-content-center align-items-center" + v-if="splitscreenLoading" + > + <font-awesome-icon icon="spinner" spin /> + </div> + </transition> + <component :is="activeSplitscreen.component" v-if="activeSplitscreen" /> + </div> + </div> + </div> +</template> + +<style lang="sass" scoped> +.splitscreen + position: absolute + bottom: -50vh + left: 0 + right: 0 + height: 50vh + overflow: hidden + z-index: 1 + box-shadow: 0 -.125rem .25rem rgba(0, 0, 0, 0.075) + transition: bottom 0.3s + &.show + bottom: 0 + + .loading + background: rgba(255, 255, 255, 0.96) + position: absolute + z-index: 99 + top: 34px + right: 0 + bottom: 0 + left: 0 +</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 { mapState, mapGetters } from "vuex"; + +export default { + components: { + Fairwayprofile: () => import("@/components/fairway/Fairwayprofile") + }, + computed: { + ...mapState("application", ["showSplitscreen", "splitscreenLoading"]), + ...mapGetters("application", ["activeSplitscreen"]) + }, + methods: { + collapse() { + if (this.activeSplitscreen.collapseCallback) + this.activeSplitscreen.collapseCallback(); + this.$store.commit("application/showSplitscreen", false); + }, + close() { + if (this.activeSplitscreen.closeCallback) + this.activeSplitscreen.closeCallback(); + this.$store.commit("application/showSplitscreen", false); + setTimeout(() => { + this.$store.commit( + "application/removeSplitscreen", + this.activeSplitscreen.id + ); + this.$store.commit("application/activeSplitscreen", null); + }, 350); + } + } +}; +</script>
--- a/client/src/components/ui/UIBoxHeader.vue Mon Mar 11 11:14:44 2019 +0100 +++ b/client/src/components/ui/UIBoxHeader.vue Mon Mar 11 11:34:54 2019 +0100 @@ -1,5 +1,5 @@ <template> - <h6 class="box-header"> + <h6 :class="['box-header', { 'rounded border-0 shadow-xs': collapsed }]"> <span class="box-title"> <font-awesome-icon :icon="icon" @@ -10,8 +10,11 @@ {{ $gettext(title) }} </span> <div class="box-controls"> - <span @click="collapseCallback" v-if="collapseCallback"> - <font-awesome-icon icon="angle-down" /> + <span @click="collapseCallback" v-if="!collapsed && collapseCallback"> + <font-awesome-icon :icon="['far', 'window-minimize']" /> + </span> + <span @click="expandCallback" v-if="collapsed && expandCallback"> + <font-awesome-icon :icon="['far', 'window-maximize']" /> </span> <span @click="closeCallback" v-if="closeCallback"> <font-awesome-icon icon="times" /> @@ -32,6 +35,7 @@ margin-bottom: 0 padding: 0.25rem font-weight: bold + background: white .box-title padding-left: 0.25rem .box-icon @@ -66,6 +70,13 @@ */ export default { - props: ["icon", "title", "collapseCallback", "closeCallback"] + props: [ + "icon", + "title", + "collapseCallback", + "closeCallback", + "expandCallback", + "collapsed" + ] }; </script>
--- a/client/src/main.js Mon Mar 11 11:14:44 2019 +0100 +++ b/client/src/main.js Mon Mar 11 11:34:54 2019 +0100 @@ -95,6 +95,10 @@ faWrench, faRedo } from "@fortawesome/free-solid-svg-icons"; +import { + faWindowMinimize, + faWindowMaximize +} from "@fortawesome/free-regular-svg-icons"; import { faAdn } from "@fortawesome/free-brands-svg-icons"; library.add( @@ -149,7 +153,9 @@ faUsersCog, faWater, faWrench, - faRedo + faRedo, + faWindowMinimize, + faWindowMaximize ); // register plugins
--- a/client/src/store/application.js Mon Mar 11 11:14:44 2019 +0100 +++ b/client/src/store/application.js Mon Mar 11 11:34:54 2019 +0100 @@ -23,11 +23,11 @@ secondaryLogo: process.env.VUE_APP_SECONDARY_LOGO_URL, logoForPDF: process.env.VUE_APP_LOGO_FOR_PDF_URL, popup: null, + splitscreens: [], + splitscreenLoading: false, + showSplitscreen: false, showSidebar: false, showUsermenu: false, - showSplitscreen: false, - splitscreenLoading: false, - splitscreen: null, showSearchbar: false, showSearchbarLastState: false, showIdentify: false, @@ -65,6 +65,9 @@ versionStr += "+" + process.env.VUE_APP_HGREV; return versionStr; + }, + activeSplitscreen: state => { + return state.splitscreens.find(s => s.id === state.activeSplitscreen); } }, mutations: { @@ -80,8 +83,17 @@ splitscreenLoading: (state, loading) => { state.splitscreenLoading = loading; }, - splitscreen: (state, config) => { - state.splitscreen = config; + activeSplitscreen: (state, id) => { + state.activeSplitscreen = id; + }, + addSplitscreen: (state, config) => { + let index = state.splitscreens.findIndex(s => s.id === config.id); + if (index !== -1) state.splitscreens[index] = config; + else state.splitscreens.push(config); + }, + removeSplitscreen: (state, id) => { + let index = state.splitscreens.findIndex(s => s.id === id); + if (index !== -1) state.splitscreens.splice(index, 1); }, showUsermenu: (state, show) => { state.showUsermenu = show;
--- a/client/src/store/bottlenecks.js Mon Mar 11 11:14:44 2019 +0100 +++ b/client/src/store/bottlenecks.js Mon Mar 11 11:34:54 2019 +0100 @@ -67,6 +67,9 @@ commit("selectedSurvey", null); commit("application/splitscreenLoading", true, { root: true }); commit("application/showSplitscreen", false, { root: true }); + commit("application/removeSplitscreen", "fairwayprofile", { + root: true + }); setTimeout(() => { commit("fairwayprofile/clearCurrentProfile", null, { root: true }); }, 350);
--- a/client/src/store/fairway.js Mon Mar 11 11:14:44 2019 +0100 +++ b/client/src/store/fairway.js Mon Mar 11 11:34:54 2019 +0100 @@ -289,20 +289,39 @@ }); }) .finally(() => { - commit( - "application/splitscreen", - { - component: "fairwayprofile", - title: `${rootState.bottlenecks.selectedBottleneck} (${ - rootState.bottlenecks.selectedSurvey.date_info - })`, - icon: "chart-area", - closeCallback: () => { - dispatch("clearSelection"); - } + let splitscreenConf = { + id: "fairwayprofile", + component: "fairwayprofile", + title: `${rootState.bottlenecks.selectedBottleneck} (${ + rootState.bottlenecks.selectedSurvey.date_info + })`, + icon: "chart-area", + closeCallback: () => { + dispatch("clearSelection"); }, - { root: true } - ); + expandCallback: () => { + let bottleneck = rootState.bottlenecks.bottlenecksList.find( + bn => + bn.properties.name === + rootState.bottlenecks.selectedBottleneck + ); + commit( + "map/moveToExtent", + { + feature: bottleneck, + zoom: 17, + preventZoomOut: true + }, + { root: true } + ); + } + }; + commit("application/addSplitscreen", splitscreenConf, { + root: true + }); + commit("application/activeSplitscreen", "fairwayprofile", { + root: true + }); commit("application/splitscreenLoading", false, { root: true }); commit("profileLoading", false); });