AC-502 start of new dashboard.

This commit is contained in:
chouseknecht 2013-10-11 01:54:57 -04:00
parent 6933255699
commit 40ddb0058c
10 changed files with 194 additions and 21 deletions

View File

@ -70,7 +70,7 @@ angular.module('ansible', [
'LicenseFormDefinition',
'License',
'HostGroupsFormDefinition',
'ObjectCountWidget',
'JobStatusWidget',
'JobsHelper',
'InventoryStatusDefinition'
])

View File

@ -16,6 +16,9 @@ function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Auth
$('#login-username').focus();
};
// Just in case, make sure the wait widget is not active
Wait('stop');
// Display the login dialog
$('#login-modal').modal({ show: true, keyboard: false, backdrop: 'static' });

View File

@ -10,7 +10,7 @@
'use strict';
function Home ($routeParams, $scope, $rootScope, $location, Wait, ObjectCount, ClearScope)
function Home ($routeParams, $scope, $rootScope, $location, Wait, JobStatus, ClearScope)
{
ClearScope('home'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
@ -23,10 +23,10 @@ function Home ($routeParams, $scope, $rootScope, $location, Wait, ObjectCount, C
Wait('start');
}
ObjectCount({ target: 'container1' });
JobStatus({ target: 'container1' });
$rootScope.$on('WidgetLoaded', function() {
// Once all the widget report back 'loaded', turn off Wait widget
// Once all the widgets report back 'loaded', turn off Wait widget
loadedCount++;
if ( loadedCount == waitCount ) {
Wait('stop');
@ -34,4 +34,4 @@ function Home ($routeParams, $scope, $rootScope, $location, Wait, ObjectCount, C
});
}
Home.$inject=[ '$routeParams', '$scope', '$rootScope', '$location', 'Wait', 'ObjectCount', 'ClearScope'];
Home.$inject=[ '$routeParams', '$scope', '$rootScope', '$location', 'Wait', 'JobStatus', 'ClearScope'];

View File

@ -74,32 +74,28 @@ function JobHostSummaryList ($scope, $rootScope, $location, $log, $routeParams,
Rest.setUrl(GetBasePath('jobs') + scope.job_id);
Rest.get()
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/jobs/' + data.id, title: data.id + ' - ' +
data.summary_fields.job_template.name });
scope.job_status = data.status;
scope.$emit('setHostLink', data.inventory);
if (!(data.status == 'pending' || data.status == 'waiting' || data.status == 'running')) {
if ($rootScope.timer) {
clearInterval($rootScope.timer);
}
}
scope.$emit('setHostLink', data.inventory);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get job status for job: ' + scope.job_id + '. GET status: ' + status });
});
}
else {
else {
// Make the host name appear in breadcrumbs
LoadBreadCrumbs({ path: '/hosts/' + scope['host_id'], title: $routeParams['host_name'] });
if ($routeParams['inventory']) {
scope.$emit('setHostLink', $routeParams['inventory']);
}
}
if (base == 'hosts' && $routeParams['host_name']) {
// Make the host name appear in breadcrumbs
LoadBreadCrumbs({ path: '/hosts/' + scope['host_id'], title: $routeParams['host_name'] });
}
else {
LoadBreadCrumbs({ path: '/jobs/' + scope.job_id, title: scope.job_id + ' - ' +
scope.jobhosts[0].summary_fields.job.job_template_name });
}
});
SearchInit({ scope: scope, set: 'jobhosts', list: list, url: defaultUrl });

View File

@ -42,10 +42,12 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
scope.projects[i].status = 'n/a';
}
switch(scope.projects[i].status) {
case 'n/a':
scope.projects[i].badge = 'none';
break;
case 'updating':
case 'successful':
case 'ok':
case 'n/a':
scope.projects[i].badge = 'false';
break;
case 'never updated':

View File

@ -31,13 +31,14 @@ angular.module('JobsListDefinition', [])
},
created: {
label: 'Date',
link: true,
link: false,
searchable: false
},
job_template: {
label: 'Job Template',
ngBind: 'job.summary_fields.job_template.name',
ngHref: "\{\{ '/#/job_templates/?name=' + job.summary_fields.job_template.name \}\}",
//ngHref: "\{\{ '/#/job_templates/?name=' + job.summary_fields.job_template.name \}\}",
ngHref:"\{\{ '/#/job_templates/' + job.job_template \}\}",
sourceModel: 'job_template',
sourceField: 'name'
},

View File

