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 @@