Mercurial > gemma
changeset 629:8278b2fb0c33
refac: UI refactorization
1) Leverage webpacks ability to import some scss sheets globally to omit
importing sheets in every component
2) making "sidebar" collapsible in a 2d way
3) fixed flickering user menu
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Wed, 12 Sep 2018 12:23:11 +0200 |
parents | ef9c733cc6aa |
children | 855cca0142ec |
files | client/src/application/Main.vue client/src/application/Sidebar.vue client/src/application/Topbar.vue client/src/application/User.vue client/src/application/assets/application.scss client/src/layers/Layers.vue client/src/login/Login.vue client/src/map/Maplayer.vue client/src/usermanagement/Userdetail.vue client/src/usermanagement/Usermanagement.vue client/src/usermanagement/Users.vue client/vue.config.js |
diffstat | 12 files changed, 249 insertions(+), 231 deletions(-) [+] |
line wrap: on
line diff
--- a/client/src/application/Main.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/application/Main.vue Wed Sep 12 12:23:11 2018 +0200 @@ -8,8 +8,6 @@ </template> <style lang="scss"> -@import "../application/assets/application.scss"; - .profile { background-color: white; height: 50vh;
--- a/client/src/application/Sidebar.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/application/Sidebar.vue Wed Sep 12 12:23:11 2018 +0200 @@ -1,14 +1,16 @@ <template> <div :class="sidebarStyle"> <div :class="menuStyle"> - <router-link to="/" class="text-body d-flex flex-row nav-link"> - <i class="fa fa-map-o align-self-center navicon"></i>Riverbed Morphology</router-link> - <div v-if="isSysAdmin"> - <hr/> - <div class="nav-link d-flex menupadding text-muted">Administration</div> - <router-link class="text-body d-flex flex-row nav-link" to="usermanagement"> - <i class="fa fa-address-card-o align-self-center navicon"></i>Users - </router-link> + <div class="menupoints" v-if="!this.sidebarCollapsed"> + <router-link to="/" class="text-body d-flex flex-row nav-link"> + <i class="fa fa-map-o align-self-center navicon"></i>Riverbed Morphology</router-link> + <div v-if="isSysAdmin"> + <hr/> + <div class="nav-link d-flex menupadding text-muted">Administration</div> + <router-link class="text-body d-flex flex-row nav-link" to="usermanagement"> + <i class="fa fa-address-card-o align-self-center navicon"></i>Users + </router-link> + </div> </div> </div> </div> @@ -44,7 +46,9 @@ </script> <style lang="scss"> -@import "./assets/application.scss"; +.menupoints { + text-align: left; +} .router-link-exact-active { background-color: #f2f2f2; @@ -73,10 +77,13 @@ } .sidebarcollapsed { - display: none; + height: 30px; + width: 30px; + transition: 0.3s; } .sidebarextended { - display: block; + height: 400px; + width: 215px; } </style>
--- a/client/src/application/Topbar.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/application/Topbar.vue Wed Sep 12 12:23:11 2018 +0200 @@ -19,8 +19,6 @@ </template> <style lang="scss"> -@import "./assets/application.scss"; - .splitscreen { background-color: white; padding: 0.5rem;
--- a/client/src/application/User.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/application/User.vue Wed Sep 12 12:23:11 2018 +0200 @@ -1,24 +1,41 @@ <template> - <div :class="userManagementStyle"> - <img @click="extendUserMenu" class="userpic" src="../application/assets/user.png"> - <span v-if="!isUsermenuCollapsed" class="username align-self-center">{{ userinfo }}</span> - <span v-if="!isUsermenuCollapsed" class="logout align-self-center" @click="logoff"> - <i class="fa fa-power-off"></i> - </span> + <div> + <img @click="extendUserMenu" class="ui-element userpic" src="../application/assets/user.png"> + <div :class="userManagementStyle"> + <span v-if="!isUsermenuCollapsed" class="username align-self-center">{{ userinfo }}</span> + <span v-if="!isUsermenuCollapsed" class="logout align-self-center" @click="logoff"> + <i class="fa fa-power-off"></i> + </span> + </div> </div> </template> <style lang="scss"> +.userpic { + background: white; + position: absolute; + bottom: $offset; + left: $offset; + height: 45px; + border-radius: $border-radius; +} + +.username { + margin-left: 40px; +} + .usermanagement { background: white; - margin-left: 1rem; - padding: 0.25rem; - border-radius: 5px; - margin-bottom: 1rem; + margin-left: $offset; + padding: $x-small-offset; + border-radius: $border-radius; + margin-bottom: $offset; + height: 45px; } .usermanagementcollapsed { - width: 50px; + transition: 0.3s; + width: 40px; } .usermanagementexpanded {
--- a/client/src/application/assets/application.scss Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/application/assets/application.scss Wed Sep 12 12:23:11 2018 +0200 @@ -1,16 +1,15 @@ $offset: 1rem; $small-offset: 0.5rem; +$x-small-offset: 0.25rem; $large-offset: 2rem; $x-large-offset: 3rem; -$iconsize: 3rem; -$iconLineHeight: 0.25rem; -$iconwidth: 20px; $basic-shadow: 1px 3px 8px 2px rgba(220, 220, 220, 0.75); $basic-shadow-light: 1px 1px 12px 1px rgba(235, 235, 235, 0.75); $transition: 0.5s; $transition-fast: 0.1s; $transition-slow: 3s; -$topbarheight: 5vh; +$smaller: 0.9rem; +$border-radius: 5px; .debug { border: 1px solid red;
--- a/client/src/layers/Layers.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/layers/Layers.vue Wed Sep 12 12:23:11 2018 +0200 @@ -13,8 +13,6 @@ </template> <style lang="scss"> -@import "../application/assets/application.scss"; - .layerselection { background-color: white; margin-left: 0.5rem;
--- a/client/src/login/Login.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/login/Login.vue Wed Sep 12 12:23:11 2018 +0200 @@ -51,8 +51,6 @@ </template>) <style lang="scss"> -@import "../application/assets/application.scss"; - .login { background-color: white; min-width: 375px;
--- a/client/src/map/Maplayer.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/map/Maplayer.vue Wed Sep 12 12:23:11 2018 +0200 @@ -3,8 +3,6 @@ </template> <style lang="scss"> -@import "../application/assets/application.scss"; - .mapsplit { height: 50vh; }
--- a/client/src/usermanagement/Userdetail.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/usermanagement/Userdetail.vue Wed Sep 12 12:23:11 2018 +0200 @@ -1,80 +1,78 @@ <template> - <div class="userdetails shadow fadeIn animated"> - <div class="card"> - <div class="card-header shadow-sm text-white bg-info mb-3"> - {{ this.cardHeader }} - <span @click="closeDetailview" class="pull-right"> - <i class="fa fa-close"></i> - </span> - </div> - <div class="card-body"> - <form @submit.prevent="save"> - <div class="formfields"> - <div v-if="currentUser.isNew" class="form-group row"> - <label for="user">Username</label> - <input type="user" :placeholder="userNamePlaceholder" class="form-control form-control-sm" id="user" aria-describedby="userHelp" v-model="currentUser.user"> - <div v-show="errors.user" class="text-danger"> - <small> - <i class="fa fa-warning"></i> {{ errors.user }}</small> - </div> - </div> - <div class="form-group row"> - <label for="country">Country</label> - <select class="form-control form-control-sm" v-on:change="validateCountry" v-model="currentUser.country"> - <option disabled value="">Please select one</option> - <option v-for="country in countries" v-bind:value="country" v-bind:key="country">{{country}}</option> - </select> - <div v-show="errors.country" class="text-danger"> - <small> - <i class="fa fa-warning"></i> {{ errors.country }}</small> - </div> + <div class="userdetails shadow fadeIn animated"> + <div class="card"> + <div class="card-header shadow-sm text-white bg-info mb-3"> + {{ this.cardHeader }} + <span @click="closeDetailview" class="pull-right"> + <i class="fa fa-close"></i> + </span> </div> - <div class="form-group row"> - <label for="email">Email address</label> - <input type="email" v-on:change="validateEmailaddress" class="form-control form-control-sm" id="email" aria-describedby="emailHelp" v-model="currentUser.email"> - <div v-show="errors.email" class="text-danger"> - <small> - <i class="fa fa-warning"></i> {{ errors.email }}</small> - </div> + <div class="card-body"> + <form @submit.prevent="save"> + <div class="formfields"> + <div v-if="currentUser.isNew" class="form-group row"> + <label for="user">Username</label> + <input type="user" :placeholder="userNamePlaceholder" class="form-control form-control-sm" id="user" aria-describedby="userHelp" v-model="currentUser.user"> + <div v-show="errors.user" class="text-danger"> + <small> + <i class="fa fa-warning"></i> {{ errors.user }}</small> + </div> + </div> + <div class="form-group row"> + <label for="country">Country</label> + <select class="form-control form-control-sm" v-on:change="validateCountry" v-model="currentUser.country"> + <option disabled value="">Please select one</option> + <option v-for="country in countries" v-bind:value="country" v-bind:key="country">{{country}}</option> + </select> + <div v-show="errors.country" class="text-danger"> + <small> + <i class="fa fa-warning"></i> {{ errors.country }}</small> + </div> + </div> + <div class="form-group row"> + <label for="email">Email address</label> + <input type="email" v-on:change="validateEmailaddress" class="form-control form-control-sm" id="email" aria-describedby="emailHelp" v-model="currentUser.email"> + <div v-show="errors.email" class="text-danger"> + <small> + <i class="fa fa-warning"></i> {{ errors.email }}</small> + </div> + </div> + <div class="form-group row"> + <label for="role">Role</label> + <select class="form-control form-control-sm" v-on:change="validateRole" v-model="currentUser.role"> + <option disabled value="">Please select one</option> + <option value="sys_admin">Sysadmin</option> + <option value="waterway_admin">Waterway Admin</option> + <option value="waterway_user">Waterway User</option> + </select> + <div v-show="errors.role" class="text-danger"> + <small> + <i class="fa fa-warning"></i> {{ errors.role }}</small> + </div> + </div> + <div class="form-group row"> + <PasswordField @fieldchange="passwordChanged" :placeholder="passwordPlaceholder" :label="passwordLabel" :passworderrors="errors.password"></PasswordField> + </div> + <div class="form-group row"> + <PasswordField @fieldchange="passwordReChanged" :placeholder="passwordRePlaceholder" :label="passwordReLabel" :passworderrors="errors.passwordre"></PasswordField> + </div> + </div> + <div> + <button type="submit" :disabled="submitted" class="shadow-sm btn btn-info pull-right">Submit</button> + </div> + </form> </div> - <div class="form-group row"> - <label for="role">Role</label> - <select class="form-control form-control-sm" v-on:change="validateRole" v-model="currentUser.role"> - <option disabled value="">Please select one</option> - <option value="sys_admin">Sysadmin</option> - <option value="waterway_admin">Waterway Admin</option> - <option value="waterway_user">Waterway User</option> - </select> - <div v-show="errors.role" class="text-danger"> - <small> - <i class="fa fa-warning"></i> {{ errors.role }}</small> - </div> - </div> - <div class="form-group row"> - <PasswordField @fieldchange="passwordChanged" :placeholder="passwordPlaceholder" :label="passwordLabel" :passworderrors="errors.password"></PasswordField> - </div> - <div class="form-group row"> - <PasswordField @fieldchange="passwordReChanged" :placeholder="passwordRePlaceholder" :label="passwordReLabel" :passworderrors="errors.passwordre"></PasswordField> - </div> - </div> - <div> - <button type="submit" :disabled="submitted" class="shadow-sm btn btn-info pull-right">Submit</button> - </div> - </form> - </div> + </div> </div> - </div> </template> <style lang="scss"> -@import "../application/assets/application.scss"; - .formfields { width: 10vw; } .userdetails { - margin-top: $topbarheight; + margin-top: $offset; min-width: 40vw; margin-right: auto; height: 100%; @@ -82,7 +80,7 @@ form { margin-left: $offset; - font-size: 0.9rem; + font-size: $smaller; } </style> <script>
--- a/client/src/usermanagement/Usermanagement.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/usermanagement/Usermanagement.vue Wed Sep 12 12:23:11 2018 +0200 @@ -1,76 +1,75 @@ <template> - <div class="main d-flex flex-column"> - <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> - <i v-tooltip="user.roleLabel" :class="{ + <div class="main d-flex flex-column"> + <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> + <i v-tooltip="user.roleLabel" :class="{ fa:true, icon:true, 'fa-user':user.role==='waterway_user', 'fa-star':user.role=='sys_admin', 'fa-adn':user.role==='waterway_admin'}"></i> - </td> - <td> - <i @click="deleteUser(user.user)" class="icon fa fa-trash-o"></i> - </td> - </tr> - </tbody> - </table> + </td> + <td> + <i @click="deleteUser(user.user)" class="icon fa fa-trash-o"></i> + </td> + </tr> + </tbody> + </table> + </div> + <div class="d-flex flex-row pagination"> + <i @click=" prevPage " v-if="this.currentPage!=1 " class="backwards btn btn-sm btn-light align-self-center pages fa fa-caret-left "></i> {{this.currentPage}} / {{this.pages}} + <i @click="nextPage " class="forwards btn btn-sm btn-light align-self-center 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> + </div> + <Userdetail v-if="isUserDetailsVisible "></Userdetail> </div> - <div class="d-flex flex-row pagination"> - <i @click=" prevPage " v-if="this.currentPage!=1 " class="backwards btn btn-sm btn-light align-self-center pages fa fa-caret-left "></i> {{this.currentPage}} / {{this.pages}} - <i @click="nextPage " class="forwards btn btn-sm btn-light align-self-center 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> </div> - <Userdetail v-if="isUserDetailsVisible "></Userdetail> - </div> </div> - </div> </template> <style lang="scss"> -@import "../application/assets/application.scss"; @import "../application/assets/tooltip.scss"; .main { @@ -78,15 +77,14 @@ } .backwards { - margin-right: 0.5rem; + margin-right: $small-offset; } .forwards { - margin-left: 0.5rem; + margin-left: $small-offset; } .content { - margin-top: $large-offset; margin-left: auto; margin-right: auto; } @@ -101,7 +99,7 @@ } .userlist { - margin-top: $topbarheight; + margin-top: $offset; margin-right: $offset; min-width: 520px; height: 100%; @@ -131,14 +129,14 @@ .table th, td { - font-size: 0.9rem; + font-size: $smaller; border-top: 0px !important; text-align: left; - padding: 0.5rem !important; + padding: $small-offset !important; } .table td { - font-size: 0.9rem; + font-size: $smaller; cursor: pointer; }
--- a/client/src/usermanagement/Users.vue Tue Sep 11 17:52:20 2018 +0200 +++ b/client/src/usermanagement/Users.vue Wed Sep 12 12:23:11 2018 +0200 @@ -1,76 +1,75 @@ <template> - <div class="main d-flex flex-column"> - <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> - <i v-tooltip="user.roleLabel" :class="{ + <div class="main d-flex flex-column"> + <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> + <i v-tooltip="user.roleLabel" :class="{ fa:true, icon:true, 'fa-user':user.role==='waterway_user', 'fa-star':user.role=='sys_admin', 'fa-adn':user.role==='waterway_admin'}"></i> - </td> - <td> - <i @click="deleteUser(user.user)" class="icon fa fa-trash-o"></i> - </td> - </tr> - </tbody> - </table> + </td> + <td> + <i @click="deleteUser(user.user)" class="icon fa fa-trash-o"></i> + </td> + </tr> + </tbody> + </table> + </div> + <div class="d-flex flex-row pagination"> + <i @click=" prevPage " v-if="this.currentPage!=1 " class="backwards btn btn-sm btn-light align-self-center pages fa fa-caret-left "></i> {{this.currentPage}} / {{this.pages}} + <i @click="nextPage " class="forwards btn btn-sm btn-light align-self-center 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> + </div> + <Userdetail v-if="isUserDetailsVisible "></Userdetail> </div> - <div class="d-flex flex-row pagination"> - <i @click=" prevPage " v-if="this.currentPage!=1 " class="backwards btn btn-sm btn-light align-self-center pages fa fa-caret-left "></i> {{this.currentPage}} / {{this.pages}} - <i @click="nextPage " class="forwards btn btn-sm btn-light align-self-center 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> </div> - <Userdetail v-if="isUserDetailsVisible "></Userdetail> - </div> </div> - </div> </template> <style lang="scss"> -@import "../application/assets/application.scss"; @import "../application/assets/tooltip.scss"; .main { height: 100vh;
--- a/client/vue.config.js Tue Sep 11 17:52:20 2018 +0200 +++ b/client/vue.config.js Wed Sep 12 12:23:11 2018 +0200 @@ -23,6 +23,16 @@ } ]); }, + css: { + loaderOptions: { + // pass options to sass-loader + sass: { + // @/ is an alias to src/ + // so this assumes you have a file named `src/variables.scss` + data: `@import "@/application/assets/application.scss";` + } + } + }, devServer: { proxy: { "/api": {