Fixed 'refresh' routine to refresh on the current url (which includes current page, sort and search criteria). In other words refresh now respects the current page state rather than resetting it back to thebeginning. Also added first attempt at a dashboard and widget.

This commit is contained in:
chouseknecht 2013-09-26 01:50:01 -04:00
parent 879936ab37
commit 44c6bca6f0
10 changed files with 205 additions and 18 deletions

View File

@ -68,7 +68,8 @@ angular.module('ansible', [
'SelectionHelper',
'LicenseFormDefinition',
'License',
'HostGroupsFormDefinition'
'HostGroupsFormDefinition',
'ObjectCountWidget'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.
@ -228,13 +229,15 @@ angular.module('ansible', [
when('/login', { templateUrl: urlPrefix + 'partials/organizations.html', controller: Authenticate }).
when('/logout', { templateUrl: urlPrefix + 'partials/organizations.html', controller: Authenticate }).
when('/home', { templateUrl: urlPrefix + 'partials/home.html', controller: Home }).
otherwise({redirectTo: '/'});
otherwise({redirectTo: '/home'});
}])
.run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization','LoadBasePaths', 'ViewLicense',
function($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense) {
LoadBasePaths();
LoadBasePaths();
if ( !(typeof $AnsibleConfig.refresh_rate == 'number' && $AnsibleConfig.refresh_rate >= 3
&& $AnsibleConfig.refresh_rate <= 99) ) {
@ -266,12 +269,12 @@ angular.module('ansible', [
// Make the correct tab active
var base = $location.path().replace(/^\//,'').split('/')[0];
if (base == '') {
$('.nav-tabs a[href="#' + 'organizations' + '"]').tab('show');
base = 'home';
}
else {
base.replace(/\_/g,' ');
$('.nav-tabs a[href="#' + base + '"]').tab('show');
base.replace(/\_/g,' ');
}
$('.nav-tabs a[href="#' + base + '"]').tab('show');
});
if (!Authorization.getToken()) {
@ -284,14 +287,13 @@ angular.module('ansible', [
// If browser refresh, activate the correct tab
var base = ($location.path().replace(/^\//,'').split('/')[0]);
if (base == '') {
base = 'organizations';
$location.path('/organizations');
$('.nav-tabs a[href="#' + base + '"]').tab('show');
base = 'home';
$location.path('/home');
}
else {
base.replace(/\_/g,' ');
$('.nav-tabs a[href="#' + base + '"]').tab('show');
}
$('.nav-tabs a[href="#' + base + '"]').tab('show');
$rootScope.viewCurrentUser = function() {
$location.path('/users/' + $rootScope.current_user.id);

View File

@ -74,7 +74,7 @@ function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Auth
Authorization.getLicense()
.success(function(data, status, headers, config) {
Authorization.setLicense(data['license_info']);
$location.path('/organizations');
$location.url('/home?login=true');
})
.error(function(data, status, headers, config) {
Alert('Error', 'Failed to access user information. GET returned status: ' + status, 'alert-danger', setLoginFocus);

View File

@ -0,0 +1,29 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
*
* Home.js
*
* Controller functions for Home tab
*
*/
'use strict';
function Home ($routeParams, $scope, $rootScope, $location, Wait, ObjectCount, ClearScope)
{
//ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
if (!$routeParams['login']) {
Wait('start');
}
ObjectCount({ target: 'container1' });
if (!$routeParams['login']) {
Wait('stop');
}
}
Home.$inject=[ '$routeParams', '$scope', '$rootScope', '$location', 'Wait', 'ObjectCount', 'ClearScope'];

View File

@ -12,7 +12,7 @@
function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, LookUpInit, SubmitJob, FormatDate)
ClearScope, ProcessErrors, GetBasePath, LookUpInit, SubmitJob, FormatDate, Refresh)
{
ClearScope('htmlTemplate');
var list = JobList;
@ -71,7 +71,9 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest,
LoadBreadCrumbs();
scope.refresh = function() {
scope.search(list.iterator);
scope['jobSearchSpin'] = true;
scope['jobLoading'] = true;
Refresh({ scope: scope, set: 'jobs', iterator: 'job', url: scope['current_url'] });
}
scope.refreshJob = scope.refresh;
@ -155,7 +157,7 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest,
JobsListCtrl.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors','GetBasePath', 'LookUpInit', 'SubmitJob', 'FormatDate'
'ProcessErrors','GetBasePath', 'LookUpInit', 'SubmitJob', 'FormatDate', 'Refresh'
];

View File

@ -13,7 +13,7 @@
function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, ProjectList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, SelectionInit, ProjectUpdate, ProjectStatus,
FormatDate)
FormatDate, Refresh)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
@ -136,7 +136,9 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
}
scope.refresh = function() {
scope.search(list.iterator);
scope['projectSearchSpin'] = true;
scope['projectLoading'] = true;
Refresh({ scope: scope, set: 'projects', iterator: 'project', url: scope['current_url'] });
}
scope.SCMUpdate = function(project_id) {
@ -158,7 +160,7 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
ProjectsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'ProjectList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'SelectionInit', 'ProjectUpdate', 'ProjectStatus', 'FormatDate' ];
'GetBasePath', 'SelectionInit', 'ProjectUpdate', 'ProjectStatus', 'FormatDate', 'Refresh' ];
function ProjectsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm,

View File

@ -23,6 +23,7 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities'])
var iterator = params.iterator;
var url = params.url;
scope.current_url = url;
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {

View File

@ -0,0 +1,131 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* ObjectCount.js
*
* Dashboard widget showing object counts and license availability.
*
*/
angular.module('ObjectCountWidget', ['RestServices', 'Utilities'])
.factory('ObjectCount', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait) {
return function(params) {
var current_version;
var scope = $rootScope.$new();
var counts = [];
var target = params.target;
scope.$on('countReady', function(e, obj, count) {
var keys=[];
var hash = {};
if (counts.length == 10) {
// sort the list of objs
for (var i=0; i < counts.length; i++) {
for (var key in counts[i]) {
if (key !== 'hosts' && key !== 'groups') {
keys.push(key);
}
hash[key] = counts[i][key];
}
}
// sort the keys, forcing groups and hosts to appear directlry after inventory
keys.sort();
var new_keys = [];
for (var i=0; i < keys.length; i++) {
if (keys[i] == 'inventory') {
new_keys.push('inventory');
new_keys.push('groups');
new_keys.push('hosts');
}
else {
new_keys.push(keys[i]);
}
}
keys = new_keys;
var html = "<div class=\"panel panel-primary\">\n";
html += "<div class=\"panel-heading\">System Summary</div>\n";
html += "<div class=\"panel-body\">\n";
html += "<ul class=\"list-group grey-txt\">\n";
for (var i=0; i < keys.length; i++) {
html += "<li class=\"list-group-item";
html += (keys[i] == 'hosts' || keys[i] == 'groups') ? ' pad-left-md' : '';
html += "\">\n";
html += "<span class=\"badge success-badge\">" + hash[keys[i]] + "</span>\n";
if (keys[i] !== 'hosts' && keys[i] !== 'groups') {
html += "<a href=\"/#/";
html += (keys[i] == 'inventory') ? 'inventories' : keys[i];
html += "\">";
}
if (keys[i] == 'inventory') {
html += 'Inventories';
}
else if (keys[i] == 'job_templates') {
html += 'Job Templates';
}
else {
html += keys[i].substring(0,1).toUpperCase() + keys[i].substring(1);
}
html += (keys[i] !== 'hosts' && keys[i] !== 'groups') ? "</a>" : "";
html += "</li>\n";
}
html += "</ul>\n";
html += "</div>\n";
html += "</div>\n";
var element = angular.element(document.getElementById(target));
element.html(html);
//scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference
// From here use 'scope' to manipulate the form, as the form is not in '$scope'
$compile(element)(scope);
}
});
var getCount = function (obj) {
scope.collection = (obj == 'inventory') ? 'inventories' : obj;
var url = current_version + scope.collection + '/';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
var count = {};
count[obj] = data.count;
counts.push(count);
scope.$emit('countReady');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get count for ' + obj + '. GET status: ' + status });
});
}
Rest.setUrl('/api/');
Rest.get()
.success( function(data, status, headers, config) {
current_version = data.current_version;
Rest.setUrl(current_version);
Rest.get()
.success( function(data, status, headers, config) {
for (obj in data) {
if (obj !== 'me' && obj !== 'authtoken' && obj !== 'config') {
getCount(obj);
}
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + current_version + '. GET status: ' + status });
})
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get /api/. GET status: ' + status });
});
}
}]);

View File

@ -25,10 +25,17 @@ body {
/* Helper Classes */
.pad-right-sm { padding-right: 10px; }
.pad-left-md { padding-left: 30px; }
.pad-left-lg { padding-left: 50px; }
.normal-weight { font-weight: normal; }
.no-bullets { list-style: none; }
.capitalize { text-transform: capitalize; }
.grey-txt { color: @grey; }
.success-badge {
color: #ffffff;
background-color: #5cb85c;
}
.bold-text .checkbox-inline {
font-weight: bold;

View File

@ -0,0 +1,10 @@
<div class="tab-pane" id="home">
<div class="row">
<div id="container1" class="col-lg-6"></div>
<div id="conatiner2" class="col-lg-6"></div>
</div>
<div class="row">
<div id="container3" class="col-lg-6"></div>
<div id="conatiner4" class="col-lg-6"></div>
</div>
</div>

View File

@ -42,6 +42,7 @@
<script src="{{ STATIC_URL }}js/controllers/Users.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Admins.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Inventories.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Home.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Hosts.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Groups.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Teams.js"></script>
@ -104,6 +105,7 @@
<script src="{{ STATIC_URL }}js/helpers/Selection.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Projects.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Users.js"></script>
<script src="{{ STATIC_URL }}js/widgets/ObjectCount.js"></script>
<script src="{{ STATIC_URL }}lib/less/less-1.4.1.min.js"></script>
@ -140,7 +142,8 @@
<div class="row">
<div class="col-lg-12">
<ul class="nav nav-tabs" id="main_tabs">
<li class="active"><a href="#organizations" id="main_organizations_tab" data-toggle="tab">Organizations</a></li>
<li class="active"><a href="#home" id="main_home_tab" data-toggle="tab">Home</a></li>
<li><a href="#organizations" id="main_organizations_tab" data-toggle="tab">Organizations</a></li>
<li><a href="#users" id="main_users_tab" data-toggle="tab">Users</a></li>
<li><a href="#teams" id="main_teams_tab" data-toggle="tab">Teams</a></li>
<li><a href="#projects" id="main_projects_tab" data-toggle="tab">Projects</a></li>