瀏覽代碼

feat(admin): admin page for all grafana organizations (list / edit view), #2457

Torkel Ödegaard 10 年之前
父節點
當前提交
43ef9f909a

+ 6 - 0
CHANGELOG.md

@@ -1,3 +1,9 @@
+# 2.2 (unreleased)
+
+**New Features && Enhancements**
+- [Issue #2457](https://github.com/grafana/grafana/issues/2457). Admin: admin page for all grafana organizations (list / edit view)
+
+
 # 2.1.1 (2015-08-11)
 
 **Fixes**

+ 3 - 0
pkg/api/api.go

@@ -37,6 +37,8 @@ func Register(r *macaron.Macaron) {
 	r.Get("/admin/users", reqGrafanaAdmin, Index)
 	r.Get("/admin/users/create", reqGrafanaAdmin, Index)
 	r.Get("/admin/users/edit/:id", reqGrafanaAdmin, Index)
+	r.Get("/admin/orgs", reqGrafanaAdmin, Index)
+	r.Get("/admin/orgs/edit/:id", reqGrafanaAdmin, Index)
 	r.Get("/dashboard/*", reqSignedIn, Index)
 
 	// sign up
@@ -109,6 +111,7 @@ func Register(r *macaron.Macaron) {
 
 		// orgs (admin routes)
 		r.Group("/orgs/:orgId", func() {
+			r.Get("/", wrap(GetOrgById))
 			r.Put("/", bind(m.UpdateOrgCommand{}), wrap(UpdateOrg))
 			r.Get("/users", wrap(GetOrgUsers))
 			r.Post("/users", bind(m.AddOrgUserCommand{}), wrap(AddOrgUser))

+ 52 - 0
public/app/features/admin/adminEditOrgCtrl.js

@@ -0,0 +1,52 @@
+define([
+  'angular',
+],
+function (angular) {
+  'use strict';
+
+  var module = angular.module('grafana.controllers');
+
+  module.controller('AdminEditOrgCtrl', function($scope, $routeParams, backendSrv, $location) {
+
+    $scope.init = function() {
+      if ($routeParams.id) {
+        $scope.getOrg($routeParams.id);
+        $scope.getOrgUsers($routeParams.id);
+      }
+    };
+
+    $scope.getOrg = function(id) {
+      backendSrv.get('/api/orgs/' + id).then(function(org) {
+        $scope.org = org;
+      });
+    };
+
+    $scope.getOrgUsers = function(id) {
+      backendSrv.get('/api/orgs/' + id + '/users').then(function(orgUsers) {
+        $scope.orgUsers = orgUsers;
+      });
+    };
+
+    $scope.update = function() {
+      if (!$scope.orgDetailsForm.$valid) { return; }
+
+      backendSrv.put('/api/orgs/' + $scope.org.id, $scope.org).then(function() {
+        $location.path('/admin/orgs');
+      });
+    };
+
+    $scope.updateOrgUser= function(orgUser) {
+      backendSrv.patch('/api/orgs/' + orgUser.orgId + '/users/' + orgUser.userId, orgUser);
+    };
+
+    $scope.removeOrgUser = function(orgUser) {
+      backendSrv.delete('/api/orgs/' + orgUser.orgId + '/users/' + orgUser.userId).then(function() {
+        $scope.getOrgUsers($scope.org.id);
+      });
+    };
+
+    $scope.init();
+
+  });
+
+});

+ 38 - 0
public/app/features/admin/adminListOrgsCtrl.js

@@ -0,0 +1,38 @@
+define([
+  'angular',
+],
+function (angular) {
+  'use strict';
+
+  var module = angular.module('grafana.controllers');
+
+  module.controller('AdminListOrgsCtrl', function($scope, backendSrv) {
+
+    $scope.init = function() {
+      $scope.getOrgs();
+    };
+
+    $scope.getOrgs = function() {
+      backendSrv.get('/api/orgs').then(function(orgs) {
+        $scope.orgs = orgs;
+      });
+    };
+
+    $scope.deleteOrg = function(org) {
+      $scope.appEvent('confirm-modal', {
+        title: 'Do you want to delete organization ' + org.name + '?',
+        icon: 'fa-trash',
+        yesText: 'Delete',
+        onConfirm: function() {
+          backendSrv.delete('/api/orgs/' + org.id).then(function() {
+            $scope.getOrgs();
+          });
+        }
+      });
+    };
+
+    $scope.init();
+
+  });
+
+});

+ 1 - 1
public/app/features/admin/adminUsersCtrl.js → public/app/features/admin/adminListUsersCtrl.js

@@ -6,7 +6,7 @@ function (angular) {
 
   var module = angular.module('grafana.controllers');
 
-  module.controller('AdminUsersCtrl', function($scope, backendSrv) {
+  module.controller('AdminListUsersCtrl', function($scope, backendSrv) {
 
     $scope.init = function() {
       $scope.getUsers();

+ 3 - 1
public/app/features/admin/all.js

@@ -1,5 +1,7 @@
 define([
-  './adminUsersCtrl',
+  './adminListUsersCtrl',
+  './adminListOrgsCtrl',
+  './adminEditOrgCtrl',
   './adminEditUserCtrl',
   './adminSettingsCtrl',
 ], function () {});

+ 60 - 0
public/app/features/admin/partials/edit_org.html

@@ -0,0 +1,60 @@
+<topnav icon="fa fa-fw fa-user" title="Global Users" subnav="true">
+	<ul class="nav">
+		<li><a href="admin/orgs">List</a></li>
+		<li class="active"><a href="admin/orgs/edit/{{org.id}}">Edit Org</a></li>
+	</ul>
+</topnav>
+
+<div class="page-container">
+	<div class="page">
+		<h2>
+			Organization Details
+		</h2>
+
+		<form name="orgDetailsForm">
+			<div>
+				<div class="tight-form">
+					<ul class="tight-form-list">
+						<li class="tight-form-item" style="width: 100px">
+							Name
+						</li>
+						<li>
+							<input type="text" required ng-model="org.name" 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()" ng-show="!createMode">Update</button>
+		</form>
+
+		<h3>
+			Organization Users
+		</h3>
+
+		<table class="grafana-options-table form-inline">
+			<tr>
+				<th>Username</th>
+				<th>Email</th>
+				<th>Role</th>
+				<th></th>
+			</tr>
+			<tr ng-repeat="orgUser in orgUsers">
+				<td>{{orgUser.login}}</td>
+				<td>{{orgUser.email}}</td>
+				<td>
+					<select type="text" ng-model="orgUser.role" class="input-small" ng-options="f for f in ['Viewer', 'Editor', 'Read Only Editor', 'Admin']" ng-change="updateOrgUser(orgUser)">
+					</select>
+				</td>
+				<td style="width: 1%">
+					<a ng-click="removeOrgUser(orgUser)" class="btn btn-danger btn-mini">
+						<i class="fa fa-remove"></i>
+					</a>
+				</td>
+			</tr>
+		</table>
+
+	</div>
+</div>

+ 22 - 2
public/app/features/admin/partials/orgs.html

@@ -1,6 +1,6 @@
 <topnav icon="fa fa-fw fa-users" title="Global Orgs" subnav="true">
 	<ul class="nav">
-		<li class="active"><a href="admin/users">Overview</a></li>
+		<li class="active"><a href="admin/orgs">List</a></li>
 	</ul>
 </topnav>
 
@@ -10,6 +10,26 @@
 			Organizations
 		</h2>
 
-		View not implemented yet...
+		<table class="grafana-options-table">
+			<tr>
+				<th style="text-align:left">Id</th>
+				<th>Name</th>
+				<th></th>
+			</tr>
+			<tr ng-repeat="org in orgs">
+				<td>{{org.name}}</td>
+				<td style="width: 1%">
+					<a href="admin/orgs/edit/{{org.id}}" class="btn btn-inverse btn-small">
+						<i class="fa fa-edit"></i>
+						Edit
+					</a>
+					&nbsp;&nbsp;
+					<a ng-click="deleteOrg(org)" class="btn btn-danger btn-small">
+						<i class="fa fa-remove"></i>
+					</a>
+				</td>
+			</tr>
+		</table>
+
 	</div>
 </div>

+ 6 - 1
public/app/routes/all.js

@@ -80,7 +80,7 @@ define([
       })
       .when('/admin/users', {
         templateUrl: 'app/features/admin/partials/users.html',
-        controller : 'AdminUsersCtrl',
+        controller : 'AdminListUsersCtrl',
       })
       .when('/admin/users/create', {
         templateUrl: 'app/features/admin/partials/new_user.html',
@@ -92,6 +92,11 @@ define([
       })
       .when('/admin/orgs', {
         templateUrl: 'app/features/admin/partials/orgs.html',
+        controller : 'AdminListOrgsCtrl',
+      })
+      .when('/admin/orgs/edit/:id', {
+        templateUrl: 'app/features/admin/partials/edit_org.html',
+        controller : 'AdminEditOrgCtrl',
       })
       .when('/login', {
         templateUrl: 'app/partials/login.html',