Commit e32ee9f0 by Torkel Ödegaard

ux(admin): admin pages overhaul

parent 48c936e9
......@@ -100,6 +100,14 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
}
}
if c.IsGrafanaAdmin {
data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{
Text: "Admin",
Icon: "fa fa-fw fa-cogs",
Url: setting.AppSubUrl + "/admin",
})
}
return &data, nil
}
......
<div class="navbar">
<div class="navbar-inner"><div class="container-fluid">
<div class="top-nav-btn top-nav-menu-btn">
<a class="pointer" ng-click="ctrl.contextSrv.toggleSideMenu()">
<span class="top-nav-logo-background">
......@@ -10,12 +11,10 @@
</a>
</div>
<div class="top-nav-btn dashnav-dashboards-btn" ng-if="ctrl.title">
<a class="pointer" href="{{ctrl.titleUrl}}">
<i ng-class="ctrl.icon"></i>
<span class="dashboard-title">{{ctrl.title}}</span>
<!-- <i class="fa fa&#45;caret&#45;down"></i> -->
</a>
<div ng-if="ctrl.title">
<nav-button title="{{ctrl.title}}" title-url="{{ctrl.titleUrl}}" icon="{{ctrl.icon}}">
</nav-button>
</div>
<div ng-transclude></div>
......
......@@ -29,4 +29,28 @@ export function navbarDirective() {
};
}
var navButtonTemplate = `
<div class="top-nav-btn dashnav-dashboards-btn">
<a href="{{::titleUrl}}">
<i class="{{::icon}}"></i>
<span class="dashboard-title">{{::title}}</span>
</a>
</div>
`;
function navButton() {
return {
restrict: 'E',
template: navButtonTemplate,
scope: {
title: "@",
titleUrl: "@",
},
link: function(scope, elem, attrs, ctrl) {
scope.icon = attrs.icon;
}
};
}
coreModule.directive('navbar', navbarDirective);
coreModule.directive('navButton', navButton);
......@@ -26,16 +26,6 @@
</ul>
</li>
<li class="sidemenu-system-section" ng-if="ctrl.systemSection">
<div class="sidemenu-system-section-inner">
<i class="icon-gf icon-gf-apps"></i>
<div class="sidemenu-section-text-wrapper">
<div class="sidemenu-section-heading">Grafana Admin</div>
<div class="sidemenu-section-tagline">v {{ctrl.grafanaVersion}}</div>
</div>
</div>
</li>
<li ng-repeat="item in ctrl.mainLinks" class="dropdown">
<a href="{{item.url}}" class="sidemenu-item sidemenu-main-link" target="{{item.target}}">
<span class="icon-circle sidemenu-icon">
......@@ -54,15 +44,6 @@
</ul>
</li>
<ul class="sidemenu sidemenu-small" style="margin-top:50px" ng-if="ctrl.systemSection">
<li>
<a href="{{ctrl.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>
</ul>
<li ng-if="!ctrl.isSignedIn">
<a href="login" class="sidemenu-item" target="_self">
<span class="icon-circle sidemenu-icon"><i class="fa fa-fw fa-sign-in"></i></span>
......
......@@ -11,8 +11,6 @@ export class SideMenuCtrl {
user: any;
mainLinks: any;
orgMenu: any;
systemSection: any;
grafanaVersion: any;
appSubUrl: string;
/** @ngInject */
......@@ -21,11 +19,11 @@ export class SideMenuCtrl {
this.user = contextSrv.user;
this.appSubUrl = config.appSubUrl;
this.showSignout = this.contextSrv.isSignedIn && !config['authProxyEnabled'];
this.updateMenu();
this.mainLinks = config.bootData.mainNavLinks;
this.openUserDropdown();
this.$scope.$on('$routeChangeSuccess', () => {
this.updateMenu();
if (!this.contextSrv.pinned) {
this.contextSrv.sidemenu = false;
}
......@@ -37,10 +35,6 @@ export class SideMenuCtrl {
return config.appSubUrl + url;
}
setupMainNav() {
this.mainLinks = config.bootData.mainNavLinks;
}
openUserDropdown() {
this.orgMenu = [
{section: 'You', cssClass: 'dropdown-menu-title'},
......@@ -70,10 +64,6 @@ export class SideMenuCtrl {
this.orgMenu.push({cssClass: "divider"});
if (this.contextSrv.isGrafanaAdmin) {
this.orgMenu.push({text: "Grafana adminstration", icon: "fa fa-fw fa-cogs", url: this.getUrl("/admin/settings")});
}
this.backendSrv.get('/api/user/orgs').then(orgs => {
orgs.forEach(org => {
if (org.orgId === this.contextSrv.user.orgId) {
......@@ -100,48 +90,6 @@ export class SideMenuCtrl {
window.location.href = window.location.href;
});
};
setupAdminNav() {
this.systemSection = true;
this.grafanaVersion = config.buildInfo.version;
this.mainLinks.push({
text: "System info",
icon: "fa fa-fw fa-info",
url: this.getUrl("/admin/settings"),
});
this.mainLinks.push({
text: "Stats",
icon: "fa fa-fw fa-bar-chart",
url: this.getUrl("/admin/stats"),
});
this.mainLinks.push({
text: "Users",
icon: "fa fa-fw fa-user",
url: this.getUrl("/admin/users"),
});
this.mainLinks.push({
text: "Organizations",
icon: "fa fa-fw fa-users",
url: this.getUrl("/admin/orgs"),
});
}
updateMenu() {
this.systemSection = false;
this.mainLinks = [];
var currentPath = this.$location.path();
if (currentPath.indexOf('/admin') === 0) {
this.setupAdminNav();
} else {
this.setupMainNav();
}
};
}
export function sideMenuDirective() {
......
......@@ -12,6 +12,7 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
var loadOrgBundle = new BundleLoader('app/features/org/all');
var loadAppsBundle = new BundleLoader('app/features/apps/all');
var loadAdminBundle = new BundleLoader('app/features/admin/admin');
$routeProvider
.when('/', {
......@@ -95,35 +96,49 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
templateUrl: 'public/app/features/profile/partials/select_org.html',
controller : 'SelectOrgCtrl',
})
// ADMIN
.when('/admin', {
templateUrl: 'public/app/features/admin/partials/admin_home.html',
controller : 'AdminHomeCtrl',
resolve: loadAdminBundle,
})
.when('/admin/settings', {
templateUrl: 'public/app/features/admin/partials/settings.html',
controller : 'AdminSettingsCtrl',
resolve: loadAdminBundle,
})
.when('/admin/users', {
templateUrl: 'public/app/features/admin/partials/users.html',
controller : 'AdminListUsersCtrl',
resolve: loadAdminBundle,
})
.when('/admin/users/create', {
templateUrl: 'public/app/features/admin/partials/new_user.html',
controller : 'AdminEditUserCtrl',
resolve: loadAdminBundle,
})
.when('/admin/users/edit/:id', {
templateUrl: 'public/app/features/admin/partials/edit_user.html',
controller : 'AdminEditUserCtrl',
resolve: loadAdminBundle,
})
.when('/admin/orgs', {
templateUrl: 'public/app/features/admin/partials/orgs.html',
controller : 'AdminListOrgsCtrl',
resolve: loadAdminBundle,
})
.when('/admin/orgs/edit/:id', {
templateUrl: 'public/app/features/admin/partials/edit_org.html',
controller : 'AdminEditOrgCtrl',
resolve: loadAdminBundle,
})
.when('/admin/stats', {
templateUrl: 'public/app/features/admin/partials/stats.html',
controller : 'AdminStatsCtrl',
controllerAs: 'ctrl',
resolve: loadAdminBundle,
})
// LOGIN / SIGNUP
.when('/login', {
templateUrl: 'public/app/partials/login.html',
controller : 'LoginCtrl',
......
import './adminListUsersCtrl';
import './adminListOrgsCtrl';
import './adminEditOrgCtrl';
import './adminEditUserCtrl';
import coreModule from 'app/core/core_module';
class AdminSettingsCtrl {
/** @ngInject **/
constructor($scope, backendSrv) {
backendSrv.get('/api/admin/settings').then(function(settings) {
$scope.settings = settings;
});
}
}
class AdminHomeCtrl {
/** @ngInject **/
constructor() {}
}
export class AdminStatsCtrl {
stats: any;
/** @ngInject */
constructor(backendSrv: any) {
backendSrv.get('/api/admin/stats').then(stats => {
this.stats = stats;
});
}
}
coreModule.controller('AdminSettingsCtrl', AdminSettingsCtrl);
coreModule.controller('AdminHomeCtrl', AdminHomeCtrl);
coreModule.controller('AdminStatsCtrl', AdminStatsCtrl);
///<reference path="../../headers/common.d.ts" />
import angular from 'angular';
export class AdminStatsCtrl {
stats: any;
/** @ngInject */
constructor(private backendSrv: any) {}
init() {
this.backendSrv.get('/api/admin/stats').then(stats => {
this.stats = stats;
});
}
}
angular.module('grafana.controllers').controller('AdminStatsCtrl', AdminStatsCtrl);
define([
'./adminListUsersCtrl',
'./adminListOrgsCtrl',
'./adminEditOrgCtrl',
'./adminEditUserCtrl',
'./adminSettingsCtrl',
'./adminStatsCtrl',
], function () {});
<navbar icon="fa fa-fw fa-cogs" title="Admin">
</navbar>
<div class="page-container">
<div class="page-header">
<h1>
Server Administration
</h1>
</div>
<a class="btn btn-inverse" href="admin/users">
Manage Users
</a>
<a class="btn btn-inverse" href="admin/orgs">
Manage Organizations
</a>
<a class="btn btn-inverse" href="admin/settings">
View Server Settings
</a>
<a class="btn btn-inverse" href="admin/stats">
View Server Stats
</a>
</div>
<navbar icon="fa fa-fw fa-user" title="Organizations" title-url="admin/orgs" subnav="true">
<ul class="nav">
<li class="active"><a href="admin/orgs/edit/{{org.id}}">{{org.name}}</a></li>
</ul>
<navbar icon="fa fa-fw fa-cogs" title="Admin" title-url="admin">
<nav-button title="Orgs" title-url="admin/orgs" icon="icon-gf icon-gf-users"></nav-button>
</navbar>
<div class="page-container">
<div class="page">
<h2>
Organization Details
</h2>
<div class="page-header">
<h1>
Edit Organization
</h1>
</div>
<form name="orgDetailsForm">
<div>
......
<navbar icon="fa fa-fw fa-user" title="Users" title-url="admin/users" subnav="true">
<ul class="nav">
<li class="active"><a href="admin/users/edit/{{user_id}}">Edit user</a></li>
</ul>
<navbar icon="fa fa-fw fa-cogs" title="Admin" title-url="admin">
<nav-button title="Users" title-url="admin/users" icon="icon-gf icon-gf-users"></nav-button>
</navbar>
<div class="page-container">
<div class="page">
<h2>
<div class="page-header">
<h1>
Edit User
</h2>
</h1>
</div>
<form name="userForm">
<div>
......@@ -146,5 +145,4 @@
</tr>
</table>
</div>
</div>
<navbar icon="fa fa-fw fa-user" title="Users" title-url="admin/users" subnav="true">
<ul class="nav">
<li class="active"><a href="admin/users/create">Add user</a></li>
</ul>
<navbar icon="fa fa-fw fa-cogs" title="Admin" title-url="admin">
<nav-button title="Users" title-url="admin/users" icon="icon-gf icon-gf-users"></nav-button>
</navbar>
<div class="page-container">
<div class="page">
<h2>
<div class="page-header">
<h1>
Add new user
</h2>
</h1>
</div>
<form name="userForm">
<div>
......@@ -61,5 +60,4 @@
<br>
<button type="submit" class="pull-right btn btn-success" ng-click="create()">Create</button>
</form>
</div>
</div>
<navbar icon="fa fa-fw fa-users" title="Organizations">
<navbar icon="fa fa-fw fa-cogs" title="Admin" title-url="admin">
<nav-button title="Orgs" title-url="admin/orgs" icon="icon-gf icon-gf-users"></nav-button>
</navbar>
<div class="page-container">
<div class="page-wide">
<h2>
<div class="page-header">
<h1>
Organizations
</h2>
</h1>
</div>
<table class="filter-table form-inline">
<thead>
<tr>
......@@ -31,5 +34,4 @@
</tr>
</tbody>
</table>
</div>
</div>
<navbar icon="fa fa-fw fa-info" title="System info">
<navbar icon="fa fa-fw fa-cogs" title="Admin" title-url="admin">
</navbar>
<div class="page-container">
<div class="page">
<h2>
System information
</h2>
<div class="page-header">
<h1>
Server settings
</h1>
</div>
<div class="grafana-info-box span8" style="margin: 20px 0 25px 0">
These system settings are defined in grafana.ini or grafana.custom.ini (or overriden in ENV variables).
......@@ -22,7 +23,6 @@
<td>{{keyValue}}</td>
</tr>
</table>
</div>
</div>
......
<navbar icon="fa fa-fw fa-bar-chart" title="Stats">
<navbar icon="fa fa-fw fa-cogs" title="Admin" title-url="admin">
</navbar>
<div class="page-container">
<div class="page-wide" ng-init="ctrl.init()">
<div class="page-header">
<h1>
Overview
Stats
</h1>
</div>
<table class="filter-table form-inline">
<thead>
......@@ -53,5 +54,4 @@
</tr>
</tbody>
</table>
</div>
</div>
<navbar icon="fa fa-fw fa-user" title="Users" title-url="admin/users">
<navbar icon="fa fa-fw fa-cogs" title="Admin" title-url="admin">
<nav-button title="Users" title-url="admin/users" icon="icon-gf icon-gf-users"></nav-button>
</navbar>
<div class="page-container">
<div class="page-wide">
<a class="btn btn-inverse pull-right" href="admin/users/create">
<div class="page-header">
<h1>Users</h1>
<a class="btn btn-success" href="admin/users/create">
<i class="fa fa-plus"></i>
Add new user
</a>
<h1>Users</h1>
</div>
<table class="filter-table form-inline">
<thead>
......@@ -41,5 +43,4 @@
</tr>
</tbody>
</table>
</div>
</div>
......@@ -10,5 +10,4 @@ define([
'./profile/profileCtrl',
'./profile/changePasswordCtrl',
'./profile/selectOrgCtrl',
'./admin/all',
], function () {});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment