Commit 37b3b1fc by Torkel Ödegaard

Merge remote-tracking branch 'origin/master' into pro

parents 1bc277fd d8656180
...@@ -6,6 +6,7 @@ dist ...@@ -6,6 +6,7 @@ dist
# locally required config files # locally required config files
web.config web.config
config.js config.js
src/css/*.min.css
# Editor junk # Editor junk
*.sublime-workspace *.sublime-workspace
......
language: node_js language: node_js
node_js: node_js:
- "0.10" - "0.10"
git:
depth: 1
before_script: before_script:
- npm install -g grunt-cli - npm install -g grunt-cli
after_script: after_script:
......
# 1.7.0 (unreleased) # 1.8.0 (unreleased)
**New features and improvements**
- [Issue #578](https://github.com/grafana/grafana/issues/578). Dashboard: Row option to display row title even when the row is visible
**Tech**
- Upgraded from angularjs 1.1.5 to 1.3 beta 17;
- Switch from underscore to lodash
- helpers to easily unit test angularjs controllers and services
- Test coverage through coveralls
# 1.7.0 (2014-08-11)
**Fixes** **Fixes**
- [Issue #655](https://github.com/grafana/grafana/issues/655). General: Auto refresh not initiated / started after dashboard loading
- [Issue #652](https://github.com/grafana/grafana/issues/652). Timepicker: Entering custom date range impossible when refresh is low (now is constantly reset) - [Issue #652](https://github.com/grafana/grafana/issues/652). Timepicker: Entering custom date range impossible when refresh is low (now is constantly reset)
- [Issue #450](https://github.com/grafana/grafana/issues/450). Graph: Tooltip does not disappear sometimes and would get stuck - [Issue #450](https://github.com/grafana/grafana/issues/450). Graph: Tooltip does not disappear sometimes and would get stuck
- [Issue #655](https://github.com/grafana/grafana/issues/655). General: Auto refresh not initiated / started after dashboard loading
- [Issue #657](https://github.com/grafana/grafana/issues/657). General: Fix for refresh icon in IE browsers
- [Issue #661](https://github.com/grafana/grafana/issues/661). Annotations: Elasticsearch querystring with filter template replacements was not interpolated
- [Issue #660](https://github.com/grafana/grafana/issues/660). OpenTSDB: fix opentsdb queries that returned more than one series
**Change**
- [Issue #681](https://github.com/grafana/grafana/issues/681). Dashboard: The panel error bar has been replaced with a small error indicator, this indicator does not change panel height and is a lot less intrusive. Hover over it for short details, click on it for more details.
# 1.7.0-rc1 (2014-08-05) # 1.7.0-rc1 (2014-08-05)
......
[Grafana](http://grafana.org) [![Build Status](https://api.travis-ci.org/grafana/grafana.png)](https://travis-ci.org/grafana/grafana) [![Gittip](http://img.shields.io/gittip/torkelo.svg)](https://www.gittip.com/torkelo) [Grafana](http://grafana.org) [![Build Status](https://api.travis-ci.org/grafana/grafana.svg)](https://travis-ci.org/grafana/grafana) [![Coverage Status](https://coveralls.io/repos/grafana/grafana/badge.png?branch=develop)](https://coveralls.io/r/grafana/grafana?branch=develop)
================ ================
[Website](http://grafana.org) | [Website](http://grafana.org) |
[Twitter](http://twitter.com/grafana) | [Twitter](http://twitter.com/grafana) |
......
{ {
"version": "1.7.0-rc1", "version": "1.7.0",
"url": "http://grafanarel.s3.amazonaws.com/grafana-1.7.0-rc1.tar.gz" "url": "http://grafanarel.s3.amazonaws.com/grafana-1.7.0"
} }
\ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"company": "Coding Instinct AB" "company": "Coding Instinct AB"
}, },
"name": "grafana", "name": "grafana",
"version": "1.7.0-rc1", "version": "1.7.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "http://github.com/torkelo/grafana.git" "url": "http://github.com/torkelo/grafana.git"
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
"grunt-contrib-less": "~0.7.0", "grunt-contrib-less": "~0.7.0",
"grunt-contrib-requirejs": "~0.4.1", "grunt-contrib-requirejs": "~0.4.1",
"grunt-contrib-uglify": "~0.2.4", "grunt-contrib-uglify": "~0.2.4",
"grunt-contrib-watch": "^0.6.1",
"grunt-filerev": "^0.2.1", "grunt-filerev": "^0.2.1",
"grunt-git-describe": "~2.3.2", "grunt-git-describe": "~2.3.2",
"grunt-karma": "~0.8.3", "grunt-karma": "~0.8.3",
......
...@@ -51,13 +51,13 @@ function (angular, $, _, appLevelRequire, config) { ...@@ -51,13 +51,13 @@ function (angular, $, _, appLevelRequire, config) {
app.config(function ($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) { app.config(function ($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
$routeProvider.otherwise({ redirectTo: config.default_route }); $routeProvider.otherwise({ redirectTo: config.default_route });
// this is how the internet told me to dynamically add modules :/ // this is how the internet told me to dynamically add modules :/
register_fns.controller = $controllerProvider.register; register_fns.controller = $controllerProvider.register;
register_fns.directive = $compileProvider.directive; register_fns.directive = $compileProvider.directive;
register_fns.factory = $provide.factory; register_fns.factory = $provide.factory;
register_fns.service = $provide.service; register_fns.service = $provide.service;
register_fns.filter = $filterProvider.register; register_fns.filter = $filterProvider.register;
}); });
var apps_deps = [ var apps_deps = [
......
...@@ -13,4 +13,5 @@ define([ ...@@ -13,4 +13,5 @@ define([
'./playlistCtrl', './playlistCtrl',
'./inspectCtrl', './inspectCtrl',
'./opentsdbTargetCtrl', './opentsdbTargetCtrl',
'./console-ctrl',
], function () {}); ], function () {});
define([
'angular',
'lodash',
'moment',
],
function (angular, _, moment) {
'use strict';
var module = angular.module('grafana.controllers');
var consoleEnabled = window.localStorage && window.localStorage.grafanaConsole === 'true';
if (!consoleEnabled) {
return;
}
var events = [];
var oldLog = console.log;
console.log = function (message) {
try {
if (_.isObject(message)) {
message = angular.toJson(message);
if (message.length > 50) {
message = message.substring(0, 50);
}
}
events.push(new ConsoleEvent('log', message, {}));
oldLog.apply(console, arguments);
} catch (e) { }
};
function ConsoleEvent(type, title, data) {
this.type = type;
this.title = title;
this.data = data;
this.time = moment().format('hh:mm:ss');
if (data.config) {
this.method = data.config.method;
this.elapsed = (new Date().getTime() - data.config.$grafana_timestamp) + ' ms';
if (data.config.params && data.config.params.q) {
this.field2 = data.config.params.q;
}
if (_.isString(data.config.data)) {
this.field2 = data.config.data;
}
if (data.status !== 200) {
this.error = true;
this.field3 = data.data;
}
if (_.isArray(data.data)) {
this.extractTimeseriesInfo(data.data);
}
}
}
ConsoleEvent.prototype.extractTimeseriesInfo = function(series) {
if (series.length === 0) {
return;
}
var points = 0;
var ok = false;
if (series[0].datapoints) {
points = _.reduce(series, function(memo, val) {
return memo + val.datapoints.length;
}, 0);
ok = true;
}
if (series[0].columns) {
points = _.reduce(series, function(memo, val) {
return memo + val.points.length;
}, 0);
ok = true;
}
if (ok) {
this.field1 = '(' + series.length + ' series';
this.field1 += ', ' + points + ' points)';
}
};
module.config(function($provide, $httpProvider) {
$provide.factory('mupp', function($q) {
return {
'request': function(config) {
if (config.inspect) {
config.$grafana_timestamp = new Date().getTime();
}
return config;
},
'response': function(response) {
if (response.config.inspect) {
events.push(new ConsoleEvent(response.config.inspect.type, response.config.url, response));
}
return response;
},
'requestError': function(rejection) {
console.log('requestError', rejection);
return $q.reject(rejection);
},
'responseError': function (rejection) {
var inspect = rejection.config.inspect || { type: 'error' };
events.push(new ConsoleEvent(inspect.type, rejection.config.url, rejection));
return $q.reject(rejection);
}
};
});
$httpProvider.interceptors.push('mupp');
});
module.controller('ConsoleCtrl', function($scope) {
$scope.events = events;
});
});
...@@ -18,6 +18,13 @@ function (angular, config, _) { ...@@ -18,6 +18,13 @@ function (angular, config, _) {
$scope.grafana = { $scope.grafana = {
style: 'dark' style: 'dark'
}; };
$scope.consoleEnabled = (window.localStorage && window.localStorage.grafanaConsole === 'true');
};
$scope.toggleConsole = function() {
$scope.consoleEnabled = !$scope.consoleEnabled;
window.localStorage.grafanaConsole = $scope.consoleEnabled ? 'true' : 'false';
}; };
$rootScope.onAppEvent = function(name, callback) { $rootScope.onAppEvent = function(name, callback) {
......
define([ define([
'angular' 'angular',
'lodash'
], ],
function (angular) { function (angular, _) {
'use strict'; 'use strict';
var module = angular.module('grafana.controllers'); var module = angular.module('grafana.controllers');
...@@ -28,6 +29,16 @@ function (angular) { ...@@ -28,6 +29,16 @@ function (angular) {
return; return;
} }
if (_.isString(model.error.data)) {
$scope.response = model.error.data;
}
if (model.error.config && model.error.config.params) {
$scope.request_parameters = _.map(model.error.config.params, function(value, key) {
return { key: key, value: value};
});
}
if (model.error.stack) { if (model.error.stack) {
$scope.editor.index = 2; $scope.editor.index = 2;
$scope.stack_trace = model.error.stack; $scope.stack_trace = model.error.stack;
...@@ -72,4 +83,4 @@ function (angular) { ...@@ -72,4 +83,4 @@ function (angular) {
}; };
}); });
}); });
\ No newline at end of file
...@@ -33,11 +33,8 @@ function (angular, app, _) { ...@@ -33,11 +33,8 @@ function (angular, app, _) {
}; };
$scope.rowSpan = function(row) { $scope.rowSpan = function(row) {
var panels = _.filter(row.panels, function(p) { return _.reduce(row.panels, function(p,v) {
return $scope.isPanel(p); return p + v.span;
});
return _.reduce(_.pluck(panels,'span'), function(p,v) {
return p+v;
},0); },0);
}; };
......
...@@ -15,16 +15,12 @@ function (angular, $) { ...@@ -15,16 +15,12 @@ function (angular, $) {
var panelHeader = var panelHeader =
'<div class="panel-header">'+ '<div class="panel-header">'+
'<div class="row-fluid">' + '<div class="row-fluid panel-extra">' +
'<div class="span12 alert-error panel-error small" ng-show="panel.error">' +
'<a class="close" ng-click="panel.error=false">&times;</a>' +
'<span><i class="icon-exclamation-sign"></i> <strong>Oops!</strong> {{panel.error}} </span>' +
'<span class="pointer panel-error-inspector-link" config-modal="app/partials/inspector.html">View details</span>' +
'</div>' +
'</div>\n' +
'<div class="row-fluid panel-extra">' +
'<div class="panel-extra-container">' + '<div class="panel-extra-container">' +
'<span class="alert-error panel-error small pointer"' +
'config-modal="app/partials/inspector.html" ng-show="panel.error" data-placement="right" bs-tooltip="panel.error">' +
'<i class="icon-exclamation-sign"></i><span class="panel-error-arrow"></span>' +
'</span>' +
'<span class="panel-loading" ng-show="panelMeta.loading == true">' + '<span class="panel-loading" ng-show="panelMeta.loading == true">' +
'<i class="icon-spinner icon-spin icon-large"></i>' + '<i class="icon-spinner icon-spin icon-large"></i>' +
......
...@@ -13,20 +13,15 @@ ...@@ -13,20 +13,15 @@
{{series.alias}} {{series.alias}}
</a> </a>
</div> </div>
<div class="graph-legend-value small" ng-show="panel.legend.values && panel.legend.current"> <div class="graph-legend-value current small" ng-show="panel.legend.values && panel.legend.current" ng-bind="series.current">
Current: {{series.current}}
</div> </div>
<div class="graph-legend-value small" ng-show="panel.legend.values && panel.legend.min"> <div class="graph-legend-value min small" ng-show="panel.legend.values && panel.legend.min" ng-bind="series.min">
Min: {{series.min}}
</div> </div>
<div class="graph-legend-value small" ng-show="panel.legend.values && panel.legend.max"> <div class="graph-legend-value max small" ng-show="panel.legend.values && panel.legend.max" ng-bind="series.max">
Max: {{series.max}}
</div> </div>
<div class="graph-legend-value small" ng-show="panel.legend.values && panel.legend.total"> <div class="graph-legend-value total small" ng-show="panel.legend.values && panel.legend.total" ng-bind="series.total">
Total: {{series.total}}
</div> </div>
<div class="graph-legend-value small" ng-show="panel.legend.values && panel.legend.avg"> <div class="graph-legend-value avg small" ng-show="panel.legend.values && panel.legend.avg" ng-bind="series.avg">
Avg: {{series.avg}}
</div> </div>
</div> </div>
......
...@@ -82,11 +82,13 @@ function (angular, app, _, require) { ...@@ -82,11 +82,13 @@ function (angular, app, _, require) {
$scope.updateContent = function(html) { $scope.updateContent = function(html) {
try { try {
$scope.content = $sce.trustAsHtml(filterSrv.applyTemplateToTarget(html)); $scope.content = $sce.trustAsHtml(filterSrv.applyTemplateToTarget(html));
if(!$scope.$$phase) {
$scope.$apply();
}
} catch(e) { } catch(e) {
console.log('Text panel error: ', e);
$scope.content = $sce.trustAsHtml(html);
}
if(!$scope.$$phase) {
$scope.$apply();
} }
}; };
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
</li> </li>
<li ng-show="!dashboard.refresh" class="grafana-menu-refresh"> <li ng-show="!dashboard.refresh" class="grafana-menu-refresh">
<a class="icon-refresh" ng-click="dashboard.emit_refresh()"></a> <a ng-click="dashboard.emit_refresh()"><i class="icon-refresh"></i></a>
</li> </li>
</ul> </ul>
......
<div class="grafana-console" ng-controller="ConsoleCtrl">
<div class="grafana-console-header">
<span class="grafana-console-title large"><i class="icon-terminal"></i></span>
</div>
<div class="grafana-console-body">
<div class="grafana-console-item" ng-repeat="item in events" ng-class="{'grafana-console-error': item.error}">
<span class="grafana-console-time gfc-col" ng-bind="item.time"></span>
<span class="grafana-console-type gfc-col">
<span class="label label-info" ng-bind="item.type"></span>
</span>
<span class="gfc-col grafana-console-method" ng-bind="item.method"></span>
<span class="gfc-col grafana-console-title" ng-bind="item.title"></span>
<span class="gfc-col grafana-console-elapsed" ng-bind="item.elapsed"></span>
<span class="gfc-col grafana-console-field1" ng-bind="item.field1"></span>
<span class="gfc-col grafana-console-field2" ng-bind="item.field2"></span>
<span class="gfc-col grafana-console-field3" ng-bind="item.field3"></span>
</div>
</div>
</div>
...@@ -31,13 +31,15 @@ ...@@ -31,13 +31,15 @@
<div class="row-control"> <div class="row-control">
<div class="row-control-inner" style="padding:0px;margin:0px;position:relative;"> <div class="row-control-inner" style="padding:0px;margin:0px;position:relative;">
<div class="row-close" ng-show="row.collapse" data-placement="bottom" > <div class="row-close" ng-show="row.collapse" data-placement="bottom" >
<span class="row-button bgWarning" config-modal="app/partials/roweditor.html" class="pointer"> <div class="row-close-buttons">
<i bs-tooltip="'Configure row'" data-placement="right" ng-show="row.editable" class="icon-cog pointer"></i> <span class="row-button bgWarning" config-modal="app/partials/roweditor.html" class="pointer">
</span> <i bs-tooltip="'Configure row'" data-placement="right" ng-show="row.editable" class="icon-cog pointer"></i>
<span class="row-button bgPrimary" ng-click="toggle_row(row)"> </span>
<i bs-tooltip="'Expand row'" data-placement="right" class="icon-caret-left pointer" ></i> <span class="row-button bgPrimary" ng-click="toggle_row(row)">
</span> <i bs-tooltip="'Expand row'" data-placement="right" class="icon-caret-left pointer" ></i>
<span class="row-button row-text" ng-click="toggle_row(row)">{{row.title || 'Row '+$index}}</span> </span>
</div>
<span class="row-text pointer" ng-click="toggle_row(row)" ng-bind="row.title"></span>
</div> </div>
<div class="row-open" ng-show="!row.collapse"> <div class="row-open" ng-show="!row.collapse">
<div class='row-tab bgPrimary' ng-click="toggle_row(row)"> <div class='row-tab bgPrimary' ng-click="toggle_row(row)">
...@@ -92,6 +94,8 @@ ...@@ -92,6 +94,8 @@
</div> </div>
<div style="padding-top:0px" ng-if="!row.collapse"> <div style="padding-top:0px" ng-if="!row.collapse">
<div class="row-text pointer" ng-click="toggle_row(row)" ng-if="row.showTitle" ng-bind="row.title">
</div>
<!-- Panels --> <!-- Panels -->
<div ng-repeat="(name, panel) in row.panels|filter:isPanel" ng-hide="panel.hide" class="panel nospace" ng-style="{'width':(panel.span/1.2)*10+'%'}" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:$index,mutate:false,onDrop:'panelMoveDrop',onOver:'panelMoveOver(true)',onOut:'panelMoveOut'}" ng-class="{'dragInProgress':dashboard.$$panelDragging}"> <div ng-repeat="(name, panel) in row.panels|filter:isPanel" ng-hide="panel.hide" class="panel nospace" ng-style="{'width':(panel.span/1.2)*10+'%'}" data-drop="true" ng-model="row.panels" data-jqyoui-options jqyoui-droppable="{index:$index,mutate:false,onDrop:'panelMoveDrop',onOver:'panelMoveOver(true)',onOut:'panelMoveOut'}" ng-class="{'dragInProgress':dashboard.$$panelDragging}">
...@@ -121,4 +125,7 @@ ...@@ -121,4 +125,7 @@
</div> </div>
</div> </div>
<div ng-include="'app/partials/console.html'" ng-if="consoleEnabled">
</div>
</div> </div>
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
<label class="small">Hide controls (CTRL+H)</label> <label class="small">Hide controls (CTRL+H)</label>
<input type="checkbox" ng-model="dashboard.hideControls" ng-checked="dashboard.hideControls"> <input type="checkbox" ng-model="dashboard.hideControls" ng-checked="dashboard.hideControls">
</div> </div>
</div> </div>
</div> </div>
<div class="editor-row"> <div class="editor-row">
<div class="section"> <div class="section">
...@@ -98,6 +98,7 @@ ...@@ -98,6 +98,7 @@
<span class="editor-option small"> <span class="editor-option small">
Grafana version: {{grafanaVersion}} Grafana version: {{grafanaVersion}}
</span> </span>
<span> | <a ng-click="toggleConsole()" ng-show="!consoleEnabled">enable console</a> <a ng-click="toggleConsole()" ng-show="consoleEnabled">disable console</a></span>
<div class="small" grafana-version-check> <div class="small" grafana-version-check>
</div> </div>
</div> </div>
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
</div> </div>
<div ng-if="editor.index == 1"> <div ng-if="editor.index == 1">
<h5 ng-if="response" ng-bind="response"></h5>
<div ng-if="response_html"> <div ng-if="response_html">
<div iframe-content="response_html"></div> <div iframe-content="response_html"></div>
...@@ -65,4 +66,4 @@ ...@@ -65,4 +66,4 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-info" ng-click="dismiss()">Close</button> <button type="button" class="btn btn-info" ng-click="dismiss()">Close</button>
</div> </div>
\ No newline at end of file
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
<label class="small"> Editable </label><input type="checkbox" ng-model="row.editable" ng-checked="row.editable" /> <label class="small"> Editable </label><input type="checkbox" ng-model="row.editable" ng-checked="row.editable" />
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small"> Collapsable </label><input type="checkbox" ng-model="row.collapsable" ng-checked="row.collapsable" /> <label class="small"> Show title </label><input type="checkbox" ng-model="row.showTitle" ng-checked="row.showTitle" />
</div> </div>
</div> </div>
<div class="row-fluid" ng-if="editor.index == 1"> <div class="row-fluid" ng-if="editor.index == 1">
<div class="span12"> <div class="span12">
<h4>Panels</h4> <h4>Panels</h4>
......
...@@ -7,7 +7,7 @@ function (angular, _) { ...@@ -7,7 +7,7 @@ function (angular, _) {
var module = angular.module('grafana.services'); var module = angular.module('grafana.services');
module.service('alertSrv', function($timeout) { module.service('alertSrv', function($timeout, $sce) {
var self = this; var self = this;
// List of all alert objects // List of all alert objects
...@@ -17,7 +17,7 @@ function (angular, _) { ...@@ -17,7 +17,7 @@ function (angular, _) {
var var
_a = { _a = {
title: title || '', title: title || '',
text: text || '', text: $sce.trustAsHtml(text || ''),
severity: severity || 'info', severity: severity || 'info',
}, },
_ca = angular.toJson(_a), _ca = angular.toJson(_a),
...@@ -46,4 +46,4 @@ function (angular, _) { ...@@ -46,4 +46,4 @@ function (angular, _) {
self.list = []; self.list = [];
}; };
}); });
}); });
\ No newline at end of file
...@@ -73,8 +73,9 @@ function (angular, _, $, config, kbn, moment) { ...@@ -73,8 +73,9 @@ function (angular, _, $, config, kbn, moment) {
to: rangeUnparsed.to, to: rangeUnparsed.to,
}; };
var queryInterpolated = filterSrv.applyTemplateToTarget(queryString);
var filter = { "bool": { "must": [{ "range": range }] } }; var filter = { "bool": { "must": [{ "range": range }] } };
var query = { "bool": { "should": [{ "query_string": { "query": queryString } }] } }; var query = { "bool": { "should": [{ "query_string": { "query": queryInterpolated } }] } };
var data = { "query" : { "filtered": { "query" : query, "filter": filter } }, "size": 100 }; var data = { "query" : { "filtered": { "query" : query, "filter": filter } }, "size": 100 };
return this._request('POST', '/_search', annotation.index, data).then(function(results) { return this._request('POST', '/_search', annotation.index, data).then(function(results) {
......
...@@ -205,6 +205,7 @@ function (angular, _, $, config, kbn, moment) { ...@@ -205,6 +205,7 @@ function (angular, _, $, config, kbn, moment) {
} }
options.url = this.url + options.url; options.url = this.url + options.url;
options.inspect = { type: 'graphite' };
return $http(options); return $http(options);
}; };
......
...@@ -132,8 +132,8 @@ function (angular, _, kbn, InfluxSeries) { ...@@ -132,8 +132,8 @@ function (angular, _, kbn, InfluxSeries) {
return new InfluxSeries({ seriesList: results, annotation: annotation }).getAnnotations(); return new InfluxSeries({ seriesList: results, annotation: annotation }).getAnnotations();
}); });
}; };
InfluxDatasource.prototype.listColumns = function(seriesName) { InfluxDatasource.prototype.listColumns = function(seriesName) {
return this._seriesQuery('select * from /' + seriesName + '/ limit 1').then(function(data) { return this._seriesQuery('select * from /' + seriesName + '/ limit 1').then(function(data) {
if (!data) { if (!data) {
return []; return [];
...@@ -184,6 +184,7 @@ function (angular, _, kbn, InfluxSeries) { ...@@ -184,6 +184,7 @@ function (angular, _, kbn, InfluxSeries) {
function retry(deferred, callback, delay) { function retry(deferred, callback, delay) {
return callback().then(undefined, function(reason) { return callback().then(undefined, function(reason) {
if (reason.status !== 0 || reason.status >= 300) { if (reason.status !== 0 || reason.status >= 300) {
reason.message = 'InfluxDB Error: <br/>' + reason.data;
deferred.reject(reason); deferred.reject(reason);
} }
else { else {
...@@ -223,7 +224,8 @@ function (angular, _, kbn, InfluxSeries) { ...@@ -223,7 +224,8 @@ function (angular, _, kbn, InfluxSeries) {
method: method, method: method,
url: currentUrl + url, url: currentUrl + url,
params: params, params: params,
data: data data: data,
inspect: { type: 'influxdb' },
}; };
return $http(options).success(function (data) { return $http(options).success(function (data) {
......
...@@ -106,7 +106,7 @@ function (angular, _, kbn) { ...@@ -106,7 +106,7 @@ function (angular, _, kbn) {
} }
function createMetricLabel(metric, tagData, options) { function createMetricLabel(metric, tagData, options) {
if (options.alias) { if (!_.isUndefined(options) && options.alias) {
return options.alias; return options.alias;
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -12,22 +12,6 @@ body { ...@@ -12,22 +12,6 @@ body {
//url('../img/light.png') repeat right top; //url('../img/light.png') repeat right top;
} }
h1 {
font-size: 50px;
}
h2, h3 {
font-size: 26px;
}
h4 {
font-size: 14px;
}
h5, h6 {
font-size: 11px;
}
blockquote { blockquote {
padding: 10px 15px; padding: 10px 15px;
...@@ -527,11 +511,6 @@ a:hover { ...@@ -527,11 +511,6 @@ a:hover {
.box-shadow(none); .box-shadow(none);
} }
[class^="icon-"], [class*=" icon-"] {
margin: 0 2px;
vertical-align: -2px;
}
a.thumbnail { a.thumbnail {
background-color: @grayLight; background-color: @grayLight;
......
.grafana-console {
position: fixed;
width: 100%;
bottom: 0px;
height: 300px;
background: @grafanaPanelBackground;
border-top: 1px solid @fullEditBorder;
}
.grafana-console-header {
background: @fullEditTabsBackground;
border-top: @fullEditTabsBorder;
padding: 2px 5px;
}
.grafana-console-item {
.icon-caret-right {
font-size: 14px;
color: @blue;
}
margin: 2px 0;
display: table-row;
}
.grafana-console-body {
overflow-y: auto;
display: table;
width: 100%;
}
.gfc-col {
display: table-cell;
padding: 2px 4px;
white-space: nowrap;
overflow: hidden;
vertical-align: middle;
}
.grafana-console-method {
text-align: center;
}
.grafana-console-error {
.grafana-console-method {
color: red;
}
}
.grafana-console-field2 {
width: 90%;
}
.grafana-console-time:before {
content: '(';
color: rgb(106, 253, 81);
}
.grafana-console-time:after {
content: ')';
color: rgb(106, 253, 81);
}
.grafana-console-time {
color: rgb(162, 196, 253);
}
.grafana-console-elapsed {
text-align: right;
color: rgb(162, 196, 253);
}
@import "submenu.less"; @import "submenu.less";
@import "graph.less"; @import "graph.less";
@import "console.less";
@import "bootstrap-tagsinput.less"; @import "bootstrap-tagsinput.less";
.hide-controls { .hide-controls {
...@@ -494,3 +495,11 @@ select.grafana-target-segment-input { ...@@ -494,3 +495,11 @@ select.grafana-target-segment-input {
border-radius: 5px; border-radius: 5px;
z-index: 9999; z-index: 9999;
} }
.tooltip.in {
.opacity(100);
}
.tooltip-inner {
max-width: 400px;
}
...@@ -25,6 +25,21 @@ ...@@ -25,6 +25,21 @@
.graph-legend-value { .graph-legend-value {
float: left; float: left;
white-space: nowrap; white-space: nowrap;
&.current:before {
content: "Current: "
}
&.max:before {
content: "Max: "
}
&.min:before {
content: "Min: "
}
&.total:before {
content: "Total: "
}
&.avg:before {
content: "Avg: "
}
} }
.graph-legend-series { .graph-legend-series {
......
...@@ -112,15 +112,27 @@ code, pre { ...@@ -112,15 +112,27 @@ code, pre {
.panel-error { .panel-error {
color: @white; color: @white;
padding: 5px 10px 0px 10px; //padding: 5px 10px 0px 10px;
position: absolute;
left: 5px;
padding: 0px 17px 6px 5px;
top: 0;
i {
position: relative;
top: -2px;
}
} }
.panel-error-arrow {
.panel-error-inspector-link { width: 0;
float: right; height: 0;
margin-right: 10px; position: absolute;
border-left: 31px solid transparent;
border-right: 30px solid transparent;
border-bottom: 27px solid @grafanaPanelBackground;
left: 0;
bottom: 0;
} }
div.editor-row { div.editor-row {
vertical-align: top; vertical-align: top;
} }
...@@ -223,9 +235,9 @@ form input.ng-invalid { ...@@ -223,9 +235,9 @@ form input.ng-invalid {
.row-button { .row-button {
width: 30px; width: 30px;
text-align: center;
float: left; float: left;
cursor: pointer; cursor: pointer;
line-height: 31px;
} }
.row-text { .row-text {
...@@ -233,15 +245,20 @@ form input.ng-invalid { ...@@ -233,15 +245,20 @@ form input.ng-invalid {
text-transform: uppercase; text-transform: uppercase;
font-weight: bold; font-weight: bold;
font-size: 0.9em; font-size: 0.9em;
margin: 0px 10px; text-align: center;
line-height: 31px;
} }
.row-close { .row-close {
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
min-height: 30px !important;
line-height: 30px;
background: @grafanaPanelBackground; background: @grafanaPanelBackground;
text-align: center;
}
.row-close-buttons {
position: absolute;
left: 0;
} }
.row-open { .row-open {
...@@ -614,4 +631,4 @@ div.flot-text { ...@@ -614,4 +631,4 @@ div.flot-text {
code, pre { code, pre {
background-color: @grafanaPanelBackground; background-color: @grafanaPanelBackground;
color: @textColor; color: @textColor;
} }
\ No newline at end of file
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
@blue: #33B5E5; @blue: #33B5E5;
@blueDark: #0099CC; @blueDark: #0099CC;
@green: #669900; @green: #669900;
@red: #CC0000; @red: #CC3900;
@yellow: #ECBB13; @yellow: #ECBB13;
@orange: #FF8800; @orange: #FF8800;
@pink: #FF4444; @pink: #FF4444;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<title>Grafana</title> <title>Grafana</title>
<link rel="stylesheet" href="css/default.min.css" title="Dark"> <link rel="stylesheet" href="css/grafana.dark.min.css" title="Dark">
<!-- build:js app/app.js --> <!-- build:js app/app.js -->
<script src="vendor/require/require.js"></script> <script src="vendor/require/require.js"></script>
...@@ -20,9 +20,7 @@ ...@@ -20,9 +20,7 @@
<body ng-cloak ng-controller="GrafanaCtrl"> <body ng-cloak ng-controller="GrafanaCtrl">
<link rel="stylesheet" href="css/bootstrap.light.min.css" ng-if="grafana.style === 'light'"> <link rel="stylesheet" href="css/grafana.light.min.css" ng-if="grafana.style === 'light'">
<link rel="stylesheet" href="css/bootstrap-responsive.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<div ng-repeat='alert in dashAlerts.list' class="alert-{{alert.severity}} dashboard-notice" ng-show="$last"> <div ng-repeat='alert in dashAlerts.list' class="alert-{{alert.severity}} dashboard-notice" ng-show="$last">
<button type="button" class="close" ng-click="dashAlerts.clear(alert)" style="padding-right:50px">&times;</button> <button type="button" class="close" ng-click="dashAlerts.clear(alert)" style="padding-right:50px">&times;</button>
......
...@@ -797,7 +797,8 @@ angular.module('$strap.directives').directive('bsTooltip', [ ...@@ -797,7 +797,8 @@ angular.module('$strap.directives').directive('bsTooltip', [
title: function () { title: function () {
return angular.isFunction(value) ? value.apply(null, arguments) : value; return angular.isFunction(value) ? value.apply(null, arguments) : value;
}, },
html: true html: true,
container: 'body', // Grafana change
}); });
var tooltip = element.data('tooltip'); var tooltip = element.data('tooltip');
tooltip.show = function () { tooltip.show = function () {
...@@ -875,4 +876,4 @@ angular.module('$strap.directives').directive('bsTypeahead', [ ...@@ -875,4 +876,4 @@ angular.module('$strap.directives').directive('bsTypeahead', [
} }
}; };
} }
]); ]);
\ No newline at end of file
...@@ -6,7 +6,8 @@ module.exports = function(grunt) { ...@@ -6,7 +6,8 @@ module.exports = function(grunt) {
'jshint:tests', 'jshint:tests',
'clean:on_start', 'clean:on_start',
'less:src', 'less:src',
'concat:css', 'concat:cssDark',
'concat:cssLight',
'copy:everything_but_less_to_temp', 'copy:everything_but_less_to_temp',
'htmlmin:build', 'htmlmin:build',
'ngtemplates', 'ngtemplates',
......
// Lint and build CSS // Lint and build CSS
module.exports = function(grunt) { module.exports = function(grunt) {
grunt.registerTask('default', ['jscs', 'jshint', 'less:src', 'concat:css']); grunt.registerTask('css', ['less:src', 'concat:cssDark', 'concat:cssLight']);
grunt.registerTask('default', ['jscs', 'jshint', 'css']);
grunt.registerTask('test', ['default', 'karma:test']); grunt.registerTask('test', ['default', 'karma:test']);
}; };
module.exports = function(config) { module.exports = function(config) {
return { return {
css: { cssDark: {
src: [ src: [
'<%= srcDir %>/css/normalize.min.css', '<%= srcDir %>/vendor/css/normalize.min.css',
'<%= srcDir %>/css/timepicker.css', '<%= srcDir %>/vendor/css/timepicker.css',
'<%= srcDir %>/css/spectrum.css', '<%= srcDir %>/vendor/css/spectrum.css',
'<%= srcDir %>/css/animate.min.css', '<%= srcDir %>/vendor/css/animate.min.css',
'<%= srcDir %>/css/bootstrap.dark.min.css' '<%= srcDir %>/css/bootstrap.dark.min.css',
'<%= srcDir %>/css/bootstrap-responsive.min.css',
'<%= srcDir %>/vendor/css/font-awesome.min.css'
], ],
dest: '<%= srcDir %>/css/default.min.css' dest: '<%= srcDir %>/css/grafana.dark.min.css'
}, },
cssLight: {
src: [
'<%= srcDir %>/vendor/css/normalize.min.css',
'<%= srcDir %>/vendor/css/timepicker.css',
'<%= srcDir %>/vendor/css/spectrum.css',
'<%= srcDir %>/vendor/css/animate.min.css',
'<%= srcDir %>/css/bootstrap.light.min.css',
'<%= srcDir %>/css/bootstrap-responsive.min.css',
'<%= srcDir %>/vendor/css/font-awesome.min.css'
],
dest: '<%= srcDir %>/css/grafana.light.min.css'
},
js: { js: {
src: [ src: [
'<%= destDir %>/vendor/require/require.js', '<%= destDir %>/vendor/require/require.js',
......
...@@ -5,8 +5,12 @@ module.exports = function(config) { ...@@ -5,8 +5,12 @@ module.exports = function(config) {
algorithm: 'md5', algorithm: 'md5',
length: 8, length: 8,
}, },
css: { cssDark: {
src: '<%= destDir %>/css/default.min.css', src: '<%= destDir %>/css/grafana.dark.min.css',
dest: '<%= destDir %>/css'
},
cssLight: {
src: '<%= destDir %>/css/grafana.light.min.css',
dest: '<%= destDir %>/css' dest: '<%= destDir %>/css'
}, },
js: { js: {
......
...@@ -51,7 +51,7 @@ module.exports = function(config,grunt) { ...@@ -51,7 +51,7 @@ module.exports = function(config,grunt) {
'modernizr', 'modernizr',
'timepicker', 'timepicker',
'datepicker', 'datepicker',
'underscore', 'lodash',
'filters/all', 'filters/all',
'jquery.flot', 'jquery.flot',
'services/all', 'services/all',
......
module.exports = function(config) {
return {
css: {
files: [ '<%= srcDir %>/css/**/*.less' ],
tasks: ['css'],
options: {
spawn: false
}
}
};
};
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