Commit 6354b1ae by Torkel Ödegaard

Merge branch 'jordanrinke-master'

parents d6814587 512dbf19
...@@ -9,3 +9,4 @@ config.js ...@@ -9,3 +9,4 @@ config.js
# Editor junk # Editor junk
*.sublime-workspace *.sublime-workspace
*.swp *.swp
.idea/
...@@ -38,7 +38,9 @@ function (angular, _, moment, config) { ...@@ -38,7 +38,9 @@ function (angular, _, moment, config) {
}; };
$scope.saveForSharing = function() { $scope.saveForSharing = function() {
$scope.db.saveDashboardTemp($scope.dashboard) var clone = angular.copy($scope.dashboard);
clone.temp = true;
$scope.db.saveDashboard(clone)
.then(function(result) { .then(function(result) {
$scope.share = { url: result.url, title: result.title }; $scope.share = { url: result.url, title: result.title };
...@@ -71,7 +73,8 @@ function (angular, _, moment, config) { ...@@ -71,7 +73,8 @@ function (angular, _, moment, config) {
$scope.saveDashboard = function() { $scope.saveDashboard = function() {
if (!this.isAdmin()) { return false; } if (!this.isAdmin()) { return false; }
$scope.db.saveDashboard($scope.dashboard, $scope.dashboard.title) var clone = angular.copy($scope.dashboard);
$scope.db.saveDashboard(clone)
.then(function(result) { .then(function(result) {
alertSrv.set('Dashboard Saved', 'Dashboard has been saved as "' + result.title + '"','success', 5000); alertSrv.set('Dashboard Saved', 'Dashboard has been saved as "' + result.title + '"','success', 5000);
......
...@@ -130,28 +130,9 @@ function (angular, app, _) { ...@@ -130,28 +130,9 @@ function (angular, app, _) {
} }
}; };
/** @scratch /panels/0
* [[panels]]
* = Panels
*
* [partintro]
* --
* *grafana* dashboards are made up of blocks called +panels+. Panels are organized into rows
* and can serve many purposes, though most are designed to provide the results of a query or
* multiple queries as a visualization. Other panels may show collections of documents or
* allow you to insert instructions for your users.
*
* Panels can be configured easily via the grafana web interface. For more advanced usage, such
* as templated or scripted dashboards, documentation of panel properties is available in this
* section. You may find settings here which are not exposed via the web interface.
*
* Each panel type has its own properties, hover there are several that are shared.
*
*/
$scope.reset_panel = function(type) { $scope.reset_panel = function(type) {
var var
defaultSpan = 4, defaultSpan = 12,
_as = 12-$scope.rowSpan($scope.row); _as = 12-$scope.rowSpan($scope.row);
$scope.panel = { $scope.panel = {
...@@ -192,4 +173,4 @@ function (angular, app, _) { ...@@ -192,4 +173,4 @@ function (angular, app, _) {
}); });
}); });
\ No newline at end of file
...@@ -134,10 +134,5 @@ ...@@ -134,10 +134,5 @@
"now": true "now": true
} }
], ],
"loader": {
"save_temp": true,
"save_temp_ttl_enable": true,
"save_temp_ttl": "30d",
},
"refresh": false "refresh": false
} }
...@@ -65,10 +65,5 @@ ...@@ -65,10 +65,5 @@
"now": true "now": true
} }
], ],
"loader": {
"save_temp": true,
"save_temp_ttl_enable": true,
"save_temp_ttl": "30d",
},
"refresh": false "refresh": false
} }
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
<li> <li>
<a class="link" ng-click="exportDashboard()">Export dashboard</a> <a class="link" ng-click="exportDashboard()">Export dashboard</a>
</li> </li>
<li ng-show="dashboard.loader.save_temp"> <li ng-show="db.saveTemp">
<a bs-tooltip="'Share'" data-placement="bottom" ng-click="saveForSharing()" config-modal="app/partials/dashLoaderShare.html"> <a bs-tooltip="'Share'" data-placement="bottom" ng-click="saveForSharing()" config-modal="app/partials/dashLoaderShare.html">
Share temp copy Share temp copy
</a> </a>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="pull-right editor-title">Dashboard settings</div> <div class="pull-right editor-title">Dashboard settings</div>
<div ng-model="editor.index" bs-tabs style="text-transform:capitalize;"> <div ng-model="editor.index" bs-tabs style="text-transform:capitalize;">
<div ng-repeat="tab in ['General', 'Rows','Controls', 'Import']" data-title="{{tab}}"> <div ng-repeat="tab in ['General', 'Rows', 'Controls', 'Import']" data-title="{{tab}}">
</div> </div>
<div ng-repeat="tab in dashboard.nav" data-title="{{tab.type}}"> <div ng-repeat="tab in dashboard.nav" data-title="{{tab.type}}">
</div> </div>
...@@ -79,18 +79,6 @@ ...@@ -79,18 +79,6 @@
<label class="small" style="text-transform:capitalize;">{{pulldown.type}}</label><input type="checkbox" ng-model="pulldown.enable" ng-checked="pulldown.enable"> <label class="small" style="text-transform:capitalize;">{{pulldown.type}}</label><input type="checkbox" ng-model="pulldown.enable" ng-checked="pulldown.enable">
</div> </div>
</div> </div>
<div class="section">
<h5>Sharing</h5>
<div class="editor-option" >
<label class="small">Allow Sharing <tip>Allow generating adhoc links to dashboards</tip></label><input type="checkbox" ng-model="dashboard.loader.save_temp" ng-checked="dashboard.loader.save_temp">
</div>
<div class="editor-option" ng-show="dashboard.loader.save_temp">
<label class="small">TTL <tip>Expire temp urls</tip></label><input type="checkbox" ng-model="dashboard.loader.save_temp_ttl_enable">
</div>
<div class="editor-option" ng-show="dashboard.loader.save_temp &amp;&amp; dashboard.loader.save_temp_ttl_enable">
<label class="small">TTL Duration <tip>Elasticsearch date math, eg: 1m,1d,1w,30d </tip></label><input class="input-small" type="text" ng-model="dashboard.loader.save_temp_ttl">
</div>
</div>
</div> </div>
</div> </div>
......
...@@ -25,7 +25,9 @@ function (angular) { ...@@ -25,7 +25,9 @@ function (angular) {
module.controller('DashFromDBProvider', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv) { module.controller('DashFromDBProvider', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv) {
var db = datasourceSrv.getGrafanaDB(); var db = datasourceSrv.getGrafanaDB();
db.getDashboard($routeParams.id) var isTemp = window.location.href.indexOf('dashboard/temp') !== -1;
db.getDashboard($routeParams.id, isTemp)
.then(function(dashboard) { .then(function(dashboard) {
$scope.emitAppEvent('setup-dashboard', dashboard); $scope.emitAppEvent('setup-dashboard', dashboard);
}).then(null, function(error) { }).then(null, function(error) {
......
...@@ -26,13 +26,6 @@ function (angular, $, kbn, _) { ...@@ -26,13 +26,6 @@ function (angular, $, kbn, _) {
this.pulldowns = data.pulldowns || []; this.pulldowns = data.pulldowns || [];
this.nav = data.nav || []; this.nav = data.nav || [];
this.services = data.services || {}; this.services = data.services || {};
this.loader = data.loader || {};
_.defaults(this.loader, {
save_temp: true,
save_temp_ttl_enable: true,
save_temp_ttl: '30d',
});
if (this.nav.length === 0) { if (this.nav.length === 0) {
this.nav.push({ type: 'timepicker' }); this.nav.push({ type: 'timepicker' });
......
...@@ -18,12 +18,16 @@ function (angular, _, $, config, kbn, moment) { ...@@ -18,12 +18,16 @@ function (angular, _, $, config, kbn, moment) {
this.basicAuth = datasource.basicAuth; this.basicAuth = datasource.basicAuth;
this.url = datasource.url; this.url = datasource.url;
this.name = datasource.name; this.name = datasource.name;
this.supportAnnotations = true;
this.supportMetrics = false;
this.index = datasource.index; this.index = datasource.index;
this.grafanaDB = datasource.grafanaDB; this.grafanaDB = datasource.grafanaDB;
this.annotationEditorSrc = 'app/partials/elasticsearch/annotation_editor.html';
this.searchMaxResults = config.search.max_results || 20; this.searchMaxResults = config.search.max_results || 20;
this.saveTemp = _.isUndefined(datasource.save_temp) ? true : datasource.save_temp;
this.saveTempTTL = _.isUndefined(datasource.save_temp_ttl) ? '30d' : datasource.save_temp_ttl;
this.annotationEditorSrc = 'app/partials/elasticsearch/annotation_editor.html';
this.supportAnnotations = true;
this.supportMetrics = false;
} }
ElasticDatasource.prototype._request = function(method, url, index, data) { ElasticDatasource.prototype._request = function(method, url, index, data) {
...@@ -103,11 +107,10 @@ function (angular, _, $, config, kbn, moment) { ...@@ -103,11 +107,10 @@ function (angular, _, $, config, kbn, moment) {
}); });
}; };
ElasticDatasource.prototype.getDashboard = function(id) { ElasticDatasource.prototype.getDashboard = function(id, isTemp) {
var url = '/dashboard/' + id; var url = '/dashboard/' + id;
// hack to check if it is a temp dashboard if (isTemp) {
if (window.location.href.indexOf('dashboard/temp') > 0) {
url = '/temp/' + id; url = '/temp/' + id;
} }
...@@ -127,44 +130,40 @@ function (angular, _, $, config, kbn, moment) { ...@@ -127,44 +130,40 @@ function (angular, _, $, config, kbn, moment) {
}); });
}; };
ElasticDatasource.prototype.saveDashboard = function(dashboard, title) { ElasticDatasource.prototype.saveDashboard = function(dashboard) {
var dashboardClone = angular.copy(dashboard); var title = dashboard.title;
title = dashboardClone.title = title ? title : dashboard.title; var temp = dashboard.temp;
if (temp) { delete dashboard.temp; }
var data = { var data = {
user: 'guest', user: 'guest',
group: 'guest', group: 'guest',
title: title, title: title,
tags: dashboardClone.tags,
dashboard: angular.toJson(dashboardClone)
};
return this._request('PUT', '/dashboard/' + encodeURIComponent(title), this.index, data)
.then(function() {
return { title: title, url: '/dashboard/db/' + title };
}, function(err) {
throw 'Failed to save to elasticsearch ' + err.data;
});
};
ElasticDatasource.prototype.saveDashboardTemp = function(dashboard) {
var data = {
user: 'guest',
group: 'guest',
title: dashboard.title,
tags: dashboard.tags, tags: dashboard.tags,
dashboard: angular.toJson(dashboard) dashboard: angular.toJson(dashboard)
}; };
var ttl = dashboard.loader.save_temp_ttl; if (temp) {
return this._saveTempDashboard(data);
}
else {
return this._request('PUT', '/dashboard/' + encodeURIComponent(title), this.index, data)
.then(function() {
return { title: title, url: '/dashboard/db/' + title };
}, function(err) {
throw 'Failed to save to elasticsearch ' + err.data;
});
}
};
return this._request('POST', '/temp/?ttl=' + ttl, this.index, data) ElasticDatasource.prototype._saveTempDashboard = function(data) {
return this._request('POST', '/temp/?ttl=' + this.saveTempTTL, this.index, data)
.then(function(result) { .then(function(result) {
var baseUrl = window.location.href.replace(window.location.hash,''); var baseUrl = window.location.href.replace(window.location.hash,'');
var url = baseUrl + "#dashboard/temp/" + result.data._id; var url = baseUrl + "#dashboard/temp/" + result.data._id;
return { title: dashboard.title, url: url }; return { title: data.title, url: url };
}, function(err) { }, function(err) {
throw "Failed to save to temp dashboard to elasticsearch " + err.data; throw "Failed to save to temp dashboard to elasticsearch " + err.data;
......
...@@ -22,6 +22,9 @@ function (angular, _, kbn, InfluxSeries) { ...@@ -22,6 +22,9 @@ function (angular, _, kbn, InfluxSeries) {
interpolate : /\[\[([\s\S]+?)\]\]/g, interpolate : /\[\[([\s\S]+?)\]\]/g,
}; };
this.saveTemp = _.isUndefined(datasource.save_temp) ? true : datasource.save_temp;
this.saveTempTTL = _.isUndefined(datasource.save_temp_ttl) ? '30d' : datasource.save_temp_ttl;
this.grafanaDB = datasource.grafanaDB; this.grafanaDB = datasource.grafanaDB;
this.supportAnnotations = true; this.supportAnnotations = true;
this.supportMetrics = true; this.supportMetrics = true;
...@@ -231,31 +234,79 @@ function (angular, _, kbn, InfluxSeries) { ...@@ -231,31 +234,79 @@ function (angular, _, kbn, InfluxSeries) {
return deferred.promise; return deferred.promise;
}; };
InfluxDatasource.prototype.saveDashboard = function(dashboard, title) { InfluxDatasource.prototype.saveDashboard = function(dashboard) {
var dashboardClone = angular.copy(dashboard); var tags = dashboard.tags.join(',');
var tags = dashboardClone.tags.join(','); var title = dashboard.title;
title = dashboardClone.title = title ? title : dashboard.title; var temp = dashboard.temp;
if (temp) { delete dashboard.temp; }
var data = [{ var data = [{
name: 'grafana.dashboard_' + btoa(title), name: 'grafana.dashboard_' + btoa(title),
columns: ['time', 'sequence_number', 'title', 'tags', 'dashboard'], columns: ['time', 'sequence_number', 'title', 'tags', 'dashboard'],
points: [[1, 1, title, tags, angular.toJson(dashboardClone)]] points: [[1000000000000, 1, title, tags, angular.toJson(dashboard)]]
}]; }];
if (temp) {
return this._saveDashboardTemp(data, title);
}
else {
return this._influxRequest('POST', '/series', data).then(function() {
return { title: title, url: '/dashboard/db/' + title };
}, function(err) {
throw 'Failed to save dashboard to InfluxDB: ' + err.data;
});
}
};
InfluxDatasource.prototype._saveDashboardTemp = function(data, title) {
data[0].name = 'grafana.dashboard_temp_' + btoa(title);
data[0].columns.push('expires');
data[0].points[0].push(this._getTempDashboardExpiresDate());
return this._influxRequest('POST', '/series', data).then(function() { return this._influxRequest('POST', '/series', data).then(function() {
return { title: title, url: '/dashboard/db/' + title }; var baseUrl = window.location.href.replace(window.location.hash,'');
var url = baseUrl + "#dashboard/temp/" + title;
return { title: title, url: url };
}, function(err) { }, function(err) {
throw 'Failed to save dashboard to InfluxDB: ' + err.data; throw 'Failed to save shared dashboard to InfluxDB: ' + err.data;
}); });
}; };
InfluxDatasource.prototype.getDashboard = function(id) { InfluxDatasource.prototype._getTempDashboardExpiresDate = function() {
return this._seriesQuery('select dashboard from "grafana.dashboard_' + btoa(id) + '"').then(function(results) { var ttlLength = this.saveTempTTL.substring(0, this.saveTempTTL.length - 1);
var ttlTerm = this.saveTempTTL.substring(this.saveTempTTL.length - 1, this.saveTempTTL.length).toLowerCase();
var expires = Date.now();
switch(ttlTerm) {
case "m":
expires += ttlLength * 60000;
break;
case "d":
expires += ttlLength * 86400000;
break;
case "w":
expires += ttlLength * 604800000;
break;
default:
throw "Unknown ttl duration format";
}
return expires;
};
InfluxDatasource.prototype.getDashboard = function(id, isTemp) {
var queryString = 'select dashboard from "grafana.dashboard_' + btoa(id) + '"';
if (isTemp) {
queryString = 'select dashboard from "grafana.dashboard_temp_' + btoa(id) + '"';
}
return this._seriesQuery(queryString).then(function(results) {
if (!results || !results.length) { if (!results || !results.length) {
throw "Dashboard not found"; throw "Dashboard not found";
} }
var dashCol = _.indexOf(results[0].columns, 'dashboard'); var dashCol = _.indexOf(results[0].columns, 'dashboard');
var dashJson = results[0].points[0][dashCol]; var dashJson = results[0].points[0][dashCol];
return angular.fromJson(dashJson); return angular.fromJson(dashJson);
}, function(err) { }, function(err) {
return "Could not load dashboard, " + err.data; return "Could not load dashboard, " + err.data;
......
...@@ -24,20 +24,6 @@ define([], ...@@ -24,20 +24,6 @@ define([],
list: [] list: []
} }
}, },
loader: {
save_gist: false,
save_elasticsearch: true,
save_local: true,
save_default: true,
save_temp: true,
save_temp_ttl_enable: true,
save_temp_ttl: '30d',
load_gist: false,
load_elasticsearch: true,
load_elasticsearch_size: 20,
load_local: false,
hide: false
},
refresh: true refresh: true
}; };
} }
......
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