diff --git a/src/app/partials/graphite/editor.html b/src/app/partials/graphite/editor.html
index b904331e77c..4e63cc1a0a8 100755
--- a/src/app/partials/graphite/editor.html
+++ b/src/app/partials/graphite/editor.html
@@ -102,7 +102,7 @@
diff --git a/src/app/services/dashboard/dashboardSrv.js b/src/app/services/dashboard/dashboardSrv.js
index e8f0a808279..21789fc1740 100644
--- a/src/app/services/dashboard/dashboardSrv.js
+++ b/src/app/services/dashboard/dashboardSrv.js
@@ -117,18 +117,8 @@ function (angular, $, kbn, _, moment) {
var newPanel = angular.copy(panel);
newPanel.id = this.getNextPanelId();
- while(rowIndex < this.rows.length) {
- var currentRow = this.rows[rowIndex];
- if (this.rowSpan(currentRow) <= 9) {
- currentRow.panels.push(newPanel);
- return;
- }
- rowIndex++;
- }
-
- var newRow = angular.copy(row);
- newRow.panels = [newPanel];
- this.rows.push(newRow);
+ var currentRow = this.rows[rowIndex];
+ currentRow.panels.push(newPanel);
};
p.formatDate = function(date, format) {
diff --git a/src/app/services/graphite/gfunc.js b/src/app/services/graphite/gfunc.js
index af186633ea2..dc912f9328c 100644
--- a/src/app/services/graphite/gfunc.js
+++ b/src/app/services/graphite/gfunc.js
@@ -1,7 +1,8 @@
define([
- 'lodash'
+ 'lodash',
+ 'jquery'
],
-function (_) {
+function (_, $) {
'use strict';
var index = [];
@@ -157,7 +158,12 @@ function (_) {
addFuncDef({
name: 'sumSeriesWithWildcards',
category: categories.Combine,
- params: [{ name: "node", type: "int" }],
+ params: [
+ { name: "node", type: "int" },
+ { name: "node", type: "int", optional: true },
+ { name: "node", type: "int", optional: true },
+ { name: "node", type: "int", optional: true }
+ ],
defaultParams: [3]
});
@@ -328,6 +334,11 @@ function (_) {
defaultParams: [10]
});
+ addFuncDef({
+ name: 'offsetToZero',
+ category: categories.Transform,
+ });
+
addFuncDef({
name: 'transformNull',
category: categories.Transform,
@@ -501,15 +512,15 @@ function (_) {
addFuncDef({
name: 'movingAverage',
category: categories.Filter,
- params: [{ name: "window size", type: "int" }],
+ params: [{ name: "windowSize", type: "int_or_interval", options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
defaultParams: [10]
});
addFuncDef({
name: 'movingMedian',
category: categories.Filter,
- params: [{ name: "windowSize", type: "select", options: ['1min', '5min', '15min', '30min', '1hour'] }],
- defaultParams: ['1min']
+ params: [{ name: "windowSize", type: "int_or_interval", options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }],
+ defaultParams: ['5']
});
addFuncDef({
@@ -561,6 +572,17 @@ function (_) {
defaultParams: [5]
});
+ addFuncDef({
+ name: 'useSeriesAbove',
+ category: categories.Filter,
+ params: [
+ { name: "value", type: "int" },
+ { name: "search", type: "string" },
+ { name: "replace", type: "string" }
+ ],
+ defaultParams: [0, 'search', 'replace']
+ });
+
_.each(categories, function(funcList, catName) {
categories[catName] = _.sortBy(funcList, 'name');
});
@@ -584,6 +606,9 @@ function (_) {
if (paramType === 'int' || paramType === 'value_or_series' || paramType === 'boolean') {
return value;
}
+ else if (paramType === 'int_or_interval' && $.isNumeric(value)) {
+ return value;
+ }
return "'" + value + "'";
diff --git a/src/app/services/graphite/graphiteDatasource.js b/src/app/services/graphite/graphiteDatasource.js
index ee1312f7bd7..cfaca71aa3d 100644
--- a/src/app/services/graphite/graphiteDatasource.js
+++ b/src/app/services/graphite/graphiteDatasource.js
@@ -24,6 +24,7 @@ function (angular, _, $, config, kbn, moment) {
this.supportMetrics = true;
this.annotationEditorSrc = 'app/partials/graphite/annotation_editor.html';
this.cacheTimeout = datasource.cacheTimeout;
+ this.withCredentials = datasource.withCredentials;
}
GraphiteDatasource.prototype.query = function(options) {
@@ -209,8 +210,10 @@ function (angular, _, $, config, kbn, moment) {
};
GraphiteDatasource.prototype.doGraphiteRequest = function(options) {
- if (this.basicAuth) {
+ if (this.basicAuth || this.withCredentials) {
options.withCredentials = true;
+ }
+ if (this.basicAuth) {
options.headers = options.headers || {};
options.headers.Authorization = 'Basic ' + this.basicAuth;
}
diff --git a/src/app/services/graphite/parser.js b/src/app/services/graphite/parser.js
index c5ee82deb38..242068f9d85 100644
--- a/src/app/services/graphite/parser.js
+++ b/src/app/services/graphite/parser.js
@@ -67,9 +67,16 @@ define([
}
if (this.match('identifier') || this.match('number')) {
+ // hack to handle float numbers in metric segments
+ var parts = this.consumeToken().value.split('.');
+ if (parts.length === 2) {
+ this.tokens.splice(this.index, 0, { type: '.' });
+ this.tokens.splice(this.index + 1, 0, { type: 'number', value: parts[1] });
+ }
+
return {
type: 'segment',
- value: this.consumeToken().value
+ value: parts[0]
};
}
diff --git a/src/css/less/grafana.less b/src/css/less/grafana.less
index 333820b2374..9dba94fd8a4 100644
--- a/src/css/less/grafana.less
+++ b/src/css/less/grafana.less
@@ -438,6 +438,9 @@ select.grafana-target-segment-input {
max-height: 600px;
overflow: hidden;
line-height: 14px;
+ a {
+ color: @tooltipLinkColor;
+ }
}
.grafana-tooltip hr {
@@ -445,8 +448,6 @@ select.grafana-target-segment-input {
color: #c8c8c8;
margin: 0px;
border-bottom:0px solid #c8c8c8;
- /*height:0px;
- background-color: rgb(58, 57, 57);*/
}
.tooltip.in {
diff --git a/src/css/less/overrides.less b/src/css/less/overrides.less
index 110f03a7773..f4139e020ea 100644
--- a/src/css/less/overrides.less
+++ b/src/css/less/overrides.less
@@ -181,6 +181,7 @@ form input.ng-invalid {
font-size: 0.9em;
text-align: center;
line-height: 31px;
+ height: 31px;
}
.row-close {
diff --git a/src/css/less/variables.dark.less b/src/css/less/variables.dark.less
index dc0e2ba4da0..6dbe943e0c2 100644
--- a/src/css/less/variables.dark.less
+++ b/src/css/less/variables.dark.less
@@ -280,6 +280,7 @@
@tooltipBackground: rgb(58, 57, 57);
@tooltipArrowWidth: 5px;
@tooltipArrowColor: @tooltipBackground;
+@tooltipLinkColor: @linkColor;
@popoverBackground: @heroUnitBackground;
@popoverArrowWidth: 10px;
diff --git a/src/css/less/variables.light.less b/src/css/less/variables.light.less
index 0e78514cea0..a745fafd978 100644
--- a/src/css/less/variables.light.less
+++ b/src/css/less/variables.light.less
@@ -289,6 +289,7 @@
@tooltipBackground: #000;
@tooltipArrowWidth: 5px;
@tooltipArrowColor: @tooltipBackground;
+@tooltipLinkColor: darken(@white,11%);
@popoverBackground: @white;
@popoverArrowWidth: 15px;
diff --git a/src/test/specs/dashboardSrv-specs.js b/src/test/specs/dashboardSrv-specs.js
index b2f33ac133a..18eb13d3a18 100644
--- a/src/test/specs/dashboardSrv-specs.js
+++ b/src/test/specs/dashboardSrv-specs.js
@@ -70,16 +70,6 @@ define([
expect(dashboard.rows[0].panels[1].id).to.be(11);
});
- it('duplicate should add row if there is no space left', function() {
- var panel = { span: 12, attr: '123' };
- dashboard.rows = [{ panels: [panel] }];
- dashboard.duplicatePanel(panel, dashboard.rows[0]);
-
- expect(dashboard.rows[0].panels[0].span).to.be(12);
- expect(dashboard.rows[0].panels.length).to.be(1);
- expect(dashboard.rows[1].panels[0].attr).to.be('123');
- });
-
});
describe('when creating dashboard with editable false', function() {
diff --git a/src/test/specs/gfunc-specs.js b/src/test/specs/gfunc-specs.js
index f0650c16077..fdfb1051217 100644
--- a/src/test/specs/gfunc-specs.js
+++ b/src/test/specs/gfunc-specs.js
@@ -46,6 +46,18 @@ define([
expect(func.render('hello')).to.equal("scaleToSeconds(hello, 1)");
});
+ it('should handle int or interval params with number', function() {
+ var func = gfunc.createFuncInstance('movingMedian');
+ func.params[0] = '5';
+ expect(func.render('hello')).to.equal("movingMedian(hello, 5)");
+ });
+
+ it('should handle int or interval params with interval string', function() {
+ var func = gfunc.createFuncInstance('movingMedian');
+ func.params[0] = '5min';
+ expect(func.render('hello')).to.equal("movingMedian(hello, '5min')");
+ });
+
it('should handle metric param and int param and string param', function() {
var func = gfunc.createFuncInstance('groupByNode');
func.params[0] = 5;
diff --git a/src/test/specs/graphiteTargetCtrl-specs.js b/src/test/specs/graphiteTargetCtrl-specs.js
index 27be0d92b26..3e321c9e4a4 100644
--- a/src/test/specs/graphiteTargetCtrl-specs.js
+++ b/src/test/specs/graphiteTargetCtrl-specs.js
@@ -136,6 +136,22 @@ define([
});
});
+ describe('when getting altSegments and metricFindQuery retuns empty array', function() {
+ beforeEach(function() {
+ ctx.scope.target.target = 'test.count';
+ ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
+ ctx.scope.init();
+ ctx.scope.getAltSegments(1);
+ ctx.scope.$digest();
+ ctx.scope.$parent = { get_data: sinon.spy() };
+ });
+
+ it('should have no segments', function() {
+ expect(ctx.scope.altSegments.length).to.be(0);
+ });
+
+ });
+
describe('targetChanged', function() {
beforeEach(function() {
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([{expandable: false}]));
diff --git a/src/test/specs/parser-specs.js b/src/test/specs/parser-specs.js
index 33c234ae823..f1b216f3f2f 100644
--- a/src/test/specs/parser-specs.js
+++ b/src/test/specs/parser-specs.js
@@ -165,6 +165,14 @@ define([
expect(rootNode.params[1].value).to.be('#B');
});
+ it('should parse metric expression with ip number segments', function() {
+ var parser = new Parser('5.10.123.5');
+ var rootNode = parser.getAst();
+ expect(rootNode.segments[0].value).to.be('5');
+ expect(rootNode.segments[1].value).to.be('10');
+ expect(rootNode.segments[2].value).to.be('123');
+ expect(rootNode.segments[3].value).to.be('5');
+ });
});
diff --git a/src/vendor/angular/angular-dragdrop.js b/src/vendor/angular/angular-dragdrop.js
index 5eb196409e7..40fb1c9e814 100644
--- a/src/vendor/angular/angular-dragdrop.js
+++ b/src/vendor/angular/angular-dragdrop.js
@@ -39,7 +39,6 @@ angular.module("ang-drag-drop",[])
element.attr("draggable", false);
attrs.$observe("uiDraggable", function (newValue) {
- console.log(newValue);
if(newValue){
element.attr("draggable", newValue);
}