@ -33,7 +33,7 @@ angular.module('ProjectsListDefinition', [])
label: 'Update Status',
ngClick: 'showSCMStatus(\{\{ project.id \}\})',
awToolTip: 'View details of last SCM Update',
dataPlacement: 'bottom',
dataPlacement: 'top',
badgeIcon: "\{\{ 'icon-failures-' + project.badge \}\}",
badgePlacement: 'left'
},

View File

@ -0,0 +1,159 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* JobStatus.js
*
* Dashboard widget showing object counts and license availability.
*
*/
angular.module('JobStatusWidget', ['RestServices', 'Utilities'])
.factory('JobStatus', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait) {
return function(params) {
var scope = $rootScope.$new();
var jobCount, jobFails, inventoryCount, inventoryFails, groupCount, groupFails, hostCount, hostFails;
var counts = 0;
var expectedCounts = 8;
var target = params.target;
scope.$on('CountReceived', function() {
function makeRow(label, count, fail) {
return "<tr><td><a href=\"/#/" + label.toLowerCase() + "\">" + label +
"</a></td><td class=\"failed-column text-right\"><a href=\"/blah/blah\">" +
fail + "</a></td><td class=\"text-right\"><a href=\"/blah/blah\">" +
count + "</a></td></tr>";
}
counts++;
if (counts == expectedCounts) {
// all the counts came back, now generate the HTML
var html = "<div class=\"panel panel-default\">\n";
html += "<div class=\"panel-heading\">Job Status</div>\n";
html += "<div class=\"panel-body\">\n";
html += "<table class=\"table table-condensed table-hover\">\n";
html += "<thead>\n";
html += "<tr>\n";
html += "<th></th>\n";
html += "<th class=\"text-right\">Failed</th>\n";
html += "<th class=\"text-right\">Total</th>\n";
html += "</tr>\n";
html += "</thead>\n";
html += "<tbody>\n";
html += makeRow('Jobs', jobCount, jobFails);
html += makeRow('Inventories', inventoryCount, inventoryFails);
html += makeRow('Groups', groupCount, groupFails);
html += makeRow('Hosts', hostCount, hostFails);
html += "</tbody>\n";
html += "</table>\n";
html += "</div>\n";
html += "</div>\n";
html += "</div>\n";
}
var element = angular.element(document.getElementById(target));
element.html(html);
$compile(element)(scope);
$rootScope.$emit('WidgetLoaded');
});
var url = GetBasePath('jobs') + '?page=1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
jobCount=data.count;
scope.$emit('CountReceived');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status });
});
url = GetBasePath('jobs') + '?failed=true&page=1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
jobFails=data.count;
scope.$emit('CountReceived');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status });
});
url = GetBasePath('inventory') + '?page=1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
inventoryCount=data.count;
scope.$emit('CountReceived');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status });
});
url = GetBasePath('inventory') + '?has_active_failures=true&page=1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
inventoryFails=data.count;
scope.$emit('CountReceived');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status });
});
url = GetBasePath('groups') + '?page=1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
groupCount = data.count;
scope.$emit('CountReceived');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status });
});
url = GetBasePath('groups') + '?has_active_failures=true&page=1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
groupFails = data.count;
scope.$emit('CountReceived');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status });
});
url = GetBasePath('hosts') + '?page=1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
hostCount = data.count;
scope.$emit('CountReceived');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status });
});
url = GetBasePath('hosts') + '?has_active_failures=true&page=1';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
hostFails = data.count;
scope.$emit('CountReceived');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status });
});
}
}]);

View File

@ -9,7 +9,8 @@
@black: #171717;
@warning: #FF9900;
@red: #da4f49;;
@red: #da4f49;
@red-hover: #AE3F3A;
@green: #5bb75b;
@blue: #1778c3; /* logo blue */
@blue-link: #0088cc;
@ -1175,6 +1176,17 @@ tr td button i {
}
/* Home page */
.failed-column {
a:link, a:visited {
color: @red;
}
a:hover {
color: @red-hover;
}
}
/* Large desktop */

View File

@ -108,7 +108,7 @@
<script src="{{ STATIC_URL }}js/helpers/Projects.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Users.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Jobs.js"></script>
<script src="{{ STATIC_URL }}js/widgets/ObjectCount.js"></script>
<script src="{{ STATIC_URL }}js/widgets/JobStatus.js"></script>
<script src="{{ STATIC_URL }}lib/less/less-1.4.1.min.js"></script>