diff --git a/public/app/core/components/grafana_app.ts b/public/app/core/components/grafana_app.ts new file mode 100644 index 00000000000..068c9bec777 --- /dev/null +++ b/public/app/core/components/grafana_app.ts @@ -0,0 +1,184 @@ +/// + +import config from 'app/core/config'; +import store from 'app/core/store'; +import _ from 'lodash'; +import angular from 'angular'; +import $ from 'jquery'; +import coreModule from '../core_module'; + +export class GrafanaCtrl { + + /** @ngInject */ + constructor($scope, alertSrv, utilSrv, $rootScope, $controller, contextSrv) { + + $scope.init = function() { + $scope.contextSrv = contextSrv; + + $scope._ = _; + + $rootScope.profilingEnabled = store.getBool('profilingEnabled'); + $rootScope.performance = { loadStart: new Date().getTime() }; + $rootScope.appSubUrl = config.appSubUrl; + + if ($rootScope.profilingEnabled) { $scope.initProfiling(); } + + alertSrv.init(); + utilSrv.init(); + + $scope.dashAlerts = alertSrv; + }; + + $scope.initDashboard = function(dashboardData, viewScope) { + $controller('DashboardCtrl', { $scope: viewScope }).init(dashboardData); + }; + + $rootScope.onAppEvent = function(name, callback, localScope) { + var unbind = $rootScope.$on(name, callback); + var callerScope = this; + if (callerScope.$id === 1 && !localScope) { + console.log('warning rootScope onAppEvent called without localscope'); + } + if (localScope) { + callerScope = localScope; + } + callerScope.$on('$destroy', unbind); + }; + + $rootScope.appEvent = function(name, payload) { + $rootScope.$emit(name, payload); + }; + + $rootScope.colors = [ + "#7EB26D","#EAB839","#6ED0E0","#EF843C","#E24D42","#1F78C1","#BA43A9","#705DA0", + "#508642","#CCA300","#447EBC","#C15C17","#890F02","#0A437C","#6D1F62","#584477", + "#B7DBAB","#F4D598","#70DBED","#F9BA8F","#F29191","#82B5D8","#E5A8E2","#AEA2E0", + "#629E51","#E5AC0E","#64B0C8","#E0752D","#BF1B00","#0A50A1","#962D82","#614D93", + "#9AC48A","#F2C96D","#65C5DB","#F9934E","#EA6460","#5195CE","#D683CE","#806EB7", + "#3F6833","#967302","#2F575E","#99440A","#58140C","#052B51","#511749","#3F2B5B", + "#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7" + ]; + + $scope.getTotalWatcherCount = function() { + var count = 0; + var scopes = 0; + var root = $(document.getElementsByTagName('body')); + + var f = function (element) { + if (element.data().hasOwnProperty('$scope')) { + scopes++; + angular.forEach(element.data().$scope.$$watchers, function () { + count++; + }); + } + + angular.forEach(element.children(), function (childElement) { + f($(childElement)); + }); + }; + + f(root); + $rootScope.performance.scopeCount = scopes; + return count; + }; + + $scope.initProfiling = function() { + var count = 0; + + $scope.$watch(function digestCounter() { + count++; + }, function() { + // something + }); + + $rootScope.performance.panels = []; + + $scope.$on('refresh', function() { + if ($rootScope.performance.panels.length > 0) { + var totalRender = 0; + var totalQuery = 0; + + _.each($rootScope.performance.panels, function(panelTiming: any) { + totalRender += panelTiming.render; + totalQuery += panelTiming.query; + }); + + console.log('total query: ' + totalQuery); + console.log('total render: ' + totalRender); + console.log('avg render: ' + totalRender / $rootScope.performance.panels.length); + } + + $rootScope.performance.panels = []; + }); + + $scope.onAppEvent('dashboard-loaded', function() { + count = 0; + + setTimeout(function() { + console.log("Dashboard::Performance Total Digests: " + count); + console.log("Dashboard::Performance Total Watchers: " + $scope.getTotalWatcherCount()); + console.log("Dashboard::Performance Total ScopeCount: " + $rootScope.performance.scopeCount); + + var timeTaken = $rootScope.performance.allPanelsInitialized - $rootScope.performance.dashboardLoadStart; + console.log("Dashboard::Performance - All panels initialized in " + timeTaken + " ms"); + + // measure digest performance + var rootDigestStart = window.performance.now(); + for (var i = 0; i < 30; i++) { + $rootScope.$apply(); + } + console.log("Dashboard::Performance Root Digest " + ((window.performance.now() - rootDigestStart) / 30)); + + }, 3000); + + }); + + }; + + $scope.init(); + } +} + +export function grafanaAppDirective() { + return { + restrict: 'E', + controller: GrafanaCtrl, + link: (scope, elem) => { + var ignoreSideMenuHide; + // handle sidemenu open state + scope.$watch('contextSrv.sidemenu', newVal => { + if (newVal !== undefined) { + elem.toggleClass('sidemenu-open', scope.contextSrv.sidemenu); + } + if (scope.contextSrv.sidemenu) { + ignoreSideMenuHide = true; + setTimeout(() => { + ignoreSideMenuHide = false; + }, 300); + } + }); + + // handle document clicks that should hide things + elem.click(function(evt) { + if ($(evt.target).parents().length === 0) { + return; + } + + // hide search + if (elem.find('.search-container').length > 0) { + if ($(evt.target).parents('.search-container').length === 0) { + scope.appEvent('hide-dash-search'); + } + } + // hide sidemenu + if (!ignoreSideMenuHide && elem.find('.sidemenu').length > 0) { + if ($(evt.target).parents('.sidemenu').length === 0) { + scope.$apply(() => scope.contextSrv.toggleSideMenu()); + } + } + }); + } + }; +} + +coreModule.directive('grafanaApp', grafanaAppDirective); diff --git a/public/app/core/controllers/all.js b/public/app/core/controllers/all.js index d22010cffdc..5c4184e609a 100644 --- a/public/app/core/controllers/all.js +++ b/public/app/core/controllers/all.js @@ -1,5 +1,4 @@ define([ - './grafana_ctrl', './search_ctrl', './inspect_ctrl', './json_editor_ctrl', @@ -7,6 +6,5 @@ define([ './invited_ctrl', './signup_ctrl', './reset_password_ctrl', - './sidemenu_ctrl', './error_ctrl', ], function () {}); diff --git a/public/app/core/controllers/grafana_ctrl.ts b/public/app/core/controllers/grafana_ctrl.ts deleted file mode 100644 index 2363ffb94b1..00000000000 --- a/public/app/core/controllers/grafana_ctrl.ts +++ /dev/null @@ -1,140 +0,0 @@ -/// - -import config from 'app/core/config'; -import store from 'app/core/store'; -import _ from 'lodash'; -import angular from 'angular'; -import $ from 'jquery'; -import coreModule from '../core_module'; - -coreModule.controller('GrafanaCtrl', function($scope, alertSrv, utilSrv, $rootScope, $controller, contextSrv) { - - $scope.init = function() { - $scope.contextSrv = contextSrv; - - $scope._ = _; - - $rootScope.profilingEnabled = store.getBool('profilingEnabled'); - $rootScope.performance = { loadStart: new Date().getTime() }; - $rootScope.appSubUrl = config.appSubUrl; - - if ($rootScope.profilingEnabled) { $scope.initProfiling(); } - - alertSrv.init(); - utilSrv.init(); - - $scope.dashAlerts = alertSrv; - }; - - $scope.initDashboard = function(dashboardData, viewScope) { - $controller('DashboardCtrl', { $scope: viewScope }).init(dashboardData); - }; - - $rootScope.onAppEvent = function(name, callback, localScope) { - var unbind = $rootScope.$on(name, callback); - var callerScope = this; - if (callerScope.$id === 1 && !localScope) { - console.log('warning rootScope onAppEvent called without localscope'); - } - if (localScope) { - callerScope = localScope; - } - callerScope.$on('$destroy', unbind); - }; - - $rootScope.appEvent = function(name, payload) { - $rootScope.$emit(name, payload); - }; - - $rootScope.colors = [ - "#7EB26D","#EAB839","#6ED0E0","#EF843C","#E24D42","#1F78C1","#BA43A9","#705DA0", - "#508642","#CCA300","#447EBC","#C15C17","#890F02","#0A437C","#6D1F62","#584477", - "#B7DBAB","#F4D598","#70DBED","#F9BA8F","#F29191","#82B5D8","#E5A8E2","#AEA2E0", - "#629E51","#E5AC0E","#64B0C8","#E0752D","#BF1B00","#0A50A1","#962D82","#614D93", - "#9AC48A","#F2C96D","#65C5DB","#F9934E","#EA6460","#5195CE","#D683CE","#806EB7", - "#3F6833","#967302","#2F575E","#99440A","#58140C","#052B51","#511749","#3F2B5B", - "#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7" - ]; - - $scope.getTotalWatcherCount = function() { - var count = 0; - var scopes = 0; - var root = $(document.getElementsByTagName('body')); - - var f = function (element) { - if (element.data().hasOwnProperty('$scope')) { - scopes++; - angular.forEach(element.data().$scope.$$watchers, function () { - count++; - }); - } - - angular.forEach(element.children(), function (childElement) { - f($(childElement)); - }); - }; - - f(root); - $rootScope.performance.scopeCount = scopes; - return count; - }; - - $scope.initProfiling = function() { - var count = 0; - - $scope.$watch(function digestCounter() { - count++; - }, function() { - // something - }); - - $rootScope.performance.panels = []; - - $scope.$on('refresh', function() { - if ($rootScope.performance.panels.length > 0) { - var totalRender = 0; - var totalQuery = 0; - - _.each($rootScope.performance.panels, function(panelTiming: any) { - totalRender += panelTiming.render; - totalQuery += panelTiming.query; - }); - - console.log('total query: ' + totalQuery); - console.log('total render: ' + totalRender); - console.log('avg render: ' + totalRender / $rootScope.performance.panels.length); - } - - $rootScope.performance.panels = []; - }); - - $scope.onAppEvent('dashboard-loaded', function() { - count = 0; - - setTimeout(function() { - console.log("Dashboard::Performance Total Digests: " + count); - console.log("Dashboard::Performance Total Watchers: " + $scope.getTotalWatcherCount()); - console.log("Dashboard::Performance Total ScopeCount: " + $rootScope.performance.scopeCount); - - var timeTaken = $rootScope.performance.allPanelsInitialized - $rootScope.performance.dashboardLoadStart; - console.log("Dashboard::Performance - All panels initialized in " + timeTaken + " ms"); - - // measure digest performance - var rootDigestStart = window.performance.now(); - for (var i = 0; i < 30; i++) { - $rootScope.$apply(); - } - console.log("Dashboard::Performance Root Digest " + ((window.performance.now() - rootDigestStart) / 30)); - - }, 3000); - - }); - - }; - - $scope.init(); - -}); - -var grafanaCtrl = {}; -export default grafanaCtrl; diff --git a/public/app/core/controllers/sidemenu_ctrl.js b/public/app/core/controllers/sidemenu_ctrl.js deleted file mode 100644 index 5bca63cb1cd..00000000000 --- a/public/app/core/controllers/sidemenu_ctrl.js +++ /dev/null @@ -1,130 +0,0 @@ -define([ - 'angular', - 'lodash', - 'jquery', - '../core_module', - 'app/core/config', -], -function (angular, _, $, coreModule, config) { - 'use strict'; - - coreModule.default.controller('SideMenuCtrl', function($scope, $location, contextSrv, backendSrv) { - - $scope.getUrl = function(url) { - return config.appSubUrl + url; - }; - - $scope.setupMainNav = function() { - _.each(config.bootData.mainNavLinks, function(item) { - $scope.mainLinks.push({ - text: item.text, - icon: item.icon, - img: item.img, - url: $scope.getUrl(item.url) - }); - }); - }; - - $scope.openUserDropdown = function() { - $scope.orgMenu = [ - {section: 'You', cssClass: 'dropdown-menu-title'}, - {text: 'Profile', url: $scope.getUrl('/profile')}, - ]; - - if (contextSrv.hasRole('Admin')) { - $scope.orgMenu.push({section: contextSrv.user.orgName, cssClass: 'dropdown-menu-title'}); - $scope.orgMenu.push({ - text: "Settings", - url: $scope.getUrl("/org"), - }); - $scope.orgMenu.push({ - text: "Users", - url: $scope.getUrl("/org/users"), - }); - $scope.orgMenu.push({ - text: "API Keys", - url: $scope.getUrl("/org/apikeys"), - }); - } - - $scope.orgMenu.push({cssClass: "divider"}); - - if (config.allowOrgCreate) { - $scope.orgMenu.push({text: "New organization", icon: "fa fa-fw fa-plus", url: $scope.getUrl('/org/new')}); - } - - backendSrv.get('/api/user/orgs').then(function(orgs) { - _.each(orgs, function(org) { - if (org.orgId === contextSrv.user.orgId) { - return; - } - - $scope.orgMenu.push({ - text: "Switch to " + org.name, - icon: "fa fa-fw fa-random", - click: function() { - $scope.switchOrg(org.orgId); - } - }); - }); - - $scope.orgMenu.push({cssClass: "divider"}); - if (contextSrv.isGrafanaAdmin) { - $scope.orgMenu.push({text: "Server admin", url: $scope.getUrl("/admin/settings")}); - } - if (contextSrv.isSignedIn) { - $scope.orgMenu.push({text: "Sign out", url: $scope.getUrl("/logout"), target: "_self"}); - } - }); - }; - - $scope.switchOrg = function(orgId) { - backendSrv.post('/api/user/using/' + orgId).then(function() { - window.location.href = $scope.getUrl('/'); - }); - }; - - $scope.setupAdminNav = function() { - $scope.systemSection = true; - $scope.grafanaVersion = config.buildInfo.version; - - $scope.mainLinks.push({ - text: "System info", - icon: "fa fa-fw fa-info", - href: $scope.getUrl("/admin/settings"), - }); - - $scope.mainLinks.push({ - text: "Global Users", - icon: "fa fa-fw fa-user", - href: $scope.getUrl("/admin/users"), - }); - - $scope.mainLinks.push({ - text: "Global Orgs", - icon: "fa fa-fw fa-users", - href: $scope.getUrl("/admin/orgs"), - }); - }; - - $scope.updateMenu = function() { - $scope.systemSection = false; - $scope.mainLinks = []; - $scope.orgMenu = []; - - var currentPath = $location.path(); - if (currentPath.indexOf('/admin') === 0) { - $scope.setupAdminNav(); - } else { - $scope.setupMainNav(); - } - }; - - $scope.init = function() { - $scope.showSignout = contextSrv.isSignedIn && !config['authProxyEnabled']; - $scope.updateMenu(); - $scope.$on('$routeChangeSuccess', $scope.updateMenu); - }; - }); - -}); diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 6882a87da69..7728ddb7a93 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -21,6 +21,7 @@ import "./directives/give_focus"; import './jquery_extended'; import './partials'; +import {grafanaAppDirective} from './components/grafana_app'; import {arrayJoin} from './directives/array_join'; import 'app/core/controllers/all'; import 'app/core/services/all'; @@ -28,4 +29,4 @@ import 'app/core/routes/all'; import './filters/filters'; import coreModule from './core_module'; -export {arrayJoin, coreModule}; +export {arrayJoin, coreModule, grafanaAppDirective}; diff --git a/public/app/core/directives/topnav.js b/public/app/core/directives/topnav.js index e8874d38027..60a09583789 100644 --- a/public/app/core/directives/topnav.js +++ b/public/app/core/directives/topnav.js @@ -18,7 +18,7 @@ function (coreModule) { '