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

This commit is contained in:
Torkel Ödegaard
2015-01-12 18:59:48 +01:00
24 changed files with 739 additions and 420 deletions
+5
View File
@@ -1,8 +1,13 @@
# 2.0.0 (unreleased)
**New features**
- [Issue #1331](https://github.com/grafana/grafana/issues/1331). Graph & Singlestat: New axis/unit format selector and more units (kbytes, Joule, Watt, eV), and new design for graph axis & grid tab and single stat options tab views
**Enhancements**
- [Issue #1297](https://github.com/grafana/grafana/issues/1297). Graphite: Added cumulative and minimumBelow graphite functions
- [Issue #1296](https://github.com/grafana/grafana/issues/1296). InfluxDB: Auto escape column names with special characters. Thanks @steven-aerts
- [Issue #1321](https://github.com/grafana/grafana/issues/1321). SingleStatPanel: You can now use template variables in pre & postfix
- [Issue #599](https://github.com/grafana/grafana/issues/599). Graph: Added right y axis label setting and graph support
**Fixes**
- [Issue #1298](https://github.com/grafana/grafana/issues/1298). InfluxDB: Fix handling of empty array in templating variable query
+51
View File
@@ -362,8 +362,14 @@ function($, _, moment) {
kbn.valueFormats.bits = kbn.formatFuncCreator(1024, [' b', ' Kib', ' Mib', ' Gib', ' Tib', ' Pib', ' Eib', ' Zib', ' Yib']);
kbn.valueFormats.bytes = kbn.formatFuncCreator(1024, [' B', ' KiB', ' MiB', ' GiB', ' TiB', ' PiB', ' EiB', ' ZiB', ' YiB']);
kbn.valueFormats.kbytes = kbn.formatFuncCreator(1024, [' KiB', ' MiB', ' GiB', ' TiB', ' PiB', ' EiB', ' ZiB', ' YiB']);
kbn.valueFormats.mbytes = kbn.formatFuncCreator(1024, [' MiB', ' GiB', ' TiB', ' PiB', ' EiB', ' ZiB', ' YiB']);
kbn.valueFormats.bps = kbn.formatFuncCreator(1000, [' bps', ' Kbps', ' Mbps', ' Gbps', ' Tbps', ' Pbps', ' Ebps', ' Zbps', ' Ybps']);
kbn.valueFormats.Bps = kbn.formatFuncCreator(1000, [' Bps', ' KBps', ' MBps', ' GBps', ' TBps', ' PBps', ' EBps', ' ZBps', ' YBps']);
kbn.valueFormats.short = kbn.formatFuncCreator(1000, ['', ' K', ' Mil', ' Bil', ' Tri', ' Qaudr', ' Quint', ' Sext', ' Sept']);
kbn.valueFormats.joule = kbn.formatFuncCreator(1000, [' J', ' kJ', ' MJ', 'GJ', 'TJ', 'PJ', 'EJ', 'ZJ', 'YJ']);
kbn.valueFormats.watt = kbn.formatFuncCreator(1000, [' W', ' kW', ' MW', 'GW', 'TW', 'PW', 'EW', 'ZW', 'YW']);
kbn.valueFormats.ev = kbn.formatFuncCreator(1000, [' eV', ' keV', ' MeV', 'GeV', 'TeV', 'PeV', 'EeV', 'ZeV', 'YeV']);
kbn.valueFormats.none = kbn.toFixed;
kbn.valueFormats.ms = function(size, decimals, scaledDecimals) {
@@ -479,5 +485,50 @@ function($, _, moment) {
return new RegExp(match[1], match[2]);
};
kbn.getUnitFormats = function() {
return [
{
text: 'none',
submenu: [
{text: 'none' , value: 'none'},
{text: 'short', value: 'short'},
{text: 'percent', value: 'percent'},
]
},
{
text: 'duration',
submenu: [
{text: 'nanoseconds (ns)' , value: 'ns'},
{text: 'microseconds (µs)', value: 'µs'},
{text: 'milliseconds (ms)', value: 'ms'},
{text: 'seconds (s)', value: 's'},
]
},
{
text: 'data',
submenu: [
{text: 'bits', value: 'bits'},
{text: 'bytes', value: 'bytes'},
{text: 'kilobytes', value: 'kbytes'},
]
},
{
text: 'data rate',
submenu: [
{text: 'bits/sec', value: 'bps'},
{text: 'bytes/sec', value: 'Bps'},
]
},
{
text: 'energy',
submenu: [
{text: 'watt', value: 'watt'},
{text: 'joule', value: 'joule'},
{text: 'eV', value: 'ev'},
]
},
];
};
return kbn;
});
+1
View File
@@ -31,4 +31,5 @@ function (angular, app, _) {
}
};
});
});
+31 -20
View File
@@ -17,35 +17,47 @@ function (angular, app, _, $) {
var buttonTemplate = '<a class="grafana-target-segment grafana-target-function dropdown-toggle"' +
' tabindex="1" gf-dropdown="menuItems" data-toggle="dropdown"' +
' data-placement="top"><i class="icon-plus"></i></a>';
' data-placement="top"><i class="fa fa-plus"></i></a>';
return {
scope: {
"menuItems": "=dropdownTypeahead",
"dropdownTypeaheadOnSelect": "&dropdownTypeaheadOnSelect"
menuItems: "=dropdownTypeahead",
dropdownTypeaheadOnSelect: "&dropdownTypeaheadOnSelect",
model: '=ngModel'
},
link: function($scope, elem) {
link: function($scope, elem, attrs) {
var $input = $(inputTemplate);
var $button = $(buttonTemplate);
$input.appendTo(elem);
$button.appendTo(elem);
var typeaheadValues = _.reduce($scope.menuItems, function(memo, value) {
_.each(value.submenu, function(item) {
if (attrs.linkText) {
$button.html(attrs.linkText);
}
if (attrs.ngModel) {
$scope.$watch('model', function(newValue) {
_.each($scope.menuItems, function(item) {
_.each(item.submenu, function(subItem) {
if (subItem.value === newValue) {
$button.html(subItem.text);
}
});
});
});
}
var typeaheadValues = _.reduce($scope.menuItems, function(memo, value, index) {
_.each(value.submenu, function(item, subIndex) {
item.click = 'menuItemSelected(' + index + ',' + subIndex + ')';
memo.push(value.text + ' ' + item.text);
});
return memo;
}, []);
$scope.menuItemSelected = function(optionIndex, valueIndex) {
var option = $scope.menuItems[optionIndex];
var result = {
$item: option.submenu[valueIndex],
$optionIndex: optionIndex,
$valueIndex: valueIndex
};
$scope.dropdownTypeaheadOnSelect(result);
$scope.menuItemSelected = function(index, subIndex) {
var item = $scope.menuItems[index];
$scope.dropdownTypeaheadOnSelect({$item: item, $subItem: item.submenu[subIndex]});
};
$input.attr('data-provide', 'typeahead');
@@ -55,12 +67,11 @@ function (angular, app, _, $) {
items: 10,
updater: function (value) {
var result = {};
_.each($scope.menuItems, function(menuItem, optionIndex) {
_.each(menuItem.submenu, function(submenuItem, valueIndex) {
_.each($scope.menuItems, function(menuItem) {
_.each(menuItem.submenu, function(submenuItem) {
if (value === (menuItem.text + ' ' + submenuItem.text)) {
result.$item = submenuItem;
result.$optionIndex = optionIndex;
result.$valueIndex = valueIndex;
result.$item = menuItem;
result.$subItem = submenuItem;
}
});
});
+12
View File
@@ -22,5 +22,17 @@ function (angular) {
});
}
};
})
.directive('emptyToNull', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.push(function (viewValue) {
if(viewValue === "") { return null; }
return viewValue;
});
}
};
});
});
@@ -53,7 +53,7 @@
<label class="small">Datasource</label>
<select ng-model="currentAnnotation.datasource" ng-options="f.name as f.name for f in datasources" ng-change="datasourceChanged()"></select>
</div>
<div class="editor-option">
<div class="editor-option text-center">
<label class="small">Icon color</label>
<spectrum-picker ng-model="currentAnnotation.iconColor"></spectrum-picker>
</div>
@@ -62,7 +62,7 @@
<select class="input-mini" ng-model="currentAnnotation.iconSize" ng-options="f for f in [7,8,9,10,13,15,17,20,25,30]"></select>
</div>
<editor-opt-bool text="Grid line" model="currentAnnotation.showLine"></editor-opt-bool>
<div class="editor-option">
<div class="editor-option text-center">
<label class="small">Line color</label>
<spectrum-picker ng-model="currentAnnotation.lineColor"></spectrum-picker>
</div>
@@ -7,66 +7,68 @@
ng-init="init()">
<div class="grafana-target-inner">
<ul class="grafana-target-controls">
<li ng-show="parserError">
<ul class="grafana-segment-list pull-right">
<li ng-show="parserError" class="grafana-target-segment">
<a bs-tooltip="parserError" style="color: rgb(229, 189, 28)" role="menuitem">
<i class="fa fa-warning"></i>
</a>
</li>
<li>
<li class="grafana-target-segment">
<a class="pointer" tabindex="1" ng-click="showTextEditor = !showTextEditor">
<i class="fa fa-pencil"></i>
</a>
</li>
<li class="dropdown">
<a class="pointer dropdown-toggle"
data-toggle="dropdown"
tabindex="1">
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem">
<a tabindex="1"
ng-click="duplicate()">
Duplicate
</a>
</li>
<li role="menuitem">
<a tabindex="1"
ng-click="moveMetricQuery($index, $index-1)">
Move up
</a>
</li>
<li role="menuitem">
<a tabindex="1"
ng-click="moveMetricQuery($index, $index+1)">
Move down
</a>
</li>
</ul>
</li>
<li>
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
</li>
</ul>
<li class="grafana-target-segment">
<div class="dropdown">
<a class="pointer dropdown-toggle"
data-toggle="dropdown"
tabindex="1">
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem">
<a tabindex="1"
ng-click="duplicate()">
Duplicate
</a>
</li>
<li role="menuitem">
<a tabindex="1"
ng-click="moveMetricQuery($index, $index-1)">
Move up
</a>
</li>
<li role="menuitem">
<a tabindex="1"
ng-click="moveMetricQuery($index, $index+1)">
Move down
</a>
</li>
</ul>
</div>
</li>
<li class="grafana-target-segment last">
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
</li>
</ul>
<ul class="grafana-segment-list">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="min-width: 15px; text-align: center">
{{targetLetters[$index]}}
</li>
<li>
<a class="grafana-target-segment"
ng-click="target.hide = !target.hide; get_data();"
role="menuitem">
<i class="fa fa-eye"></i>
</a>
</li>
</ul>
</li>
<li>
<a class="grafana-target-segment"
ng-click="target.hide = !target.hide; get_data();"
role="menuitem">
<i class="fa fa-eye"></i>
</a>
</li>
</ul>
<input type="text"
class="grafana-target-text-input span10"
<input type="text"
class="grafana-target-text-input span10"
ng-model="target.target"
focus-me="showTextEditor"
spellcheck='false'
+1 -1
View File
@@ -133,4 +133,4 @@ function (angular, _, $) {
});
});
});
@@ -8,22 +8,24 @@
<div class="grafana-target-inner-wrapper">
<div class="grafana-target-inner">
<ul class="grafana-target-controls">
<li class="dropdown">
<a class="pointer dropdown-toggle"
data-toggle="dropdown"
tabindex="1">
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"><a tabindex="1" ng-click="duplicate()">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="showQuery()" ng-hide="target.rawQuery">Raw query mode</a></li>
<li role="menuitem"><a tabindex="1" ng-click="hideQuery()" ng-show="target.rawQuery">Query editor mode</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveMetricQuery($index, $index-1)">Move up </a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveMetricQuery($index, $index+1)">Move down</a></li>
</ul>
<ul class="grafana-segment-list pull-right">
<li class="grafana-target-segment">
<div class="dropdown">
<a class="pointer dropdown-toggle"
data-toggle="dropdown"
tabindex="1">
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem"><a tabindex="1" ng-click="duplicate()">Duplicate</a></li>
<li role="menuitem"><a tabindex="1" ng-click="showQuery()" ng-hide="target.rawQuery">Raw query mode</a></li>
<li role="menuitem"><a tabindex="1" ng-click="hideQuery()" ng-show="target.rawQuery">Query editor mode</a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveMetricQuery($index, $index-1)">Move up </a></li>
<li role="menuitem"><a tabindex="1" ng-click="moveMetricQuery($index, $index+1)">Move down</a></li>
</ul>
</div>
</li>
<li>
<li class="grafana-target-segment last">
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
@@ -42,7 +44,7 @@
<ul class="grafana-segment-list" ng-show="target.rawQuery">
<li>
<input type="text"
class="grafana-target-text-input span10"
class="grafana-target-segment-input span10"
ng-model="target.query"
placeholder="select ..."
focus-me="target.rawQuery"
@@ -60,7 +62,7 @@
</li>
<li>
<input type="text"
class="grafana-target-text-input span8"
class="grafana-target-segment-input span8"
ng-model="target.series"
spellcheck='false'
bs-typeahead="listSeries"
@@ -76,7 +78,7 @@
</li>
<li>
<input type="text" class="input-medium grafana-target-text-input" ng-model="target.alias"
<input type="text" class="input-medium grafana-target-segment-input" ng-model="target.alias"
spellcheck='false' placeholder="alias" ng-blur="get_data()">
</li>
@@ -89,14 +91,14 @@
<!-- Raw Query mode -->
<ul class="grafana-segment-list" ng-show="target.rawQuery">
<li class="grafana-target-segment">
<i class="fa eye invisible"></i>
<i class="fa fa-eye invisible"></i>
</li>
<li class="grafana-target-segment">
alias
</li>
<li>
<input type="text"
class="input-medium grafana-target-text-input"
class="input-medium grafana-target-segment-input"
ng-model="target.alias"
spellcheck='false'
placeholder="alias"
@@ -106,7 +108,7 @@
group by time
</li>
<li>
<input type="text" class="input-mini grafana-target-text-input" ng-model="target.interval"
<input type="text" class="input-mini grafana-target-segment-input" ng-model="target.interval"
spellcheck='false' placeholder="{{interval}}" data-placement="right"
bs-tooltip="'Leave blank for auto handling based on time range and panel width'"
ng-model-onblur ng-change="get_data()" >
@@ -122,7 +124,7 @@
select
</li>
<li class="dropdown">
<span influxdb-func-editor class="grafana-target-segment">
<span influxdb-func-editor class="grafana-target-segment grafana-target-function">
</span>
</li>
@@ -130,7 +132,7 @@
where
</li>
<li>
<input type="text" class="input-medium grafana-target-text-input" ng-model="target.condition"
<input type="text" class="input-medium grafana-target-segment-input" ng-model="target.condition"
bs-tooltip="'Add a where clause'" data-placement="right" spellcheck='false' placeholder="column ~= value" ng-blur="get_data()">
</li>
@@ -138,18 +140,18 @@
group by time
</li>
<li>
<input type="text" class="input-mini grafana-target-text-input" ng-model="target.interval"
<input type="text" class="input-mini grafana-target-segment-input" ng-model="target.interval"
spellcheck='false' placeholder="{{interval}}" data-placement="right"
bs-tooltip="'Leave blank for auto handling based on time range and panel width'"
ng-model-onblur ng-change="get_data()" >
</li>
<li class="grafana-target-segment">
<i class="fa fa-plus"></i>
and
</li>
<li>
<input type="text" class="input-small grafana-target-text-input" ng-model="target.groupby_field" bs-tooltip="'Add a group by column or leave blank'"
<input type="text" class="input-small grafana-target-segment-input" ng-model="target.groupby_field" bs-tooltip="'Add a group by column or leave blank'"
placeholder="column" spellcheck="false" bs-typeahead="listColumns" data-min-length=0 ng-blur="get_data()">
</li>
@@ -190,7 +192,7 @@
group by time
</li>
<li>
<input type="text" class="input-medium grafana-target-text-input" ng-model="panel.interval" ng-blur="get_data();"
<input type="text" class="input-medium grafana-target-segment-input" ng-model="panel.interval" ng-blur="get_data();"
spellcheck='false' placeholder="example: >10s">
</li>
<li class="grafana-target-segment">
@@ -7,24 +7,26 @@
<div class="grafana-target-inner-wrapper">
<div class="grafana-target-inner">
<ul class="grafana-target-controls">
<li class="dropdown">
<a class="pointer dropdown-toggle"
data-toggle="dropdown"
tabindex="1">
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem">
<a tabindex="1"
ng-click="duplicate()">
Duplicate
</a>
</li>
</ul>
</li>
<li>
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<ul class="grafana-segment-list pull-right">
<li class="grafana-target-segment">
<div class="dropdown">
<a class="pointer dropdown-toggle"
data-toggle="dropdown"
tabindex="1">
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem">
<a tabindex="1"
ng-click="duplicate()">
Duplicate
</a>
</li>
</ul>
</div>
</li>
<li class="grafana-target-segment last">
<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
<i class="fa fa-remove"></i>
</a>
</li>
+221 -80
View File
@@ -1,86 +1,227 @@
<div class="editor-row">
<div class="section">
<h5>Left Y Axis</h5>
<div class="editor-option">
<label class="small">Format <tip>Y-axis formatting</tip></label>
<select class="input-small" ng-model="panel.y_formats[0]" ng-options="f for f in ['none','short','bytes', 'bits', 'bps', 's', 'ms', 'µs', 'ns', 'percent']" ng-change="render()"></select>
</div>
<div class="editor-option">
<label class="small">Min / <a ng-click="toggleGridMinMax('leftMin')">Auto <i class="fa fa-star" ng-show="_.isNull(panel.grid.leftMin)"></i></a></label>
<input type="number" class="input-small" ng-model="panel.grid.leftMin" ng-change="render()" ng-model-onblur />
</div>
<div class="editor-option">
<label class="small">Max / <a ng-click="toggleGridMinMax('leftMax')">Auto <i class="fa fa-star" ng-show="_.isNull(panel.grid.leftMax)"></i></a></label>
<input type="number" class="input-small" ng-model="panel.grid.leftMax" ng-change="render()" ng-model-onblur />
</div>
<div class="editor-option">
<label class="small">Label</label>
<input ng-change="get_data()" ng-model-onblur placeholder="" type="text" class="input-medium" ng-model="panel.leftYAxisLabel">
</div>
</div>
<div class="section">
<h5>Right Y Axis</h5>
<div class="editor-option">
<label class="small">Format <tip>Y-axis formatting</tip></label>
<select class="input-small" ng-model="panel.y_formats[1]" ng-options="f for f in ['none','short','bytes', 'bits', 'bps', 's', 'ms', 'µs', 'ns', 'percent']" ng-change="render()"></select>
</div>
<div class="editor-option">
<label class="small">Min / <a ng-click="toggleGridMinMax('rightMin')">Auto <i class="fa fa-star" ng-show="_.isNull(panel.grid.rightMin)"></i></a></label>
<input type="number" class="input-small" ng-model="panel.grid.rightMin" ng-change="render()" ng-model-onblur />
</div>
<div class="editor-option">
<label class="small">Max / <a ng-click="toggleGridMinMax('rightMax')">Auto <i class="fa fa-star" ng-show="_.isNull(panel.grid.rightMax)"></i></a></label>
<input type="number" class="input-small" ng-model="panel.grid.rightMax" ng-change="render()" ng-model-onblur />
</div>
</div>
</div>
<div class="editor-row">
<div class="section">
<h5>Legend styles</h5>
<editor-opt-bool text="Show" model="panel.legend.show" change="get_data();"></editor-opt-bool>
<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 class="section" style="margin-bottom: 20px">
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Left Y</strong>
</li>
<li class="grafana-target-segment">
Unit
</li>
<li class="dropdown" style="width: 130px;"
ng-model="panel.y_formats[0]"
dropdown-typeahead="unitFormats"
dropdown-typeahead-on-select="setUnitFormat(0, $subItem)">
</li>
<li class="grafana-target-segment">
&nbsp;&nbsp; Grid Max
</li>
<li>
<input type="number" class="input-small grafana-target-segment-input" placeholder="auto"
empty-to-null ng-model="panel.grid.leftMax"
ng-change="render()" ng-model-onblur>
</li>
<li class="grafana-target-segment">
Min
</li>
<li>
<input type="number" class="input-small grafana-target-segment-input" placeholder="auto"
empty-to-null ng-model="panel.grid.leftMin"
ng-change="render()" ng-model-onblur>
</li>
<li class="grafana-target-segment">
Label
</li>
<li>
<input type="text" class="input-small grafana-target-segment-input last"
ng-model="panel.leftYAxisLabel" ng-change="render()" ng-model-onblur>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Right Y</strong>
</li>
<li class="grafana-target-segment">
Unit
</li>
<li class="dropdown" style="width: 130px"
ng-model="panel.y_formats[1]"
dropdown-typeahead="unitFormats"
dropdown-typeahead-on-select="setUnitFormat(1, $subItem)">
</li>
<li class="grafana-target-segment">
&nbsp;&nbsp; Grid Max
</li>
<li>
<input type="number" class="input-small grafana-target-segment-input" placeholder="auto"
empty-to-null ng-model="panel.grid.rightMax"
ng-change="render()" ng-model-onblur>
</li>
<li class="grafana-target-segment">
Min
</li>
<li>
<input type="number" class="input-small grafana-target-segment-input" placeholder="auto"
empty-to-null ng-model="panel.grid.rightMin"
ng-change="render()" ng-model-onblur>
</li>
<li class="grafana-target-segment">
Label
</li>
<li>
<input type="text" class="input-small grafana-target-segment-input last"
ng-model="panel.rightYAxisLabel" ng-change="render()" ng-model-onblur>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="section" ng-if="panel.legend.values">
<h5>Legend values</h5>
<editor-opt-bool text="Min" model="panel.legend.min" change="render()"></editor-opt-bool>
<editor-opt-bool text="Max" model="panel.legend.max" change="render()"></editor-opt-bool>
<editor-opt-bool text="Current" model="panel.legend.current" change="render()"></editor-opt-bool>
<editor-opt-bool text="Total" model="panel.legend.total" change="render()"></editor-opt-bool>
<editor-opt-bool text="Avg" model="panel.legend.avg" change="render()"></editor-opt-bool>
</div>
<div class="section">
<h5>Grid thresholds</h5>
<div class="editor-option">
<label class="small">Level1</label>
<input type="number" class="input-small" ng-model="panel.grid.threshold1" ng-change="render()" ng-model-onblur />
</div>
<div class="editor-option">
<label class="small">Color</label>
<spectrum-picker ng-model="panel.grid.threshold1Color" ng-change="render()" ></spectrum-picker>
</div>
<div class="editor-option">
<label class="small">Level2</label>
<input type="number" class="input-small" ng-model="panel.grid.threshold2" ng-change="render()" ng-model-onblur />
</div>
<div class="editor-option">
<label class="small">Color</label>
<spectrum-picker ng-model="panel.grid.threshold2Color" ng-change="render()" ></spectrum-picker>
</div>
<editor-opt-bool text="Line mode" model="panel.grid.thresholdLine" change="render()"></editor-opt-bool>
</div>
<div class="section">
<h5>Show Axes</h5>
<editor-opt-bool text="X-Axis" model="panel['x-axis']" change="render()"></editor-opt-bool>
<editor-opt-bool text="Y-axis" model="panel['y-axis']" change="render()"></editor-opt-bool>
</div>
<div class="section" style="margin-bottom: 20px">
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Show Axis</strong>
</li>
<li class="grafana-target-segment">
X-Axis&nbsp;
<input class="cr1" id="hideXAxis" type="checkbox"
ng-model="panel['x-axis']" ng-checked="panel['x-axis']" ng-change="render()">
<label for="hideXAxis" class="cr1"></label>
</li>
<li class="grafana-target-segment last">
Y-Axis&nbsp;
<input class="cr1" id="hideYAxis" type="checkbox"
ng-model="panel['y-axis']" ng-checked="panel['y-axis']" ng-change="render()">
<label for="hideYAxis" class="cr1"></label>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Thresholds</strong>
</li>
<li class="grafana-target-segment">
Level 1
</li>
<li>
<input type="number" class="input-small grafana-target-segment-input"
ng-model="panel.grid.threshold1" ng-change="render()" ng-model-onblur>
</li>
<li class="grafana-target-segment">
<spectrum-picker ng-model="panel.grid.threshold1Color" ng-change="render()" ></spectrum-picker>
</li>
<li class="grafana-target-segment">
Level 2
</li>
<li>
<input type="number" class="input-small grafana-target-segment-input"
ng-model="panel.grid.threshold2" ng-change="render()" ng-model-onblur>
</li>
<li class="grafana-target-segment">
<spectrum-picker ng-model="panel.grid.threshold2Color" ng-change="render()" ></spectrum-picker>
</li>
<li class="grafana-target-segment last">
Line mode&nbsp;
<input class="cr1" id="panel.grid.thresholdLine" type="checkbox"
ng-model="panel.grid.thresholdLine" ng-checked="panel.grid.thresholdLine" ng-change="render()">
<label for="panel.grid.thresholdLine" class="cr1"></label>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
<div class="editor-row">
<div class="section">
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Legend</strong>
</li>
<li class="grafana-target-segment">
Show&nbsp;
<input class="cr1" id="panel.legend.show" type="checkbox"
ng-model="panel.legend.show" ng-checked="panel.legend.show" ng-change="render()">
<label for="panel.legend.show" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Table&nbsp;
<input class="cr1" id="panel.legend.alignAsTable" type="checkbox"
ng-model="panel.legend.alignAsTable" ng-checked="panel.legend.alignAsTable" ng-change="render()">
<label for="panel.legend.alignAsTable" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Right side&nbsp;
<input class="cr1" id="panel.legend.rightSide" type="checkbox"
ng-model="panel.legend.rightSide" ng-checked="panel.legend.rightSide" ng-change="render()">
<label for="panel.legend.rightSide" class="cr1"></label>
</li>
<li class="grafana-target-segment last">
<span bs-tooltip="'Hides series with only null values'">Hide empty&nbsp;<span>
<input class="cr1" id="panel.legend.hideEmpty" type="checkbox"
ng-model="panel.legend.hideEmpty" ng-checked="panel.legend.hideEmpty" ng-change="render()">
<label for="panel.legend.hideEmpty" class="cr1"></label>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="section">
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 100px">
<strong>Legend values</strong>
</li>
<li class="grafana-target-segment">
Min&nbsp;
<input class="cr1" id="panel.legend.min" type="checkbox"
ng-model="panel.legend.min" ng-checked="panel.legend.min" ng-change="legendValuesOptionChanged()">
<label for="panel.legend.min" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Max&nbsp;
<input class="cr1" id="panel.legend.max" type="checkbox"
ng-model="panel.legend.max" ng-checked="panel.legend.max" ng-change="legendValuesOptionChanged()">
<label for="panel.legend.max" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Avg&nbsp;
<input class="cr1" id="panel.legend.avg" type="checkbox"
ng-model="panel.legend.avg" ng-checked="panel.legend.avg" ng-change="legendValuesOptionChanged()">
<label for="panel.legend.avg" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Current&nbsp;
<input class="cr1" id="panel.legend.current" type="checkbox"
ng-model="panel.legend.current" ng-checked="panel.legend.current" ng-change="legendValuesOptionChanged()">
<label for="panel.legend.current" class="cr1"></label>
</li>
<li class="grafana-target-segment last">
Total&nbsp;
<input class="cr1" id="panel.legend.total" type="checkbox"
ng-model="panel.legend.total" ng-checked="panel.legend.total" ng-change="legendValuesOptionChanged()">
<label for="panel.legend.total" class="cr1"></label>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
+43 -19
View File
@@ -109,9 +109,9 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
}
}
function updateLegendValues(plot) {
function drawHook(plot) {
// Update legend values
var yaxis = plot.getYAxes();
for (var i = 0; i < data.length; i++) {
var series = data[i];
var axis = yaxis[series.yaxis - 1];
@@ -124,6 +124,29 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
series.updateLegendValues(formater, tickDecimals, axis.scaledDecimals + 2);
if(!scope.$$phase) { scope.$digest(); }
}
// add left axis labels
if (scope.panel.leftYAxisLabel) {
var yaxisLabel = $("<div class='axisLabel left-yaxis-label'></div>")
.text(scope.panel.leftYAxisLabel)
.appendTo(elem);
yaxisLabel.css("margin-top", yaxisLabel.width() / 2);
}
// add right axis labels
if (scope.panel.rightYAxisLabel) {
var rightLabel = $("<div class='axisLabel right-yaxis-label'></div>")
.text(scope.panel.rightYAxisLabel)
.appendTo(elem);
rightLabel.css("margin-top", rightLabel.width() / 2);
}
}
function processOffsetHook(plot, gridMargin) {
if (scope.panel.leftYAxisLabel) { gridMargin.left = 20; }
if (scope.panel.rightYAxisLabel) { gridMargin.right = 20; }
}
// Function for rendering panel
@@ -137,7 +160,10 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
// Populate element
var options = {
hooks: { draw: [updateLegendValues] },
hooks: {
draw: [drawHook],
processOffset: [processOffsetHook],
},
legend: { show: false },
series: {
stackpercent: panel.stack ? panel.percentage : false,
@@ -173,7 +199,8 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
backgroundColor: null,
borderWidth: 0,
hoverable: true,
color: '#c8c8c8'
color: '#c8c8c8',
margin: { left: 0, right: 0 },
},
selection: {
mode: "x",
@@ -213,8 +240,6 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
} catch (e) {
console.log('flotcharts error', e);
}
addAxisLabels();
}
if (shouldDelayDraw(panel)) {
@@ -317,19 +342,6 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
};
}
function addAxisLabels() {
if (scope.panel.leftYAxisLabel) {
elem.css('margin-left', '10px');
var yaxisLabel = $("<div class='axisLabel yaxisLabel'></div>")
.text(scope.panel.leftYAxisLabel)
.appendTo(elem);
yaxisLabel.css("margin-top", yaxisLabel.width() / 2 - 20);
} else if (elem.css('margin-left')) {
elem.css('margin-left', '');
}
}
function configureAxisOptions(data, options) {
var defaults = {
position: 'left',
@@ -406,9 +418,21 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
case 'bps':
url += '&yUnitSystem=si';
break;
case 'Bps':
url += '&yUnitSystem=si';
break;
case 'short':
url += '&yUnitSystem=si';
break;
case 'joule':
url += '&yUnitSystem=si';
break;
case 'watt':
url += '&yUnitSystem=si';
break;
case 'ev':
url += '&yUnitSystem=si';
break;
case 'none':
url += '&yUnitSystem=none';
break;
+12 -5
View File
@@ -104,6 +104,12 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
$scope.hiddenSeries = {};
$scope.seriesList = [];
$scope.unitFormats = kbn.getUnitFormats();
$scope.setUnitFormat = function(axis, subItem) {
$scope.panel.y_formats[axis] = subItem.value;
$scope.render();
};
$scope.updateTimeRange = function () {
$scope.range = timeSrv.timeRange();
@@ -262,11 +268,6 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
$scope.render();
};
$scope.toggleGridMinMax = function(key) {
$scope.panel.grid[key] = _.toggle($scope.panel.grid[key], null, 0);
$scope.render();
};
$scope.addSeriesOverride = function(override) {
$scope.panel.seriesOverrides.push(override || {});
};
@@ -282,6 +283,12 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
$scope.get_data();
};
$scope.legendValuesOptionChanged = function() {
var legend = $scope.panel.legend;
legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
$scope.render();
};
$scope.exportCsv = function() {
kbn.exportSeriesListToCsv($scope.seriesList);
};
+6 -11
View File
@@ -20,26 +20,21 @@ define([
option.index = $scope.overrideMenu.length;
option.values = values;
option.submenu = _.map(values, function(value, index) {
return {
text: String(value),
click: 'menuItemSelected(' + option.index + ',' + index + ')'
};
option.submenu = _.map(values, function(value) {
return { text: String(value), value: value };
});
$scope.overrideMenu.push(option);
};
$scope.setOverride = function(optionIndex, valueIndex) {
var option = $scope.overrideMenu[optionIndex];
var value = option.values[valueIndex];
$scope.override[option.propertyName] = value;
$scope.setOverride = function(item, subItem) {
$scope.override[item.propertyName] = subItem.value;
// automatically disable lines for this series and the fill bellow to series
// can be removed by the user if they still want lines
if (option.propertyName === 'fillBelowTo') {
if (item.propertyName === 'fillBelowTo') {
$scope.override['lines'] = false;
$scope.addSeriesOverride({ alias: value, lines: false });
$scope.addSeriesOverride({ alias: subItem.value, lines: false });
}
$scope.updateCurrentOverrides();
+1 -1
View File
@@ -89,7 +89,7 @@
{{option.name}}: {{option.value}}
</li>
<li class="dropdown" dropdown-typeahead="overrideMenu" dropdown-typeahead-on-select="setOverride($optionIndex, $valueIndex)">
<li class="dropdown" dropdown-typeahead="overrideMenu" dropdown-typeahead-on-select="setOverride($item, $subItem)">
</li>
</ul>
+184 -109
View File
@@ -1,115 +1,190 @@
<div class="editor-row">
<div class="section">
<h5>Big value</h5>
<div class="editor-option">
<label class="small">Prefix</label>
<input type="text" class="input-small" ng-model="panel.prefix" ng-blur="render()"></input>
</div>
<div class="editor-option">
<label class="small">Value</label>
<select class="input-small" ng-model="panel.valueName" ng-options="f for f in ['min','max','avg', 'current', 'total']" ng-change="render()"></select>
</div>
<div class="editor-option">
<label class="small">Postfix</label>
<input type="text" class="input-small" ng-model="panel.postfix" ng-blur="render()" ng-trim="false"></input>
</div>
<div class="editor-option">
<label class="small">Null point mode<tip>Define how null values should handled, connected = ignored</tip></label>
<select class="input-medium" ng-model="panel.nullPointMode" ng-options="f for f in ['connected', 'null', 'null as zero']" ng-change="get_data()"></select>
</div>
</div>
<div class="section">
<h5>Big value font size</h5>
<div class="editor-option">
<label class="small">Prefix</label>
<select class="input-mini" style="width: 75px;" ng-model="panel.prefixFontSize" ng-options="f for f in fontSizes" ng-change="render()"></select>
</div>
<div class="editor-option">
<label class="small">Value</label>
<select class="input-mini" style="width: 75px;" ng-model="panel.valueFontSize" ng-options="f for f in fontSizes" ng-change="render()"></select>
</div>
<div class="editor-option">
<label class="small">Postfix</label>
<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 class="section">
<h5>Formats</h5>
<div class="editor-option">
<label class="small">Unit format</label>
<select class="input-small" ng-model="panel.format" ng-options="f for f in ['none','short','bytes', 'bits', 'bps', 's', 'ms', 'µs', 'ns', 'percent']" ng-change="render()"></select>
</div>
</div>
</div>
<div class="editor-row">
<div class="section">
<h5>Coloring</h5>
<editor-opt-bool text="Background" model="panel.colorBackground" change="setColoring({background: true})"></editor-opt-bool>
<editor-opt-bool text="Value" model="panel.colorValue" change="setColoring({value: true})"></editor-opt-bool>
<div class="editor-option" ng-show="panel.colorBackground || panel.colorValue">
<label class="small">Thresholds<tip>Comma seperated values</tip></label>
<input type="text" class="input-large" ng-model="panel.thresholds" ng-blur="render()" placeholder="0,50,80"></input>
</div>
<div class="editor-option" ng-show="panel.colorBackground || panel.colorValue">
<label class="small">Colors</label>
<spectrum-picker ng-model="panel.colors[0]" ng-change="render()" ></spectrum-picker>
<spectrum-picker ng-model="panel.colors[1]" ng-change="render()" ></spectrum-picker>
<spectrum-picker ng-model="panel.colors[2]" ng-change="render()" ></spectrum-picker>
<a class="pointer" ng-click="invertColorOrder()">invert order</a>
</div>
</div>
<div class="section">
<h5>Spark lines</h5>
<editor-opt-bool text="Spark line" model="panel.sparkline.show" change="render()"></editor-opt-bool>
<editor-opt-bool text="Background mode" model="panel.sparkline.full" change="render()"></editor-opt-bool>
<div class="editor-option">
<label class="small">Line color</label>
<spectrum-picker ng-model="panel.sparkline.lineColor" ng-change="render()" ></spectrum-picker>
</div>
<div class="editor-option">
<label class="small">Fill color</label>
<spectrum-picker ng-model="panel.sparkline.fillColor" ng-change="render()" ></spectrum-picker>
</div>
</div>
</div>
<div class="editor-row">
<div class="section">
<h5>Value to text mapping</h5>
<div class="editor-option">
<label class="small">Specify mappings</label>
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" ng-repeat-start="map in panel.valueMaps">
<i class="fa fa-remove pointer" ng-click="removeValueMap(map)"></i>
</li>
<li>
<input type="text" ng-model="map.value" placeholder="value" class="input-mini grafana-target-segment-input" ng-blur="render()">
</li>
<li class="grafana-target-segment">
<i class="fa fa-arrow-right"></i>
</li>
<li ng-repeat-end>
<input type="text" placeholder="text" ng-model="map.text" class="input-mini grafana-target-segment-input" ng-blur="render()">
</li>
<li>
<a class="pointer grafana-target-segment" ng-click="addValueMap();">
<i class="fa fa-plus"></i>
</a>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="section" style="margin-bottom: 20px">
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Big value</strong>
</li>
<li class="grafana-target-segment">
Prefix
</li>
<li>
<input type="text" class="input-small grafana-target-segment-input"
ng-model="panel.prefix" ng-change="render()" ng-model-onblur>
</li>
<li class="grafana-target-segment">
Value
</li>
<li>
<select class="input-small grafana-target-segment-input" ng-model="panel.valueName" ng-options="f for f in ['min','max','avg', 'current', 'total']" ng-change="render()"></select>
</li>
<li class="grafana-target-segment">
Postfix
</li>
<li>
<input type="text" class="input-small grafana-target-segment-input last"
ng-model="panel.postfix" ng-change="render()" ng-model-onblur>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Font size</strong>
</li>
<li class="grafana-target-segment">
Prefix
</li>
<li>
<select class="input-small grafana-target-segment-input" style="width: 99px;" ng-model="panel.prefixFontSize" ng-options="f for f in fontSizes" ng-change="render()"></select>
</li>
<li class="grafana-target-segment">
Value
</li>
<li>
<select class="input-small grafana-target-segment-input" ng-model="panel.valueFontSize" ng-options="f for f in fontSizes" ng-change="render()"></select>
</li>
<li class="grafana-target-segment">
Postfix
</li>
<li>
<select class="input-small grafana-target-segment-input last" style="width: 99px" ng-model="panel.postfixFontSize" ng-options="f for f in fontSizes" ng-change="render()"></select>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Unit</strong>
</li>
<li class="dropdown" style="width: 130px;"
ng-model="panel.format"
dropdown-typeahead="unitFormats"
dropdown-typeahead-on-select="setUnitFormat($subItem)">
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
<div class="editor-row">
<div class="section" style="margin-bottom: 20px">
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Coloring</strong>
</li>
<li class="grafana-target-segment">
Background&nbsp;
<input class="cr1" id="panel.colorBackground" type="checkbox"
ng-model="panel.colorBackground" ng-checked="panel.colorBackground" ng-change="render()">
<label for="panel.colorBackground" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Value&nbsp;
<input class="cr1" id="panel.colorValue" type="checkbox"
ng-model="panel.colorValue" ng-checked="panel.colorValue" ng-change="render()">
<label for="panel.colorValue" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Thresholds<tip>Comma seperated values</tip>
</li>
<li>
<input type="text" class="input-large grafana-target-segment-input" ng-model="panel.thresholds" ng-blur="render()" placeholder="0,50,80"></input>
</li>
<li class="grafana-target-segment">
Colors
</li>
<li class="grafana-target-segment">
<spectrum-picker ng-model="panel.colors[0]" ng-change="render()" ></spectrum-picker>
<spectrum-picker ng-model="panel.colors[1]" ng-change="render()" ></spectrum-picker>
<spectrum-picker ng-model="panel.colors[2]" ng-change="render()" ></spectrum-picker>
</li>
<li class="grafana-target-segment last">
<a class="pointer" ng-click="invertColorOrder()">invert order</a>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
<div class="editor-row">
<div class="section" style="margin-bottom: 20px">
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment" style="width: 80px">
<strong>Spark lines</strong>
</li>
<li class="grafana-target-segment">
Show&nbsp;
<input class="cr1" id="panel.sparkline.show" type="checkbox"
ng-model="panel.sparkline.show" ng-checked="panel.sparkline.show" ng-change="render()">
<label for="panel.sparkline.show" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Background mode&nbsp;
<input class="cr1" id="panel.sparkline.full" type="checkbox"
ng-model="panel.sparkline.full" ng-checked="panel.sparkline.full" ng-change="render()">
<label for="panel.sparkline.full" class="cr1"></label>
</li>
<li class="grafana-target-segment">
Line Color
</li>
<li class="grafana-target-segment">
<spectrum-picker ng-model="panel.sparkline.lineColor" ng-change="render()" ></spectrum-picker>
</li>
<li class="grafana-target-segment">
Fill Color
</li>
<li class="grafana-target-segment">
<spectrum-picker ng-model="panel.sparkline.fillColor" ng-change="render()" ></spectrum-picker>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
<div class="editor-row">
<div class="section" style="margin-bottom: 20px">
<div class="grafana-target">
<div class="grafana-target-inner">
<ul class="grafana-segment-list">
<li class="grafana-target-segment">
<strong>Value to text mapping</strong>
</li>
<li class="grafana-target-segment" ng-repeat-start="map in panel.valueMaps">
<i class="fa fa-remove pointer" ng-click="removeValueMap(map)"></i>
</li>
<li>
<input type="text" ng-model="map.value" placeholder="value" class="input-mini grafana-target-segment-input" ng-blur="render()">
</li>
<li class="grafana-target-segment">
<i class="fa fa-arrow-right"></i>
</li>
<li ng-repeat-end>
<input type="text" placeholder="text" ng-model="map.text" class="input-mini grafana-target-segment-input" ng-blur="render()">
</li>
<li>
<a class="pointer grafana-target-segment" ng-click="addValueMap();">
<i class="fa fa-plus"></i>
</a>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
+6
View File
@@ -57,6 +57,12 @@ function (angular, app, _, TimeSeries, kbn, PanelMeta) {
};
_.defaults($scope.panel, _d);
$scope.unitFormats = kbn.getUnitFormats();
$scope.setUnitFormat = function(subItem) {
$scope.panel.format = subItem.value;
$scope.render();
};
$scope.init = function() {
panelSrv.init($scope);
+3 -4
View File
@@ -11,7 +11,7 @@ function (angular, app, _, $) {
var module = angular.module('grafana.panels.singlestat', []);
app.useModule(module);
module.directive('singlestatPanel', function($location, linkSrv, $timeout) {
module.directive('singlestatPanel', function($location, linkSrv, $timeout, templateSrv) {
return {
link: function(scope, elem) {
@@ -63,6 +63,7 @@ function (angular, app, _, $) {
}
function getSpan(className, fontSize, value) {
value = templateSrv.replace(value);
return '<span class="' + className + '" style="font-size:' + fontSize + '">' +
value + '</span>';
}
@@ -133,9 +134,7 @@ function (angular, app, _, $) {
color: panel.sparkline.lineColor
};
setTimeout(function() {
$.plot(plotCanvas, [plotSeries], options);
}, 10);
$.plot(plotCanvas, [plotSeries], options);
}
function render() {
+1 -1
View File
@@ -15,7 +15,7 @@ input[type="checkbox"]+.cr1 {
height: 19px;
clear: none;
text-indent: 2px;
margin-top: 4px;
margin: 0;
padding: 0 0 0 20px;
vertical-align:middle;
background: url(@checkboxImageUrl) left top no-repeat;
+11 -56
View File
@@ -88,29 +88,6 @@
}
}
.yaxisLabel {
top: 50%;
left: -20px;
transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
transform-origin: 0 0;
-o-transform-origin: 0 0;
-ms-transform-origin: 0 0;
-moz-transform-origin: 0 0;
-webkit-transform-origin: 0 0;
}
.axisLabel {
color: @textColor;
font-size: @fontSizeSmall;
position: absolute;
text-align: center;
font-size: 12px;
}
.dashboard-fullscreen {
.main-view-container {
overflow: hidden;
@@ -146,7 +123,6 @@
.grafana-segment-list {
list-style: none;
margin: 0;
margin-right: 90px;
>li {
float: left;
}
@@ -192,6 +168,9 @@
padding: 8px 15px;
}
&.last {
border-right: none;
}
}
.grafana-target-segment-icon {
@@ -225,37 +204,6 @@ input[type=text].grafana-function-param-input {
padding: 0;
}
.grafana-target-controls {
float: right;
list-style: none;
margin: 0;
text-align: right;
>li {
display: inline-block;
white-space: nowrap;
}
.fa {
position: relative;
top: 8px;
}
a {
padding: 8px 7px;
color: @grafanaTargetColor;
font-size: 16px;
.grafana-target-hidden & {
color: @grafanaTargetColorHide;
}
&:hover, &:focus {
text-decoration: none;
}
}
}
input[type=text].grafana-target-text-input {
padding: 8px 7px;
border: none;
@@ -267,12 +215,15 @@ input[type=text].grafana-target-text-input {
border-right: 1px solid @grafanaTargetSegmentBorder;
}
input[type=text].grafana-target-segment-input {
[type=text].grafana-target-segment-input, [type=number].grafana-target-segment-input {
border: none;
border-right: 1px solid @grafanaTargetSegmentBorder;
margin: 0px;
border-radius: 0;
padding: 8px 4px;
&.last {
border-right: none;
}
}
input[type=checkbox].grafana-target-option-checkbox {
@@ -286,6 +237,9 @@ select.grafana-target-segment-input {
border-radius: 0;
height: 36px;
padding: 8px 5px;
&.last {
border-right: none;
}
}
.grafana-target .dropdown {
@@ -371,6 +325,7 @@ select.grafana-target-segment-input {
background: inherit;
border: none;
color: inherit;
padding: 0;
}
.sp-replacer:hover, .sp-replacer.sp-active {
+41
View File
@@ -228,3 +228,44 @@
text-align: right;
}
}
.left-yaxis-label {
top: 50%;
left: -5px;
transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
transform-origin: left top;
-o-transform-origin: left top;
-ms-transform-origin: left top;
-moz-transform-origin: left top;
-webkit-transform-origin: left top;
}
.right-yaxis-label {
top: 50%;
right: -5px;
-webkit-transform: rotate(90deg);
-webkit-transform-origin: right top;
-moz-transform: rotate(90deg);
-moz-transform-origin: right top;
-ms-transform: rotate(90deg);
-ms-transform-origin: right top;
-o-transform: rotate(90deg);
-o-transform-origin: right top;
transform: rotate(90deg);
transform-origin: right top;
}
.axisLabel {
color: @textColor;
font-size: @fontSizeSmall;
position: absolute;
text-align: center;
font-size: 12px;
}
+1 -1
View File
@@ -31,7 +31,7 @@
<div class="page-alert-list">
<div ng-repeat='alert in dashAlerts.list' class="alert-{{alert.severity}} alert">
<button type="button" class="alert-close" ng-click="dashAlerts.clear(alert)">
<i class="icon-remove-sign"></i>
<i class="fa fa-times-circle"></i>
</button>
<div class="alert-title">{{alert.title}}</div>
<div ng-bind-html='alert.text'></div>
+6 -10
View File
@@ -2,9 +2,9 @@ define([
'angular',
'app',
'lodash',
'require',
'components/panelmeta',
],
function (angular, app, _) {
function (angular, app, _, PanelMeta) {
'use strict';
var module = angular.module('grafana.panels.custom', []);
@@ -12,9 +12,9 @@ function (angular, app, _) {
module.controller('CustomPanelCtrl', function($scope, panelSrv) {
$scope.panelMeta = {
description : "Example plugin panel",
};
$scope.panelMeta = new PanelMeta({
description : "A static text panel that can use plain text, markdown, or (sanitized) HTML"
});
// set and populate defaults
var _d = {
@@ -22,10 +22,6 @@ function (angular, app, _) {
_.defaults($scope.panel, _d);
$scope.init = function() {
panelSrv.init($scope);
};
$scope.init();
panelSrv.init($scope);
});
});
+1 -7
View File
@@ -16,15 +16,9 @@ define([
ctx.scope.render = function() {};
});
describe('Controller should init overrideMenu', function() {
it('click should include option and value index', function() {
expect(ctx.scope.overrideMenu[1].submenu[1].click).to.be('menuItemSelected(1,1)');
});
});
describe('When setting an override', function() {
beforeEach(function() {
ctx.scope.setOverride(1, 0);
ctx.scope.setOverride({propertyName: 'lines'}, {value: true});
});
it('should set override property', function() {