فهرست منبع

A lot of work on new organization selection and sidenav dropdown, #1506

Torkel Ödegaard 10 سال پیش
والد
کامیت
c14a90a3d0

+ 45 - 36
src/app/controllers/sidemenuCtrl.js

@@ -9,7 +9,7 @@ function (angular, _, $, config) {
 
   var module = angular.module('grafana.controllers');
 
-  module.controller('SideMenuCtrl', function($scope, $location, contextSrv) {
+  module.controller('SideMenuCtrl', function($scope, $location, contextSrv, backendSrv) {
 
     $scope.getUrl = function(url) {
       return config.appSubUrl + url;
@@ -29,35 +29,57 @@ function (angular, _, $, config) {
           href: $scope.getUrl("/datasources"),
         });
       }
+    };
 
-      if (contextSrv.user.isSignedIn) {
-        $scope.bottomLinks.push({
-          text: contextSrv.user.name,
-          imgSrc: contextSrv.user.gravatarUrl,
-          href: $scope.getUrl("/profile"),
-        });
+    $scope.loadOrgs = function() {
+      $scope.orgMenu = [];
 
-        $scope.bottomLinks.push({
-          text: contextSrv.user.orgName,
+      if (contextSrv.hasRole('Admin')) {
+        $scope.orgMenu.push({
+          text: "Organization settings",
           href: $scope.getUrl("/org"),
-          icon: "fa fa-fw fa-users",
         });
+        $scope.orgMenu.push({
+          text: "Users",
+          href: $scope.getUrl("/org/users"),
+        });
+        $scope.orgMenu.push({
+          text: "API Keys",
+          href: $scope.getUrl("/org/apikeys"),
+        });
+      }
+
+      if ($scope.orgMenu.length > 0) {
+        $scope.orgMenu.push({ cssClass: 'divider' });
+      }
 
-        if (contextSrv.hasRole('Admin')) {
-          $scope.bottomLinks.push({
-            text: "Grafana admin",
-            icon: "fa fa-fw fa-cog",
-            href: $scope.getUrl("/admin/settings"),
+      backendSrv.get('/api/user/orgs').then(function(orgs) {
+        _.each(orgs, function(org) {
+          if (org.isUsing) {
+            return;
+          }
+
+          $scope.orgMenu.push({
+            text: "Switch to " + org.name,
+            icon: "fa fa-fw fa-random",
+            click: function() {
+              $scope.switchOrg(org.orgId);
+            }
           });
-        }
+        });
 
-        $scope.bottomLinks.push({
-          text: "Sign out",
-          target: "_self",
-          icon: "fa fa-fw fa-sign-out",
-          href: $scope.getUrl("/logout"),
+        $scope.orgMenu.push({
+          text: "New Organization",
+          icon: "fa fa-fw fa-plus",
+          href: $scope.getUrl('/org/new')
         });
-      }
+      });
+    };
+
+    $scope.switchOrg = function(orgId) {
+      backendSrv.post('/api/user/using/' + orgId).then(function() {
+        window.location.href = $scope.getUrl('/');
+      });
     };
 
     $scope.setupAdminNav = function() {
@@ -81,25 +103,12 @@ function (angular, _, $, config) {
         icon: "fa fa-fw fa-users",
         href: $scope.getUrl("/admin/orgs"),
       });
-
-      $scope.bottomLinks.push({
-        text: "Exit admin",
-        icon: "fa fa-fw fa-backward",
-        href: $scope.getUrl("/"),
-      });
-
-      $scope.bottomLinks.push({
-        text: "Sign out",
-        icon: "fa fa-fw fa-sign-out",
-        target: "_self",
-        href: $scope.getUrl("/logout"),
-      });
     };
 
     $scope.updateMenu = function() {
       $scope.systemSection = false;
       $scope.mainLinks = [];
-      $scope.bottomLinks = [];
+      $scope.orgMenu = [];
 
       var currentPath = $location.path();
       if (currentPath.indexOf('/admin') === 0) {

+ 1 - 0
src/app/features/org/all.js

@@ -2,6 +2,7 @@ define([
   './datasourcesCtrl',
   './datasourceEditCtrl',
   './orgUsersCtrl',
+  './newOrgCtrl',
   './orgApiKeysCtrl',
   './orgDetailsCtrl',
 ], function () {});

+ 18 - 0
src/app/features/org/newOrgCtrl.js

@@ -0,0 +1,18 @@
+define([
+  'angular',
+],
+function (angular) {
+  'use strict';
+
+  var module = angular.module('grafana.controllers');
+
+  module.controller('NewOrgCtrl', function($scope, $http, backendSrv) {
+
+    $scope.newOrg = {name: ''};
+
+    $scope.createOrg = function() {
+      backendSrv.post('/api/org/', $scope.newOrg).then($scope.getUserOrgs);
+    };
+
+  });
+});

+ 34 - 0
src/app/features/org/partials/newOrg.html

@@ -0,0 +1,34 @@
+<topnav title="Organization" icon="fa fa-fw fa-users" subnav="true">
+	<ul class="nav">
+		<li class="active"><a href="org/new">New organization</a></li>
+	</ul>
+</topnav>
+
+<div class="page-container">
+	<div class="page">
+
+		<h2 style="margin-top: 30px;">Add Organization</h2>
+
+		<form name="form">
+			<div>
+				<div class="tight-form">
+					<ul class="tight-form-list">
+						<li class="tight-form-item" style="width: 100px;">
+							<strong>Org. name</strong>
+						</li>
+						<li>
+							<input type="text" ng-model="newOrg.name" required class="input-xxlarge tight-form-input last" placeholder="organization name">
+						</li>
+						<li>
+						</li>
+					</ul>
+					<div class="clearfix"></div>
+				</div>
+			</div>
+			<br>
+			<button class="btn btn-success pull-right" ng-click="createOrg()">Create</button>
+		</form>
+
+	</div>
+</div>
+

+ 44 - 43
src/app/features/org/partials/orgApiKeys.html

@@ -1,51 +1,52 @@
-<topnav title="API Keys"
-				icon="fa fa-shield"
-				section="Account">
+<topnav icon="fa fa-fw fa-users" title="Organization" subnav="true">
+	<ul class="nav">
+		<li class="active"><a href="org/apikeys">API Keys</a></li>
+	</ul>
 </topnav>
 
-<div class="gf-box" style="min-height: 500px">
-	<div class="gf-box-body">
-		<div class="editor-row">
-			<div class="section">
-				<form name="addTokenrForm" class="form-inline tight-form">
-					<ul class="tight-form-list">
-						<li class="tight-form-item">
-							Add a key
-						</li>
-						<li>
-							<input type="text" class="input-xlarge tight-form-input" ng-model='token.name' placeholder="Name"></input>
-						</li>
-						<li class="tight-form-item">
-							Role
-						</li>
-						<li>
-							<select class="input-small tight-form-input" ng-model="token.role" ng-options="r for r in roleTypes"></select>
-						</li>
-						<button class="btn btn-success tight-form-btn" ng-click="addToken()">Add</button>
-					</li>
-				</ul>
+<div class="page-container">
+	<div class="page">
+
+		<h2>
+			API Keys
+		</h2>
+
+		<form name="addTokenrForm" class="form-inline tight-form last">
+			<ul class="tight-form-list">
+				<li class="tight-form-item" style="width: 100px">
+					Add a key
+				</li>
+				<li>
+					<input type="text" class="input-xlarge tight-form-input" ng-model='token.name' placeholder="Name"></input>
+				</li>
+				<li class="tight-form-item">
+					Role
+				</li>
+				<li>
+					<select class="input-small tight-form-input" ng-model="token.role" ng-options="r for r in roleTypes"></select>
+				</li>
+				<li style="float: right">
+					<button class="btn btn-success tight-form-btn" ng-click="addToken()">Add</button>
+				</li>
 				<div class="clearfix"></div>
-			</form>
-		</div>
+			</ul>
+		</form>
+		<br>
 
-		<div class="editor-row row">
-			<div class="section span6">
-				<table class="grafana-options-table">
-					<tr ng-repeat="t in tokens">
-						<td>{{t.name}}</td>
-						<td>{{t.role}}</td>
-						<td>{{t.key}}</td>
-						<td style="width: 1%">
-							<a ng-click="removeToken(t.id)" class="btn btn-danger btn-mini">
-								<i class="fa fa-remove"></i>
-							</a>
-						</td>
-					</tr>
-				</table>
-			</div>
-		</div>
+		<table class="grafana-options-table">
+			<tr ng-repeat="t in tokens">
+				<td>{{t.name}}</td>
+				<td>{{t.role}}</td>
+				<td>{{t.key}}</td>
+				<td style="width: 1%">
+					<a ng-click="removeToken(t.id)" class="btn btn-danger btn-mini">
+						<i class="fa fa-remove"></i>
+					</a>
+				</td>
+			</tr>
+		</table>
 	</div>
-</div>
 
+</div>
 
 

+ 37 - 45
src/app/features/org/partials/orgDetails.html

@@ -1,21 +1,20 @@
 <topnav icon="fa fa-fw fa-users" title="Organization" subnav="true">
 	<ul class="nav">
-		<li class="active"><a href="org">Overview</a></li>
-		<li><a href="org/users">Users</a></li>
+		<li class="active"><a href="org">Info</a></li>
 	</ul>
 </topnav>
 
 <div class="page-container">
 	<div class="page">
 
-		<h2>Organization Details</h2>
+		<h2>Organization info</h2>
 
 		<form name="orgForm">
 			<div>
 				<div class="tight-form">
 					<ul class="tight-form-list">
 						<li class="tight-form-item" style="width: 100px">
-							<strong>Name</strong>
+							<strong>Org. name</strong>
 						</li>
 						<li>
 							<input type="text" required ng-model="org.name" class="input-xxlarge tight-form-input last" >
@@ -23,52 +22,45 @@
 					</ul>
 					<div class="clearfix"></div>
 				</div>
+				<div class="tight-form">
+					<ul class="tight-form-list">
+						<li class="tight-form-item" style="width: 100px">
+							<strong>Address 1</strong>
+						</li>
+						<li>
+							<input type="text" required ng-model="org.address1" class="input-xxlarge tight-form-input last" >
+						</li>
+					</ul>
+					<div class="clearfix"></div>
+				</div>
+				<div class="tight-form">
+					<ul class="tight-form-list">
+						<li class="tight-form-item" style="width: 100px">
+							<strong>Address 2</strong>
+						</li>
+						<li>
+							<input type="text" required ng-model="org.address2" class="input-xxlarge tight-form-input last" >
+						</li>
+					</ul>
+					<div class="clearfix"></div>
+				</div>
+				<div class="tight-form">
+					<ul class="tight-form-list">
+						<li class="tight-form-item" style="width: 100px">
+							<strong>City</strong>
+						</li>
+						<li>
+							<input type="text" required ng-model="org.city" class="input-xxlarge tight-form-input last" >
+						</li>
+					</ul>
+					<div class="clearfix"></div>
+				</div>
+
 			</div>
 			<br>
 			<button type="submit" class="pull-right btn btn-success" ng-click="update()">Update</button>
 		</form>
 
-		<h2>
-			API Keys
-		</h2>
-
-		<div ng-controller="OrgApiKeysCtrl">
-			<form name="addTokenrForm" class="form-inline tight-form last">
-				<ul class="tight-form-list">
-					<li class="tight-form-item" style="width: 100px">
-						Add a key
-					</li>
-					<li>
-						<input type="text" class="input-xlarge tight-form-input" ng-model='token.name' placeholder="Name"></input>
-					</li>
-					<li class="tight-form-item">
-						Role
-					</li>
-					<li>
-						<select class="input-small tight-form-input" ng-model="token.role" ng-options="r for r in roleTypes"></select>
-					</li>
-					<li style="float: right">
-						<button class="btn btn-success tight-form-btn" ng-click="addToken()">Add</button>
-					</li>
-					<div class="clearfix"></div>
-				</ul>
-			</form>
-		<br>
-
-		<table class="grafana-options-table">
-			<tr ng-repeat="t in tokens">
-				<td>{{t.name}}</td>
-				<td>{{t.role}}</td>
-				<td>{{t.key}}</td>
-				<td style="width: 1%">
-					<a ng-click="removeToken(t.id)" class="btn btn-danger btn-mini">
-						<i class="fa fa-remove"></i>
-					</a>
-				</td>
-			</tr>
-		</table>
-	</div>
-
 	</div>
 </div>
 

+ 0 - 1
src/app/features/org/partials/orgUsers.html

@@ -1,6 +1,5 @@
 <topnav title="Organization" icon="fa fa-fw fa-users" subnav="true">
 	<ul class="nav">
-		<li><a href="org">Overview</a></li>
 		<li class="active"><a href="org/users">Users</a></li>
 	</ul>
 </topnav>

+ 1 - 23
src/app/features/profile/partials/profile.html

@@ -1,4 +1,4 @@
-<topnav title="{{contextSrv.user.name}}" section="Profile" icon="fa fa-user" subnav="true">
+<topnav title="{{contextSrv.user.name}}" section="Profile" icon="fa fw fa-user" subnav="true">
 	<ul class="nav">
 		<li class="active"><a href="profile">Overview</a></li>
 		<li><a href="profile/password">Change password</a></li>
@@ -68,28 +68,6 @@
 			</tr>
 		</table>
 
-		<h2 style="margin-top: 30px;">Add Organization</h2>
-
-		<form name="form">
-			<div>
-				<div class="tight-form">
-					<ul class="tight-form-list">
-						<li class="tight-form-item" style="width: 100px;">
-							<strong>Org. name</strong>
-						</li>
-						<li>
-							<input type="text" ng-model="newOrg.name" required class="input-xxlarge tight-form-input last" placeholder="organization name">
-						</li>
-						<li>
-						</li>
-					</ul>
-					<div class="clearfix"></div>
-				</div>
-			</div>
-			<br>
-			<button class="btn btn-success pull-right" ng-click="createOrg()">Create</button>
-		</form>
-
 	</div>
 </div>
 

+ 0 - 6
src/app/features/profile/profileCtrl.js

@@ -9,8 +9,6 @@ function (angular, config) {
 
   module.controller('ProfileCtrl', function($scope, backendSrv) {
 
-    $scope.newOrg = {name: ''};
-
     $scope.init = function() {
       $scope.getUser();
       $scope.getUserOrgs();
@@ -39,10 +37,6 @@ function (angular, config) {
       backendSrv.put('/api/user/', $scope.user);
     };
 
-    $scope.createOrg = function() {
-      backendSrv.post('/api/org/', $scope.newOrg).then($scope.getUserOrgs);
-    };
-
     $scope.init();
 
   });

+ 58 - 7
src/app/partials/sidemenu.html

@@ -1,4 +1,3 @@
-
 <div ng-controller="SideMenuCtrl" ng-init="init()">
 
 	<ul class="sidemenu sidemenu-main">
@@ -27,13 +26,65 @@
 		</li>
 	</ul>
 
-	<ul class="sidemenu sidemenu-small"  style="margin-top:50px">
-		<li ng-repeat="item in bottomLinks">
-			<a href="{{item.href}}" class="sidemenu-item" target="{{item.target}}">
-				<img ng-if="item.imgSrc" ng-src="{{item.imgSrc}}">
-				<span class="icon-circle sidemenu-icon" ng-if="item.icon"><i class="{{item.icon}}"></i></span>
-				<span class="sidemenu-item-text">{{item.text}}</span>
+	<ul class="sidemenu sidemenu-small" style="margin-top:50px" ng-if="!systemSection">
+
+		<li>
+			<a href="profile" class="sidemenu-item">
+				<img ng-src="{{contextSrv.user.gravatarUrl}}">
+				<span class="sidemenu-item-text">{{contextSrv.user.name}}</span>
+	   	</a>
+		</li>
+
+		<li class="dropdown">
+			<a class="sidemenu-item pointer" data-toggle="dropdown" ng-click="loadOrgs()">
+				<span class="icon-circle sidemenu-icon"><i class="fa fa-fw fa-users"></i></span>
+				<span class="sidemenu-item-text">
+					{{contextSrv.user.orgName}}
+					<i class="fa fa-caret-down small"></i>
+				</span>
+	   	</a>
+			<ul class="dropdown-menu" role="menu" style="left: 65px">
+				<li ng-repeat="menuItem in orgMenu" ng-class="menuItem.cssClass">
+					<a href="{{menuItem.href}}" ng-if="menuItem.href">
+						<i class="{{menuItem.icon}}" ng-if="menuItem.icon"></i>
+						{{menuItem.text}}
+					</a>
+					<a ng-click="menuItem.click()" ng-if="menuItem.click">
+						<i class="{{menuItem.icon}}"></i>
+						{{menuItem.text}}
+					</a>
+				</li>
+			</ul>
+		</li>
+
+		<li ng-if="contextSrv.isGrafanaAdmin">
+			<a href="admin/settings" class="sidemenu-item">
+				<span class="icon-circle sidemenu-icon"><i class="fa fa-fw fa-cog"></i></span>
+				<span class="sidemenu-item-text">Grafana admin</span>
+	   	</a>
+		</li>
+
+		<li>
+			<a href="logout" class="sidemenu-item" target="_self">
+				<span class="icon-circle sidemenu-icon"><i class="fa fa-fw fa-sign-out"></i></span>
+				<span class="sidemenu-item-text">Sign out</span>
+	   	</a>
+		</li>
+	</ul>
+
+	<ul class="sidemenu sidemenu-small" style="margin-top:50px" ng-if="systemSection">
+		<li>
+			<a href="{{appSubUrl}}/" class="sidemenu-item">
+				<span class="icon-circle sidemenu-icon"><i class="fa fa-fw fa-backward"></i></span>
+				<span class="sidemenu-item-text">Exit admin</span>
+	   	</a>
+		</li>
+		<li>
+			<a href="logout" class="sidemenu-item" target="_self">
+				<span class="icon-circle sidemenu-icon"><i class="fa fa-fw fa-sign-out"></i></span>
+				<span class="sidemenu-item-text">Sign out</span>
 	   	</a>
 		</li>
 	</ul>
+
 </div>

+ 5 - 1
src/app/routes/backend/all.js

@@ -50,13 +50,17 @@ define([
         templateUrl: 'app/features/org/partials/orgDetails.html',
         controller : 'OrgDetailsCtrl',
       })
+      .when('/org/new', {
+        templateUrl: 'app/features/org/partials/newOrg.html',
+        controller : 'NewOrgCtrl',
+      })
       .when('/org/users', {
         templateUrl: 'app/features/org/partials/orgUsers.html',
         controller : 'OrgUsersCtrl',
       })
       .when('/org/apikeys', {
         templateUrl: 'app/features/org/partials/orgApiKeys.html',
-        controller : 'ApiKeysCtrl',
+        controller : 'OrgApiKeysCtrl',
       })
       .when('/profile', {
         templateUrl: 'app/features/profile/partials/profile.html',

+ 2 - 0
src/app/services/contextSrv.js

@@ -20,6 +20,8 @@ function (angular, _, store) {
     this.version = grafanaVersion;
     this.lightTheme = false;
     this.user = new User();
+    this.isSignedIn = this.user.isSignedIn;
+    this.isGrafanaAdmin = this.user.isGrafanaAdmin;
     this.sidemenu = store.getBool('grafana.sidemenu');
 
     // events

+ 1 - 1
src/css/less/sidemenu.less

@@ -42,7 +42,7 @@
   margin: 0;
   padding: 0;
 
-  li {
+  >li {
     margin-bottom: 9px;
   }
 

+ 1 - 1
src/css/less/variables.dark.less

@@ -144,7 +144,7 @@
 @dropdownBackground:            @heroUnitBackground;
 @dropdownBorder:                rgba(0,0,0,.2);
 @dropdownDividerTop:            transparent;
-@dropdownDividerBottom:         #222;
+@dropdownDividerBottom:         #444;
 
 @dropdownLinkColor:             @textColor;
 @dropdownLinkColorHover:        @white;