mirror of
https://github.com/ansible/awx.git
synced 2026-02-27 07:56:06 -03:30
Job detail page re-refactor
Host events viewer. Search now wired up. HTML re-load working. Table scrolling works.
This commit is contained in:
@@ -1009,7 +1009,7 @@ function JobDetailController ($location, $rootScope, $scope, $compile, $routePar
|
|||||||
scope: scope,
|
scope: scope,
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
name: name,
|
||||||
url: scope.job.related.job_events + '?event__icontains=runner'
|
url: scope.job.related.job_events
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,15 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities'])
|
|||||||
function($log, $compile, CreateDialog, Wait, GetBasePath, Empty, GetEvents) {
|
function($log, $compile, CreateDialog, Wait, GetBasePath, Empty, GetEvents) {
|
||||||
return function(params) {
|
return function(params) {
|
||||||
var parent_scope = params.scope,
|
var parent_scope = params.scope,
|
||||||
|
scope = parent_scope.$new(true),
|
||||||
url = params.url,
|
url = params.url,
|
||||||
host_id = params.id,
|
|
||||||
host_name = params.name,
|
|
||||||
title = params.title, //optional
|
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) {
|
if (scope.removeModalReady) {
|
||||||
scope.removeModalReady();
|
scope.removeModalReady();
|
||||||
@@ -37,29 +39,52 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities'])
|
|||||||
scope.removeEventReady = scope.$on('EventsReady', function(e, data) {
|
scope.removeEventReady = scope.$on('EventsReady', function(e, data) {
|
||||||
var elem, html;
|
var elem, html;
|
||||||
|
|
||||||
//scope.host_events = data.results;
|
html = buildTable(data);
|
||||||
//$log.debug(scope.host_events);
|
$('#host-events').html(html);
|
||||||
|
elem = angular.element(document.getElementById('host-events-modal-dialog'));
|
||||||
|
$compile(elem)(scope);
|
||||||
|
|
||||||
scope.host_events = data.results;
|
CreateDialog({
|
||||||
scope.host_events_search_name = host_name;
|
scope: scope,
|
||||||
scope.host_events_search_status = 'all';
|
width: 675,
|
||||||
scope.host_events = [];
|
height: 600,
|
||||||
html = "<table class=\"table\">\n";
|
minWidth: 450,
|
||||||
html += "<thead>\n";
|
callback: 'ModalReady',
|
||||||
html += "<tr><th class=\"col-md-3\">Status</th>" +
|
id: 'host-events-modal-dialog',
|
||||||
"<th class=\"col-md-3\">Play</th>" +
|
onResizeStop: fixHeight,
|
||||||
"<th class=\"col-md-3\">Task</th>" +
|
title: ( (title) ? title : 'Host Events' ),
|
||||||
"<th class=\"col-md-3\">Result</th></tr>\n";
|
onOpen: function() {
|
||||||
html += "</thead>\n";
|
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";
|
html += "<tbody>\n";
|
||||||
data.results.forEach(function(result) {
|
data.results.forEach(function(result) {
|
||||||
var msg = '',
|
var msg = '',
|
||||||
status = 'ok',
|
status = 'ok',
|
||||||
status_text = '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;
|
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";
|
msg = "No hosts remaining";
|
||||||
}
|
}
|
||||||
if (result.event === 'runner_on_unreachable') {
|
if (result.event === 'runner_on_unreachable') {
|
||||||
@@ -75,54 +100,86 @@ angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities'])
|
|||||||
status_text = 'Changed';
|
status_text = 'Changed';
|
||||||
}
|
}
|
||||||
html += "<tr ng-click=\"showDetails()\" class=\"cursor-pointer\" aw-tool-tip=\"Click to view details\" data-placement=\"top\">\n";
|
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 class=\"col-md-3\"><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 class=\"col-md-3\"><a href=\"\">" + result.play + "</a></td>\n";
|
||||||
html += "<td><a href=\"\">" + result.task + "</a></td>\n";
|
html += "<td class=\"col-md-3\"><a href=\"\">" + result.task + "</a></td>\n";
|
||||||
html += "<td><a href=\"\">" + msg + "</a></td>";
|
html += "<td class=\"col-md-3\"><a href=\"\">" + msg + "</a></td>";
|
||||||
html += "</tr>"
|
html += "</tr>";
|
||||||
});
|
});
|
||||||
html += "</tbody>\n";
|
html += "</tbody>\n";
|
||||||
html += "</table>\n";
|
html += "</table>\n";
|
||||||
$('#host-events').html(html);
|
return html;
|
||||||
|
};
|
||||||
|
|
||||||
elem = angular.element(document.getElementById('host-events-modal-dialog'));
|
fixHeight = function() {
|
||||||
$compile(elem)(scope);
|
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);
|
||||||
CreateDialog({
|
$log.debug('set height to: ' + available_height);
|
||||||
scope: scope,
|
};
|
||||||
width: 675,
|
|
||||||
height: 600,
|
|
||||||
minWidth: 450,
|
|
||||||
callback: 'ModalReady',
|
|
||||||
id: 'host-events-modal-dialog',
|
|
||||||
// onResizeStop: resizeText,
|
|
||||||
title: ( (title) ? title : 'Host Events' )
|
|
||||||
//onOpen: function() {
|
|
||||||
//}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
GetEvents({
|
GetEvents({
|
||||||
url: url,
|
url: url,
|
||||||
scope: scope
|
scope: scope,
|
||||||
|
callback: 'EventsReady'
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.modalOK = function() {
|
scope.modalOK = function() {
|
||||||
$('#host-events-modal-dialog').dialog('close');
|
$('#host-events-modal-dialog').dialog('close');
|
||||||
scope.$destroy();
|
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) {
|
.factory('GetEvents', ['Wait', 'Rest', 'ProcessErrors', function(Wait, Rest, ProcessErrors) {
|
||||||
return function(params) {
|
return function(params) {
|
||||||
var url = params.url,
|
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¬__event=runner_on_skipped';
|
||||||
|
}
|
||||||
|
|
||||||
Wait('start');
|
Wait('start');
|
||||||
Rest.setUrl(url);
|
Rest.setUrl(url);
|
||||||
Rest.get()
|
Rest.get()
|
||||||
.success(function(data) {
|
.success(function(data) {
|
||||||
scope.$emit('EventsReady', data);
|
scope.$emit(callback, data);
|
||||||
})
|
})
|
||||||
.error(function(data, status) {
|
.error(function(data, status) {
|
||||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
||||||
|
|||||||
@@ -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: { },
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -15,17 +15,22 @@
|
|||||||
|
|
||||||
|
|
||||||
#host-events-modal-dialog {
|
#host-events-modal-dialog {
|
||||||
|
overflow: hidden;
|
||||||
|
i {
|
||||||
|
font-size: 12px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
#search-form {
|
#search-form {
|
||||||
margin-left: 7px;
|
margin-left: 7px;
|
||||||
}
|
}
|
||||||
#host-events-search-name {
|
#host-events-search-name {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
padding-right: 15px;
|
||||||
}
|
}
|
||||||
#search-form-input-icons {
|
#search-form-input-icons {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 3px;
|
|
||||||
top: 5px;
|
top: 5px;
|
||||||
z-index: 100;
|
left: 235px;
|
||||||
a {
|
a {
|
||||||
color: #a9a9a9;
|
color: #a9a9a9;
|
||||||
}
|
}
|
||||||
@@ -36,10 +41,38 @@
|
|||||||
#status-field {
|
#status-field {
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
|
#host-events-table {
|
||||||
table {
|
|
||||||
margin-top: 15px;
|
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 {
|
#jobs-detail {
|
||||||
|
|||||||
20
awx/ui/static/lib/angular-scheduler/package.json
Normal file
20
awx/ui/static/lib/angular-scheduler/package.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
36
awx/ui/static/lib/socket.io-client/package.json
Normal file
36
awx/ui/static/lib/socket.io-client/package.json
Normal 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" }
|
||||||
|
}
|
||||||
@@ -268,7 +268,7 @@
|
|||||||
<form id="search-form" class="form-inline">
|
<form id="search-form" class="form-inline">
|
||||||
<div class="form-group" style="position:relative;">
|
<div class="form-group" style="position:relative;">
|
||||||
<label>Search</label>
|
<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">
|
<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="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>
|
<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>
|
||||||
<div class="form-group" id="status-field">
|
<div class="form-group" id="status-field">
|
||||||
<label>Status</label>
|
<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="all">All</option>
|
||||||
<option value="changed">Changed</option>
|
<option value="changed">Changed</option>
|
||||||
<option value="failed">Failed</option>
|
<option value="failed">Failed</option>
|
||||||
@@ -285,9 +285,19 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</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 id="host-events"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user