Merge branch 'master' of github.com:torkelo/grafana-private into pro

Conflicts:
	src/app/app.js
	src/app/controllers/all.js
	src/app/routes/all.js
	src/app/services/datasourceSrv.js
	src/test/test-main.js
This commit is contained in:
Torkel Ödegaard 2014-12-31 12:07:22 +01:00
commit 75c77a44c9
98 changed files with 226 additions and 162 deletions

View File

@ -1,9 +1,12 @@
# 1.9.1 (unreleased) # 1.9.1 (2014-12-29)
**Enhancements** **Enhancements**
- [Issue #1028](https://github.com/grafana/grafana/issues/1028). Graph: New legend option ``hideEmtpy`` to hide series with only null values - [Issue #1028](https://github.com/grafana/grafana/issues/1028). Graph: New legend option ``hideEmtpy`` to hide series with only null values from legend
- [Issue #1242](https://github.com/grafana/grafana/issues/1242). OpenTSDB: Downsample query field now supports interval template variable
- [Issue #1126](https://github.com/grafana/grafana/issues/1126). InfluxDB: Support more than 10 series name segments when using alias ``$number`` patterns
**Fixes** **Fixes**
- [Issue #1251](https://github.com/grafana/grafana/issues/1251). Graph: Fix for y axis and scaled units (GiB etc) caused rounding, for example 400 GiB instead of 378 GiB
- [Issue #1199](https://github.com/grafana/grafana/issues/1199). Graph: fix for series tooltip when one series is hidden/disabled - [Issue #1199](https://github.com/grafana/grafana/issues/1199). Graph: fix for series tooltip when one series is hidden/disabled
- [Issue #1207](https://github.com/grafana/grafana/issues/1207). Graphite: movingAverage / movingMedian parameter type impovement, now handles int and interval parameter - [Issue #1207](https://github.com/grafana/grafana/issues/1207). Graphite: movingAverage / movingMedian parameter type impovement, now handles int and interval parameter

View File

@ -1,4 +1,4 @@
{ {
"version": "1.9.0", "version": "1.9.1",
"url": "http://grafanarel.s3.amazonaws.com/grafana-1.9.0.tar.gz" "url": "http://grafanarel.s3.amazonaws.com/grafana-1.9.1.tar.gz"
} }

View File

@ -4,7 +4,7 @@
"company": "Coding Instinct AB" "company": "Coding Instinct AB"
}, },
"name": "grafana", "name": "grafana",
"version": "1.9.0", "version": "1.9.1",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "http://github.com/torkelo/grafana.git" "url": "http://github.com/torkelo/grafana.git"

View File

@ -85,7 +85,7 @@ function (angular, $, _, appLevelRequire, config) {
'directives/all', 'directives/all',
'filters/all', 'filters/all',
'components/partials', 'components/partials',
'routes/all', 'routes/backend/all',
]; ];
_.each(config.plugins.dependencies, function(dep) { _.each(config.plugins.dependencies, function(dep) {

View File

@ -339,7 +339,7 @@ function($, _, moment) {
return ""; return "";
} }
var factor = decimals ? Math.pow(10, decimals) : 1; var factor = decimals ? Math.pow(10, Math.max(0, decimals)) : 1;
var formatted = String(Math.round(value * factor) / factor); var formatted = String(Math.round(value * factor) / factor);
// if exponent return directly // if exponent return directly

View File

@ -1,20 +1,9 @@
define([ define([
'./pro/grafanaCtrl', './grafanaCtrl',
'./pro/sharePanelCtrl',
'./dashboardCtrl',
'./dashboardNavCtrl',
'./row',
'./submenuCtrl',
'./pulldown', './pulldown',
'./search', './search',
'./metricKeys', './metricKeys',
'./graphiteTarget',
'./graphiteImport', './graphiteImport',
'./influxTargetCtrl',
'./playlistCtrl',
'./inspectCtrl', './inspectCtrl',
'./opentsdbTargetCtrl',
'./annotationsEditorCtrl',
'./templateEditorCtrl',
'./jsonEditorCtrl', './jsonEditorCtrl',
], function () {}); ], function () {});

View File

@ -1,6 +1,5 @@
define([ define([
'angular', 'angular',
'services/pro/backendSrv',
], ],
function (angular) { function (angular) {
'use strict'; 'use strict';

View File

@ -1,6 +1,5 @@
define([ define([
'angular', 'angular',
'services/pro/backendSrv',
], ],
function (angular) { function (angular) {
'use strict'; 'use strict';

View File

@ -19,6 +19,9 @@ function (angular, _, config, $) {
$scope.db = datasourceSrv.getGrafanaDB(); $scope.db = datasourceSrv.getGrafanaDB();
$scope.currentSearchId = 0; $scope.currentSearchId = 0;
// events
$scope.onAppEvent('dashboard-deleted', $scope.dashboardDeleted);
$timeout(function() { $timeout(function() {
$scope.giveSearchFocus = $scope.giveSearchFocus + 1; $scope.giveSearchFocus = $scope.giveSearchFocus + 1;
$scope.query.query = 'title:'; $scope.query.query = 'title:';
@ -123,6 +126,10 @@ function (angular, _, config, $) {
$scope.deleteDashboard = function(dash, evt) { $scope.deleteDashboard = function(dash, evt) {
evt.stopPropagation(); evt.stopPropagation();
$scope.appEvent('delete-dashboard', { id: dash.id, title: dash.title }); $scope.appEvent('delete-dashboard', { id: dash.id, title: dash.title });
};
$scope.dashboardDeleted = function(evt, id) {
var dash = _.findWhere($scope.results.dashboards, {id: id});
$scope.results.dashboards = _.without($scope.results.dashboards, dash); $scope.results.dashboards = _.without($scope.results.dashboards, dash);
}; };

View File

@ -12,11 +12,8 @@ define([
'./spectrumPicker', './spectrumPicker',
'./bootstrap-tagsinput', './bootstrap-tagsinput',
'./bodyClass', './bodyClass',
'./addGraphiteFunc',
'./graphiteFuncEditor',
'./templateParamSelector', './templateParamSelector',
'./graphiteSegment', './graphiteSegment',
'./grafanaVersionCheck', './grafanaVersionCheck',
'./dropdown.typeahead', './dropdown.typeahead',
'./influxdbFuncEditor'
], function () {}); ], function () {});

View File

@ -18,7 +18,7 @@ function (angular, $, config) {
'<div class="panel-header">'+ '<div class="panel-header">'+
'<span class="alert-error panel-error small pointer"' + '<span class="alert-error panel-error small pointer"' +
'config-modal="app/partials/inspector.html" ng-if="panelMeta.error">' + 'config-modal="app/partials/inspector.html" ng-if="panelMeta.error">' +
'<span data-placement="right" bs-tooltip="panelMeta.error">' + '<span data-placement="top" bs-tooltip="panelMeta.error">' +
'<i class="icon-exclamation-sign"></i><span class="panel-error-arrow"></span>' + '<i class="icon-exclamation-sign"></i><span class="panel-error-arrow"></span>' +
'</span>' + '</span>' +
'</span>' + '</span>' +

View File

@ -1,3 +1,10 @@
define([ define([
'./panellinkeditor/module', './panellinkeditor/module',
'./annotations/annotationsSrv',
'./templating/templateSrv',
'./graphite/datasource',
'./influxdb/datasource',
'./opentsdb/datasource',
'./elasticsearch/datasource',
'./dashboard/all',
], function () {}); ], function () {});

View File

@ -1,7 +1,8 @@
define([ define([
'angular', 'angular',
'lodash', 'lodash',
'moment' 'moment',
'./editorCtrl'
], function (angular, _, moment) { ], function (angular, _, moment) {
'use strict'; 'use strict';

View File

@ -16,7 +16,7 @@
<div class="dashboard-editor-body"> <div class="dashboard-editor-body">
<div class="editor-row row" ng-if="editor.index == 0"> <div class="editor-row row" ng-if="editor.index == 0">
<div class="span6"> <div class="span6">
<div ng-if="variables.length === 0"> <div ng-if="annotations.length === 0">
<em>No annotations defined</em> <em>No annotations defined</em>
</div> </div>
<table class="grafana-options-table"> <table class="grafana-options-table">

View File

@ -0,0 +1,14 @@
define([
'./dashboardCtrl',
'./dashboardNavCtrl',
'./playlistCtrl',
'./rowCtrl',
'./sharePanelCtrl',
'./submenuCtrl',
'./dashboardSrv',
'./keybindings',
'./viewStateSrv',
'./playlistSrv',
'./panelSrv',
'./timeSrv',
], function () {});

View File

@ -107,6 +107,7 @@ function (angular, _, moment, config, store) {
$scope.deleteDashboardConfirmed = function(options) { $scope.deleteDashboardConfirmed = function(options) {
var id = options.id; var id = options.id;
$scope.db.deleteDashboard(id).then(function(id) { $scope.db.deleteDashboard(id).then(function(id) {
$scope.appEvent('dashboard-deleted', id);
$scope.appEvent('alert-success', ['Dashboard Deleted', id + ' has been deleted']); $scope.appEvent('alert-success', ['Dashboard Deleted', id + ' has been deleted']);
}, function(err) { }, function(err) {
$scope.appEvent('alert-error', ['Deleted failed', err]); $scope.appEvent('alert-error', ['Deleted failed', err]);

View File

@ -4,7 +4,6 @@ define([
'kbn', 'kbn',
'lodash', 'lodash',
'moment', 'moment',
'../timer',
], ],
function (angular, $, kbn, _, moment) { function (angular, $, kbn, _, moment) {
'use strict'; 'use strict';

View File

@ -24,7 +24,7 @@ function (angular, _, config, kbn, moment) {
this.saveTemp = _.isUndefined(datasource.save_temp) ? true : datasource.save_temp; this.saveTemp = _.isUndefined(datasource.save_temp) ? true : datasource.save_temp;
this.saveTempTTL = _.isUndefined(datasource.save_temp_ttl) ? '30d' : datasource.save_temp_ttl; this.saveTempTTL = _.isUndefined(datasource.save_temp_ttl) ? '30d' : datasource.save_temp_ttl;
this.annotationEditorSrc = 'app/partials/elasticsearch/annotation_editor.html'; this.annotationEditorSrc = 'app/features/elasticsearch/partials/annotations.editor.html';
this.supportAnnotations = true; this.supportAnnotations = true;
this.supportMetrics = false; this.supportMetrics = false;
} }

View File

@ -3,7 +3,7 @@ define([
'app', 'app',
'lodash', 'lodash',
'jquery', 'jquery',
'../services/graphite/gfunc', './gfunc',
], ],
function (angular, app, _, $, gfunc) { function (angular, app, _, $, gfunc) {
'use strict'; 'use strict';

View File

@ -4,7 +4,10 @@ define([
'jquery', 'jquery',
'config', 'config',
'kbn', 'kbn',
'moment' 'moment',
'./queryCtrl',
'./funcEditor',
'./addGraphiteFunc',
], ],
function (angular, _, $, config, kbn, moment) { function (angular, _, $, config, kbn, moment) {
'use strict'; 'use strict';
@ -17,14 +20,15 @@ function (angular, _, $, config, kbn, moment) {
this.type = 'graphite'; this.type = 'graphite';
this.basicAuth = datasource.basicAuth; this.basicAuth = datasource.basicAuth;
this.url = datasource.url; this.url = datasource.url;
this.editorSrc = 'app/partials/graphite/editor.html';
this.name = datasource.name; this.name = datasource.name;
this.render_method = datasource.render_method || 'POST';
this.supportAnnotations = true;
this.supportMetrics = true;
this.annotationEditorSrc = 'app/partials/graphite/annotation_editor.html';
this.cacheTimeout = datasource.cacheTimeout; this.cacheTimeout = datasource.cacheTimeout;
this.withCredentials = datasource.withCredentials; this.withCredentials = datasource.withCredentials;
this.render_method = datasource.render_method || 'POST';
this.supportAnnotations = true;
this.supportMetrics = true;
this.editorSrc = 'app/features/graphite/partials/query.editor.html';
this.annotationEditorSrc = 'app/features/graphite/partials/annotations.editor.html';
} }
GraphiteDatasource.prototype.query = function(options) { GraphiteDatasource.prototype.query = function(options) {

View File

@ -3,7 +3,7 @@
<div ng-repeat="target in panel.targets" <div ng-repeat="target in panel.targets"
class="grafana-target" class="grafana-target"
ng-class="{'grafana-target-hidden': target.hide}" ng-class="{'grafana-target-hidden': target.hide}"
ng-controller="GraphiteTargetCtrl" ng-controller="GraphiteQueryCtrl"
ng-init="init()"> ng-init="init()">
<div class="grafana-target-inner"> <div class="grafana-target-inner">

View File

@ -2,8 +2,8 @@ define([
'angular', 'angular',
'lodash', 'lodash',
'config', 'config',
'../services/graphite/gfunc', './gfunc',
'../services/graphite/parser' './parser'
], ],
function (angular, _, config, gfunc, Parser) { function (angular, _, config, gfunc, Parser) {
'use strict'; 'use strict';
@ -11,7 +11,7 @@ function (angular, _, config, gfunc, Parser) {
var module = angular.module('grafana.controllers'); var module = angular.module('grafana.controllers');
var targetLetters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O']; var targetLetters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'];
module.controller('GraphiteTargetCtrl', function($scope, $sce, templateSrv) { module.controller('GraphiteQueryCtrl', function($scope, $sce, templateSrv) {
$scope.init = function() { $scope.init = function() {
$scope.target.target = $scope.target.target || ''; $scope.target.target = $scope.target.target || '';

View File

@ -3,7 +3,9 @@ define([
'lodash', 'lodash',
'kbn', 'kbn',
'./influxSeries', './influxSeries',
'./influxQueryBuilder' './queryBuilder',
'./queryCtrl',
'./funcEditor',
], ],
function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) { function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
'use strict'; 'use strict';
@ -14,20 +16,20 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
function InfluxDatasource(datasource) { function InfluxDatasource(datasource) {
this.type = 'influxDB'; this.type = 'influxDB';
this.editorSrc = 'app/partials/influxdb/editor.html';
this.urls = datasource.urls; this.urls = datasource.urls;
this.username = datasource.username; this.username = datasource.username;
this.password = datasource.password; this.password = datasource.password;
this.name = datasource.name; this.name = datasource.name;
this.basicAuth = datasource.basicAuth; this.basicAuth = datasource.basicAuth;
this.grafanaDB = datasource.grafanaDB;
this.saveTemp = _.isUndefined(datasource.save_temp) ? true : datasource.save_temp; this.saveTemp = _.isUndefined(datasource.save_temp) ? true : datasource.save_temp;
this.saveTempTTL = _.isUndefined(datasource.save_temp_ttl) ? '30d' : datasource.save_temp_ttl; this.saveTempTTL = _.isUndefined(datasource.save_temp_ttl) ? '30d' : datasource.save_temp_ttl;
this.grafanaDB = datasource.grafanaDB;
this.supportAnnotations = true; this.supportAnnotations = true;
this.supportMetrics = true; this.supportMetrics = true;
this.annotationEditorSrc = 'app/partials/influxdb/annotation_editor.html'; this.editorSrc = 'app/features/influxdb/partials/query.editor.html';
this.annotationEditorSrc = 'app/features/influxdb/partials/annotations.editor.html';
} }
InfluxDatasource.prototype.query = function(options) { InfluxDatasource.prototype.query = function(options) {

View File

@ -106,21 +106,23 @@ function (_) {
}; };
p.createNameForSeries = function(seriesName, groupByColValue) { p.createNameForSeries = function(seriesName, groupByColValue) {
var name = this.alias var regex = /\$(\w+)/g;
.replace('$s', seriesName);
var segments = seriesName.split('.'); var segments = seriesName.split('.');
for (var i = 0; i < segments.length; i++) {
if (segments[i].length > 0) { return this.alias.replace(regex, function(match, group) {
name = name.replace('$' + i, segments[i]); if (group === 's') {
return seriesName;
} }
} else if (group === 'g') {
return groupByColValue;
}
var index = parseInt(group);
if (_.isNumber(index) && index < segments.length) {
return segments[index];
}
return match;
});
if (this.groupByField) {
name = name.replace('$g', groupByColValue);
}
return name;
}; };
return InfluxSeries; return InfluxSeries;

View File

@ -3,7 +3,7 @@
<div ng-repeat="target in panel.targets" <div ng-repeat="target in panel.targets"
class="grafana-target" class="grafana-target"
ng-class="{'grafana-target-hidden': target.hide}" ng-class="{'grafana-target-hidden': target.hide}"
ng-controller="InfluxTargetCtrl" ng-controller="InfluxQueryCtrl"
ng-init="init()"> ng-init="init()">
<div class="grafana-target-inner-wrapper"> <div class="grafana-target-inner-wrapper">

View File

@ -9,7 +9,7 @@ function (angular, _) {
var seriesList = null; var seriesList = null;
module.controller('InfluxTargetCtrl', function($scope, $timeout) { module.controller('InfluxQueryCtrl', function($scope, $timeout) {
$scope.init = function() { $scope.init = function() {
var target = $scope.target; var target = $scope.target;

View File

@ -2,7 +2,8 @@ define([
'angular', 'angular',
'lodash', 'lodash',
'kbn', 'kbn',
'moment' 'moment',
'./queryCtrl',
], ],
function (angular, _, kbn) { function (angular, _, kbn) {
'use strict'; 'use strict';
@ -13,7 +14,7 @@ function (angular, _, kbn) {
function OpenTSDBDatasource(datasource) { function OpenTSDBDatasource(datasource) {
this.type = 'opentsdb'; this.type = 'opentsdb';
this.editorSrc = 'app/partials/opentsdb/editor.html'; this.editorSrc = 'app/features/opentsdb/partials/query.editor.html';
this.url = datasource.url; this.url = datasource.url;
this.name = datasource.name; this.name = datasource.name;
this.supportMetrics = true; this.supportMetrics = true;
@ -148,7 +149,7 @@ function (angular, _, kbn) {
} }
if (target.shouldDownsample) { if (target.shouldDownsample) {
query.downsample = target.downsampleInterval + "-" + target.downsampleAggregator; query.downsample = templateSrv.replace(target.downsampleInterval) + "-" + target.downsampleAggregator;
} }
query.tags = angular.copy(target.tags); query.tags = angular.copy(target.tags);

View File

@ -2,7 +2,7 @@
<div ng-repeat="target in panel.targets" <div ng-repeat="target in panel.targets"
class="grafana-target" class="grafana-target"
ng-class="{'grafana-target-hidden': target.hide}" ng-class="{'grafana-target-hidden': target.hide}"
ng-controller="OpenTSDBTargetCtrl" ng-controller="OpenTSDBQueryCtrl"
ng-init="init()"> ng-init="init()">
<div class="grafana-target-inner-wrapper"> <div class="grafana-target-inner-wrapper">

View File

@ -8,7 +8,7 @@ function (angular, _, kbn) {
var module = angular.module('grafana.controllers'); var module = angular.module('grafana.controllers');
module.controller('OpenTSDBTargetCtrl', function($scope, $timeout) { module.controller('OpenTSDBQueryCtrl', function($scope, $timeout) {
$scope.init = function() { $scope.init = function() {
$scope.target.errors = validateTarget($scope.target); $scope.target.errors = validateTarget($scope.target);

View File

@ -1,6 +1,8 @@
define([ define([
'angular', 'angular',
'lodash', 'lodash',
'./editorCtrl',
'./templateValuesSrv',
], ],
function (angular, _) { function (angular, _) {
'use strict'; 'use strict';

View File

@ -70,7 +70,11 @@ function ($) {
for (i = 0; i < seriesList.length; i++) { for (i = 0; i < seriesList.length; i++) {
series = seriesList[i]; series = seriesList[i];
if (!series.data.length) { continue; }
if (!series.data.length) {
results.push({ hidden: true });
continue;
}
if (scope.panel.stack) { if (scope.panel.stack) {
if (scope.panel.tooltip.value_type === 'individual') { if (scope.panel.tooltip.value_type === 'individual') {
@ -99,9 +103,9 @@ function ($) {
lasthoverIndex = hoverIndex; lasthoverIndex = hoverIndex;
} }
results.push({ value: value, hoverIndex: newhoverIndex, series: series }); results.push({ value: value, hoverIndex: newhoverIndex});
} else { } else {
results.push({ value: value, hoverIndex: hoverIndex, series: series }); results.push({ value: value, hoverIndex: hoverIndex});
} }
} }
@ -150,7 +154,12 @@ function ($) {
for (i = 0; i < seriesHoverInfo.length; i++) { for (i = 0; i < seriesHoverInfo.length; i++) {
hoverInfo = seriesHoverInfo[i]; hoverInfo = seriesHoverInfo[i];
series = hoverInfo.series;
if (hoverInfo.hidden) {
continue;
}
series = seriesList[i];
value = series.formatValue(hoverInfo.value); value = series.formatValue(hoverInfo.value);
seriesHtml += '<div class="graph-tooltip-list-item"><div class="graph-tooltip-series-name">'; seriesHtml += '<div class="graph-tooltip-list-item"><div class="graph-tooltip-series-name">';

View File

@ -7,9 +7,6 @@ define([
'moment', 'moment',
'components/timeSeries', 'components/timeSeries',
'components/panelmeta', 'components/panelmeta',
'services/panelSrv',
'services/annotationsSrv',
'services/datasourceSrv',
'./seriesOverridesCtrl', './seriesOverridesCtrl',
'./graph', './graph',
'./legend', './legend',
@ -146,10 +143,9 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
}; };
$scope.dataHandler = function(results) { $scope.dataHandler = function(results) {
$scope.panelMeta.loading = false;
// png renderer returns just a url // png renderer returns just a url
if (_.isString(results)) { if (_.isString(results)) {
$scope.panelMeta.loading = false;
$scope.render(results); $scope.render(results);
return; return;
} }
@ -164,9 +160,11 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
$scope.annotationsPromise $scope.annotationsPromise
.then(function(annotations) { .then(function(annotations) {
$scope.panelMeta.loading = false;
$scope.seriesList.annotations = annotations; $scope.seriesList.annotations = annotations;
$scope.render($scope.seriesList); $scope.render($scope.seriesList);
}, function() { }, function() {
$scope.panelMeta.loading = false;
$scope.render($scope.seriesList); $scope.render($scope.seriesList);
}); });
}; };

View File

@ -23,15 +23,15 @@
<h5>Big value font size</h5> <h5>Big value font size</h5>
<div class="editor-option"> <div class="editor-option">
<label class="small">Prefix</label> <label class="small">Prefix</label>
<select class="input-mini" style="width: 75px;" ng-model="panel.prefixFontSize" ng-options="f for f in ['30%','50%','70%','80%','100%']" ng-change="render()"></select> <select class="input-mini" style="width: 75px;" ng-model="panel.prefixFontSize" ng-options="f for f in fontSizes" ng-change="render()"></select>
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small">Value</label> <label class="small">Value</label>
<select class="input-mini" style="width: 75px;" ng-model="panel.valueFontSize" ng-options="f for f in ['30%','50%','70%','80%','100%', '110%', '120%']" ng-change="render()"></select> <select class="input-mini" style="width: 75px;" ng-model="panel.valueFontSize" ng-options="f for f in fontSizes" ng-change="render()"></select>
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small">Postfix</label> <label class="small">Postfix</label>
<select class="input-mini" style="width: 75px;" ng-model="panel.postfixFontSize" ng-options="f for f in ['30%','50%','70%','80%','100%']" ng-change="render()"></select> <select class="input-mini" style="width: 75px;" ng-model="panel.postfixFontSize" ng-options="f for f in fontSizes" ng-change="render()"></select>
</div> </div>
</div> </div>

View File

@ -5,7 +5,6 @@ define([
'components/timeSeries', 'components/timeSeries',
'kbn', 'kbn',
'components/panelmeta', 'components/panelmeta',
'services/panelSrv',
'./singleStatPanel', './singleStatPanel',
], ],
function (angular, app, _, TimeSeries, kbn, PanelMeta) { function (angular, app, _, TimeSeries, kbn, PanelMeta) {
@ -22,6 +21,8 @@ function (angular, app, _, TimeSeries, kbn, PanelMeta) {
metricsEditor: true metricsEditor: true
}); });
$scope.fontSizes = ['20%', '30%','50%','70%','80%','100%', '110%', '120%', '150%', '170%', '200%'];
$scope.panelMeta.addEditorTab('Options', 'app/panels/singlestat/editor.html'); $scope.panelMeta.addEditorTab('Options', 'app/panels/singlestat/editor.html');
// Set and populate defaults // Set and populate defaults

View File

@ -10,7 +10,7 @@
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a class="pointer" dash-editor-link="app/partials/templating_editor.html">Templating</a></li> <li><a class="pointer" dash-editor-link="app/partials/templating_editor.html">Templating</a></li>
<li><a class="pointer" dash-editor-link="app/partials/annotations_editor.html">Annotations</a></li> <li><a class="pointer" dash-editor-link="app/features/annotations/partials/editor.html">Annotations</a></li>
</ul> </ul>
</div> </div>
</li> </li>

View File

@ -1,7 +0,0 @@
define([
'./pro/dashboard',
'./pro/admin',
'./pro/solo-panel',
'./pro/login',
],
function () {});

View File

@ -0,0 +1,6 @@
define([
'./dashboard',
'./admin',
'./login',
'./solo-panel',
], function() {});

View File

@ -1,20 +0,0 @@
define([
'angular',
'config',
'store'
],
function (angular, config, store) {
"use strict";
var module = angular.module('grafana.routes');
module.config(function($routeProvider) {
$routeProvider
.when('/', {
redirectTo: function() {
return store.get('grafanaDashboardDefault') || config.default_route;
}
});
});
});

View File

@ -0,0 +1,23 @@
define([
'angular',
'config',
'store',
'./fromDB',
'./fromFile',
'./fromScript',
],
function (angular, config, store) {
'use strict';
var module = angular.module('grafana.routes');
module.config(function($routeProvider) {
$routeProvider
.when('/', {
redirectTo: function() {
return store.get('grafanaDashboardDefault') || config.default_route;
}
});
});
});

View File

@ -2,18 +2,10 @@ define([
'./alertSrv', './alertSrv',
'./utilSrv', './utilSrv',
'./datasourceSrv', './datasourceSrv',
'./timeSrv',
'./templateSrv',
'./templateValuesSrv',
'./panelSrv',
'./timer', './timer',
'./keyboardManager', './keyboardManager',
'./annotationsSrv',
'./popoverSrv', './popoverSrv',
'./playlistSrv', './backendSrv',
'./unsavedChangesSrv', './grafanaDatasource',
'./dashboard/dashboardKeyBindings',
'./dashboard/dashboardSrv',
'./dashboard/dashboardViewStateSrv',
], ],
function () {}); function () {});

View File

@ -2,11 +2,6 @@ define([
'angular', 'angular',
'lodash', 'lodash',
'config', 'config',
'./graphite/graphiteDatasource',
'./grafana/grafanaDatasource',
'./influxdb/influxdbDatasource',
'./opentsdb/opentsdbDatasource',
'./elasticsearch/es-datasource',
], ],
function (angular, _, config) { function (angular, _, config) {
'use strict'; 'use strict';
@ -68,6 +63,9 @@ function (angular, _, config) {
case 'opentsdb': case 'opentsdb':
Datasource = $injector.get('OpenTSDBDatasource'); Datasource = $injector.get('OpenTSDBDatasource');
break; break;
case 'elasticsearch':
Datasource = $injector.get('ElasticDatasource');
break;
case 'grafana': case 'grafana':
Datasource = $injector.get('GrafanaDatasource'); Datasource = $injector.get('GrafanaDatasource');
break; break;

View File

@ -62,6 +62,7 @@
left: 0; left: 0;
padding: 0px 17px 6px 5px; padding: 0px 17px 6px 5px;
top: 0; top: 0;
z-index: 10;
i { i {
position: relative; position: relative;
top: -2px; top: -2px;

View File

@ -21,8 +21,8 @@ function (angular, _, kbn) {
CustomDatasource.prototype.query = function(options) { CustomDatasource.prototype.query = function(options) {
// get from & to in seconds // get from & to in seconds
var from = kbn.parseDate(options.range.from).getTime() / 1000; var from = kbn.parseDate(options.range.from).getTime();
var to = kbn.parseDate(options.range.to).getTime() / 1000; var to = kbn.parseDate(options.range.to).getTime();
var series = []; var series = [];
var stepInSeconds = (to - from) / options.maxDataPoints; var stepInSeconds = (to - from) / options.maxDataPoints;

View File

@ -1,5 +1,5 @@
define([ define([
'services/dashboard/dashboardSrv' 'features/dashboard/dashboardSrv'
], function() { ], function() {
'use strict'; 'use strict';
@ -95,7 +95,7 @@ define([
beforeEach(module('grafana.services')); beforeEach(module('grafana.services'));
beforeEach(inject(function(dashboardSrv) { beforeEach(inject(function(dashboardSrv) {
model = dashboardSrv.create({ model = dashboardSrv.create({
services: { filter: { time: { from: 'now-1d', to: 'now'}, list: [1] }}, services: { filter: { time: { from: 'now-1d', to: 'now'}, list: [{}] }},
pulldowns: [ pulldowns: [
{ {
type: 'filtering', type: 'filtering',
@ -135,7 +135,7 @@ define([
it('should move time and filtering list', function() { it('should move time and filtering list', function() {
expect(model.time.from).to.be('now-1d'); expect(model.time.from).to.be('now-1d');
expect(model.templating.list[0]).to.be(1); expect(model.templating.list[0].allFormat).to.be('glob');
}); });
it('graphite panel should change name too graph', function() { it('graphite panel should change name too graph', function() {

View File

@ -1,5 +1,5 @@
define([ define([
'services/dashboard/dashboardViewStateSrv' 'features/dashboard/viewStateSrv'
], function() { ], function() {
'use strict'; 'use strict';

View File

@ -1,5 +1,5 @@
define([ define([
'services/graphite/gfunc' 'features/graphite/gfunc'
], function(gfunc) { ], function(gfunc) {
'use strict'; 'use strict';

View File

@ -1,5 +1,6 @@
define([ define([
'./helpers', 'helpers',
'features/dashboard/panelSrv',
'panels/graph/module' 'panels/graph/module'
], function(helpers) { ], function(helpers) {
'use strict'; 'use strict';

View File

@ -1,5 +1,5 @@
define([ define([
'./helpers', 'helpers',
'angular', 'angular',
'jquery', 'jquery',
'components/timeSeries', 'components/timeSeries',

View File

@ -1,6 +1,6 @@
define([ define([
'./helpers', 'helpers',
'services/graphite/graphiteDatasource' 'features/graphite/datasource'
], function(helpers) { ], function(helpers) {
'use strict'; 'use strict';

View File

@ -1,16 +1,16 @@
define([ define([
'./helpers', 'helpers',
'services/graphite/gfunc', 'features/graphite/gfunc',
'controllers/graphiteTarget' 'features/graphite/queryCtrl'
], function(helpers, gfunc) { ], function(helpers, gfunc) {
'use strict'; 'use strict';
describe('GraphiteTargetCtrl', function() { describe('GraphiteQueryCtrl', function() {
var ctx = new helpers.ControllerTestContext(); var ctx = new helpers.ControllerTestContext();
beforeEach(module('grafana.controllers')); beforeEach(module('grafana.controllers'));
beforeEach(ctx.providePhase()); beforeEach(ctx.providePhase());
beforeEach(ctx.createControllerPhase('GraphiteTargetCtrl')); beforeEach(ctx.createControllerPhase('GraphiteQueryCtrl'));
beforeEach(function() { beforeEach(function() {
ctx.scope.target = { ctx.scope.target = {

View File

@ -1,5 +1,5 @@
define([ define([
'services/influxdb/influxQueryBuilder' 'features/influxdb/queryBuilder'
], function(InfluxQueryBuilder) { ], function(InfluxQueryBuilder) {
'use strict'; 'use strict';
@ -68,7 +68,7 @@ define([
var query = builder.build(); var query = builder.build();
expect(query).to.be('select mean(value) from "merge.google.test" where $timeFilter ' + expect(query).to.be('select mean(value) from "merge.google.test" where $timeFilter ' +
'group by time($interval) order asc'); 'group by time($interval) order asc');
}); });
}); });

View File

@ -1,5 +1,5 @@
define([ define([
'services/influxdb/influxSeries' 'features/influxdb/influxSeries'
], function(InfluxSeries) { ], function(InfluxSeries) {
'use strict'; 'use strict';
@ -80,6 +80,27 @@ define([
}); });
describe('given an alias format and many segments', function() {
var series = new InfluxSeries({
seriesList: [
{
columns: ['time', 'mean', 'sequence_number'],
name: 'a0.a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12',
points: [[1402596000, 10, 1], [1402596001, 12, 2]]
}
],
alias: '$5.$11.mean'
});
var result = series.getTimeSeries();
it('should generate correct series name', function() {
expect(result[0].target).to.be('a5.a11.mean');
});
});
describe('given an alias format with group by field', function() { describe('given an alias format with group by field', function() {
var series = new InfluxSeries({ var series = new InfluxSeries({
seriesList: [ seriesList: [

View File

@ -1,6 +1,6 @@
define([ define([
'./helpers', 'helpers',
'services/influxdb/influxdbDatasource' 'features/influxdb/datasource'
], function(helpers) { ], function(helpers) {
'use strict'; 'use strict';

View File

@ -29,6 +29,13 @@ define([
describeValueFormat('ns', 25, 1, 0, '25 ns'); describeValueFormat('ns', 25, 1, 0, '25 ns');
describeValueFormat('ns', 2558, 50, 0, '2.56 µs'); describeValueFormat('ns', 2558, 50, 0, '2.56 µs');
describe('kbn.toFixed and negative decimals', function() {
it('should treat as zero decimals', function() {
var str = kbn.toFixed(186.123, -2);
expect(str).to.be('186');
});
});
describe('calculateInterval', function() { describe('calculateInterval', function() {
it('1h 100 resultion', function() { it('1h 100 resultion', function() {
var range = { from: kbn.parseDate('now-1h'), to: kbn.parseDate('now') }; var range = { from: kbn.parseDate('now-1h'), to: kbn.parseDate('now') };

View File

@ -1,5 +1,5 @@
define([ define([
'services/graphite/lexer' 'features/graphite/lexer'
], function(Lexer) { ], function(Lexer) {
'use strict'; 'use strict';

View File

@ -1,5 +1,5 @@
define([ define([
'services/graphite/parser' 'features/graphite/parser'
], function(Parser) { ], function(Parser) {
'use strict'; 'use strict';

View File

@ -1,6 +1,6 @@
define([ define([
'./helpers', 'helpers',
'controllers/row' 'features/dashboard/rowCtrl'
], function(helpers) { ], function(helpers) {
'use strict'; 'use strict';

View File

@ -1,5 +1,5 @@
define([ define([
'./helpers', 'helpers',
'panels/graph/seriesOverridesCtrl' 'panels/graph/seriesOverridesCtrl'
], function(helpers) { ], function(helpers) {
'use strict'; 'use strict';

View File

@ -1,6 +1,6 @@
define([ define([
'./helpers', 'helpers',
'controllers/sharePanelCtrl' 'features/dashboard/sharePanelCtrl'
], function(helpers) { ], function(helpers) {
'use strict'; 'use strict';

View File

@ -1,7 +1,7 @@
define([ define([
'mocks/dashboard-mock', 'mocks/dashboard-mock',
'lodash', 'lodash',
'services/templateSrv' 'features/templating/templateSrv'
], function(dashboardMock) { ], function(dashboardMock) {
'use strict'; 'use strict';

View File

@ -1,8 +1,8 @@
define([ define([
'mocks/dashboard-mock', 'mocks/dashboard-mock',
'./helpers', 'helpers',
'moment', 'moment',
'services/templateValuesSrv' 'features/templating/templateValuesSrv'
], function(dashboardMock, helpers, moment) { ], function(dashboardMock, helpers, moment) {
'use strict'; 'use strict';

View File

@ -1,8 +1,9 @@
define([ define([
'mocks/dashboard-mock', 'mocks/dashboard-mock',
'./helpers', 'helpers',
'lodash', 'lodash',
'services/timeSrv' 'services/timer',
'features/dashboard/timeSrv'
], function(dashboardMock, helpers, _) { ], function(dashboardMock, helpers, _) {
'use strict'; 'use strict';

View File

@ -4,7 +4,8 @@ require.config({
paths: { paths: {
specs: '../test/specs', specs: '../test/specs',
mocks: '../test/mocks', mocks: '../test/mocks',
config: '../config.sample', helpers: '../test/specs/helpers',
config: ['../config', '../config.sample'],
kbn: 'components/kbn', kbn: 'components/kbn',
store: 'components/store', store: 'components/store',
@ -96,9 +97,10 @@ require.config({
require([ require([
'angular', 'angular',
'config',
'angularMocks', 'angularMocks',
'app', 'app',
], function(angular) { ], function(angular, config) {
'use strict'; 'use strict';
for (var file in window.__karma__.files) { for (var file in window.__karma__.files) {
@ -111,11 +113,9 @@ require([
angular.module('grafana', ['ngRoute']); angular.module('grafana', ['ngRoute']);
angular.module('grafana.services', ['ngRoute', '$strap.directives']); angular.module('grafana.services', ['ngRoute', '$strap.directives']);
angular.module('grafana.panels', []); angular.module('grafana.panels', []);
angular.module('grafana.routes', ['ngRoute']);
angular.module('grafana.filters', []); angular.module('grafana.filters', []);
require([ var specs = [
'specs/overview-ctrl-specs',
'specs/lexer-specs', 'specs/lexer-specs',
'specs/parser-specs', 'specs/parser-specs',
'specs/gfunc-specs', 'specs/gfunc-specs',
@ -136,12 +136,16 @@ require([
'specs/templateValuesSrv-specs', 'specs/templateValuesSrv-specs',
'specs/kbn-format-specs', 'specs/kbn-format-specs',
'specs/dashboardSrv-specs', 'specs/dashboardSrv-specs',
'specs/dashboardViewStateSrv-specs', 'specs/dashboardViewStateSrv-specs'
'specs/overview-ctrl-specs',
'specs/pro/soloPanelCtrl-specs', 'specs/pro/soloPanelCtrl-specs',
], function () { ];
window.__karma__.start();
var pluginSpecs = (config.plugins.specs || []).map(function (spec) {
return '../plugins/' + spec;
}); });
require(specs.concat(pluginSpecs), function () {
window.__karma__.start();
});
}); });

View File

@ -4,6 +4,7 @@ module.exports = function(grunt) {
grunt.registerTask('build', [ grunt.registerTask('build', [
'jshint:source', 'jshint:source',
'jshint:tests', 'jshint:tests',
'karma:test',
'clean:on_start', 'clean:on_start',
'less:src', 'less:src',
'concat:cssDark', 'concat:cssDark',

View File

@ -3,6 +3,7 @@ module.exports = function(config) {
src: [ src: [
'Gruntfile.js', 'Gruntfile.js',
'<%= srcDir %>/app/**/*.js', '<%= srcDir %>/app/**/*.js',
'<%= srcDir %>/plugins/**/*.js',
'!<%= srcDir %>/app/panels/*/{lib,leaflet}/*', '!<%= srcDir %>/app/panels/*/{lib,leaflet}/*',
'!<%= srcDir %>/app/dashboards/*' '!<%= srcDir %>/app/dashboards/*'
], ],

View File

@ -63,7 +63,7 @@ module.exports = function(config,grunt) {
'directives/all', 'directives/all',
'filters/all', 'filters/all',
'controllers/all', 'controllers/all',
'routes/all', 'routes/standalone/default',
'components/partials', 'components/partials',
] ]
} }