Skip to content

Commit

Permalink
[admin] Minor UI Improvements
Browse files Browse the repository at this point in the history
  * Also added support for loading more scheduler logs
  * Added multiple empty-state messages
  * Added filtering capabilities to multiple interfaces
  • Loading branch information
jcarvalho committed Jul 13, 2015
1 parent 6acd5ba commit 665475b
Show file tree
Hide file tree
Showing 13 changed files with 311 additions and 204 deletions.
88 changes: 51 additions & 37 deletions bennu-admin/src/main/webapp/bennu-admin/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ app.config(['$stateProvider', '$urlRouterProvider',

$urlRouterProvider.otherwise("/monitoring/metrics");
$urlRouterProvider.when("/monitoring", "/monitoring/metrics");
$urlRouterProvider.when("/scheduler", "/scheduler/tasks");
$urlRouterProvider.when("/scheduler", "/scheduler/logs/");

// IO
$stateProvider.
Expand Down Expand Up @@ -150,6 +150,12 @@ app.filter('capitalize', function() {
}
});

app.filter('filename', function () {
return function(fullPath) {
return (fullPath || '').split('\\').pop().split('/').pop();
}
});

// Utility methods

function chunk(arr, n) {
Expand Down Expand Up @@ -596,8 +602,41 @@ app.controller('GroupsController', ['$scope', '$http', function($scope, $http) {

// Scheduler

app.controller('SchedulerController', ['$scope', function ($scope) {
$scope.$root.pageTitle = 'Scheduler';
app.controller('SchedulerController', ['$scope', '$http', '$timeout', function ($scope, $http, $timeout) {
$scope.$root.pageTitle = undefined;
$scope.contextPath = Bennu.contextPath;
$http.get(contextPath + '/api/bennu-scheduler/config').success(function (data) {
$scope.config = data;
});
$scope.saveStore = function() {
$http.put(contextPath + '/api/bennu-scheduler/config/' + $scope.config.loggingStorage.id).success(function (data) {
$scope.config = data; $scope.storeSuccess = true;
$timeout(function () {
$scope.storeSuccess = false;
}, 2000);
});
};
$scope.clear = function() {
if(confirm('Are you sure you wish to clear all schedules?')) {
$http['delete'](contextPath + '/api/bennu-scheduler/schedule').success(function () {
location.reload();
});
}
};
$scope.load = function() {
$("#input-load-dump-file").on('change', function (e) {
e.preventDefault();
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function() {
$http.post(contextPath + '/api/bennu-scheduler/schedule/load-dump', reader.result).success(function (data) {
location.reload();
});
};
reader.readAsText(file);
});
$("#input-load-dump-file").click();
};
}]);

app.controller('TasksController', ['$scope', '$http', '$state', '$timeout', function ($scope, $http, $state, $timeout) {
Expand All @@ -623,52 +662,27 @@ app.controller('SchedulesController', ['$scope', '$http', function ($scope, $htt
$http.get(contextPath + '/api/bennu-scheduler/schedule').success(function (data) {
$scope.schedules = data.schedule;
});
$http.get(contextPath + '/api/bennu-scheduler/config').success(function (data) {
$scope.config = data;
});
$scope.contextPath = window.contextPath;
$scope.saveStore = function() {
$scope.saving = true;
$http.put(contextPath + '/api/bennu-scheduler/config/' + $scope.config.loggingStorage.id).success(function (data) {
$scope.config = data; $scope.saving = false;
});
}
$scope['delete'] = function(schedule) {
$http['delete'](contextPath + '/api/bennu-scheduler/schedule/' + schedule.id).success(function () {
$scope.schedules.splice($scope.schedules.indexOf(schedule), 1);
});
}
$scope.clear = function() {
if(confirm('Are you sure you wish to clear all schedules?')) {
$http['delete'](contextPath + '/api/bennu-scheduler/schedule').success(function () {
$scope.schedules = new Array();
});
}
}
$scope.load = function() {
$("#input-load-dump-file").on('change', function (e) {
e.preventDefault();
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function() {
$http.post(contextPath + '/api/bennu-scheduler/schedule/load-dump', reader.result).success(function (data) {
$scope.schedules = data.schedule;
});
};
reader.readAsText(file);
});
$("#input-load-dump-file").click();
}
}]);

app.controller('LogsController', ['$scope', '$http', '$state', function ($scope, $http, $state) {
$scope.type = $state.params.type;
$scope.type = $state.params.type; $scope.numResults = 20;
var url = $state.params.type ? contextPath + '/api/bennu-scheduler/log/' + $scope.type : contextPath + '/api/bennu-scheduler/log/';
$scope.reload = function () {
$http.get(url).success(function (data) {
$scope.logs = data;
$http.get(url + '?count=' + $scope.numResults).success(function (data) {
$scope.logs = data; $scope.moreResults = data.length == $scope.numResults;
});
}
$scope.loadMore = function() {
$http.get(url + '?count=' + ($scope.numResults + 1) + '&start=' + $scope.logs[$scope.logs.length -1].id).success(function(data) {
data.shift();
$scope.logs = $scope.logs.concat(data); $scope.moreResults = data.length == $scope.numResults;
});
};
$scope.reload();
}]);

Expand Down
38 changes: 23 additions & 15 deletions bennu-admin/src/main/webapp/bennu-admin/template/IO.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@
Loading...
</div>

<p>
<button class="btn btn-primary" data-toggle="modal" data-target="#newStorageModal"><span class="glyphicon glyphicon-plus"></span> New</button>
</p>
<table class="table table-condensed table-striped" ng-if="storages">
<div class="row">
<div class="col-sm-6">
<button class="btn btn-primary" data-toggle="modal" data-target="#newStorageModal"><span class="glyphicon glyphicon-plus"></span> New</button>
</div>
<div class="col-sm-offset-3 col-sm-3">
<input type="text" class="form-control" ng-model="filter" placeholder="Filter...">
</div>
</div>
<table class="table table-striped" ng-if="storages">
<thead>
<tr>
<th>Name</th>
Expand All @@ -29,16 +34,16 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="storage in storages | orderBy:'name'">
<tr ng-repeat="storage in storages | filter:filter | orderBy:'name'">
<td>{{storage.name}}</td>
<td>{{storage.type}}</td>
<td>{{storage.path}}</td>
<td ng-if="counts"><code>{{counts[storage.id]}}</code></td>
<td ng-if="!counts">Loading...</td>
<td>
<button class="btn btn-xs btn-default" ng-if="!storage.default" ng-click="setDefault(storage)">Set Default</button>
<button class="btn btn-xs btn-default" ng-if="storage.default" disabled>Default</button>
<button class="btn btn-xs btn-danger" ng-class="{disabled: storage.default || !counts || counts[storage.id] > 0}" ng-click="delete(storage)">Delete</button>
<button class="btn btn-sm btn-default" ng-if="!storage.default" ng-click="setDefault(storage)">Set Default</button>
<button class="btn btn-sm btn-default" ng-if="storage.default" disabled>Default</button>
<button class="btn btn-sm btn-danger" ng-class="{disabled: storage.default || !counts || counts[storage.id] > 0}" ng-click="delete(storage)">Delete</button>
</td>
</tr>
</tbody>
Expand All @@ -57,7 +62,7 @@ <h4 class="modal-title">New Storage</h4>
<li><a href="" data-target="#localFSStore" data-toggle="tab">File System Store</a></li>
</ul>
<br />
<div class="tab-content">
<div class="tab-content clearfix">
<div class="tab-pane active" id="domainStore">
<form class="form-horizontal" ng-submit="newDomainStorage()">
<div class="form-group">
Expand All @@ -66,7 +71,7 @@ <h4 class="modal-title">New Storage</h4>
<input type="text" class="form-control" id="name" ng-model="domainName" required placeholder="Name">
</div>
</div>
<button type="submit" class="btn btn-success pull-right">Create</button>
<button type="submit" class="btn btn-primary pull-right">Create</button>
</form>
</div>
<div class="tab-pane" id="localFSStore">
Expand Down Expand Up @@ -94,8 +99,6 @@ <h4 class="modal-title">New Storage</h4>
</div>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
Expand All @@ -105,18 +108,23 @@ <h4 class="modal-title">New Storage</h4>
Loading...
</div>

<table class="table table-condensed table-striped" ng-if="configs">
<div class="row">
<div class="col-sm-offset-9 col-sm-3">
<input type="text" class="form-control" ng-model="configFilter" placeholder="Filter...">
</div>
</div>
<table class="table table-striped" ng-if="configs">
<thead>
<tr>
<th>File Type</th>
<th>Repository</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="config in configs | orderBy:'type'" ng-class="{success: config.success}" >
<tr ng-repeat="config in configs | filter: configFilter | orderBy:'type'" ng-class="{success: config.success}" >
<td>{{config.type}}</td>
<td>
<select ng-model="config.storage.id" ng-change="save(config)" ng-options="storage.id as storage.name group by storage.type for storage in storages | orderBy:'name'">
<select class="form-control" ng-model="config.storage.id" ng-change="save(config)" ng-options="storage.id as storage.name group by storage.type for storage in storages | orderBy:'name'">
<option value="null">----</option>
</select>
</td>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
<table class="table table-striped">
<div class="row">
<h4 class="col-sm-6">
Static Configurations
</h4>
<div class="col-sm-offset-3 col-sm-3">
<input type="text" class="form-control" ng-model="sys.filter" placeholder="Filter..." />
</div>
</div>
<br />
<table class="table table-striped" style="table-layout: fixed">
<tbody>
<tr ng-repeat="property in data.conf | orderBy:'key'">
<th>{{property.key}}</th>
<td>{{property.value}}</td>
<tr ng-repeat="property in data.conf | filter:sys.filter | orderBy:'key'">
<th class="col-sm-4" style="word-wrap: break-word">{{property.key}}</th>
<td class="col-sm-8" style="word-wrap: break-word">{{property.value}}</td>
</tr>
</tbody>
</table>
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
<h4 class="page-header">
System Properties

<span class="pull-right">
<input type="text" ng-model="sys.filter" placeholder="Filter..." />
</span>
</h4>
<table class="table table-striped">
<div class="row">
<h4 class="col-sm-6">
System Properties
</h4>
<div class="col-sm-offset-3 col-sm-3">
<input type="text" class="form-control" ng-model="sys.filter" placeholder="Filter..." />
</div>
</div>
<br />
<table class="table table-striped" style="table-layout: fixed">
<tbody>
<tr ng-repeat="property in data.sys | filter:sys.filter | orderBy:'key'">
<th>{{property.key}}</th>
<td>{{property.value}}</td>
<th class="col-sm-4" style="word-wrap: break-word">{{property.key}}</th>
<td class="col-sm-8" style="word-wrap: break-word">{{property.value}}</td>
</tr>
</tbody>
</table>

<h4 class="page-header">
Environment Properties
<hr />

<span class="pull-right">
<input type="text" ng-model="env.filter" placeholder="Filter..." />
</span>
</h4><table class="table table-striped">
<div class="row">
<h4 class="col-sm-6">
Environment Properties
</h4>
<div class="col-sm-offset-3 col-sm-3">
<input type="text" class="form-control" ng-model="sys.filter" placeholder="Filter..." />
</div>
</div>
<br />
<table class="table table-striped" style="table-layout: fixed">
<tbody>
<tr ng-repeat="property in data.env | filter:env.filter | orderBy:'key'">
<th>{{property.key}}</th>
<td>{{property.value}}</td>
<tr ng-repeat="property in data.env | filter:sys.filter | orderBy:'key'">
<th class="col-sm-4" style="word-wrap: break-word">{{property.key}}</th>
<td class="col-sm-8" style="word-wrap: break-word">{{property.value}}</td>
</tr>
</tbody>
</table>
</table>
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<div class="clearfix" ng-repeat="(name, domain) in jmxData">
<div class="panel panel-default">
<div class="panel-heading clearfix" ng-click="shown = !shown">
<div class="panel-heading clearfix" ng-click="shown = !shown" role="button">
<span class="badge">Domain</span> <small>{{name}}</small>
</div>
<div class="panel-body row" ng-if="shown">
<div class="col-sm-4">
<ul class="list-group">
<a href="" class="list-group-item" ng-class="{'active':selected == bean}" ng-click="$parent.selected = bean" ng-repeat="bean in domain | filter: filter | orderBy:'name.properties.type'">
<a href="" class="list-group-item" ng-class="{'active':selected == bean}" ng-click="$parent.selected = bean" ng-repeat="bean in domain | filter: filter | orderBy:'name.properties.name'">
{{bean.name.properties.name}} {{bean.name.properties.type}}
</a>
</ul>
<input type="text" class="form-control" ng-model="filter" placeholder="Filter..."/>
</div>
<div class="col-sm-8" ng-show="selected">
<h2>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
<table class="table table-striped table-bordered table-condensed">
<table class="table table-striped" ng-show="data.libraries.length">
<thead>
<tr>
<th>GroupId</th>
<th>ArtifactId</th>
<th>Name</th>
<th>Version</th>
<th>Creation Date</th>
<th>Jdk Version</th>
<th>Built By</th>
<th>Library</th>
<th>Build</th>
<th>JAR File</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="library in data.libraries">
<td>{{library.groupId}}</td>
<td>{{library.artifactId}}</td>
<td>{{library['Implementation-Title']}}</td>
<td>{{library.version}}</td>
<td>{{library.creation}}</td>
<td>{{library['Build-Jdk']}}</td>
<td>{{library['Built-By']}}</td>
<tr ng-repeat="library in data.libraries | orderBy:'jar'">
<td>
<h6>{{library['Implementation-Title']}}</h6>
<small><code>{{library.groupId}}:{{library.artifactId}}:{{library.version}}</code></small>
</td>
<td>
<h6>{{library.creation}}</h6>
<small>{{library['Build-Jdk']}} - {{library['Built-By']}}</small>
</td>
<td>
<h6 class="small" title="{{library.jar}}">
<samp>{{library.jar | filename}}</samp>
</h6>
<small><code>{{library.checksum}}</code></small>
</td>
</tr>
</tbody>
</table>
</table>


<div class="panel panel-default" ng-show="!data.libraries.length">
<div class="panel-body">
<p><span class="glyphicon glyphicon-info-sign"></span> No libraries were found</p>
<small>This information is typically unavailable in development mode or when using embedded containers.</small>
</div>
</div>
Loading

0 comments on commit 665475b

Please sign in to comment.