diff --git a/public/app/features/all.js b/public/app/features/all.js
index d4436c9deaa..e3c9f92b531 100644
--- a/public/app/features/all.js
+++ b/public/app/features/all.js
@@ -1,5 +1,6 @@
define([
'./panellinks/module',
+ './sidemenu/sidemenu',
'./dashlinks/module',
'./annotations/annotations_srv',
'./templating/templateSrv',
diff --git a/public/app/features/dashboard/timepicker/timepicker.ts b/public/app/features/dashboard/timepicker/timepicker.ts
index c8d319a12f2..59d2e62e7ae 100644
--- a/public/app/features/dashboard/timepicker/timepicker.ts
+++ b/public/app/features/dashboard/timepicker/timepicker.ts
@@ -144,7 +144,6 @@ export class TimePickerCtrl {
}
export function settingsDirective() {
- 'use strict';
return {
restrict: 'E',
templateUrl: 'app/features/dashboard/timepicker/settings.html',
@@ -158,7 +157,6 @@ export function settingsDirective() {
}
export function timePickerDirective() {
- 'use strict';
return {
restrict: 'E',
templateUrl: 'app/features/dashboard/timepicker/timepicker.html',
diff --git a/public/app/features/sidemenu/sidemenu.html b/public/app/features/sidemenu/sidemenu.html
new file mode 100644
index 00000000000..49431683db6
--- /dev/null
+++ b/public/app/features/sidemenu/sidemenu.html
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
diff --git a/public/app/features/sidemenu/sidemenu.ts b/public/app/features/sidemenu/sidemenu.ts
new file mode 100644
index 00000000000..0d2b32ddf38
--- /dev/null
+++ b/public/app/features/sidemenu/sidemenu.ts
@@ -0,0 +1,146 @@
+///
+
+import config from 'app/core/config';
+import store from 'app/core/store';
+import _ from 'lodash';
+import angular from 'angular';
+import $ from 'jquery';
+
+class SideMenuCtrl {
+ isSignedIn: boolean;
+ showSignout: boolean;
+ user: any;
+ mainLinks: any;
+ orgMenu: any;
+ systemSection: any;
+ grafanaVersion: any;
+ appSubUrl: string;
+
+ constructor(private $scope, private $location, private contextSrv, private backendSrv) {
+ this.isSignedIn = contextSrv.isSignedIn;
+ this.user = contextSrv.user;
+ this.appSubUrl = config.appSubUrl;
+ this.showSignout = this.contextSrv.isSignedIn && !config['authProxyEnabled'];
+ this.updateMenu();
+ this.$scope.$on('$routeChangeSuccess', () => this.updateMenu());
+ }
+
+ getUrl(url) {
+ return config.appSubUrl + url;
+ }
+
+ setupMainNav() {
+ this.mainLinks = config.bootData.mainNavLinks.map(item => {
+ return {text: item.text, icon: item.icon, img: item.img, url: this.getUrl(item.url)};
+ });
+ }
+
+ openUserDropdown() {
+ this.orgMenu = [
+ {section: 'You', cssClass: 'dropdown-menu-title'},
+ {text: 'Profile', url: this.getUrl('/profile')},
+ ];
+
+ if (this.contextSrv.hasRole('Admin')) {
+ this.orgMenu.push({section: this.user.orgName, cssClass: 'dropdown-menu-title'});
+ this.orgMenu.push({
+ text: "Settings",
+ url: this.getUrl("/org"),
+ });
+ this.orgMenu.push({
+ text: "Users",
+ url: this.getUrl("/org/users"),
+ });
+ this.orgMenu.push({
+ text: "API Keys",
+ url: this.getUrl("/org/apikeys"),
+ });
+ }
+
+ this.orgMenu.push({cssClass: "divider"});
+
+ if (config.allowOrgCreate) {
+ this.orgMenu.push({text: "New organization", icon: "fa fa-fw fa-plus", url: this.getUrl('/org/new')});
+ }
+
+ this.backendSrv.get('/api/user/orgs').then(orgs => {
+ orgs.forEach(org => {
+ if (org.orgId === this.contextSrv.user.orgId) {
+ return;
+ }
+
+ this.orgMenu.push({
+ text: "Switch to " + org.name,
+ icon: "fa fa-fw fa-random",
+ click: () => {
+ this.switchOrg(org.orgId);
+ }
+ });
+ });
+
+ this.orgMenu.push({cssClass: "divider"});
+
+ if (this.contextSrv.isGrafanaAdmin) {
+ this.orgMenu.push({text: "Server admin", url: this.getUrl("/admin/settings")});
+ }
+ if (this.isSignedIn) {
+ this.orgMenu.push({text: "Sign out", url: this.getUrl("/logout"), target: "_self"});
+ }
+ });
+ }
+
+ switchOrg(orgId) {
+ this.backendSrv.post('/api/user/using/' + orgId).then(() => {
+ 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",
+ href: this.getUrl("/admin/settings"),
+ });
+
+ this.mainLinks.push({
+ text: "Global Users",
+ icon: "fa fa-fw fa-user",
+ href: this.getUrl("/admin/users"),
+ });
+
+ this.mainLinks.push({
+ text: "Global Orgs",
+ icon: "fa fa-fw fa-users",
+ href: this.getUrl("/admin/orgs"),
+ });
+ }
+
+ updateMenu() {
+ this.systemSection = false;
+ this.mainLinks = [];
+ this.orgMenu = [];
+
+ var currentPath = this.$location.path();
+ if (currentPath.indexOf('/admin') === 0) {
+ this.setupAdminNav();
+ } else {
+ this.setupMainNav();
+ }
+ };
+}
+
+function sideMenuDirective() {
+ return {
+ restrict: 'E',
+ templateUrl: 'app/features/sidemenu/sidemenu.html',
+ controller: SideMenuCtrl,
+ bindToController: true,
+ controllerAs: 'ctrl',
+ scope: {},
+ };
+}
+
+angular.module('grafana.directives').directive('sidemenu', sideMenuDirective);
diff --git a/public/app/partials/sidemenu.html b/public/app/partials/sidemenu.html
deleted file mode 100644
index 24ec4905d0a..00000000000
--- a/public/app/partials/sidemenu.html
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
diff --git a/public/less/navbar.less b/public/less/navbar.less
index 7be191e4d73..9ce07effb43 100644
--- a/public/less/navbar.less
+++ b/public/less/navbar.less
@@ -20,70 +20,28 @@
color: @textColor;
}
-// .top-nav-menu-btn {
-// float: left;
-// .top-nav-menu-circle {
-// border: 1px solid @bodyBackground;
-// margin: 6px 6px 3px 9px;
-// display: inline-block;
-// padding: 4px;
-// border-radius: 50%;
-// background: @iconContainerBackground;
-// width: 30px;
-// height: 30px;
-// float: left;
-// }
-// .fa-bars {
-// color: @textColor;
-// width: 30px;
-// height: 30px;
-// left: 9px;
-// top: 7px;
-// font-size: 150%;
-// opacity: 0;
-// position: absolute;
-// transition: opacity .20s ease-in-out;
-// }
-// .fa-caret-down {
-// position: relative;
-// font-size: 80%;
-// }
-// img {
-// width: 30px;
-// position: absolute;
-// opacity: 1;
-// transition: opacity .20s ease-in-out;
-// }
-// &:hover {
-// .fa {
-// opacity: .7;
-// }
-// img {
-// opacity: 0;
-// }
-// }
-// }
-
.top-nav-btn {
display: block;
+ position: relative;
float: left;
margin: 0;
font-size: 1.4em;
- color: #a2a2a2;
- border-right: 1px solid black;
+ border-right: 1px solid @grafanaTargetBorder;
.fa-caret-down {
- font-size: 60%;
- position: relative;
- top: 4px;
+ font-size: 50%;
+ position: absolute;
+ right: 7px;
+ top: 21px;
}
a {
- background-color: darken(@grafanaTargetFuncBackground, 2%);
+ color: darken(@linkColor, 5%);
+ background-color: @navbarButtonBackground;
+ border-bottom: 1px solid @navbarButtonBackground;
display: inline-block;
- color: #a2a2a2;
&:hover {
- background: @grafanaTargetFuncBackground;
+ background: @navbarButtonBackgroundHighlight;
color: @linkColor;
border-bottom: 1px solid @blue;
}
@@ -92,7 +50,7 @@
.top-nav-menu-btn {
a {
- padding: 6px 15px 6px 10px;
+ padding: 6px 20px 6px 13px;
}
img {
width: 30px;
@@ -111,7 +69,7 @@
.top-nav-dashboards-btn {
a {
- padding: 14px 15px 14px 10px;
+ padding: 14px 17px 14px 13px;
}
.fa-th-large {
@@ -122,7 +80,6 @@
.dashboard-title {
padding: 0px 6px 5px 5px;
- color: @linkColorHover;
font-size: 17px;
}
diff --git a/public/less/sidemenu.less b/public/less/sidemenu.less
index 69601046f0d..b911cdb7a51 100644
--- a/public/less/sidemenu.less
+++ b/public/less/sidemenu.less
@@ -3,12 +3,13 @@
}
.sidemenu-wrapper {
- position: absolute;
- top: 51px;
+ position: fixed;
+ top: 53px;
bottom: 0;
left: 0;
width: 200px;
- background-color: darken(@grafanaTargetFuncBackground, 2%);
+ background-color: @sideMenuBackground;
+ border: @sideMenuBorder;
min-height: 100%;
z-index: 101;
@@ -83,18 +84,15 @@
padding: 0px 10px 0px 20px;
display: block;
white-space: nowrap;
+
&:hover {
- background-color: @grafanaTargetFuncBackground;
+ background-color: @sideMenuBackgroundHighlight;
}
.sidemenu-item-text {
padding-left: 11px;
- transition: color 100ms ease-out;
-
- &.no-icon {
- padding-left: 59px;
- }
}
+
img {
border-radius: 50%;
width: 28px;
@@ -169,8 +167,8 @@
}
.sidemenu-org-section {
- box-shadow: inset 0 4px 15px -4px #161616;
- border-bottom: 2px solid @sideMenuOrgBorder;
+ box-shadow: @sideMenuTopShadow;
+ border-bottom: @sideMenuBorder;
padding: 17px 10px 15px 21px;
cursor: pointer;
&:hover {
diff --git a/public/less/variables.dark.less b/public/less/variables.dark.less
index 3a46efced47..6fc9ab1cf64 100644
--- a/public/less/variables.dark.less
+++ b/public/less/variables.dark.less
@@ -159,7 +159,10 @@
// Sidemenu
// -------------------------
-@sideMenuOrgBorder: rgb(37,37,37);
+@sideMenuTopShadow: inset 0 4px 15px -4px @black;
+@sideMenuBorder: 1px solid @bodyBackground;
+@sideMenuBackground: @grayDark;
+@sideMenuBackgroundHighlight: lighten(@grayDark, 4%);
// Dropdowns
// -------------------------
@@ -239,6 +242,8 @@
@navbarBrandColor: @linkColor;
@navbarDropdownShadow: inset 0px 4px 10px -4px @bodyBackground;
+@navbarButtonBackground: lighten(@navbarBackground, 3%);
+@navbarButtonBackgroundHighlight: lighten(@navbarBackground, 5%);
// Pagination
// -------------------------
diff --git a/public/less/variables.light.less b/public/less/variables.light.less
index 9e2056743ca..81d0c81528a 100644
--- a/public/less/variables.light.less
+++ b/public/less/variables.light.less
@@ -173,7 +173,10 @@
// Sidemenu
// -------------------------
-@sideMenuOrgBorder: #555;
+@sideMenuTopShadow: @navbarDropdownShadow;
+@sideMenuBorder: 1px solid @grafanaTargetBorder;
+@sideMenuBackground: @grafanaPanelBackground;
+@sideMenuBackgroundHighlight: darken(@sideMenuBackground, 4%);
// Dropdowns
// -------------------------
@@ -255,6 +258,9 @@
@navbarBrandColor: @navbarLinkColor;
+@navbarButtonBackground: lighten(@navbarBackground, 3%);
+@navbarButtonBackgroundHighlight: lighten(@navbarBackground, 5%);
+
// Pagination
// -------------------------
diff --git a/public/views/index.html b/public/views/index.html
index 2b4b5c4e37b..0e51f7bc3a4 100644
--- a/public/views/index.html
+++ b/public/views/index.html
@@ -29,7 +29,7 @@