started on some big refactoring of how the app starts and how dashboard object is loaded, created. This should make it easier to add other dashboard storage backends and other views

This commit is contained in:
Torkel Ödegaard
2014-06-07 19:43:15 +02:00
parent 92318d5804
commit 79404e754e
14 changed files with 207 additions and 101 deletions
+6 -16
View File
@@ -6,15 +6,16 @@ define([
'jquery',
'underscore',
'require',
'config',
'elasticjs',
'bootstrap',
'angular-sanitize',
'angular-strap',
'angular-dragdrop',
'extend-jquery',
'bindonce'
'bindonce',
],
function (angular, $, _, appLevelRequire) {
function (angular, $, _, appLevelRequire, config) {
"use strict";
@@ -67,19 +68,7 @@ function (angular, $, _, appLevelRequire) {
app.config(function ($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
$routeProvider
.when('/dashboard', {
templateUrl: 'app/partials/dashboard.html',
})
.when('/dashboard/:kbnType/:kbnId', {
templateUrl: 'app/partials/dashboard.html',
})
.when('/dashboard/:kbnType/:kbnId/:params', {
templateUrl: 'app/partials/dashboard.html'
})
.otherwise({
redirectTo: 'dashboard'
});
$routeProvider.otherwise({ redirectTo: config.default_route });
// this is how the internet told me to dynamically add modules :/
register_fns.controller = $controllerProvider.register;
@@ -98,7 +87,7 @@ function (angular, $, _, appLevelRequire) {
'pasvaz.bindonce'
];
var module_types = ['controllers', 'directives', 'factories', 'services', 'services.dashboard', 'filters'];
var module_types = ['controllers', 'directives', 'factories', 'services', 'filters', 'routes'];
_.each(module_types, function (type) {
var module_name = 'kibana.'+type;
@@ -120,6 +109,7 @@ function (angular, $, _, appLevelRequire) {
'directives/all',
'filters/all',
'components/partials',
'routes/dashboard-loader',
], function () {
// bootstrap the app
+1 -11
View File
@@ -31,11 +31,9 @@ function (angular, $, config, _) {
var module = angular.module('kibana.controllers');
module.controller('DashCtrl', function(
$scope, $rootScope, $timeout, ejsResource, dashboard, filterSrv, dashboardKeybindings,
$scope, $rootScope, $timeout, ejsResource, filterSrv, dashboardKeybindings,
alertSrv, panelMove, keyboardManager, grafanaVersion) {
$scope.requiredElasticSearchVersion = ">=0.90.3";
$scope.editor = {
index: 0
};
@@ -54,16 +52,8 @@ function (angular, $, config, _) {
// Make stuff, including underscore.js available to views
$scope._ = _;
$scope.dashboard = dashboard;
$scope.dashAlerts = alertSrv;
$scope.filter = filterSrv;
$scope.filter.init(dashboard.current);
$rootScope.$on("dashboard-loaded", function(event, dashboard) {
$scope.filter.init(dashboard);
});
// Clear existing alerts
alertSrv.clearAll();
+9 -6
View File
@@ -8,8 +8,7 @@ function (angular, _, moment) {
var module = angular.module('kibana.controllers');
module.controller('dashLoader', function($scope, $rootScope, $http, dashboard, alertSrv, $location, playlistSrv) {
$scope.loader = dashboard.current.loader;
module.controller('dashLoader', function($scope, $rootScope, $http, alertSrv, $location, playlistSrv) {
$scope.init = function() {
$scope.gist_pattern = /(^\d{5,}$)|(^[a-z0-9]{10,}$)|(gist.github.com(\/*.*)\/[a-z0-9]{5,}\/*$)/;
@@ -23,6 +22,10 @@ function (angular, _, moment) {
$rootScope.$on('zoom-out', function() {
$scope.zoom(2);
});
$rootScope.$on('dashboard-loaded', function(event, dashboard) {
$scope.loader = dashboard.loader;
});
};
$scope.exitFullscreen = function() {
@@ -30,11 +33,11 @@ function (angular, _, moment) {
};
$scope.showDropdown = function(type) {
if(_.isUndefined(dashboard.current.loader)) {
if(_.isUndefined($scope.loader)) {
return true;
}
var _l = dashboard.current.loader;
var _l = $scope.loader;
if(type === 'load') {
return (_l.load_elasticsearch || _l.load_gist || _l.load_local);
}
@@ -129,7 +132,7 @@ function (angular, _, moment) {
// function $scope.zoom
// factor :: Zoom factor, so 0.5 = cuts timespan in half, 2 doubles timespan
$scope.zoom = function(factor) {
var _range = this.filter.timeRange();
var _range = $scope.filter.timeRange();
var _timespan = (_range.to.valueOf() - _range.from.valueOf());
var _center = _range.to.valueOf() - _timespan/2;
@@ -143,7 +146,7 @@ function (angular, _, moment) {
_to = Date.now();
}
this.filter.setTime({
$scope.filter.setTime({
from:moment.utc(_from).toDate(),
to:moment.utc(_to).toDate(),
});
+12 -4
View File
@@ -15,8 +15,12 @@ function (angular, app, _) {
var lastPulldownVal;
var lastHideControlsVal;
$scope.$watch('dashboard.current.pulldowns', function() {
var panel = _.find($scope.dashboard.current.pulldowns, function(pulldown) { return pulldown.enable; });
$scope.$watch('dashboard.pulldowns', function() {
if (!$scope.dashboard) {
return;
}
var panel = _.find($scope.dashboard.pulldowns, function(pulldown) { return pulldown.enable; });
var panelEnabled = panel ? panel.enable : false;
if (lastPulldownVal !== panelEnabled) {
elem.toggleClass('submenu-controls-visible', panelEnabled);
@@ -24,8 +28,12 @@ function (angular, app, _) {
}
}, true);
$scope.$watch('dashboard.current.hideControls', function() {
var hideControls = $scope.dashboard.current.hideControls || $scope.playlist_active;
$scope.$watch('dashboard.hideControls', function() {
if (!$scope.dashboard) {
return;
}
var hideControls = $scope.dashboard.hideControls || $scope.playlist_active;
if (lastHideControlsVal !== hideControls) {
elem.toggleClass('hide-controls', hideControls);
+4 -3
View File
@@ -10,13 +10,14 @@ function (angular, $, kbn, moment, _) {
var module = angular.module('kibana.directives');
module.directive('grafanaGraph', function($rootScope, dashboard) {
module.directive('grafanaGraph', function($rootScope) {
return {
restrict: 'A',
template: '<div> </div>',
link: function(scope, elem) {
var data, plot, annotations;
var hiddenData = {};
var dashboard = scope.dashboard;
scope.$on('refresh',function() {
if (scope.otherPanelInFullscreenMode()) { return; }
@@ -172,7 +173,7 @@ function (angular, $, kbn, moment, _) {
var max = _.isUndefined(scope.range.to) ? null : scope.range.to.getTime();
options.xaxis = {
timezone: dashboard.current.timezone,
timezone: dashboard.timezone,
show: scope.panel['x-axis'],
mode: "time",
min: min,
@@ -329,7 +330,7 @@ function (angular, $, kbn, moment, _) {
value = kbn.getFormatFunction(format, 2)(value);
timestamp = dashboard.current.timezone === 'browser' ?
timestamp = dashboard.timezone === 'browser' ?
moment(item.datapoint[0]).format('YYYY-MM-DD HH:mm:ss') :
moment.utc(item.datapoint[0]).format('YYYY-MM-DD HH:mm:ss');
$tooltip
+3 -2
View File
@@ -259,10 +259,11 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
targets: $scope.panel.targets,
format: $scope.panel.renderer === 'png' ? 'png' : 'json',
maxDataPoints: $scope.resolution,
datasource: $scope.panel.datasource
datasource: $scope.panel.datasource,
timezone: $scope.dashboard.timezone
};
$scope.annotationsPromise = annotationsSrv.getAnnotations($scope.filter, $scope.rangeUnparsed);
$scope.annotationsPromise = annotationsSrv.getAnnotations($scope.filter, $scope.rangeUnparsed, $scope.dashboard);
return $scope.datasource.query($scope.filter, graphiteQuery)
.then($scope.dataHandler)
+13 -3
View File
@@ -1,5 +1,15 @@
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<span class="brand"><img src="img/small.png" bs-tooltip="'Grafana'" data-placement="bottom"> {{dashboard.title}}</span>
<ul class="nav pull-right" ng-controller='dashLoader' ng-init="init()" ng-include="'app/partials/dashLoader.html'">
</ul>
</div>
</div>
</div>
<div class="submenu-controls">
<div class="submenu-panel" ng-controller="SubmenuCtrl" ng-repeat="pulldown in dashboard.current.pulldowns | filter:{ enable: true }">
<div class="submenu-panel" ng-controller="SubmenuCtrl" ng-repeat="pulldown in dashboard.pulldowns | filter:{ enable: true }">
<div class="submenu-panel-title">
<span class="small"><strong>{{pulldown.type}}:</strong></span>
</div>
@@ -15,7 +25,7 @@
<div>
<div class="grafana-container container">
<!-- Rows -->
<div class="kibana-row" ng-controller="RowCtrl" ng-repeat="(row_name, row) in dashboard.current.rows" ng-style="row_style(row)">
<div class="kibana-row" ng-controller="RowCtrl" ng-repeat="(row_name, row) in dashboard.rows" ng-style="row_style(row)">
<div class="row-control">
<div class="grafana-row" style="padding:0px;margin:0px;position:relative;">
<div class="row-close" ng-show="row.collapse" data-placement="bottom" >
@@ -97,7 +107,7 @@
</div>
</div>
<div ng-show='dashboard.current.editable && dashboard.current.panel_hints' class="row-fluid add-row-panel-hint">
<div ng-show='dashboard.editable && dashboard.current.panel_hints' class="row-fluid add-row-panel-hint">
<div class="span12" style="text-align:right;">
<span style="margin-right: 10px;" ng-click="add_row_default()" class="pointer btn btn-info btn-mini">
<span><i class="icon-plus-sign"></i> ADD A ROW</span>
+70
View File
@@ -0,0 +1,70 @@
define([
'angular',
'jquery',
'config',
'underscore'
],
function (angular, $, config, _) {
"use strict";
var module = angular.module('kibana.routes');
module.config(function($routeProvider) {
$routeProvider
.when('/dashboard/file/:jsonFile', {
templateUrl: 'app/partials/dashboard.html',
controller : 'DashFromFileProvider',
});
});
module.controller('DashFromFileProvider', function($scope, $rootScope, $http, $routeParams, alertSrv, dashboard, filterSrv) {
$scope.init = function() {
console.log('DashFromFileProvider->init()')
file_load($routeParams.jsonFile)
.then(function(data) {
$scope.dashboard = dashboard.create(data);
$scope.filter = filterSrv;
$scope.filter.init($scope.dashboard);
$rootScope.$emit("dashboard-loaded", $scope.dashboard);
});
};
var renderTemplate = function(json,params) {
var _r;
_.templateSettings = {interpolate : /\{\{(.+?)\}\}/g};
var template = _.template(json);
var rendered = template({ARGS:params});
try {
_r = angular.fromJson(rendered);
} catch(e) {
_r = false;
}
return _r;
};
var file_load = function(file) {
return $http({
url: "app/dashboards/"+file.replace(/\.(?!json)/,"/")+'?' + new Date().getTime(),
method: "GET",
transformResponse: function(response) {
return renderTemplate(response,$routeParams);
}
}).then(function(result) {
if(!result) {
return false;
}
return result.data;
},function() {
alertSrv.set('Error',"Could not load <i>dashboards/"+file+"</i>. Please make sure it exists" ,'error');
return false;
});
};
$scope.init();
});
});
+3 -10
View File
@@ -7,20 +7,12 @@ define([
var module = angular.module('kibana.services');
module.service('annotationsSrv', function(dashboard, datasourceSrv, $q, alertSrv, $rootScope) {
module.service('annotationsSrv', function(datasourceSrv, $q, alertSrv, $rootScope) {
var promiseCached;
var annotationPanel;
var list = [];
this.init = function() {
$rootScope.$on('refresh', this.clearCache);
$rootScope.$on('dashboard-loaded', this.dashboardLoaded);
this.dashboardLoaded();
};
this.dashboardLoaded = function () {
annotationPanel = _.findWhere(dashboard.current.pulldowns, { type: 'annotations' });
};
this.clearCache = function() {
@@ -28,7 +20,8 @@ define([
list = [];
};
this.getAnnotations = function(filterSrv, rangeUnparsed) {
this.getAnnotations = function(filterSrv, rangeUnparsed, dashboard) {
var annotationPanel = _.findWhere(dashboard.pulldowns, { type: 'annotations' });
if (!annotationPanel.enable) {
return $q.when(null);
}
+75 -24
View File
@@ -8,33 +8,28 @@ define([
'modernizr',
'filesaver'
],
function (angular, $, kbn, _, config, moment, Modernizr) {
function (angular, $, kbn, _) {
'use strict';
var module = angular.module('kibana.services');
module.service('dashboard', function(
$routeParams, $http, $rootScope, $injector, $location, $timeout,
ejsResource, timer, alertSrv, $q
) {
// A hash of defaults to use when loading a dashboard
module.service('dashboard', function(timer, $rootScope) {
var _dash = {
title: "",
tags: [],
style: "dark",
timezone: 'browser',
editable: true,
failover: false,
panel_hints: true,
rows: [],
pulldowns: [{ type: 'templating' }, { type: 'annotations' }],
nav: [{ type: 'timepicker' }],
services: {},
loader: {
function DashboardModel (data) {
this.title = data.title;
this.tags = data.tags || [];
this.style = data.style || "dark";
this.timezone = data.browser || 'browser';
this.editable = data.editble || true;
this.rows = data.rows || [];
this.pulldowns = data.pulldowns || [];
this.nav = data.nav || [];
this.services = data.services || {};
this.loader = data.loader;
_.defaults(this.loader, {
save_gist: false,
save_elasticsearch: true,
save_local: true,
save_default: true,
save_temp: true,
save_temp_ttl_enable: true,
@@ -42,10 +37,64 @@ function (angular, $, kbn, _, config, moment, Modernizr) {
load_gist: false,
load_elasticsearch: true,
load_elasticsearch_size: 20,
load_local: false,
hide: false
},
refresh: false
});
if (this.nav.length === 0) {
this.nav.push({ type: 'timepicker' });
}
if (!_.findWhere(this.pulldowns, {type: 'filtering'})) {
this.pulldowns.push({ type: 'filtering', enable: false });
}
if (!_.findWhere(this.pulldowns, {type: 'annotations'})) {
this.pulldowns.push({ type: 'annotations', enable: false });
}
_.each(this.rows, function(row) {
_.each(row.panels, function(panel) {
if (panel.type === 'graphite') {
panel.type = 'graph';
}
});
});
}
var p = DashboardModel.prototype;
p.refresh = function() {
$rootScope.$broadcast('refresh');
};
p.set_interval = function(interval) {
this.refresh = interval;
if (interval) {
var _i = kbn.interval_to_ms(interval);
timer.cancel(this.refresh_timer);
var dashboard_reference = this;
this.refresh_timer = timer.register($timeout(function() {
dashboard_reference.set_interval(interval);
dashboard_reference.full_refresh();
},_i));
this.full_refresh();
} else {
timer.cancel(this.refresh_timer);
}
};
return {
create: function(dashboard) {
return new DashboardModel(dashboard);
}
};
/*// A hash of defaults to use when loading a dashboard
var _dash = {
};
// An elasticJS client to use
@@ -326,6 +375,7 @@ function (angular, $, kbn, _, config, moment, Modernizr) {
})
.then(function(result) {
/*jshint -W054 */
/*
var script_func = new Function('ARGS','kbn','_','moment','window','document','$','jQuery', result.data);
var script_result = script_func($routeParams,kbn,_,moment, window, document, $, $);
@@ -459,6 +509,7 @@ function (angular, $, kbn, _, config, moment, Modernizr) {
timer.cancel(self.refresh_timer);
}
};
});
*/
});
});
@@ -6,7 +6,7 @@ define([
function(angular, $) {
"use strict";
var module = angular.module('kibana.services.dashboard');
var module = angular.module('kibana.services');
module.service('dashboardKeybindings', function($rootScope, keyboardManager, dashboard) {
this.shortcuts = function() {
+4 -6
View File
@@ -8,7 +8,7 @@ define([
var module = angular.module('kibana.services');
module.factory('filterSrv', function(dashboard, $rootScope, $timeout, $routeParams) {
module.factory('filterSrv', function($rootScope, $timeout, $routeParams) {
// defaults
var _d = {
templateParameters: [],
@@ -53,16 +53,14 @@ define([
// disable refresh if we have an absolute time
if (time.to !== 'now') {
this.old_refresh = this.dashboard.refresh;
dashboard.set_interval(false);
this.dashboard.set_interval(false);
}
else if (this.old_refresh && this.old_refresh !== this.dashboard.refresh) {
dashboard.set_interval(this.old_refresh);
this.dashboard.set_interval(this.old_refresh);
this.old_refresh = null;
}
$timeout(function() {
dashboard.refresh();
},0);
$timeout(this.dashboard.refresh, 0);
},
timeRange: function(parse) {
@@ -11,7 +11,7 @@ function (angular, _, $, config, kbn, moment) {
var module = angular.module('kibana.services');
module.factory('GraphiteDatasource', function(dashboard, $q, $http) {
module.factory('GraphiteDatasource', function($q, $http) {
function GraphiteDatasource(datasource) {
this.type = 'graphite';
@@ -25,8 +25,8 @@ function (angular, _, $, config, kbn, moment) {
GraphiteDatasource.prototype.query = function(filterSrv, options) {
try {
var graphOptions = {
from: this.translateTime(options.range.from, 'round-down'),
until: this.translateTime(options.range.to, 'round-up'),
from: this.translateTime(options.range.from, options.timezone, 'round-down'),
until: this.translateTime(options.range.to, options.timezone, 'round-up'),
targets: options.targets,
format: options.format,
maxDataPoints: options.maxDataPoints,
@@ -72,7 +72,7 @@ function (angular, _, $, config, kbn, moment) {
}
};
GraphiteDatasource.prototype.translateTime = function(date, rounding) {
GraphiteDatasource.prototype.translateTime = function(date, timezone, rounding) {
if (_.isString(date)) {
if (date === 'now') {
return 'now';
@@ -104,7 +104,7 @@ function (angular, _, $, config, kbn, moment) {
}
}
if (dashboard.current.timezone === 'browser') {
if (timezone === 'browser') {
date = date.local();
}
+1 -10
View File
@@ -20,7 +20,7 @@
<body ng-cloak body-class>
<link rel="stylesheet" href="css/bootstrap.light.min.css" ng-if="dashboard.current.style === 'light'">
<link rel="stylesheet" href="css/bootstrap.light.min.css" ng-if="dashboard.style === 'light'">
<link rel="stylesheet" href="css/bootstrap-responsive.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
@@ -28,15 +28,6 @@
<button type="button" class="close" ng-click="dashAlerts.clear(alert)" style="padding-right:50px">&times;</button>
<strong>{{alert.title}}</strong> <span ng-bind-html='alert.text'></span> <div style="padding-right:10px" class='pull-right small'> {{$index + 1}} alert(s) </div>
</div>
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<span class="brand"><img src="img/small.png" bs-tooltip="'Grafana'" data-placement="bottom"> {{dashboard.current.title}}</span>
<ul class="nav pull-right" ng-controller='dashLoader' ng-init="init()" ng-include="'app/partials/dashLoader.html'">
</ul>
</div>
</div>
</div>
<div ng-view ng-class="{'dashboard-fullscreen': fullscreen}"></div>