Commit 6354b1ae by Torkel Ödegaard

Merge branch 'jordanrinke-master'

parents d6814587 512dbf19
......@@ -9,3 +9,4 @@ config.js
# Editor junk
*.sublime-workspace
*.swp
.idea/
......@@ -38,7 +38,9 @@ function (angular, _, moment, config) {
};
$scope.saveForSharing = function() {
$scope.db.saveDashboardTemp($scope.dashboard)
var clone = angular.copy($scope.dashboard);
clone.temp = true;
$scope.db.saveDashboard(clone)
.then(function(result) {
$scope.share = { url: result.url, title: result.title };
......@@ -71,7 +73,8 @@ function (angular, _, moment, config) {
$scope.saveDashboard = function() {
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) {
alertSrv.set('Dashboard Saved', 'Dashboard has been saved as "' + result.title + '"','success', 5000);
......
......@@ -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) {
var
defaultSpan = 4,
defaultSpan = 12,
_as = 12-$scope.rowSpan($scope.row);
$scope.panel = {
......@@ -192,4 +173,4 @@ function (angular, app, _) {
});
});
\ No newline at end of file
});
......@@ -134,10 +134,5 @@
"now": true
}
],
"loader": {
"save_temp": true,
"save_temp_ttl_enable": true,
"save_temp_ttl": "30d",
},
"refresh": false
}
......@@ -65,10 +65,5 @@
"now": true
}
],
"loader": {
"save_temp": true,
"save_temp_ttl_enable": true,
"save_temp_ttl": "30d",
},
"refresh": false
}
......@@ -47,7 +47,7 @@
<li>
<a class="link" ng-click="exportDashboard()">Export dashboard</a>
</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">
Share temp copy
</a>
......
......@@ -2,7 +2,7 @@
<div class="pull-right editor-title">Dashboard settings</div>
<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 ng-repeat="tab in dashboard.nav" data-title="{{tab.type}}">
</div>
......@@ -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">
</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>
......
......@@ -25,7 +25,9 @@ function (angular) {
module.controller('DashFromDBProvider', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv) {
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) {
$scope.emitAppEvent('setup-dashboard', dashboard);
}).then(null, function(error) {
......
......@@ -26,13 +26,6 @@ function (angular, $, kbn, _) {
this.pulldowns = data.pulldowns || [];
this.nav = data.nav || [];
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) {
this.nav.push({ type: 'timepicker' });
......
......@@ -18,12 +18,16 @@ function (angular, _, $, config, kbn, moment) {
this.basicAuth = datasource.basicAuth;
this.url = datasource.url;
this.name = datasource.name;
this.supportAnnotations = true;
this.supportMetrics = false;
this.index = datasource.index;
this.grafanaDB = datasource.grafanaDB;
this.annotationEditorSrc = 'app/partials/elasticsearch/annotation_editor.html';
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) {
......@@ -103,11 +107,10 @@ function (angular, _, $, config, kbn, moment) {
});
};
ElasticDatasource.prototype.getDashboard = function(id) {
ElasticDatasource.prototype.getDashboard = function(id, isTemp) {
var url = '/dashboard/' + id;
// hack to check if it is a temp dashboard
if (window.location.href.indexOf('dashboard/temp') > 0) {
if (isTemp) {
url = '/temp/' + id;
}
......@@ -127,44 +130,40 @@ function (angular, _, $, config, kbn, moment) {
});
};
ElasticDatasource.prototype.saveDashboard = function(dashboard, title) {
var dashboardClone = angular.copy(dashboard);
title = dashboardClone.title = title ? title : dashboard.title;
ElasticDatasource.prototype.saveDashboard = function(dashboard) {
var title = dashboard.title;
var temp = dashboard.temp;
if (temp) { delete dashboard.temp; }
var data = {
user: 'guest',
group: 'guest',
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,
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) {
var baseUrl = window.location.href.replace(window.location.hash,'');
var url = baseUrl + "#dashboard/temp/" + result.data._id;
return { title: dashboard.title, url: url };
return { title: data.title, url: url };
}, function(err) {
throw "Failed to save to temp dashboard to elasticsearch " + err.data;
......
......@@ -22,6 +22,9 @@ function (angular, _, kbn, InfluxSeries) {
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.supportAnnotations = true;
this.supportMetrics = true;
......@@ -231,31 +234,79 @@ function (angular, _, kbn, InfluxSeries) {
return deferred.promise;
};
InfluxDatasource.prototype.saveDashboard = function(dashboard, title) {
var dashboardClone = angular.copy(dashboard);
var tags = dashboardClone.tags.join(',');
title = dashboardClone.title = title ? title : dashboard.title;
InfluxDatasource.prototype.saveDashboard = function(dashboard) {
var tags = dashboard.tags.join(',');
var title = dashboard.title;
var temp = dashboard.temp;
if (temp) { delete dashboard.temp; }
var data = [{
name: 'grafana.dashboard_' + btoa(title),
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 { 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) {
throw 'Failed to save dashboard to InfluxDB: ' + err.data;
throw 'Failed to save shared dashboard to InfluxDB: ' + err.data;
});
};
InfluxDatasource.prototype.getDashboard = function(id) {
return this._seriesQuery('select dashboard from "grafana.dashboard_' + btoa(id) + '"').then(function(results) {
InfluxDatasource.prototype._getTempDashboardExpiresDate = function() {
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) {
throw "Dashboard not found";
}
var dashCol = _.indexOf(results[0].columns, 'dashboard');
var dashJson = results[0].points[0][dashCol];
return angular.fromJson(dashJson);
}, function(err) {
return "Could not load dashboard, " + err.data;
......
......@@ -24,20 +24,6 @@ define([],
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
};
}
......
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