changeset 542:505656a9947f

refac: layout refactored Introduced Topbar and Hamburger Menu
author Thomas Junk <thomas.junk@intevation.de>
date Thu, 30 Aug 2018 14:39:24 +0200
parents ee86ab038a7e
children b111b765b6cd 7feeb341bb4d
files client/src/App.vue client/src/assets/application.scss client/src/components/Layerselect.vue client/src/components/Maplayer.vue client/src/components/Sidebar.vue client/src/components/Topbar.vue client/src/stores/application.js client/src/views/Main.vue client/src/views/Users.vue
diffstat 9 files changed, 147 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/App.vue	Thu Aug 30 12:57:27 2018 +0200
+++ b/client/src/App.vue	Thu Aug 30 14:39:24 2018 +0200
@@ -11,11 +11,14 @@
   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;
--- a/client/src/assets/application.scss	Thu Aug 30 12:57:27 2018 +0200
+++ b/client/src/assets/application.scss	Thu Aug 30 14:39:24 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	Thu Aug 30 12:57:27 2018 +0200
+++ b/client/src/components/Layerselect.vue	Thu Aug 30 14:39:24 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	Thu Aug 30 12:57:27 2018 +0200
+++ b/client/src/components/Maplayer.vue	Thu Aug 30 14:39:24 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	Thu Aug 30 12:57:27 2018 +0200
+++ b/client/src/components/Sidebar.vue	Thu Aug 30 14:39:24 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:39:24 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	Thu Aug 30 12:57:27 2018 +0200
+++ b/client/src/stores/application.js	Thu Aug 30 14:39:24 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/Main.vue	Thu Aug 30 12:57:27 2018 +0200
+++ b/client/src/views/Main.vue	Thu Aug 30 14:39:24 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	Thu Aug 30 12:57:27 2018 +0200
+++ b/client/src/views/Users.vue	Thu Aug 30 14:39:24 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&nbsp;<i v-if="sortCriterion=='user'" class="fa fa-angle-down"></i></span></th>
-                        <th scope="col" @click="sortBy('country')"><span>Country&nbsp;<i v-if="sortCriterion=='country'" class="fa fa-angle-down"></i></span></th>
-                        <th scope="col" @click="sortBy('email')"><span>Email&nbsp;<i v-if="sortCriterion=='email'" class="fa fa-angle-down"></i></span></th>
-                        <th scope="col" @click="sortBy('role')"><span>Role&nbsp;<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&nbsp;
+                        <i v-if="sortCriterion=='user'" class="fa fa-angle-down"></i>
+                      </span>
+                    </th>
+                    <th scope="col" @click="sortBy('country')">
+                      <span>Country&nbsp;
+                        <i v-if="sortCriterion=='country'" class="fa fa-angle-down"></i>
+                      </span>
+                    </th>
+                    <th scope="col" @click="sortBy('email')">
+                      <span>Email&nbsp;
+                        <i v-if="sortCriterion=='email'" class="fa fa-angle-down"></i>
+                      </span>
+                    </th>
+                    <th scope="col" @click="sortBy('role')">
+                      <span>Role&nbsp;
+                        <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"]),