job details - fix date formatting, remove $rootScope.setInterval() stuff & listen to socket events to update DOM, clean up Codemirror styles, responsive styles. Resolves #1438 && # #1245 && #1185

remove old code
This commit is contained in:
Leigh Johnson 2016-04-09 14:52:41 -04:00
parent 833f68dd7f
commit b598fc41f5
12 changed files with 84 additions and 181 deletions

View File

@ -488,15 +488,6 @@ export default
counter = params.counter,
h, host;
/*
scope.host_summary.ok += (status === 'successful') ? 1 : 0;
scope.host_summary.changed += (status === 'changed') ? 1 : 0;
scope.host_summary.unreachable += (status === 'unreachable') ? 1 : 0;
scope.host_summary.failed += (status === 'failed') ? 1 : 0;
scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed + scope.host_summary.unreachable +
scope.host_summary.failed;
*/
if (scope.jobData.hostSummaries[host_id] !== undefined) {
scope.jobData.hostSummaries[host_id].ok += (status === 'successful') ? 1 : 0;
scope.jobData.hostSummaries[host_id].changed += (status === 'changed') ? 1 : 0;
@ -517,29 +508,6 @@ export default
status: (status === 'failed' || status === 'unreachable') ? 'failed' : 'successful'
};
}
scope.host_summary.ok = 0;
scope.host_summary.changed = 0;
scope.host_summary.unreachable = 0;
scope.host_summary.failed = 0;
for (h in scope.jobData.hostSummaries) {
host = scope.jobData.hostSummaries[h];
if (host.ok > 0 && host.failed === 0 && host.unreachable === 0 && host.changed === 0) {
scope.host_summary.ok++;
}
if (host.changed > 0 && host.failed === 0 && host.unreachable === 0) {
scope.host_summary.changed++;
}
if (host.failed > 0) {
scope.host_summary.failed++;
}
if (host.unreachable > 0) {
scope.host_summary.unreachable++;
}
}
scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed + scope.host_summary.unreachable +
scope.host_summary.failed;
UpdateTaskStatus({
scope: scope,
task_id: task_id,
@ -985,10 +953,10 @@ export default
color: '#FF0000'
});
}
if (count.failed.length > 0) {
if (count.failures.length > 0) {
graph_data.push({
label: 'FAILED',
value: count.failed.length,
value: count.failures.length,
color: '#ff5850'
});
}
@ -1085,7 +1053,8 @@ export default
idx = 0,
result = [],
newKeys = [],
plays = JSON.parse(JSON.stringify(scope.jobData.plays)),
//plays = JSON.parse(JSON.stringify(scope.jobData.plays)),
plays = scope.jobData.plays,
filteredListX = [],
filteredListA = [],
filteredListB = [],
@ -1174,7 +1143,8 @@ export default
if (scope.activePlay && scope.jobData.plays[scope.activePlay]) {
tasks = JSON.parse(JSON.stringify(scope.jobData.plays[scope.activePlay].tasks));
//tasks = JSON.parse(JSON.stringify(scope.jobData.plays[scope.activePlay].tasks));
tasks = scope.jobData.plays[scope.activePlay].tasks;
// Only draw tasks that are in the 'active' list
for (key in tasks) {
@ -1248,7 +1218,8 @@ export default
if (scope.activePlay && scope.activeTask && scope.jobData.plays[scope.activePlay] &&
scope.jobData.plays[scope.activePlay].tasks[scope.activeTask]) {
hostResults = JSON.parse(JSON.stringify(scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults));
//hostResults = JSON.parse(JSON.stringify(scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults));
hostResults = scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults;
if (scope.search_host_name) {
for (key in hostResults) {

View File

@ -49,6 +49,7 @@
width: 80px;
margin-right: 20px;
font-size: 12px;
word-wrap: break-word;
}
.HostEvent-field{
.OnePlusTwo-left--detailsRow;
@ -58,12 +59,17 @@
}
.HostEvent-details--left, .HostEvent-details--right{
vertical-align:top;
width:270px;
width:265px;
display: inline-block;
}
.HostEvent-details--left{
margin-right: 10px;
}
.HostEvent-details--right{
.HostEvent-field--label{
width: 170px;
width: auto;
}
}
.HostEvent-field--content{
text-align: right;
}
}

View File

@ -6,8 +6,8 @@
export default
['$stateParams', '$scope', '$state', 'Wait', 'JobDetailService', 'moment', 'event',
function($stateParams, $scope, $state, Wait, JobDetailService, moment, event){
['$stateParams', '$scope', '$state', 'Wait', 'JobDetailService', 'event',
function($stateParams, $scope, $state, Wait, JobDetailService, event){
$scope.processEventStatus = JobDetailService.processEventStatus;
$scope.hostResults = [];
@ -24,7 +24,8 @@
lineNumbers: true,
mode: {name: "javascript", json: true}
});
editor.getDoc().setValue(JSON.stringify(json, null, 4));
editor.setSize("100%", 300)
editor.getDoc().setValue(JSON.stringify(json, null, 4));
};
$scope.getActiveHostIndex = function(){
@ -55,8 +56,7 @@
};
var init = function(){
$scope.event = event.data.results[0];
$scope.event.created = moment($scope.event.created).format();
$scope.event = event;
JobDetailService.getJobEventChildren($stateParams.taskId).success(function(res){
$scope.hostResults = res.results;
});

View File

@ -15,10 +15,13 @@ var hostEventModal = {
features: ['FeaturesService', function(FeaturesService){
return FeaturesService.get();
}],
event: ['JobDetailService','$stateParams', function(JobDetailService, $stateParams) {
return JobDetailService.getRelatedJobEvents($stateParams.id, {
event: ['JobDetailService','$stateParams', 'moment', function(JobDetailService, $stateParams, moment) {
return JobDetailService.getRelatedJobEvents($stateParams.id, {
id: $stateParams.eventId,
}).success(function(res){ return res;})
}).then(function(res){
res.data.results[0].created = moment(res.data.results[0].created).format('MMMM Do YYYY, h:mm:ss a');
return res.data.results[0];
});
}]
},
onExit: function($state){

View File

@ -72,7 +72,8 @@
if (filter == 'ok'){
return JobDetailService.getRelatedJobEvents($stateParams.id, {
host_name: $stateParams.hostName,
event: 'runner_on_ok',
or__field__event: 'runner_on_ok',
or__field__event: 'runner_on_ok_async',
changed: false
})
.success(function(res){
@ -92,7 +93,7 @@
}
if (filter == 'failed'){
return JobDetailService.getRelatedJobEvents($stateParams.id, {
host_name: $stateParams.hostName,
host_name: $stateParams.hostName,
failed: true})
.success(function(res){
$scope.results = res.results;

View File

@ -7,4 +7,7 @@
.HostSummary-graph--changed{
text-anchor: end !important;
}
.HostSUmmary-graph--unreachable{}
.HostSUmmary-graph--unreachable{}
.HostSummary-loading{
border: none;
}

View File

@ -15,7 +15,8 @@
var buildTooltips = function(hosts){
// status waterfall: unreachable > failed > changed > ok > skipped
var count = {
var count, grammar, text = {};
count = {
ok : _.filter(hosts, function(o){
return o.failures === 0 && o.changed === 0 && o.ok > 0;
}),
@ -25,19 +26,30 @@
unreachable : _.filter(hosts, function(o){
return o.dark > 0;
}),
failed : _.filter(hosts, function(o){
failures : _.filter(hosts, function(o){
return o.failed === true;
}),
changed : _.filter(hosts, function(o){
return o.changed > 0;
})
};
var tooltips = {
0: 'No host events were ',
1: ' host event was ',
2: ' host events were '
var grammar = function(n, status){
var dict = {
0: 'No host events were ',
1: ' host event was ',
2: ' host events were '
};
if (n >= 2){
return n + dict[2] + status;
}
else{
return n !== 0 ? n + dict[n] + status : dict[n] + status;
}
};
return {count, tooltips}
_.forIn(count, function(value, key){
text[key] = grammar(value.length, key);
});
return {count, text}
};
var socketListener = function(){
// emitted by the API in the same function used to persist host summary data
@ -56,6 +68,17 @@
});
};
$scope.getNextPage = function(){
if ($scope.next){
JobDetailService.getNextPage($scope.next).success(function(res){
res.results.forEach(function(key, index){
$scope.hosts.push(res.results[index]);
})
$scope.hosts.push(res.results);
$scope.next = res.next;
});
}
};
$scope.search = function(){
Wait('start')
JobDetailService.getJobHostSummaries($stateParams.id, {

View File

@ -1,6 +1,6 @@
<div id="hosts-summary-section" class="section">
<div class="JobDetail-searchHeaderRow">
<div class="JobDetail-searchHeaderRow" ng-hide="hosts.length == 0">
<div class="JobDetail-searchContainer form-group">
<div class="search-name">
<form ng-submit="search()">
@ -21,7 +21,7 @@
</div>
</div>
<div class="table-header">
<div class="table-header" ng-hide="hosts.length == 0">
<table class="table table-condensed">
<thead>
<tr>
@ -32,7 +32,7 @@
</table>
</div>
<div id="hosts-summary-table" class="table-detail" lr-infinite-scroll="hostSummariesScrollDown" scroll-threshold="10" time-threshold="500">
<div id="hosts-summary-table" class="table-detail" lr-infinite-scroll="getNextPage" scroll-threshold="10" time-threshold="500">
<table class="table">
<tbody>
<tr class="List-tableRow" ng-repeat="host in hosts track by $index" id="{{ host.id }}" ng-class-even="'List-tableRow--evenRow'" ng-class-odd="'List-tableRow--oddRow'">
@ -40,21 +40,21 @@
<a ui-sref="jobDetail.host-events({hostName: host.host_name})" aw-tool-tip="View events" data-placement="top">{{ host.host_name }}</a>
</td>
<td class="List-tableCell col-lg-6 col-md-5 col-sm-5 col-xs-5 badge-column">
<a ui-sref="jobDetail.host-events({hostName: host.host_name, filter: 'ok'})" aw-tool-tip="{{ host.okTip }}" data-tip-watch="host.okTip" data-placement="top" ng-hide="host.ok == 0"><span class="badge successful-hosts">{{ host.ok }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.host_name, filter: 'changed'})" aw-tool-tip="{{ host.changedTip }}" data-tip-watch="host.changedTip" data-placement="top" ng-hide="host.changed == 0"><span class="badge changed-hosts">{{ host.changed }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.host_name, filter: 'skipped'})" aw-tool-tip="{{ host.skippedTip }}" data-tip-watch="host.failedTip" data-placement="top" ng-hide="host.skipped == 0"><span class="badge skipped-hosts">{{ host.skipped }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.host_name, filter: 'unreachable'})" aw-tool-tip="{{ host.unreachableTip }}" data-tip-watch="host.unreachableTip" data-placement="top" ng-hide="host.dark == 0"><span class="badge unreachable-hosts">{{ host.dark }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.name, filter: 'failed'})" aw-tool-tip="{{ host.failedTip }}" data-tip-watch="host.failedTip" data-placement="top" ng-hide="host.failed == 0"><span class="badge failed-hosts">{{ host.failures }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.host_name, filter: 'ok'})" aw-tool-tip="{{ tooltips.text.ok }}" data-placement="top" ng-hide="host.ok == 0"><span class="badge successful-hosts">{{ host.ok - host.changed }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.host_name, filter: 'changed'})" aw-tool-tip="{{ tooltips.text.changed }}" data-placement="top" ng-hide="host.changed == 0"><span class="badge changed-hosts">{{ host.changed }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.host_name, filter: 'skipped'})" aw-tool-tip="{{ tooltips.text.skipped }}" data-placement="top" ng-hide="host.skipped == 0"><span class="badge skipped-hosts">{{ host.skipped }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.host_name, filter: 'unreachable'})" aw-tool-tip="{{ tooltips.text.unreachable}}" data-placement="top" ng-hide="host.dark == 0"><span class="badge unreachable-hosts">{{ host.dark }}</span></a>
<a ui-sref="jobDetail.host-events({hostName: host.name, filter: 'failed'})" aw-tool-tip="{{ tooltips.text.failures}}" data-placement="top" ng-hide="host.failed == 0"><span class="badge failed-hosts">{{ host.failures }}</span></a>
</td>
</tr>
<tr ng-show="hosts.length === 0 && status === 'pending'">
<td colspan="5" class="col-lg-12 loading-info">Waiting...</td>
<td colspan="5" class="col-lg-12 HostSummary-loading">Waiting...</td>
</tr>
<tr ng-show="hosts.length === 0 && status === 'running' ">
<td colspan="5" class="col-lg-12 loading-info">Loading...</td>
<td colspan="5" class="col-lg-12 HostSummary-loading">Loading...</td>
</tr>
<tr ng-show="status === 'failed' || status === 'successful' && hosts.length === 0 ">
<td colspan="2" class="col-lg-12 loading-info">No matching hosts</td>
<td colspan="2" class="col-lg-12 HostSummary-loading">No matching hosts</td>
</tr>
</tbody>
</table>

View File

@ -81,38 +81,6 @@ export default
}
});
scope.hosts = [];
scope.$watch('hosts', function(hosts) {
for (var host in hosts) {
if (hosts[host].ok) {
hosts[host].okTip = hosts[host].ok;
hosts[host].okTip += (hosts[host].ok === 1) ? " host event was" : " host events were";
hosts[host].okTip += " ok.";
} else {
hosts[host].okTip = "No host events were ok.";
}
if (hosts[host].changed) {
hosts[host].changedTip = hosts[host].changed;
hosts[host].changedTip += (hosts[host].changed === 1) ? " host event" : " host events";
hosts[host].changedTip += " changed.";
} else {
hosts[host].changedTip = "No host events changed.";
}
if (hosts[host].failed) {
hosts[host].failedTip = hosts[host].failed;
hosts[host].failedTip += (hosts[host].failed === 1) ? " host event" : " host events";
hosts[host].failedTip += " failed.";
} else {
hosts[host].failedTip = "No host events failed.";
}
if (hosts[host].unreachable) {
hosts[host].unreachableTip = hosts[host].unreachable;
hosts[host].unreachableTip += (hosts[host].unreachable === 1) ? " host event was" : " hosts events were";
hosts[host].unreachableTip += " unreachable";
} else {
hosts[host].unreachableTip = "No host events were unreachable.";
}
}
});
scope.tasks = [];
scope.$watch('tasks', function(tasks) {
for (var task in tasks) {
@ -168,7 +136,6 @@ export default
scope.hostResults = [];
scope.hostResultsMaxRows = 200;
scope.hostSummariesMaxRows = 200;
scope.tasksMaxRows = 200;
scope.playsMaxRows = 200;
@ -176,7 +143,6 @@ export default
scope.playsLoading = true;
scope.tasksLoading = true;
scope.hostResultsLoading = true;
scope.hostSummariesLoading = true;
// Turn on the 'Waiting...' message until events begin arriving
scope.waiting = true;
@ -194,7 +160,6 @@ export default
scope.search_play_status = 'all';
scope.search_task_status = 'all';
scope.search_host_status = 'all';
scope.search_host_summary_status = 'all';
scope.haltEventQueue = false;
scope.processing = false;
@ -202,13 +167,6 @@ export default
scope.lessDetail = false;
scope.lessEvents = true;
scope.host_summary = {};
scope.host_summary.ok = 0;
scope.host_summary.changed = 0;
scope.host_summary.unreachable = 0;
scope.host_summary.failed = 0;
scope.host_summary.total = 0;
scope.jobData = {};
scope.jobData.hostSummaries = {};
@ -228,7 +186,6 @@ export default
url: GetBasePath('unified_jobs'),
field: 'status',
variable: 'status_choices',
// callback: 'choicesReady'
});
scope.eventsHelpText = "<p><i class=\"fa fa-circle successful-hosts-color\"></i> Successful</p>\n" +
@ -237,11 +194,13 @@ export default
"<p><i class=\"fa fa-circle failed-hosts-color\"></i> Failed</p>\n";
function openSocket() {
$rootScope.event_socket.on("job_events-" + job_id, function(data) {
console.log(data)
if (api_complete && data.id > lastEventId) {
scope.waiting = false;
data.event = data.event_name;
DigestEvent({ scope: scope, event: data });
}
UpdateDOM({ scope: scope });
});
}
openSocket();
@ -256,9 +215,6 @@ export default
if (data.status === 'failed' || data.status === 'canceled' ||
data.status === 'error' || data.status === 'successful' || data.status === 'running') {
$scope.liveEventProcessing = false;
if ($rootScope.jobDetailInterval) {
window.clearInterval($rootScope.jobDetailInterval);
}
if (!scope.pauseLiveEvents) {
$scope.$emit('LoadJob'); //this is what is used for the refresh
}
@ -295,27 +251,15 @@ export default
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status });
});
if ($rootScope.jobDetailInterval) {
window.clearInterval($rootScope.jobDetailInterval);
}
$log.debug('Job completed!');
$log.debug(scope.jobData);
}
else {
api_complete = true; //trigger events to start processing
if ($rootScope.jobDetailInterval) {
window.clearInterval($rootScope.jobDetailInterval);
}
$rootScope.jobDetailInterval = setInterval(function() {
UpdateDOM({ scope: scope });
}, 2000);
UpdateDOM({ scope: scope})
}
});
if (scope.removeLoadHostSummaries) {
scope.removeLoadHostSummaries();
}
if (scope.removeLoadHosts) {
scope.removeLoadHosts();
}
@ -466,12 +410,6 @@ export default
scope.removeLoadPlays();
}
scope.removeLoadPlays = scope.$on('LoadPlays', function(e, events_url) {
scope.host_summary.ok = 0;
scope.host_summary.changed = 0;
scope.host_summary.unreachable = 0;
scope.host_summary.failed = 0;
scope.host_summary.total = 0;
scope.jobData.plays = {};
var params = {
order_by: 'id'
@ -555,13 +493,6 @@ export default
scope.jobData.plays[event.id].status_text = 'No matching hosts';
scope.jobData.plays[event.id].status_tip = "Event ID: " + event.id + "<br />Status: No matching hosts";
}
scope.host_summary.ok += ok;
scope.host_summary.changed += changed;
scope.host_summary.unreachable += (event.unreachable_count) ? event.unreachable_count : 0;
scope.host_summary.failed += failed;
scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed + scope.host_summary.unreachable +
scope.host_summary.failed;
});
if (scope.activePlay && scope.jobData.plays[scope.activePlay]) {
scope.jobData.plays[scope.activePlay].playActiveClass = 'JobDetail-tableRow--selected';
@ -664,7 +595,6 @@ export default
scope.playsLoading = false;
scope.tasksLoading = false;
scope.hostResultsLoading = false;
scope.hostSummariesLoading = false;
}
else {
scope.job_status.finished = null;
@ -1158,41 +1088,6 @@ export default
}
};
scope.hostSummariesScrollDown = function() {
// check for more hosts when user scrolls to bottom of host summaries list...
if (((!scope.liveEventProcessing) || (scope.liveEventProcessing && scope.pauseLiveEvents)) && scope.next_host_summaries) {
scope.hostSummariesLoading = true;
JobDetailService.getNextPage(scope.next_host_summaries)
.success(function(data) {
scope.next_host_summaries = data.next;
data.results.forEach(function(row) {
var name;
if (row.host_name) {
name = row.host_name;
}
else {
name = "<deleted host>";
}
scope.hosts.push({
id: row.id,
name: name,
ok: row.ok,
changed: row.changed,
unreachable: row.dark,
failed: row.failures
});
});
$('#hostSummariesMoreRows').fadeOut();
scope.hostSummariesLoading = false;
})
.error(function(data, status) {
$('#hostSummariesMoreRows').fadeOut();
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + scope.next_host_summaries + '. GET returned: ' + status });
});
}
};
scope.refresh = function(){
$scope.$emit('LoadJob');
};

View File

@ -62,7 +62,7 @@
<div class="form-group JobDetail-resultRow toggle-show" ng-show="job_status.started">
<label class="JobDetail-resultRowLabel col-lg-2 col-md-2 col-sm-2 col-xs-3 control-label">Started</label>
<div class="JobDetail-resultRowText">{{ job_status.started | date:'MM/dd/yy HH:mm:ss' }}</div>
<div class="JobDetail-resultRowText">{{ job_status.started | date:'M/d/yy HH:mm:ss a' }}</div>
</div>
<div class="form-group JobDetail-resultRow toggle-show" ng-show="job_type">
@ -72,7 +72,7 @@
<div class="form-group JobDetail-resultRow toggle-show" ng-show="job_status.started">
<label class="JobDetail-resultRowLabel col-lg-2 col-md-2 col-sm-2 col-xs-3 control-label">Finished</label>
<div class="JobDetail-resultRowText">{{ job_status.finished | date:'MM/dd/yy HH:mm:ss' }}</div>
<div class="JobDetail-resultRowText">{{ job_status.finished | date:'M/d/yy HH:mm:ss a' }}</div>
</div>
<div class="form-group JobDetail-resultRow toggle-show" ng-show="created_by">

View File

@ -1,5 +1,5 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/

View File

@ -230,6 +230,7 @@ export default
// expects 'next' param returned by the API e.g.
// "/api/v1/jobs/51/job_plays/?order_by=id&page=2&page_size=1"
getNextPage: function(url){
Rest.setUrl(url);
return Rest.get()
.success(function(data){
return data