Job detail page re-refactor

Host events viewer. Search now wired up. HTML re-load working. Table scrolling works.
This commit is contained in:
Chris Houseknecht 2014-07-08 16:56:55 -04:00
parent 39a5366237
commit fb9b5ae43c
7 changed files with 209 additions and 135 deletions

View File

@ -1009,7 +1009,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
scope: scope,
id: id,
name: name,
url: scope.job.related.job_events + '?event__icontains=runner'
url: scope.job.related.job_events
});
};

View File

@ -15,13 +15,15 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities'])
function($log, $compile, CreateDialog, Wait, GetBasePath, Empty, GetEvents) {
return function(params) {
var parent_scope = params.scope,
scope = parent_scope.$new(true),
url = params.url,
host_id = params.id,
host_name = params.name,
title = params.title, //optional
scope = parent_scope.$new(true);
fixHeight, buildTable;
$log.debug('host_id: ' + host_id + ' host_name: ' + host_name);
scope.host_events_search_name = params.name;
scope.host_events_search_status = 'all';
scope.eventsSearchActive = (scope.host_events_search_name) ? true : false;
if (scope.removeModalReady) {
scope.removeModalReady();
@ -37,29 +39,52 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities'])
scope.removeEventReady = scope.$on('EventsReady', function(e, data) {
var elem, html;
//scope.host_events = data.results;
//$log.debug(scope.host_events);
html = buildTable(data);
$('#host-events').html(html);
elem = angular.element(document.getElementById('host-events-modal-dialog'));
$compile(elem)(scope);
scope.host_events = data.results;
scope.host_events_search_name = host_name;
scope.host_events_search_status = 'all';
scope.host_events = [];
html = "<table class=\"table\">\n";
html += "<thead>\n";
html += "<tr><th class=\"col-md-3\">Status</th>" +
"<th class=\"col-md-3\">Play</th>" +
"<th class=\"col-md-3\">Task</th>" +
"<th class=\"col-md-3\">Result</th></tr>\n";
html += "</thead>\n";
CreateDialog({
scope: scope,
width: 675,
height: 600,
minWidth: 450,
callback: 'ModalReady',
id: 'host-events-modal-dialog',
onResizeStop: fixHeight,
title: ( (title) ? title : 'Host Events' ),
onOpen: function() {
fixHeight();
}
});
});
if (scope.removeRefreshHTML) {
scope.removeRefreshHTML();
}
scope.removeRefreshHTML = scope.$on('RefreshHTML', function(e, data) {
var elem, html = buildTable(data);
$('#host-events').html(html);
elem = angular.element(document.getElementById('host-events'));
$compile(elem)(scope);
Wait('stop');
});
buildTable = function(data) {
var html = "<table class=\"table\">\n";
html += "<tbody>\n";
data.results.forEach(function(result) {
var msg = '',
status = 'ok',
status_text = 'OK';
if (result.event_data.res) {
if (result.event_data.res && result.event_data.res.msg) {
msg = result.event_data.res.msg;
}
if (result.event === "runner_on_no_hoss") {
if (!result.task && result.event_data.res.ansible_facts) {
result.task = "Gathering Facts";
}
if (result.event === "runner_on_no_hosts") {
msg = "No hosts remaining";
}
if (result.event === 'runner_on_unreachable') {
@ -75,54 +100,86 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities'])
status_text = 'Changed';
}
html += "<tr ng-click=\"showDetails()\" class=\"cursor-pointer\" aw-tool-tip=\"Click to view details\" data-placement=\"top\">\n";
html += "<td><i class=\"fa icon-job-" + status + "\"></i> <a href=\"\">" + status_text + "</a></td>\n";
html += "<td><a href=\"\">" + result.play + "</a></td>\n";
html += "<td><a href=\"\">" + result.task + "</a></td>\n";
html += "<td><a href=\"\">" + msg + "</a></td>";
html += "</tr>"
html += "<td class=\"col-md-3\"><i class=\"fa icon-job-" + status + "\"></i> <a href=\"\">" + status_text + "</a></td>\n";
html += "<td class=\"col-md-3\"><a href=\"\">" + result.play + "</a></td>\n";
html += "<td class=\"col-md-3\"><a href=\"\">" + result.task + "</a></td>\n";
html += "<td class=\"col-md-3\"><a href=\"\">" + msg + "</a></td>";
html += "</tr>";
});
html += "</tbody>\n";
html += "</table>\n";
$('#host-events').html(html);
return html;
};
elem = angular.element(document.getElementById('host-events-modal-dialog'));
$compile(elem)(scope);
CreateDialog({
scope: scope,
width: 675,
height: 600,
minWidth: 450,
callback: 'ModalReady',
id: 'host-events-modal-dialog',
// onResizeStop: resizeText,
title: ( (title) ? title : 'Host Events' )
//onOpen: function() {
//}
});
});
fixHeight = function() {
var available_height = $('#host-events-modal-dialog').height() - $('#host-events-modal-dialog #search-form').height() - $('#host-events-modal-dialog #fixed-table-header').height();
$('#host-events').height(available_height);
$log.debug('set height to: ' + available_height);
};
GetEvents({
url: url,
scope: scope
scope: scope,
callback: 'EventsReady'
});
scope.modalOK = function() {
$('#host-events-modal-dialog').dialog('close');
scope.$destroy();
};
scope.searchEvents = function() {
scope.eventsSearchActive = (scope.host_events_search_name) ? true : false;
GetEvents({
scope: scope,
url: url,
callback: 'RefreshHTML'
});
};
scope.searchEventKeyPress = function(e) {
if (e.keyCode === 13) {
scope.searchEvents();
}
};
};
}])
.factory('GetEvents', ['Wait', 'Rest', 'ProcessErrors', function(Wait, Rest, ProcessErrors) {
return function(params) {
var url = params.url,
scope = params.scope;
scope = params.scope,
callback = params.callback;
if (scope.host_events_search_name) {
url += '?host_name=' + scope.host_events_search_name;
}
else {
url += '?host_name__isnull=false';
}
if (scope.host_events_search_status === 'changed') {
url += '&event__icontains=runner&changed=true';
}
else if (scope.host_events_search_status === 'failed') {
url += '&event__icontains=runner&failed=true';
}
else if (scope.host_events_search_status === 'ok') {
url += '&event=runner_on_ok&changed=false';
}
else if (scope.host_events_search_status === 'unreachable') {
url += '&event=runner_on_unreachable';
}
else if (!scope.host_events_search_status) {
url += '&event__icontains=runner&not__event=runner_on_skipped';
}
Wait('start');
Rest.setUrl(url);
Rest.get()
.success(function(data) {
scope.$emit('EventsReady', data);
scope.$emit(callback, data);
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',

View File

@ -1,82 +0,0 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* HostEvents.js
* Host summary event viewer dialog.
*
*/
'use strict';
angular.module('HostEventsListDefinition', [])
.value('HostEventList', {
name: 'host_events',
iterator: 'host_event',
editTitle: 'Host Events',
index: false,
hover: true,
fields: {
status: {
label: 'Status',
columnClass: 'col-md-2',
},
play: {
label: 'Play',
columnClass: 'col-md-3',
key: true,
nosort: true,
searchable: false,
noLink: true
},
status: {
label: 'Status',
showValue: false,
columnClass: 'col-sm-1 col-xs-2 text-center',
searchField: 'failed',
searchType: 'boolean',
searchOptions: [{
name: 'success',
value: 0
}, {
name: 'error',
value: 1
}],
nosort: true,
searchable: false,
ngClick: 'viewJobEvent(jobevent.id)',
awToolTip: '{{ jobevent.statusBadgeToolTip }}',
dataPlacement: 'top',
badgeIcon: 'fa icon-job-{{ jobevent.status }}',
badgePlacement: 'left',
badgeToolTip: '{{ jobevent.statusBadgeToolTip }}',
badgeTipPlacement: 'top',
badgeNgClick: 'viewJobEvent(jobevent.id)'
},
event_display: {
label: 'Event',
hasChildren: true,
ngClick: 'toggleChildren(jobevent.id, jobevent.related.children)',
nosort: true,
searchable: false,
ngClass: '{{ jobevent.class }}',
appendHTML: 'jobevent.event_detail'
},
host: {
label: 'Host',
ngBind: 'jobevent.summary_fields.host.name',
ngHref: '{{ jobevent.hostLink }}',
searchField: 'hosts__name',
nosort: true,
searchOnly: false,
id: 'job-event-host-header',
'class': 'break',
columnClass: 'col-lg-2 hidden-sm hidden-xs'
}
},
actions: { },
});

View File

@ -15,17 +15,22 @@
#host-events-modal-dialog {
overflow: hidden;
i {
font-size: 12px;
vertical-align: middle;
}
#search-form {
margin-left: 7px;
}
#host-events-search-name {
width: 200px;
padding-right: 15px;
}
#search-form-input-icons {
position: absolute;
right: 3px;
top: 5px;
z-index: 100;
left: 235px;
a {
color: #a9a9a9;
}
@ -36,10 +41,38 @@
#status-field {
margin-left: 15px;
}
table {
#host-events-table {
margin-top: 15px;
}
#host-events {
height: 200px;
overflow: scroll;
tr:first-of-type {
border-top-color: @white;
td {
border-top-color: @white;
}
}
}
#fixed-table-header {
margin-bottom: 0;
}
}
@media (max-width: 768px) {
#host-events-modal-dialog {
#search-form-input-icons {
position: absolute;
top: 30px;
left: 185px;
}
#status-field {
margin-left: 0;
}
.form-group {
margin-bottom: 15px;
}
}
}
#jobs-detail {

View File

@ -0,0 +1,20 @@
{
"name": "angular-scheduler",
"version": "0.0.14",
"devDependencies": {
"grunt": "~0.4.2",
"grunt-contrib-jshint": "~0.6.3",
"grunt-contrib-uglify": "~0.2.2",
"grunt-contrib-less": "~0.9.0",
"karma-chrome-launcher": "~0.1.2",
"karma-script-launcher": "~0.1.0",
"karma-firefox-launcher": "~0.1.3",
"karma-html2js-preprocessor": "~0.1.0",
"requirejs": "~2.1.11",
"karma-requirejs": "~0.2.1",
"karma-coffee-preprocessor": "~0.1.3",
"karma-phantomjs-launcher": "~0.1.2",
"karma": "~0.10.9",
"karma-jasmine": "~0.2.1"
}
}

View File

@ -0,0 +1,36 @@
{
"name": "socket.io-client"
, "description": "Socket.IO client for the browser and node.js"
, "version": "0.9.16"
, "main" : "./lib/io.js"
, "browserify": "./dist/socket.io.js"
, "homepage": "http://socket.io"
, "keywords": ["websocket", "socket", "realtime", "socket.io", "comet", "ajax"]
, "author": "Guillermo Rauch <guillermo@learnboost.com>"
, "contributors": [
{ "name": "Guillermo Rauch", "email": "rauchg@gmail.com" }
, { "name": "Arnout Kazemier", "email": "info@3rd-eden.com" }
, { "name": "Vladimir Dronnikov", "email": "dronnikov@gmail.com" }
, { "name": "Einar Otto Stangvik", "email": "einaros@gmail.com" }
]
, "repository": {
"type": "git"
, "url": "https://github.com/LearnBoost/socket.io-client.git"
}
, "dependencies": {
"uglify-js": "1.2.5"
, "ws": "0.4.x"
, "xmlhttprequest": "1.4.2"
, "active-x-obfuscator": "0.0.1"
}
, "devDependencies": {
"expresso": "*"
, "express": "2.5.x"
, "jade": "*"
, "stylus": "*"
, "socket.io": "0.9.16"
, "socket.io-client": "0.9.16"
, "should": "*"
}
, "engines": { "node": ">= 0.4.0" }
}

View File

@ -268,7 +268,7 @@
<form id="search-form" class="form-inline">
<div class="form-group" style="position:relative;">
<label>Search</label>
<input type="text" class="form-control input-sm" id="host-events-search-name" ng-model="host_events_search_name" placeholder="Host name" >
<input type="text" class="form-control input-sm" id="host-events-search-name" ng-model="host_events_search_name" placeholder="Host name" ng-keypress="searchEventKeyPress($event)" >
<div id="search-form-input-icons">
<a class="search-icon" ng-show="!eventsSearchActive" ng-click="searchEvents()"><i class="fa fa-search"></i></a>
<a class="search-icon" ng-show="eventsSearchActive" ng-click="host_events_search_name=''; searchEvents()"><i class="fa fa-times"></i></a>
@ -276,7 +276,7 @@
</div>
<div class="form-group" id="status-field">
<label>Status</label>
<select id="host-events-search-status" class="form-control input-sm" ng-model="host_events_search_status" name="host-events-search-name">
<select id="host-events-search-status" class="form-control input-sm" ng-model="host_events_search_status" name="host-events-search-name" ng-change="searchEvents()">
<option value="all">All</option>
<option value="changed">Changed</option>
<option value="failed">Failed</option>
@ -285,9 +285,19 @@
</select>
</div>
</form>
<div id="host-events-table" lr-infinite-scroll="hostEventsTable" scroll-threshold="10" time-threshold="500">
<!-- lr-infinite-scroll="hostEventsTable" scroll-threshold="10" time-threshold="500" -->
<div id="host-events-table">
<table id="fixed-table-header" class="table">
<thead>
<tr><th class="col-md-3">Status</th>
<th class="col-md-3">Play</th>
<th class="col-md-3">Task</th>
<th class="col-md-3">Result</th>
</tr>
</thead>
</table>
<div id="host-events"></div>
</div>
</div>
</div>
</div>