Mercurial > gemma
changeset 548:7feeb341bb4d
Merged
author | Sascha Wilde <wilde@intevation.de> |
---|---|
date | Thu, 30 Aug 2018 14:59:13 +0200 |
parents | 9b67c4f5a7b2 (current diff) 505656a9947f (diff) |
children | b3f825c8445b |
files | |
diffstat | 11 files changed, 237 insertions(+), 230 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/App.vue Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/App.vue Thu Aug 30 14:59:13 2018 +0200 @@ -7,27 +7,22 @@ <style lang="scss"> html { height: 100%; + width: 100%; + margin: 0 auto; } body { - min-height: 100%; + height: 100%; + width: 100%; background-color: #efefef !important; } #app { + height: 100%; + width: 100%; font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } -#nav { - padding: 30px; - a { - font-weight: bold; - color: #2c3e50; - &.router-link-exact-active { - color: #42b983; - } - } -} </style>
--- a/client/src/assets/application.scss Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/assets/application.scss Thu Aug 30 14:59:13 2018 +0200 @@ -10,6 +10,7 @@ $transition: 0.5s; $transition-fast: 0.1s; $transition-slow: 3s; +$topbarheight: 4vh; %fully-centered { position: absolute;
--- a/client/src/components/Layerselect.vue Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/components/Layerselect.vue Thu Aug 30 14:59:13 2018 +0200 @@ -1,11 +1,8 @@ <template> - <div class="d-flex"> - <label :for="layername">{{this.layername}}</label> - <input @change="visibilityToggled" - :id="layername" - type="checkbox" - :checked="isVisible"> - </div> + <div class="form-check d-flex flex-row"> + <input class="form-check-input" @change="visibilityToggled" :id="layername" type="checkbox" :checked="isVisible"> + <label class="form-check-label" :for="layername">{{this.layername}}</label> + </div> </template> <style lang="sass">
--- a/client/src/components/Maplayer.vue Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/components/Maplayer.vue Thu Aug 30 14:59:13 2018 +0200 @@ -1,36 +1,40 @@ <template> <div class="mapdisplay"> <div id="map"></div> - <div v-if="this.openLayersMap" class="layerselection"> - <h4>Layers</h4> - <hr> - <Layerselect :layerindex="index" - :layername="layer.name" - v-for="(layer, index) in layers" - :key="layer.name" - :isVisible="layer.isVisible" - @visibilityToggled="visibilityToggled" - ></Layerselect> + <div v-if="this.openLayersMap" class="card layerselection shadow"> + <div class="card-body"> + <div class="headline"> + <h4 class="card-title">Layers</h4> + </div> + <hr> + <div class="d-flex flex-column"> + <Layerselect :layerindex="index" :layername="layer.name" v-for="(layer, index) in layers" :key="layer.name" :isVisible="layer.isVisible" @visibilityToggled="visibilityToggled"></Layerselect> + </div> + </div> </div> </div> </template> <style lang="scss"> +@import "../assets/application.scss"; + .mapdisplay { height: 100%; - width: 100%; } + #map { - height: 100%; - width: 100%; + height: 96vh; } + .layerselection { position: absolute; - top: 0; - right: 0; + top: $topbarheight; + margin-top: $small-offset; + right: $small-offset; min-height: 20%; min-width: 10%; background-color: white; + z-index: 10; } </style>
--- a/client/src/components/Sidebar.vue Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/components/Sidebar.vue Thu Aug 30 14:59:13 2018 +0200 @@ -1,6 +1,5 @@ <template> <div :class="sidebarStyle"> - <div :class="collapseStyle"><i @click="collapse" :class="collapseicon"></i></div> <nav :class="menuStyle"> <router-link to="/" class="d-flex nav-link">Riverbed Morphology</router-link> <a class="d-flex nav-link" href="#">Link</a> @@ -13,10 +12,13 @@ </nav> <div :class="userinfoStyle"> <div class="menupadding userinfo"> - <img class="userpic" src="../assets/user.png"><span class="username">{{ userinfo }}</span> + <img class="userpic" src="../assets/user.png"> + <span class="username">{{ userinfo }}</span> </div> <div> - <span class="logout" @click="logoff"><i class="fa fa-power-off"></i></span> + <span class="logout" @click="logoff"> + <i class="fa fa-power-off"></i> + </span> </div> </div> </div> @@ -27,62 +29,48 @@ export default { name: "sidebar", - props: ["isOverlay"], computed: { ...mapGetters("user", ["userinfo", "isSysAdmin"]), - collapseicon() { - return { - fa: true, - "fa-angle-double-left": !this.isCollapsed, - "fa-angle-double-right": this.isCollapsed - }; - }, + ...mapGetters("application", ["sidebarCollapsed"]), menuStyle() { return { menu: true, nav: true, "flex-column": true, - "visibility-extended": !this.isCollapsed, - "visibility-collapsed": this.isCollapsed + "visibility-extended": !this.sidebarCollapsed, + "visibility-collapsed": this.sidebarCollapsed }; }, userinfoStyle() { return { user: true, "d-flex": true, - "visibility-extended": !this.isCollapsed, - "visibility-collapsed": this.isCollapsed + "visibility-extended": !this.sidebarCollapsed, + "visibility-collapsed": this.sidebarCollapsed }; }, collapseStyle() { return { collapser: true, - collapserextended: !this.isCollapsed, - collapsercollapsed: this.isCollapsed + collapserextended: !this.sidebarCollapsed, + collapsercollapsed: this.sidebarCollapsed }; }, sidebarStyle() { return { sidebar: true, - overlay: this.isOverlay, - sidebarcollapsed: this.isCollapsed, - sidebarextended: !this.isCollapsed + overlay: true, + sidebarcollapsed: this.sidebarCollapsed, + sidebarextended: !this.sidebarCollapsed, + shadow: true }; } }, methods: { - collapse() { - this.isCollapsed = !this.isCollapsed; - }, logoff() { this.$store.commit("user/clear_auth"); this.$router.push("/login"); } - }, - data() { - return { - isCollapsed: false - }; } }; </script> @@ -137,9 +125,10 @@ margin-top: auto; } .sidebar { + margin-top: $topbarheight; background-color: #ffffff; padding-top: $large-offset; - height: 100vh; + height: 96vh; } .overlay {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/components/Topbar.vue Thu Aug 30 14:59:13 2018 +0200 @@ -0,0 +1,24 @@ +<template> + <div class="topbar shadow-sm d-flex flex-row justify-content-between"> + <div class="align-self-center"> + <i @click="toggleSidebar" class="menubutton fa fa-bars"></i> + </div> + <div class=""> + <h2>Topbar</h2> + </div> + <div> + + </div> + </div> +</template> + +<script> +export default { + name: "topbar", + methods: { + toggleSidebar() { + this.$store.commit("application/toggleSidebar"); + } + } +}; +</script>
--- a/client/src/stores/application.js Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/stores/application.js Thu Aug 30 14:59:13 2018 +0200 @@ -4,7 +4,7 @@ appTitle: process.env.VUE_APP_TITLE, secondaryLogo: process.env.VUE_APP_SECONDARY_LOGO_URL, sidebar: { - iscollapsed: false + iscollapsed: true }, countries: ["AT", "SK", "HU", "HR", "RS", "BiH", "BG", "RO", "UA"] }, @@ -23,8 +23,8 @@ } }, mutations: { - toggleSidebar: () => { - this.sidebar.iscollapsed = !this.sidebar.iscollapsed; + toggleSidebar: state => { + state.sidebar.iscollapsed = !state.sidebar.iscollapsed; } }, actions: {}
--- a/client/src/views/Login.vue Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/views/Login.vue Thu Aug 30 14:59:13 2018 +0200 @@ -1,138 +1,90 @@ (<template> - <div :class="loginStyle"> - <div> - <div class="logogroup d-flex flex-row justify-content-center"> + <div class="d-flex flex-column login shadow-lg"> + <div class="loginmask"> + <!-- logo section --> + <div class="d-flex flex-row justify-content-center mb-3"> <div class="logo"><img src="../assets/logo.png"></div> - <div class="title"><h1>{{ appTitle }}</h1></div> + <div class="title"> + <h1>{{ appTitle }}</h1> + </div> </div> - </div> - <div class="login-wrapper d-flex flex-row justify-content-center"> - <form class="loginform form-signin" @submit.prevent="login"> - <div id="alert" v-if="loginFailed" class="loginerrormessage alert alert-danger" role="alert"> - <span class="loginerror"><translate>Login failed</translate></span> - </div> - <div id="alert" v-if="passwordJustResetted" - class="loginerrormessage alert alert-danger" role="alert"> - <span class="loginerror" - ><translate>Password reset requested!</translate></span> - </div> - <div class="input-group mb-3 usernamegroup"> - <input type="text" v-model="user" id="inputUsername" class="form-control" :placeholder="usernameLabel" required autofocus> + <!-- end logo section --> + <div id="alert" :style="errorMessageStyle" :class="errorMessageClass" role="alert"> + <span>{{ errorMessage }}</span> + </div> + <form class="loginform" @submit.prevent="login"> + <div class="input-group mb-3"> + <input type="text" v-model="user" id="inputUsername" class="form-control shadow-sm" :placeholder="usernameLabel" required autofocus> </div> - <div class="input-group mb-3 passwordgroup"> - <input :type="isPasswordVisible" v-model="password" - id="inputPassword" class="form-control" - :placeholder='passwordLabel' - :required='!showPasswordReset' :disabled='showPasswordReset'> + <div class="input-group mb-3"> + <input :type="isPasswordVisible" v-model="password" id="inputPassword" class="form-control shadow-sm" :placeholder='passwordLabel' :required='!showPasswordReset' :disabled='showPasswordReset'> <div class="input-group-append"> - <span class="input-group-text disabled" id="basic-addon2" - @click="showPassword"><i :class="eyeIcon"></i></span> + <span class="input-group-text disabled" id="basic-addon2" @click="showPassword"> + <i :class="eyeIcon"></i> + </span> </div> </div> - <button class="submitbutton btn btn-primary btn-block" - :disabled="submitted || showPasswordReset" type="submit" - ><translate>Login</translate></button> - </form> - </div> - - <!-- password forgotten part --> - <div class="d-flex flex-row justify-content-center"> - <form class="loginform form-signin"> + <button v-if="showPasswordReset==false" class="btn btn-primary btn-block shadow-sm" :disabled="submitted || showPasswordReset" type="submit"> + <translate>Login</translate> + </button> <div v-if="showPasswordReset" class="passwordreset"> - <!-- - TODO text and action for password reset - <div class="input-group mb-3 usernamegroup"> - <input type="text" v-model="usernameToReset" class="form-control" :placeholder="usernameLabel" required> + <button class="btn btn-block btn-info" type="button" @click="resetPassword"> + <translate>Request password reset!</translate> + </button> + <div class="pull-right"> + <a href="#" @click.prevent="togglePasswordReset"> + <translate>back to login</translate> + </a> </div> - --> - <button class="btn btn-warning btn-block" type="button" - @click="resetPassword" - ><translate>Request password reset!</translate></button> - <div class="forgottenlink small"> - <a href="#" @click.prevent="togglePasswordReset" - ><translate>back to login</translate></a></div> + </div> + <div v-else class="pull-right"> + <a href="#" @click.prevent="togglePasswordReset"> + <translate>Forgot password</translate> + </a> </div> - <div v-else class="forgottenlink small"> - <a href="#" @click.prevent="togglePasswordReset" - ><translate>Forgot password</translate></a></div> </form> + + <!-- bottom logo section --> + <div class="mb-3 secondary-logo"><img :src="secondaryLogo"></div> </div> - - <!-- bottom logo section --> - <div class="secondary-logo d-flex flex-row justify-content-center" - ><img :src="secondaryLogo"></div> </div> </template>) <style lang="scss"> @import "../assets/application.scss"; -$logincollapsed: 470px; -$loginextended: 550px; -.usernamegroup { - box-shadow: $basic-shadow-light !important; -} -.forgottenlink { - text-align: right; - margin-top: $small-offset; - margin-bottom: $small-offset; -} -#inputPassword { - border-right: none; -} -.input-group-text { - background-color: white !important; +.login { + background-color: white; + min-width: 375px; + min-height: 500px; + @extend %fully-centered; } -.login { - width: 375px; - @extend %fully-centered; - padding-top: $offset; - padding-bottom: $offset; - box-shadow: $basic-shadow; -} -.logincollapsed { - height: $logincollapsed; +.loginform { + max-width: 375px; + margin-left: auto; + margin-right: auto; } -.loginextended { - height: $loginextended; -} -.loginerror { - white-space: pre; +.loginmask { + margin-left: $large-offset; + margin-right: $large-offset; + margin-top: $large-offset; } -.loginerrormessage { - box-shadow: $basic-shadow-light !important; -} -.loginform { - width: 300px; -} -.logogroup { - margin-top: $offset; - margin-bottom: $offset; + +.logo { + margin-right: $offset; } -.passwordreset { - margin-top: $offset; - margin-bottom: $offset; -} -.mail-icon { - width: $iconwidth; -} -.passwordgroup { - box-shadow: $basic-shadow-light !important; + +.alert { + padding: 0.5rem; } -.password-icon { - position: relative; - top: 10px; - font-size: $iconsize; - line-height: $iconLineHeight; - width: $iconwidth; -} -.submitbutton { - box-shadow: $basic-shadow-light !important; -} -.title { - margin-left: $offset; + +.secondary-logo { + max-width: 375px; + margin-left: auto; + margin-right: auto; + margin-bottom: auto; } </style> @@ -155,6 +107,12 @@ }; }, computed: { + errorMessage() { + if (this.loginFailed) return this.$gettext("Login failed"); + if (this.passwordJustResetted) + return this.$gettext("Password reset requested!"); + return "&npsp;"; + }, passwordLabel() { return this.$gettext("Enter passphrase"); }, @@ -171,14 +129,25 @@ "fa-eye-slash": this.readablePassword }; }, - loginStyle() { - return { - login: true, - logincollapsed: !this.loginFailed, - loginextended: this.loginFailed, - "bg-white": true, - rounded: true + errorMessageStyle() { + if (this.loginFailed || this.passwordJustResetted) { + return "visibility:visible"; + } + return "visibility:hidden"; + }, + errorMessageClass() { + let result = { + "mb-3": true, + errormessage: true, + alert: true }; + if (this.loginFailed) { + result["alert-danger"] = true; + } + if (this.passwordJustResetted) { + result["alert-info"] = true; + } + return result; }, ...mapGetters("application", ["appTitle", "secondaryLogo"]) }, @@ -207,6 +176,7 @@ togglePasswordReset() { this.passwordJustResetted = false; this.showPasswordReset = !this.showPasswordReset; + this.loginFailed = false; }, resetPassword() { if (this.user) {
--- a/client/src/views/Main.vue Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/views/Main.vue Thu Aug 30 14:59:13 2018 +0200 @@ -1,32 +1,34 @@ <template> - <div class="main d-flex"> - <Sidebar v-bind:isOverlay="true"></Sidebar> - <Maplayer :lat="6155376" - :long="1819178" - :zoom="11" - ></Maplayer> + <div class="main d-flex flex-column"> + <Topbar></Topbar> + <Sidebar></Sidebar> + <Maplayer :lat="6155376" :long="1819178" :zoom="11"></Maplayer> </div> </template> <style lang="scss"> -.main { - height: 100vh; +@import "../assets/application.scss"; +.topbar { + background-color: white; + height: $topbarheight; + z-index: 10; } -#map { - background-color: #ffffff; - width: 100%; +.menubutton { + margin-left: $small-offset; } </style> <script> import Maplayer from "../components/Maplayer"; import Sidebar from "../components/Sidebar"; +import Topbar from "../components/Topbar"; export default { name: "mainview", components: { Maplayer, - Sidebar + Sidebar, + Topbar } }; </script>
--- a/client/src/views/Users.vue Wed Aug 29 16:45:22 2018 +0200 +++ b/client/src/views/Users.vue Thu Aug 30 14:59:13 2018 +0200 @@ -1,42 +1,64 @@ <template> - <div class="main d-flex"> - <Sidebar v-bind:isOverlay="false"></Sidebar> + <div class="main d-flex flex-column"> + <Topbar></Topbar> + <Sidebar></Sidebar> <div class="d-flex content flex-column"> - <div class="d-flex flex-row"> - <div :class="userlistStyle"> - <div class="card"> - <div class="card-header shadow-sm text-white bg-info mb-3"> - Users - </div> - <div class="card-body"> - <table id="datatable" :class="tableStyle"> - <thead> - <tr> - <th scope="col" @click="sortBy('user')" ><span>Username <i v-if="sortCriterion=='user'" class="fa fa-angle-down"></i></span></th> - <th scope="col" @click="sortBy('country')"><span>Country <i v-if="sortCriterion=='country'" class="fa fa-angle-down"></i></span></th> - <th scope="col" @click="sortBy('email')"><span>Email <i v-if="sortCriterion=='email'" class="fa fa-angle-down"></i></span></th> - <th scope="col" @click="sortBy('role')"><span>Role <i v-if="sortCriterion=='role'" class="fa fa-angle-down"></i></span></th> - <th scope="col"></th> - </tr> - </thead> - <tbody> - <tr v-for="user in users" :key="user.user" @click="selectUser(user.user)"> - <td>{{ user.user }}</td> - <td>{{ user.country }}</td> - <td>{{ user.email}}</td> - <td>{{ user.role }}</td> - <td><i @click="deleteUser(user.user)" class="fa fa-trash-o"></i></td> - </tr> - </tbody> - </table> - </div> - <div><i @click="prevPage" v-if="this.currentPage!=1" class="pages fa fa-caret-left"></i> {{this.currentPage}} / {{this.pages}} <i @click="nextPage" class="pages fa fa-caret-right"></i></div> - <div class="adduser"> - <button @click="addUser" class="btn btn-info pull-right shadow-sm">Add User</button> - </div> + <div class="d-flex flex-row"> + <div :class="userlistStyle"> + <div class="card"> + <div class="card-header shadow-sm text-white bg-info mb-3"> + Users + </div> + <div class="card-body"> + <table id="datatable" :class="tableStyle"> + <thead> + <tr> + <th scope="col" @click="sortBy('user')"> + <span>Username + <i v-if="sortCriterion=='user'" class="fa fa-angle-down"></i> + </span> + </th> + <th scope="col" @click="sortBy('country')"> + <span>Country + <i v-if="sortCriterion=='country'" class="fa fa-angle-down"></i> + </span> + </th> + <th scope="col" @click="sortBy('email')"> + <span>Email + <i v-if="sortCriterion=='email'" class="fa fa-angle-down"></i> + </span> + </th> + <th scope="col" @click="sortBy('role')"> + <span>Role + <i v-if="sortCriterion=='role'" class="fa fa-angle-down"></i> + </span> + </th> + <th scope="col"></th> + </tr> + </thead> + <tbody> + <tr v-for="user in users" :key="user.user" @click="selectUser(user.user)"> + <td>{{ user.user }}</td> + <td>{{ user.country }}</td> + <td>{{ user.email}}</td> + <td>{{ user.role }}</td> + <td> + <i @click="deleteUser(user.user)" class="fa fa-trash-o"></i> + </td> + </tr> + </tbody> + </table> + </div> + <div> + <i @click="prevPage" v-if="this.currentPage!=1" class="pages fa fa-caret-left"></i> {{this.currentPage}} / {{this.pages}} + <i @click="nextPage" class="pages fa fa-caret-right"></i> + </div> + <div class="adduser"> + <button @click="addUser" class="btn btn-info pull-right shadow-sm">Add User</button> </div> </div> - <Userdetail v-if="isUserDetailsVisible"></Userdetail> + </div> + <Userdetail v-if="isUserDetailsVisible"></Userdetail> </div> </div> </div> @@ -103,6 +125,7 @@ <script> import Sidebar from "../components/Sidebar"; +import Topbar from "../components/Topbar"; import Userdetail from "../components/Userdetail"; import store from "../store"; import { mapGetters } from "vuex"; @@ -119,7 +142,8 @@ }, components: { Sidebar, - Userdetail + Userdetail, + Topbar }, computed: { ...mapGetters("usermanagement", ["isUserDetailsVisible"]),
--- a/pkg/controllers/proxy.go Wed Aug 29 16:45:22 2018 +0200 +++ b/pkg/controllers/proxy.go Thu Aug 30 14:59:13 2018 +0200 @@ -33,6 +33,7 @@ "http://www.opengis.net/gml/3.2": struct{}{}, "http://www.opengis.net/fes/2.0": struct{}{}, "http://schemas.opengis.net/gml": struct{}{}, + "http://www.opengis.net/wfs": struct{}{}, } func proxyDirector(lookup func(string) (string, bool)) func(*http.Request) {