Commit 373118c5 by Torkel Ödegaard

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

parents 634d8c99 846cf934
# 1.9.0 (unreleased)
# 1.9.1 (unreleased)
**Enhancements**
- [Issue #1028](https://github.com/grafana/grafana/issues/1028). Graph: New legend option ``hideEmtpy`` to hide series with only null values
**Fixes**
- [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
# 1.9.0 (2014-12-02)
**Enhancements**
- [Issue #1130](https://github.com/grafana/grafana/issues/1130). SinglestatPanel: Added null point handling, and value to text mapping
......@@ -16,7 +25,7 @@
# 1.9.0-rc1 (2014-11-17)
**UI Improvements*
**UI Improvements**
- [Issue #770](https://github.com/grafana/grafana/issues/770). UI: Panel dropdown menu replaced with a new panel menu
**Graph**
......
{
"version": "1.9.0-rc1",
"url": "http://grafanarel.s3.amazonaws.com/grafana-1.9.0-rc1.tar.gz"
"version": "1.9.0",
"url": "http://grafanarel.s3.amazonaws.com/grafana-1.9.0.tar.gz"
}
......@@ -4,7 +4,7 @@
"company": "Coding Instinct AB"
},
"name": "grafana",
"version": "1.9.0-rc1",
"version": "1.9.0",
"repository": {
"type": "git",
"url": "http://github.com/torkelo/grafana.git"
......
......@@ -162,6 +162,11 @@ function (angular, _, config, gfunc, Parser) {
return new MetricSegment({ value: segment.text, expandable: segment.expandable });
});
if ($scope.altSegments.length === 0) {
return;
}
// add template variables
_.each(templateSrv.variables, function(variable) {
$scope.altSegments.unshift(new MetricSegment({
type: 'template',
......@@ -170,6 +175,7 @@ function (angular, _, config, gfunc, Parser) {
}));
});
// add wildcard option
$scope.altSegments.unshift(new MetricSegment('*'));
})
.then(null, function(err) {
......
<div class="editor-row">
<div class="section">
<h5>Drilldown / detail link<tip>These links appear in the dropdown menu in the panel menu</tip></h5>
<h5>Drilldown / detail link<tip>These links appear in the dropdown menu in the panel menu. </tip></h5>
<div class="grafana-target" ng-repeat="link in panel.links"j>
<div class="grafana-target-inner">
......@@ -32,7 +32,9 @@
<input type="text" ng-model="link.url" class="input-large grafana-target-segment-input">
</li>
<li class="grafana-target-segment">params</li>
<li class="grafana-target-segment">params
<tip>Use var-variableName=value to pass templating variables.</tip>
</li>
<li>
<input type="text" ng-model="link.params" class="input-medium grafana-target-segment-input">
</li>
......
......@@ -44,6 +44,7 @@
<editor-opt-bool text="Values" model="panel.legend.values" change="render()"></editor-opt-bool>
<editor-opt-bool text="Table" model="panel.legend.alignAsTable" change="render()"></editor-opt-bool>
<editor-opt-bool text="Right side" model="panel.legend.rightSide" change="render()"></editor-opt-bool>
<editor-opt-bool text="Hide empty" model="panel.legend.hideEmpty" tip="Hides series with only null values" change="render()"></editor-opt-bool>
</div>
<div class="section" ng-if="panel.legend.values">
......
......@@ -99,9 +99,9 @@ function ($) {
lasthoverIndex = hoverIndex;
}
results.push({ value: value, hoverIndex: newhoverIndex });
results.push({ value: value, hoverIndex: newhoverIndex, series: series });
} else {
results.push({ value: value, hoverIndex: hoverIndex });
results.push({ value: value, hoverIndex: hoverIndex, series: series });
}
}
......@@ -149,8 +149,8 @@ function ($) {
timestamp = dashboard.formatDate(seriesHoverInfo.time);
for (i = 0; i < seriesHoverInfo.length; i++) {
series = seriesList[i];
hoverInfo = seriesHoverInfo[i];
series = hoverInfo.series;
value = series.formatValue(hoverInfo.value);
seriesHtml += '<div class="graph-tooltip-list-item"><div class="graph-tooltip-series-name">';
......
......@@ -125,6 +125,12 @@ function (angular, app, _, kbn, $) {
for (i = 0; i < seriesList.length; i++) {
var series = seriesList[i];
// ignore empty series
if (panel.legend.hideEmpty && series.allIsNull) {
continue;
}
var html = '<div class="graph-legend-series';
if (series.yaxis === 2) { html += ' pull-right'; }
if (scope.hiddenSeries[series.alias]) { html += ' graph-legend-series-hidden'; }
......
......@@ -128,10 +128,6 @@ function (angular, app, _, TimeSeries, kbn, PanelMeta) {
};
$scope.getDecimalsForValue = function(value) {
var opts = {};
if (value === 0 || value === 1) {
return { decimals: 0, scaledDecimals: 0 };
}
var delta = value / 2;
var dec = -Math.floor(Math.log(delta) / Math.LN10);
......@@ -157,13 +153,12 @@ function (angular, app, _, TimeSeries, kbn, PanelMeta) {
size *= magn;
if (opts.minTickSize != null && size < opts.minTickSize) {
size = opts.minTickSize;
}
// reduce starting decimals if not needed
if (Math.floor(value) === value) { dec = 0; }
var result = {};
result.decimals = Math.max(0, dec);
result.scaledDecimals = result.decimals - Math.floor(Math.log(size) / Math.LN11) + 2;
result.scaledDecimals = result.decimals - Math.floor(Math.log(size) / Math.LN10) + 2;
return result;
};
......
......@@ -55,7 +55,7 @@ function (angular, app, _, $) {
function getColorForValue(value) {
for (var i = data.thresholds.length - 1; i >= 0 ; i--) {
if (value > data.thresholds[i]) {
if (value >= data.thresholds[i]) {
return data.colorMap[i];
}
}
......
......@@ -21,7 +21,7 @@
<i bs-tooltip="'Expand row'" data-placement="right" class="icon-caret-left pointer" ></i>
</span>
</div>
<span class="row-text pointer" ng-click="toggle_row(row)" ng-bind="row.title"></span>
<div class="row-text pointer" ng-click="toggle_row(row)" ng-bind="row.title"></div>
</div>
<div class="row-open" ng-show="!row.collapse">
<div class='row-tab bgSuccess dropdown' ng-show="row.editable">
......
......@@ -102,7 +102,7 @@
<input type="text"
class="input-mini grafana-target-segment-input"
ng-model="panel.cacheTimeout"
bs-tooltip="'Graphite parameter to overwride memcache default timeout (unit is seconds)'"
bs-tooltip="'Graphite parameter to override memcache default timeout (unit is seconds)'"
data-placement="right"
spellcheck='false'
placeholder="60">
......
......@@ -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) {
......
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]
});
......@@ -329,6 +335,11 @@ function (_) {
});
addFuncDef({
name: 'offsetToZero',
category: categories.Transform,
});
addFuncDef({
name: 'transformNull',
category: categories.Transform,
params: [{ name: "amount", type: "int", }],
......@@ -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 + "'";
......
......@@ -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;
}
......
......@@ -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]
};
}
......
......@@ -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 {
......
......@@ -181,6 +181,7 @@ form input.ng-invalid {
font-size: 0.9em;
text-align: center;
line-height: 31px;
height: 31px;
}
.row-close {
......
......@@ -280,6 +280,7 @@
@tooltipBackground: rgb(58, 57, 57);
@tooltipArrowWidth: 5px;
@tooltipArrowColor: @tooltipBackground;
@tooltipLinkColor: @linkColor;
@popoverBackground: @heroUnitBackground;
@popoverArrowWidth: 10px;
......
......@@ -289,6 +289,7 @@
@tooltipBackground: #000;
@tooltipArrowWidth: 5px;
@tooltipArrowColor: @tooltipBackground;
@tooltipLinkColor: darken(@white,11%);
@popoverBackground: @white;
@popoverArrowWidth: 15px;
......
......@@ -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() {
......
......@@ -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;
......
......@@ -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}]));
......
......@@ -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');
});
});
......
......@@ -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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment