Added dashboard import feature
This commit is contained in:
@@ -15,6 +15,13 @@ function (angular) {
|
||||
access: 'proxy'
|
||||
};
|
||||
|
||||
$scope.types = [
|
||||
{ name: 'Graphite', type: 'graphite' },
|
||||
{ name: 'InfluxDB', type: 'influxdb' },
|
||||
{ name: 'Elasticsearch', type: 'elasticsearch' },
|
||||
{ name: 'OpenTSDB', type: 'opentsdb' },
|
||||
];
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.reset();
|
||||
$scope.editor = {index: 0};
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
define([
|
||||
'angular',
|
||||
'lodash',
|
||||
],
|
||||
function (angular, _) {
|
||||
'use strict';
|
||||
|
||||
var module = angular.module('grafana.controllers');
|
||||
|
||||
module.controller('ImportCtrl', function($scope, $http, backendSrv, datasourceSrv) {
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.datasources = [];
|
||||
$scope.sourceName = 'grafana';
|
||||
$scope.destName = 'grafana';
|
||||
$scope.imported = [];
|
||||
$scope.dashboards = [];
|
||||
$scope.infoText = '';
|
||||
$scope.importing = false;
|
||||
|
||||
_.each(datasourceSrv.getAll(), function(ds) {
|
||||
if (ds.type === 'influxdb' || ds.type === 'elasticsearch') {
|
||||
$scope.sourceName = ds.name;
|
||||
$scope.datasources.push(ds.name);
|
||||
} else if (ds.type === 'grafana') {
|
||||
$scope.datasources.push(ds.name);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.startImport = function() {
|
||||
$scope.sourceDs = datasourceSrv.get($scope.sourceName);
|
||||
$scope.destDs = datasourceSrv.get($scope.destName);
|
||||
|
||||
$scope.sourceDs.searchDashboards('title:').then(function(results) {
|
||||
$scope.dashboards = results.dashboards;
|
||||
|
||||
if ($scope.dashboards.length === 0) {
|
||||
$scope.infoText = 'No dashboards found';
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.importing = true;
|
||||
$scope.imported = [];
|
||||
$scope.next();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.next = function() {
|
||||
if ($scope.dashboards.length === 0) {
|
||||
$scope.infoText = "Done! Imported " + $scope.imported.length + " dashboards";
|
||||
}
|
||||
|
||||
var dash = $scope.dashboards.shift();
|
||||
if (!dash.title) {
|
||||
console.log(dash);
|
||||
return;
|
||||
}
|
||||
|
||||
var infoObj = {name: dash.title, info: 'Importing...'};
|
||||
$scope.imported.push(infoObj);
|
||||
$scope.infoText = "Importing " + $scope.imported.length + '/' + ($scope.imported.length + $scope.dashboards.length);
|
||||
|
||||
$scope.sourceDs.getDashboard(dash.id).then(function(loadedDash) {
|
||||
$scope.destDs.saveDashboard(loadedDash).then(function() {
|
||||
infoObj.info = "Done!";
|
||||
$scope.next();
|
||||
}, function(err) {
|
||||
infoObj.info = "Error: " + err;
|
||||
$scope.next();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$scope.init();
|
||||
|
||||
});
|
||||
});
|
||||
@@ -17,20 +17,20 @@
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 160px">
|
||||
<strong>Username or Email</strong>
|
||||
<strong>username or email</strong>
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" ng-model="collaborator.loginOrEmail" required class="input-xlarge tight-form-input" placeholder="collaborator@email.com">
|
||||
<input type="text" ng-model="collaborator.loginoremail" required class="input-xlarge tight-form-input" placeholder="collaborator@email.com">
|
||||
</li>
|
||||
<li class="tight-form-item">
|
||||
Role
|
||||
role
|
||||
</li>
|
||||
<li>
|
||||
<select type="text" ng-model="collaborator.role" class="input-small tight-form-input" ng-options="f for f in ['Viewer', 'Editor', 'Admin']">
|
||||
<select type="text" ng-model="collaborator.role" class="input-small tight-form-input" ng-options="f for f in ['viewer', 'editor', 'admin']">
|
||||
</select>
|
||||
</li>
|
||||
<li>
|
||||
<button class="btn btn-success tight-form-btn" ng-click="addCollaborator()">Add</button>
|
||||
<button class="btn btn-success tight-form-btn" ng-click="addcollaborator()">add</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</div>
|
||||
<div class="editor-option">
|
||||
<label class="small">Type</label>
|
||||
<select class="input-medium" ng-model="current.type" ng-options="f for f in ['graphite', 'influxdb', 'opentsdb']" ng-change="typeChanged()"></select>
|
||||
<select class="input-medium" ng-model="current.type" ng-options="f.type as f.name for f in types" ng-change="typeChanged()"></select>
|
||||
</div>
|
||||
<editor-opt-bool text="Mark as default" model="current.isDefault" change="render()"></editor-opt-bool>
|
||||
</div>
|
||||
@@ -103,6 +103,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="editor-row" ng-if="current.type === 'elasticsearch'">
|
||||
<div class="section">
|
||||
<h5>Elastic search details</h5>
|
||||
<div class="editor-option">
|
||||
<label class="small">Index name</label>
|
||||
<input type="text" class="input-large" required ng-model='current.database' placeholder=""></input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-editor-footer" style="margin-top: 20px">
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<div ng-include="'app/partials/navbar.html'" ng-init="pageTitle='Import'"></div>
|
||||
|
||||
<div class="dashboard-edit-view" style="min-height: 500px">
|
||||
|
||||
<div class="dashboard-editor-header">
|
||||
<div class="dashboard-editor-title">
|
||||
<i class="fa fa-th-large"></i>
|
||||
Import Dashboards
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-editor-body">
|
||||
|
||||
<div class="editor-row">
|
||||
<div class="section">
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="width: 160px">
|
||||
<strong>Dashboard source</strong>
|
||||
</li>
|
||||
<li>
|
||||
<select type="text" ng-model="sourceName" class="input-small tight-form-input" ng-options="f for f in datasources">
|
||||
</select>
|
||||
</li>
|
||||
<li class="tight-form-item" style="width: 160px">
|
||||
<strong>Destination</strong>
|
||||
</li>
|
||||
<li>
|
||||
<select type="text" ng-model="destName" class="input-small tight-form-input" ng-options="f for f in datasources">
|
||||
</select>
|
||||
</li>
|
||||
<li>
|
||||
<button class="btn btn-success tight-form-btn" ng-click="startImport()">Import</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="editor-row" ng-if="importing">
|
||||
<section class="section">
|
||||
<h5>{{infoText}}</h5>
|
||||
|
||||
<div class="editor-row row">
|
||||
<table class="grafana-options-table span5">
|
||||
<tr ng-repeat="dash in imported">
|
||||
<td>{{dash.name}}</td>
|
||||
<td>
|
||||
{{dash.info}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,37 +1,39 @@
|
||||
<div ng-include="'app/partials/navbar.html'" ng-init="pageTitle='Accounts'"></div>
|
||||
<div ng-include="'app/partials/navbar.html'" ng-init="pageTitle='Admin > Accounts'"></div>
|
||||
|
||||
<div class="dashboard-edit-view" style="min-height: 500px">
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span8">
|
||||
<div class="dashboard-editor-body">
|
||||
|
||||
<table class="grafana-options-table">
|
||||
<tr>
|
||||
<th style="text-align:left">Id</th>
|
||||
<th>Login</th>
|
||||
<th>Email</th>
|
||||
<th>Name</th>
|
||||
<th>Admin</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr ng-repeat="account in accounts">
|
||||
<td>{{account.id}}</td>
|
||||
<td>{{account.login}}</td>
|
||||
<td>{{account.email}}</td>
|
||||
<td>{{account.name}}</td>
|
||||
<td>{{account.isAdmin}}</td>
|
||||
<td style="width: 1%">
|
||||
<a ng-click="edit(variable)" class="btn btn-success">
|
||||
<i class="fa fa-edit"></i>
|
||||
Edit
|
||||
</a>
|
||||
|
||||
<a ng-click="edit(variable)" class="btn btn-danger">
|
||||
<i class="fa fa-remove"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="editor-row row">
|
||||
<div class="section span6">
|
||||
<table class="grafana-options-table">
|
||||
<tr>
|
||||
<th style="text-align:left">Id</th>
|
||||
<th>Login</th>
|
||||
<th>Email</th>
|
||||
<th>Name</th>
|
||||
<th>Admin</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr ng-repeat="account in accounts">
|
||||
<td>{{account.id}}</td>
|
||||
<td>{{account.login}}</td>
|
||||
<td>{{account.email}}</td>
|
||||
<td>{{account.name}}</td>
|
||||
<td>{{account.isAdmin}}</td>
|
||||
<td style="width: 1%">
|
||||
<a ng-click="edit(variable)" class="btn btn-success btn-small">
|
||||
<i class="fa fa-edit"></i>
|
||||
Edit
|
||||
</a>
|
||||
|
||||
<a ng-click="edit(variable)" class="btn btn-danger btn-small">
|
||||
<i class="fa fa-remove"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,7 @@ define([
|
||||
'./account/collaboratorsCtrl',
|
||||
'./account/datasourcesCtrl',
|
||||
'./account/apiKeysCtrl',
|
||||
'./account/importCtrl',
|
||||
'./admin/accountsCtrl',
|
||||
'./grafanaDatasource/datasource',
|
||||
], function () {});
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
{{annotation.name}}
|
||||
</td>
|
||||
<td style="width: 1%">
|
||||
<a ng-click="edit(annotation)" class="btn btn-success btn-mini">
|
||||
<a ng-click="edit(annotation)" class="btn btn-success btn-small">
|
||||
<i class="fa fa-edit"></i>
|
||||
Edit
|
||||
</a>
|
||||
@@ -34,7 +34,7 @@
|
||||
<td style="width: 1%"><i ng-click="_.move(annotations,$index,$index-1)" ng-hide="$first" class="pointer fa fa-arrow-up"></i></td>
|
||||
<td style="width: 1%"><i ng-click="_.move(annotations,$index,$index+1)" ng-hide="$last" class="pointer fa fa-arrow-down"></i></td>
|
||||
<td style="width: 1%">
|
||||
<a ng-click="removeAnnotation(annotation)" class="btn btn-danger btn-mini">
|
||||
<a ng-click="removeAnnotation(annotation)" class="btn btn-danger btn-small">
|
||||
<i class="fa fa-remove"></i>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -13,7 +13,7 @@ function (angular, _, config, kbn, moment) {
|
||||
module.factory('ElasticDatasource', function($q, $http, templateSrv) {
|
||||
|
||||
function ElasticDatasource(datasource) {
|
||||
this.type = 'elastic';
|
||||
this.type = 'elasticsearch';
|
||||
this.basicAuth = datasource.basicAuth;
|
||||
this.url = datasource.url;
|
||||
this.name = datasource.name;
|
||||
|
||||
@@ -15,7 +15,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
|
||||
module.factory('InfluxDatasource', function($q, $http, templateSrv) {
|
||||
|
||||
function InfluxDatasource(datasource) {
|
||||
this.type = 'influxDB';
|
||||
this.type = 'influxdb';
|
||||
this.urls = datasource.urls;
|
||||
this.username = datasource.username;
|
||||
this.password = datasource.password;
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
<a class="pro-sidemenu-link" href="account/apikeys">
|
||||
<i class="fa fa-key"></i>API Keys
|
||||
</a>
|
||||
<a class="pro-sidemenu-link" href="account/import">
|
||||
<i class="fa fa-download"></i>
|
||||
Import
|
||||
</a>
|
||||
<a class="pro-sidemenu-link" href="admin/accounts" ng-if="grafana.user.isGrafanaAdmin">
|
||||
<i class="fa fa-institution"></i>Admin
|
||||
</a>
|
||||
|
||||
@@ -42,6 +42,10 @@ define([
|
||||
templateUrl: 'app/features/account/partials/apikeys.html',
|
||||
controller : 'ApiKeysCtrl',
|
||||
})
|
||||
.when('/account/import', {
|
||||
templateUrl: 'app/features/account/partials/import.html',
|
||||
controller : 'ImportCtrl',
|
||||
})
|
||||
.when('/account', {
|
||||
templateUrl: 'app/features/account/partials/account.html',
|
||||
controller : 'AccountCtrl',
|
||||
|
||||
@@ -82,6 +82,10 @@ function (angular, _, config) {
|
||||
return this.default;
|
||||
};
|
||||
|
||||
this.getAll = function() {
|
||||
return datasources;
|
||||
};
|
||||
|
||||
this.getAnnotationSources = function() {
|
||||
return annotationSources;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user