Commit f6c07fda by Torkel Ödegaard

Rewrote and redesign how the data source edit views look and work so they…

Rewrote and redesign how the data source edit views look and work so they conform better to how account views look, removed tabs and put top nav items to add data source etc, made list, edit and new seperate url routes, #1483
parent ed0fabd9
......@@ -75,6 +75,7 @@ func Register(r *macaron.Macaron) {
r.Group("/datasources", func() {
r.Combo("/").Get(GetDataSources).Put(AddDataSource).Post(UpdateDataSource)
r.Delete("/:id", DeleteDataSource)
r.Get("/:id", GetDataSourceById)
}, reqAccountAdmin)
r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest)
......
......@@ -9,9 +9,8 @@ import (
func GetDataSources(c *middleware.Context) {
query := m.GetDataSourcesQuery{AccountId: c.AccountId}
err := bus.Dispatch(&query)
if err != nil {
if err := bus.Dispatch(&query); err != nil {
c.JsonApiErr(500, "Failed to query datasources", err)
return
}
......@@ -36,6 +35,34 @@ func GetDataSources(c *middleware.Context) {
c.JSON(200, result)
}
func GetDataSourceById(c *middleware.Context) {
query := m.GetDataSourceByIdQuery{
Id: c.ParamsInt64(":id"),
AccountId: c.AccountId,
}
if err := bus.Dispatch(&query); err != nil {
c.JsonApiErr(500, "Failed to query datasources", err)
return
}
ds := query.Result
c.JSON(200, &dtos.DataSource{
Id: ds.Id,
AccountId: ds.AccountId,
Name: ds.Name,
Url: ds.Url,
Type: ds.Type,
Access: ds.Access,
Password: ds.Password,
Database: ds.Database,
User: ds.User,
BasicAuth: ds.BasicAuth,
IsDefault: ds.IsDefault,
})
}
func DeleteDataSource(c *middleware.Context) {
id := c.ParamsInt64(":id")
......
......@@ -37,7 +37,7 @@ function (angular, _, $, config) {
if (contextSrv.user.isGrafanaAdmin) {
$scope.menu.push({
text: "Admin", href: $scope.getUrl("/admin/users"),
text: "Admin", href: $scope.getUrl("/admin/settings"),
icon: "fa fa-cube",
requireSignedIn: true,
});
......
define([
'./accountUsersCtrl',
'./datasourcesCtrl',
'./datasourceEditCtrl',
'./apiKeysCtrl',
'./importCtrl',
'./accountCtrl',
......
define([
'angular',
'lodash',
],
function (angular) {
'use strict';
var module = angular.module('grafana.controllers');
module.controller('DataSourceEditCtrl', function($scope, $http, backendSrv, $routeParams, $location) {
var defaults = {
name: '',
type: 'graphite',
url: '',
access: 'proxy'
};
$scope.types = [
{ name: 'Graphite', type: 'graphite' },
{ name: 'InfluxDB', type: 'influxdb' },
{ name: 'Elasticsearch', type: 'elasticsearch' },
{ name: 'OpenTSDB', type: 'opentsdb' },
];
$scope.init = function() {
$scope.isNew = true;
$scope.datasources = [];
if ($routeParams.id) {
$scope.isNew = false;
$scope.getDatasourceById($routeParams.id);
} else {
$scope.current = angular.copy(defaults);
}
};
$scope.getDatasourceById = function(id) {
backendSrv.get('/api/datasources/' + id).then(function(ds) {
$scope.current = ds;
});
};
$scope.update = function() {
if (!$scope.editForm.$valid) {
return;
}
backendSrv.post('/api/datasources', $scope.current).then(function() {
$location.path("account/datasources");
});
};
$scope.add = function() {
if (!$scope.editForm.$valid) {
return;
}
backendSrv.put('/api/datasources', $scope.current)
.then(function() {
$scope.editor.index = 0;
$scope.getDatasources();
});
};
$scope.init();
});
});
define([
'angular',
'lodash',
],
function (angular) {
'use strict';
......@@ -8,47 +9,9 @@ function (angular) {
module.controller('DataSourcesCtrl', function($scope, $http, backendSrv) {
var defaults = {
name: '',
type: 'graphite',
url: '',
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};
$scope.datasources = [];
$scope.getDatasources();
$scope.$watch('editor.index', function(newVal) {
if (newVal !== 2) {
$scope.reset();
}
});
};
$scope.reset = function() {
$scope.current = angular.copy(defaults);
$scope.currentIsNew = true;
};
$scope.edit = function(ds) {
$scope.current = ds;
$scope.currentIsNew = false;
$scope.editor.index = 2;
};
$scope.cancel = function() {
$scope.reset();
$scope.editor.index = 0;
};
$scope.getDatasources = function() {
......@@ -63,25 +26,6 @@ function (angular) {
});
};
$scope.update = function() {
backendSrv.post('/api/datasources', $scope.current).then(function() {
$scope.editor.index = 0;
$scope.getDatasources();
});
};
$scope.add = function() {
if (!$scope.editForm.$valid) {
return;
}
backendSrv.put('/api/datasources', $scope.current)
.then(function() {
$scope.editor.index = 0;
$scope.getDatasources();
});
};
$scope.init();
});
......
<topnav title="Data sources" icon="fa fa-database" subnav="true">
<ul class="nav">
<li><a href="account/datasources">Overview</a></li>
<li ng-class="{active: isNew}"><a href="account/datasources/new">Add new</a></li>
<li class="active" ng-show="!isNew"><a href="account/datasources/edit/{{current.name}}">Edit</a></li>
</ul>
</topnav>
<div class="page-container">
<div class="page">
<h2 ng-show="isNew">Add data source</h2>
<h2 ng-show="!isNew">Edit {{current.name}}</h2>
<form name="editForm">
<div class="editor-row">
<div class="editor-option">
<label class="small">Data source name</label>
<input type="text" class="input-large" ng-model='current.name' placeholder="production" required></input>
</div>
<div class="editor-option">
<label class="small">Type</label>
<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>
<div class="editor-row">
<div class="editor-option">
<label class="small">Url</label>
<input type="text" class="input-xxlarge" ng-model='current.url' placeholder="http://my.graphite.com:8080" required></input>
</div>
<div class="editor-option">
<label class="small">Access method <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</label>
<select class="input-medium" ng-model="current.access" ng-options="f for f in ['direct', 'proxy']"></select>
</div>
</div>
<div class="editor-row" ng-if="current.type === 'influxdb'">
<div class="section">
<h5>InfluxDB Details</h5>
<div class="editor-option">
<label class="small">Database name</label>
<input type="text" class="input-large" required ng-model='current.database' placeholder=""></input>
</div>
<div class="editor-option">
<label class="small">User</label>
<input type="text" class="input-large" ng-model='current.user' placeholder=""></input>
</div>
<div class="editor-option">
<label class="small">Password</label>
<input type="password" class="input-large" ng-model='current.password' placeholder=""></input>
</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>
<br>
<button type="submit" class="btn btn-success" ng-show="isNew" ng-click="add()">Add</button>
<button type="submit" class="btn btn-success" ng-show="!isNew" ng-click="update()">Update</button>
<a class="btn btn-inverse" ng-show="!isNew" href="account/datasources">Cancel</a>
<br>
</form>
</div>
</div>
<topnav title="Data sources"
icon="fa fa-database">
<topnav title="Data sources" icon="fa fa-database" subnav="true">
<ul class="nav">
<li class="active" ><a href="account/datasources">Overview</a></li>
<li><a href="account/datasources/new">Add new</a></li>
</ul>
</topnav>
<div class="gf-box" style="min-height: 500px; max-width: 900px">
<div class="gf-box-header">
<div ng-model="editor.index" bs-tabs style="text-transform:capitalize;">
<div ng-repeat="tab in ['Overview', 'Add', 'Edit']" data-title="{{tab}}">
</div>
</div>
</div>
<form name="editForm">
<div class="gf-box-body">
<div class="editor-row row" ng-if="editor.index == 0">
<div class="span8">
<div ng-if="datasources.length === 0">
<em>No datasources defined</em>
</div>
<table class="grafana-options-table" ng-if="datasources.length > 0">
<tr>
<td><strong>Name</strong></td>
<td><strong>Url</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="ds in datasources">
<td style="width:1%">
<i class="fa fa-database"></i> &nbsp;
{{ds.name}}
</td>
<td style="width:90%">
{{ds.url}}
</td>
<td style="width:2%" class="text-center">
<span ng-if="ds.isDefault">
<span class="label label-info">default</span>
</span>
</td>
<td style="width: 1%">
<a ng-click="edit(ds)" class="btn btn-success btn-mini">
<i class="fa fa-edit"></i>
Edit
</a>
</td>
<td style="width: 1%">
<a ng-click="remove(ds)" class="btn btn-danger btn-mini">
<i class="fa fa-remove"></i>
</a>
</td>
</tr>
</table>
</div>
</div>
<div class="page-container">
<div class="page">
<h2>Data sources</h2>
<div ng-if="editor.index == 1 || (editor.index == 2 && !currentIsNew)">
<div class="editor-row">
<div class="editor-option">
<label class="small">Data source name</label>
<input type="text" class="input-large" ng-model='current.name' placeholder="production" required></input>
</div>
<div class="editor-option">
<label class="small">Type</label>
<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>
<div class="editor-row">
<div class="editor-option">
<label class="small">Url</label>
<input type="text" class="input-xxlarge" ng-model='current.url' placeholder="http://my.graphite.com:8080" required></input>
</div>
<div class="editor-option">
<label class="small">Access method <tip>Direct = url is used directly from browser, Proxy = Grafana backend will proxy the request</label>
<select class="input-medium" ng-model="current.access" ng-options="f for f in ['direct', 'proxy']"></select>
</div>
</div>
<div ng-if="datasources.length === 0">
<em>No datasources defined</em>
</div>
<div class="editor-row" ng-if="current.type === 'influxdb'">
<div class="section">
<h5>InfluxDB Details</h5>
<div class="editor-option">
<label class="small">Database name</label>
<input type="text" class="input-large" required ng-model='current.database' placeholder=""></input>
</div>
<div class="editor-option">
<label class="small">User</label>
<input type="text" class="input-large" ng-model='current.user' placeholder=""></input>
</div>
<div class="editor-option">
<label class="small">Password</label>
<input type="password" class="input-large" ng-model='current.password' placeholder=""></input>
</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>
<table class="grafana-options-table" ng-if="datasources.length > 0">
<tr>
<td><strong>Name</strong></td>
<td><strong>Url</strong></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="ds in datasources">
<td style="width:1%">
<i class="fa fa-database"></i> &nbsp;
{{ds.name}}
</td>
<td style="width:90%">
{{ds.url}}
</td>
<td style="width:2%" class="text-center">
<span ng-if="ds.isDefault">
<span class="label label-info">default</span>
</span>
</td>
<td style="width: 1%">
<a href="account/datasources/edit/{{ds.id}}" class="btn btn-inverse btn-mini">
<i class="fa fa-edit"></i>
Edit
</a>
</td>
<td style="width: 1%">
<a ng-click="remove(ds)" class="btn btn-danger btn-mini">
<i class="fa fa-remove"></i>
</a>
</td>
</tr>
</table>
<br>
<button type="submit" class="btn btn-success" ng-show="editor.index === 1" ng-click="add()">Add</button>
<button type="submit" class="btn btn-success" ng-show="editor.index === 2 && !currentIsNew" ng-click="update()">Update</button>
<button type="submit" class="btn btn-inverse" ng-show="editor.index === 2 && !currentIsNew" ng-click="cancel()">Cancel</button>
<br>
</form>
</div>
</div>
......@@ -38,6 +38,14 @@ define([
templateUrl: 'app/features/account/partials/datasources.html',
controller : 'DataSourcesCtrl',
})
.when('/account/datasources/edit/:id', {
templateUrl: 'app/features/account/partials/datasourceEdit.html',
controller : 'DataSourceEditCtrl',
})
.when('/account/datasources/new', {
templateUrl: 'app/features/account/partials/datasourceEdit.html',
controller : 'DataSourceEditCtrl',
})
.when('/account/users', {
templateUrl: 'app/features/account/partials/users.html',
controller : 'AccountUsersCtrl',
......
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