Browse Source

ux: sidemenu toggling

Torkel Ödegaard 8 years ago
parent
commit
4dd4631b87

+ 6 - 27
public/app/core/components/grafana_app.ts

@@ -70,31 +70,19 @@ export function grafanaAppDirective(playlistSrv, contextSrv) {
     restrict: 'E',
     controller: GrafanaCtrl,
     link: (scope, elem) => {
-      var ignoreSideMenuHide;
+      var sidemenuOpen;
       var body = $('body');
 
       // see https://github.com/zenorocha/clipboard.js/issues/155
       $.fn.modal.Constructor.prototype.enforceFocus = function() {};
 
-      // handle sidemenu open state
+      sidemenuOpen = scope.contextSrv.sidemenu;
+      body.toggleClass('sidemenu-open', sidemenuOpen);
+
       scope.$watch('contextSrv.sidemenu', newVal => {
-        if (newVal !== undefined) {
+        if (sidemenuOpen !== scope.contextSrv.sidemenu) {
+          sidemenuOpen = scope.contextSrv.sidemenu;
           body.toggleClass('sidemenu-open', scope.contextSrv.sidemenu);
-          if (!newVal) {
-            contextSrv.setPinnedState(false);
-          }
-        }
-        if (contextSrv.sidemenu) {
-          ignoreSideMenuHide = true;
-          setTimeout(() => {
-            ignoreSideMenuHide = false;
-          }, 300);
-        }
-      });
-
-      scope.$watch('contextSrv.pinned', newVal => {
-        if (newVal !== undefined) {
-          body.toggleClass('sidemenu-pinned', newVal);
         }
       });
 
@@ -199,15 +187,6 @@ export function grafanaAppDirective(playlistSrv, contextSrv) {
           }
         }
 
-        // hide sidemenu
-        if (!ignoreSideMenuHide && !contextSrv.pinned && body.find('.sidemenu').length > 0) {
-          if (target.parents('.sidemenu').length === 0) {
-            scope.$apply(function() {
-              scope.contextSrv.toggleSideMenu();
-            });
-          }
-        }
-
         // hide popovers
         var popover = elem.find('.popover');
         if (popover.length > 0 && target.parents('.graph-legend').length === 0) {

+ 25 - 26
public/app/core/components/sidemenu/sidemenu.html

@@ -1,11 +1,10 @@
-<div class="sidemenu__top">
-
-	<a class="navbar-brand-btn pointer" ng-click="ctrl.contextSrv.toggleSideMenu()">
-		<span class="navbar-brand-btn-background">
-			<img src="public/img/grafana_icon.svg"></img>
-		</span>
-	</a>
+<a class="sidemenu__logo" ng-click="ctrl.toggleSideMenu()">
+	<span class="navbar-brand-btn-background">
+		<img src="public/img/grafana_icon.svg"></img>
+	</span>
+</a>
 
+<div class="sidemenu__top">
 	<div ng-repeat="item in ::ctrl.mainLinks" class="sidemenu-item dropdown">
 		<a href="{{::item.url}}" class="sidemenu-link" target="{{::item.target}}">
 			<span class="icon-circle sidemenu-icon">
@@ -39,14 +38,14 @@
 		</ul>
 	</div>
 
-  <div ng-repeat="item in ::ctrl.bottomNav" class="sidemenu-item dropdown dropup">
-    <a href="{{::item.url}}" class="sidemenu-link" target="{{::item.target}}">
-      <span class="icon-circle sidemenu-icon">
-        <i class="{{::item.icon}}" ng-show="::item.icon"></i>
-        <img ng-src="{{::item.img}}" ng-show="::item.img">
-      </span>
-    </a>
-    <ul class="dropdown-menu dropdown-menu--sidemenu" role="menu">
+	<div ng-repeat="item in ::ctrl.bottomNav" class="sidemenu-item dropdown dropup">
+		<a href="{{::item.url}}" class="sidemenu-link" target="{{::item.target}}">
+			<span class="icon-circle sidemenu-icon">
+				<i class="{{::item.icon}}" ng-show="::item.icon"></i>
+				<img ng-src="{{::item.img}}" ng-show="::item.img">
+			</span>
+		</a>
+		<ul class="dropdown-menu dropdown-menu--sidemenu" role="menu">
 			<li ng-if="item.showOrgSwitcher" class="sidemenu-org-switcher">
 				<a ng-click="ctrl.switchOrg()">
 					<div>
@@ -56,16 +55,16 @@
 					<div class="sidemenu-org-switcher__switch"><i class="fa fa-fw fa-random"></i>Switch</div>
 				</a>
 			</li>
-      <li ng-repeat="child in ::item.children" ng-class="{divider: child.divider}" ng-hide="::child.hideFromMenu">
-        <a href="{{::child.url}}" target="{{::child.target}}">
-          <i class="{{::child.icon}}" ng-show="::child.icon"></i>
-          {{::child.text}}
-        </a>
-      </li>
-      <li class="side-menu-header">
-        <span class="sidemenu-item-text">{{::item.text}}</span>
-      </li>
-    </ul>
-  </div>
+			<li ng-repeat="child in ::item.children" ng-class="{divider: child.divider}" ng-hide="::child.hideFromMenu">
+				<a href="{{::child.url}}" target="{{::child.target}}">
+					<i class="{{::child.icon}}" ng-show="::child.icon"></i>
+					{{::child.text}}
+				</a>
+			</li>
+			<li class="side-menu-header">
+				<span class="sidemenu-item-text">{{::item.text}}</span>
+			</li>
+		</ul>
+	</div>
 </div>
 

+ 8 - 4
public/app/core/components/sidemenu/sidemenu.ts

@@ -13,7 +13,7 @@ export class SideMenuCtrl {
   isSignedIn: boolean;
 
   /** @ngInject */
-  constructor(private $scope, private $rootScope, private $location, private contextSrv, private backendSrv, private $element) {
+  constructor(private $scope, private $rootScope, private $location, private contextSrv, private $timeout) {
     this.isSignedIn = contextSrv.isSignedIn;
     this.user = contextSrv.user;
     this.mainLinks = _.filter(config.bootData.navTree, item => !item.hideFromMenu);
@@ -28,13 +28,17 @@ export class SideMenuCtrl {
     }
 
     this.$scope.$on('$routeChangeSuccess', () => {
-      if (!this.contextSrv.pinned) {
-        this.contextSrv.sidemenu = false;
-      }
       this.loginUrl = 'login?redirect=' + encodeURIComponent(this.$location.path());
     });
   }
 
+  toggleSideMenu() {
+    this.contextSrv.toggleSideMenu();
+    this.$timeout(() => {
+      this.$rootScope.$broadcast('render');
+    });
+  }
+
   switchOrg() {
     this.$rootScope.appEvent('show-modal', {
       templateHtml: '<org-switcher dismiss="dismiss()"></org-switcher>',

+ 2 - 10
public/app/core/services/context_srv.ts

@@ -31,10 +31,7 @@ export class ContextSrv {
   sidemenu: any;
 
   constructor() {
-    this.pinned = store.getBool('grafana.sidemenu.pinned', false);
-    if (this.pinned) {
-      this.sidemenu = true;
-    }
+    this.sidemenu = store.getBool('grafana.sidemenu', false);
 
     if (!config.buildInfo) {
       config.buildInfo = {};
@@ -54,18 +51,13 @@ export class ContextSrv {
     return this.user.orgRole === role;
   }
 
-  setPinnedState(val) {
-    this.pinned = val;
-    store.set('grafana.sidemenu.pinned', val);
-  }
-
   isGrafanaVisible() {
     return !!(document.visibilityState === undefined || document.visibilityState === 'visible');
   }
 
   toggleSideMenu() {
     this.sidemenu = !this.sidemenu;
-    this.setPinnedState(this.sidemenu);
+    store.set('grafana.sidemenu',this.sidemenu);
   }
 }
 

+ 7 - 1
public/sass/components/_navbar.scss

@@ -3,7 +3,6 @@
   display: block;
   overflow: visible;
   position: relative;
-  z-index: 110;
 }
 
 .navbar-inner {
@@ -11,9 +10,16 @@
   padding-right: $spacer;
   background-color: $navbarBackground;
   border-bottom: $navbarBorder;
+  margin-left: $side-menu-width;
   @include clearfix();
 }
 
+.sidemenu-open {
+  .navbar-inner {
+    margin-left: 0;
+  }
+}
+
 .navbar .nav {
   position: relative;
   left: 0;

+ 40 - 0
public/sass/components/_sidemenu.scss

@@ -1,6 +1,9 @@
 
 
 .sidemenu {
+  position: fixed;
+  height: 30px;
+
   display: flex;
   flex-flow: column;
   flex-direction: column;
@@ -13,12 +16,25 @@
   }
 }
 
+.sidemenu-open {
+  .sidemenu {
+    position: initial;
+    height: auto;
+  }
+  .sidemenu__top,
+  .sidemenu__bottom {
+    display: block;
+  }
+}
+
 .sidemenu__top {
   flex-grow: 1;
+  display: none;
 }
 
 .sidemenu__bottom {
   padding-bottom: $spacer;
+  display: none;
 }
 
 .sidemenu-item {
@@ -134,3 +150,27 @@ li.sidemenu-org-switcher {
     top: 1px;
   }
 }
+
+.sidemenu__logo {
+  display: block;
+  margin-bottom: 3rem;
+  background-color: $side-menu-bg;
+  padding: 0.4rem 1.0rem 0.4rem 0.65rem;
+  min-height: $navbarHeight;
+
+  &:hover {
+    background: $navbarButtonBackgroundHighlight;
+
+    .sidemenu__logo-expand {
+      display: block;
+    }
+  }
+
+  img {
+    width: 30px;
+    position: relative;
+    top: 3px;
+    left: 4px;
+  }
+}
+