Merge branch 'master' into panel_edit_menu_poc
This commit is contained in:
@@ -1,3 +1,14 @@
|
||||
# 1.9.0 (unreleased)
|
||||
|
||||
# 1.8.1 (unreleased)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #847](https://github.com/grafana/grafana/issues/847). Graph: Fix for series draw order not being the same after hiding/unhiding series
|
||||
- [Issue #851](https://github.com/grafana/grafana/issues/851). Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations
|
||||
- [Issue #846](https://github.com/grafana/grafana/issues/846). Edit panes: Issue when open row or json editor when scrolled down the page, unable to scroll and you did not see editor
|
||||
- [Issue #840](https://github.com/grafana/grafana/issues/840). Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard.
|
||||
- [Issue #859](https://github.com/grafana/grafana/issues/859). InfluxDB: Fix for bug when saving dashboard where title is the same as slugified url id
|
||||
|
||||
# 1.8.0 (2014-09-22)
|
||||
|
||||
Read this [blog post](http://grafana.org/blog/2014/09/11/grafana-1-8-0-rc1-released.html) for an overview of all improvements.
|
||||
|
||||
@@ -19,19 +19,18 @@ function (angular, $, config, _) {
|
||||
dashboardSrv,
|
||||
dashboardViewStateSrv,
|
||||
panelMoveSrv,
|
||||
timer,
|
||||
$timeout) {
|
||||
|
||||
$scope.editor = { index: 0 };
|
||||
$scope.panelNames = config.panels;
|
||||
var resizeEventTimeout;
|
||||
|
||||
$scope.init = function() {
|
||||
this.init = function(dashboardData) {
|
||||
$scope.availablePanels = config.panels;
|
||||
$scope.onAppEvent('setup-dashboard', $scope.setupDashboard);
|
||||
$scope.onAppEvent('show-json-editor', $scope.showJsonEditor);
|
||||
$scope.reset_row();
|
||||
$scope.registerWindowResizeEvent();
|
||||
$scope.onAppEvent('show-json-editor', $scope.showJsonEditor);
|
||||
$scope.setupDashboard(dashboardData);
|
||||
};
|
||||
|
||||
$scope.registerWindowResizeEvent = function() {
|
||||
@@ -41,7 +40,7 @@ function (angular, $, config, _) {
|
||||
});
|
||||
};
|
||||
|
||||
$scope.setupDashboard = function(event, dashboardData) {
|
||||
$scope.setupDashboard = function(dashboardData) {
|
||||
$rootScope.performance.dashboardLoadStart = new Date().getTime();
|
||||
$rootScope.performance.panelsInitialized = 0;
|
||||
$rootScope.performance.panelsRendered = 0;
|
||||
@@ -129,6 +128,5 @@ function (angular, $, config, _) {
|
||||
return $scope.editorTabs;
|
||||
};
|
||||
|
||||
$scope.init();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ function (angular, config, _, $, store) {
|
||||
|
||||
var module = angular.module('grafana.controllers');
|
||||
|
||||
module.controller('GrafanaCtrl', function($scope, alertSrv, grafanaVersion, $rootScope) {
|
||||
module.controller('GrafanaCtrl', function($scope, alertSrv, grafanaVersion, $rootScope, $controller) {
|
||||
|
||||
$scope.grafanaVersion = grafanaVersion[0] === '@' ? 'master' : grafanaVersion;
|
||||
$scope.consoleEnabled = store.getBool('grafanaConsole');
|
||||
@@ -32,6 +32,10 @@ function (angular, config, _, $, store) {
|
||||
store.set('grafanaConsole', $scope.consoleEnabled);
|
||||
};
|
||||
|
||||
$scope.initDashboard = function(dashboardData, viewScope) {
|
||||
$controller('DashboardCtrl', { $scope: viewScope }).init(dashboardData);
|
||||
};
|
||||
|
||||
$rootScope.onAppEvent = function(name, callback) {
|
||||
var unbind = $rootScope.$on(name, callback);
|
||||
this.$on('$destroy', unbind);
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
define([
|
||||
'angular',
|
||||
'app',
|
||||
'lodash'
|
||||
'lodash',
|
||||
'kbn'
|
||||
],
|
||||
function (angular, app, _) {
|
||||
function (angular, app, _, kbn) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.controllers');
|
||||
|
||||
module.controller('GraphiteImportCtrl', function($scope, $rootScope, $timeout, datasourceSrv) {
|
||||
module.controller('GraphiteImportCtrl', function($scope, $rootScope, $timeout, datasourceSrv, $location) {
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.datasources = datasourceSrv.getMetricSources();
|
||||
@@ -72,18 +73,19 @@ function (angular, app, _) {
|
||||
newDashboard.title = state.name;
|
||||
newDashboard.rows.push(currentRow);
|
||||
|
||||
_.each(state.graphs, function(graph) {
|
||||
_.each(state.graphs, function(graph, index) {
|
||||
if (currentRow.panels.length === graphsPerRow) {
|
||||
currentRow = angular.copy(rowTemplate);
|
||||
newDashboard.rows.push(currentRow);
|
||||
}
|
||||
|
||||
panel = {
|
||||
type: 'graphite',
|
||||
type: 'graph',
|
||||
span: 12 / graphsPerRow,
|
||||
title: graph[1].title,
|
||||
targets: [],
|
||||
datasource: datasource
|
||||
datasource: datasource,
|
||||
id: index + 1
|
||||
};
|
||||
|
||||
_.each(graph[1].target, function(target) {
|
||||
@@ -95,7 +97,9 @@ function (angular, app, _) {
|
||||
currentRow.panels.push(panel);
|
||||
});
|
||||
|
||||
$scope.emitAppEvent('setup-dashboard', newDashboard);
|
||||
window.grafanaImportDashboard = newDashboard;
|
||||
$location.path('/dashboard/import/' + kbn.slugifyForUrl(newDashboard.title));
|
||||
|
||||
$scope.dismiss();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ function (angular, app, _) {
|
||||
title: "Row",
|
||||
height: "150px",
|
||||
collapse: false,
|
||||
editable: true,
|
||||
panels: [],
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ function (angular, $) {
|
||||
|
||||
function hideScrollbars(value) {
|
||||
if (value) {
|
||||
window.scrollTo(0,0);
|
||||
document.documentElement.style.overflow = 'hidden'; // firefox, chrome
|
||||
document.body.scroll = "no"; // ie only
|
||||
} else {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
define([
|
||||
'angular'
|
||||
'angular',
|
||||
'kbn'
|
||||
],
|
||||
function (angular) {
|
||||
function (angular, kbn) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.directives');
|
||||
|
||||
module.directive('dashUpload', function(timer, alertSrv) {
|
||||
module.directive('dashUpload', function(timer, alertSrv, $location) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope) {
|
||||
@@ -14,9 +15,10 @@ function (angular) {
|
||||
var files = evt.target.files; // FileList object
|
||||
var readerOnload = function() {
|
||||
return function(e) {
|
||||
var dashboard = JSON.parse(e.target.result);
|
||||
scope.$apply(function() {
|
||||
scope.emitAppEvent('setup-dashboard', dashboard);
|
||||
window.grafanaImportDashboard = JSON.parse(e.target.result);
|
||||
var title = kbn.slugifyForUrl(window.grafanaImportDashboard.title);
|
||||
$location.path('/dashboard/import/' + title);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -16,7 +16,6 @@ function (angular, $, kbn, moment, _) {
|
||||
template: '<div> </div>',
|
||||
link: function(scope, elem) {
|
||||
var data, annotations;
|
||||
var hiddenData = {};
|
||||
var dashboard = scope.dashboard;
|
||||
var legendSideLastValue = null;
|
||||
|
||||
@@ -24,14 +23,7 @@ function (angular, $, kbn, moment, _) {
|
||||
scope.get_data();
|
||||
});
|
||||
|
||||
scope.$on('toggleLegend', function(e, series) {
|
||||
_.each(series, function(serie) {
|
||||
if (hiddenData[serie.alias]) {
|
||||
data.push(hiddenData[serie.alias]);
|
||||
delete hiddenData[serie.alias];
|
||||
}
|
||||
});
|
||||
|
||||
scope.$on('toggleLegend', function() {
|
||||
render_panel();
|
||||
});
|
||||
|
||||
@@ -95,17 +87,6 @@ function (angular, $, kbn, moment, _) {
|
||||
}
|
||||
|
||||
var panel = scope.panel;
|
||||
|
||||
_.each(_.keys(scope.hiddenSeries), function(seriesAlias) {
|
||||
var dataSeries = _.find(data, function(series) {
|
||||
return series.info.alias === seriesAlias;
|
||||
});
|
||||
if (dataSeries) {
|
||||
hiddenData[dataSeries.info.alias] = dataSeries;
|
||||
data = _.without(data, dataSeries);
|
||||
}
|
||||
});
|
||||
|
||||
var stack = panel.stack ? true : null;
|
||||
|
||||
// Populate element
|
||||
@@ -156,6 +137,11 @@ function (angular, $, kbn, moment, _) {
|
||||
var series = data[i];
|
||||
series.applySeriesOverrides(panel.seriesOverrides);
|
||||
series.data = series.getFlotPairs(panel.nullPointMode, panel.y_formats);
|
||||
// if hidden remove points and disable stack
|
||||
if (scope.hiddenSeries[series.info.alias]) {
|
||||
series.data = [];
|
||||
series.stack = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.length && data[0].info.timeStep) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div ng-controller="DashboardCtrl" body-class class="dashboard" ng-class="{'dashboard-fullscreen': dashboardViewState.fullscreen}">
|
||||
<div body-class class="dashboard" ng-class="{'dashboard-fullscreen': dashboardViewState.fullscreen}">
|
||||
|
||||
<div ng-include="'app/partials/dashboard_topnav.html'">
|
||||
</div>
|
||||
|
||||
@@ -16,11 +16,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="editor-row" style="margin-top: 10px;">
|
||||
<table class="table table-condensed table-striped">
|
||||
<div class="editor-row" style="margin-top: 10px;max-height: 400px; overflow-y: scroll;max-width: 500px;">
|
||||
<table class="grafana-options-table">
|
||||
<tr ng-repeat="dash in dashboards">
|
||||
<td style="padding-right: 20px;"><button class="btn btn-success" ng-click="import(dash.name)">Import</button>
|
||||
<td style="width: 100%; vertical-align: middle;">{{dash.name}}</td>
|
||||
<td style="">{{dash.name}}</td>
|
||||
<td style="padding-left: 20px;">
|
||||
<a class="pointer" ng-click="import(dash.name)">
|
||||
import
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,13 @@ function (angular) {
|
||||
templateUrl: 'app/partials/dashboard.html',
|
||||
controller : 'DashFromDBProvider',
|
||||
reloadOnSearch: false,
|
||||
})
|
||||
.when('/dashboard/import/:id', {
|
||||
templateUrl: 'app/partials/dashboard.html',
|
||||
controller : 'DashFromImportCtrl',
|
||||
reloadOnSearch: false,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
module.controller('DashFromDBProvider', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv) {
|
||||
@@ -31,12 +37,23 @@ function (angular) {
|
||||
var isTemp = window.location.href.indexOf('dashboard/temp') !== -1;
|
||||
|
||||
db.getDashboard($routeParams.id, isTemp)
|
||||
.then(function(dashboard) {
|
||||
$scope.emitAppEvent('setup-dashboard', dashboard);
|
||||
}).then(null, function(error) {
|
||||
$scope.emitAppEvent('setup-dashboard', { title: 'Grafana'});
|
||||
alertSrv.set('Error', error, 'error');
|
||||
});
|
||||
.then(function(dashboard) {
|
||||
$scope.initDashboard(dashboard, $scope);
|
||||
}).then(null, function(error) {
|
||||
$scope.initDashboard({ title: 'Grafana'}, $scope);
|
||||
alertSrv.set('Error', error, 'error');
|
||||
});
|
||||
});
|
||||
|
||||
module.controller('DashFromImportCtrl', function($scope, $location, alertSrv) {
|
||||
|
||||
if (!window.grafanaImportDashboard) {
|
||||
alertSrv.set('Not found', 'Cannot reload page with unsaved imported dashboard', 'warning', 7000);
|
||||
$location.path('');
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.initDashboard(window.grafanaImportDashboard, $scope);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -52,7 +52,7 @@ function (angular, $, config, _) {
|
||||
};
|
||||
|
||||
file_load($routeParams.jsonFile).then(function(result) {
|
||||
$scope.emitAppEvent('setup-dashboard', result);
|
||||
$scope.initDashboard(result, $scope);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ function (angular, $, config, _, kbn, moment) {
|
||||
};
|
||||
|
||||
script_load($routeParams.jsFile).then(function(result) {
|
||||
$scope.emitAppEvent('setup-dashboard', result.data);
|
||||
$scope.initDashboard(result.data, $scope);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -13,7 +13,8 @@ define([
|
||||
var timezone;
|
||||
|
||||
this.init = function() {
|
||||
$rootScope.$on('refresh', this.clearCache);
|
||||
$rootScope.onAppEvent('refresh', this.clearCache);
|
||||
$rootScope.onAppEvent('setup-dashboard', this.clearCache);
|
||||
};
|
||||
|
||||
this.clearCache = function() {
|
||||
|
||||
@@ -94,6 +94,10 @@ function (angular, _, config, kbn, moment) {
|
||||
|
||||
for (var i = 0; i < fieldNames.length; i++) {
|
||||
fieldValue = fieldValue[fieldNames[i]];
|
||||
if (!fieldValue) {
|
||||
console.log('could not find field in annotatation: ', fieldName);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if (_.isArray(fieldValue)) {
|
||||
|
||||
@@ -203,7 +203,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
|
||||
else {
|
||||
var self = this;
|
||||
return this._influxRequest('POST', '/series', data).then(function() {
|
||||
self._removeUnslugifiedDashboard(title, false);
|
||||
self._removeUnslugifiedDashboard(id, title, false);
|
||||
return { title: title, url: '/dashboard/db/' + id };
|
||||
}, function(err) {
|
||||
throw 'Failed to save dashboard to InfluxDB: ' + err.data;
|
||||
@@ -211,7 +211,9 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
|
||||
}
|
||||
};
|
||||
|
||||
InfluxDatasource.prototype._removeUnslugifiedDashboard = function(id, isTemp) {
|
||||
InfluxDatasource.prototype._removeUnslugifiedDashboard = function(id, title, isTemp) {
|
||||
if (id === title) { return; }
|
||||
|
||||
var self = this;
|
||||
self._getDashboardInternal(id, isTemp).then(function(dashboard) {
|
||||
if (dashboard !== null) {
|
||||
|
||||
@@ -29,6 +29,7 @@ define([
|
||||
y_formats: [],
|
||||
seriesOverrides: []
|
||||
};
|
||||
scope.hiddenSeries = {};
|
||||
scope.dashboard = { timezone: 'browser' };
|
||||
scope.range = {
|
||||
from: new Date('2014-08-09 10:00:00'),
|
||||
@@ -145,6 +146,18 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
graphScenario('when series is hidden', function(ctx) {
|
||||
ctx.setup(function(scope) {
|
||||
scope.hiddenSeries = {'series2': true};
|
||||
});
|
||||
|
||||
it('should remove datapoints and disable stack', function() {
|
||||
expect(ctx.plotData[0].info.alias).to.be('series1');
|
||||
expect(ctx.plotData[1].data.length).to.be(0);
|
||||
expect(ctx.plotData[1].stack).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user