diff --git a/awx/ui/static/js/controllers/JobDetail.js b/awx/ui/static/js/controllers/JobDetail.js
index 6fbc24042a..0120953661 100644
--- a/awx/ui/static/js/controllers/JobDetail.js
+++ b/awx/ui/static/js/controllers/JobDetail.js
@@ -8,7 +8,7 @@
'use strict';
function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest, ProcessErrors, DigestEvents,
- SelectPlay) {
+ SelectPlay, SelectTask) {
ClearScope();
@@ -91,8 +91,15 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
id: id
});
};
+
+ $scope.selectTask = function(id) {
+ SelectTask({
+ scope: $scope,
+ id: id
+ });
+ };
}
JobDetailController.$inject = [ '$scope', '$compile', '$routeParams', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath', 'Wait',
- 'Rest', 'ProcessErrors', 'DigestEvents', 'SelectPlay'
+ 'Rest', 'ProcessErrors', 'DigestEvents', 'SelectPlay', 'SelectTask'
];
diff --git a/awx/ui/static/js/helpers/JobDetail.js b/awx/ui/static/js/helpers/JobDetail.js
index 80b9e86303..011a46737d 100644
--- a/awx/ui/static/js/helpers/JobDetail.js
+++ b/awx/ui/static/js/helpers/JobDetail.js
@@ -39,8 +39,8 @@
angular.module('JobDetailHelper', ['Utilities', 'RestServices'])
-.factory('DigestEvents', ['UpdatePlayStatus', 'UpdatePlayNoHostsMatched', 'UpdateHostStatus', 'UpdatePlayChild', 'AddHostResult',
-function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePlayChild, AddHostResult) {
+.factory('DigestEvents', ['UpdatePlayStatus', 'UpdatePlayNoHostsMatched', 'UpdateHostStatus', 'UpdatePlayChild', 'AddHostResult', 'MakeLastRowActive',
+function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePlayChild, AddHostResult, MakeLastRowActive) {
return function(params) {
var scope = params.scope,
events = params.events;
@@ -49,9 +49,11 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
scope.plays.push({
id: event.id,
name: event.play,
- status: (event.failed) ? 'failed' : 'successful',
+ status: (event.changed) ? 'changed' : (event.failed) ? 'failed' : 'none',
children: []
});
+ scope.activePlay = event.id;
+ MakeLastRowActive({ scope: scope, list: scope.plays, field: 'playActiveClass', set: 'activePlay' });
}
if (event.event === 'playbook_on_setup') {
scope.tasks.push({
@@ -63,7 +65,8 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
UpdatePlayStatus({
scope: scope,
play_id: event.parent,
- failed: event.failed
+ failed: event.failed,
+ changed: event.changed
});
}
if (event.event === 'playbook_on_task_start') {
@@ -71,17 +74,19 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
id: event.id,
name: event.task,
play_id: event.parent,
- status: (event.failed) ? 'failed' : 'successful'
+ status: (event.changed) ? 'changed' : (event.failed) ? 'failed' : 'successful'
});
UpdatePlayStatus({
scope: scope,
play_id: event.parent,
- failed: event.failed
+ failed: event.failed,
+ changed: event.changed
});
+ MakeLastRowActive({ scope: scope, list: scope.tasks, field: 'taskActiveClass', set: 'activeTask' });
}
- if (event.event === 'playbook_on_no_hosts_matched') {
+ /*if (event.event === 'playbook_on_no_hosts_matched') {
UpdatePlayNoHostsMatched({ scope: scope, play_id: event.parent });
- }
+ }*/
if (event.event === 'runner_on_failed') {
}
@@ -106,6 +111,22 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
};
}])
+.factory('MakeLastRowActive', [ function() {
+ return function(params) {
+ var scope = params.scope,
+ list = params.list,
+ field = params.field,
+ set = params.set;
+ list.forEach(function(row, idx) {
+ list[idx][field] = '';
+ });
+ if (list.length > 0) {
+ list[list.length - 1][field] = 'active';
+ scope[set] = list[list.length - 1].id;
+ }
+ };
+}])
+
.factory('UpdatePlayChild', [ function() {
return function(params) {
var scope = params.scope,
@@ -144,10 +165,11 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
return function(params) {
var scope = params.scope,
failed = params.failed,
+ changed = params.changed,
id = params.play_id;
scope.plays.every(function(play,idx) {
if (play.id === id) {
- scope.plays[idx].status = (failed) ? 'failed' : 'successful';
+ scope.plays[idx].status = (changed) ? 'changed' : (failed) ? 'failed' : 'none';
return false;
}
return true;
@@ -155,14 +177,21 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
};
}])
-.factory('UpdateTaskStatus', [ function() {
+.factory('UpdateTaskStatus', ['UpdatePlayStatus', function(UpdatePlayStatus) {
return function(params) {
var scope = params.scope,
- task_id = params.task_id,
- failed = params.failed;
+ failed = params.failed,
+ changed = params.changed,
+ id = params.task_id;
scope.tasks.every(function (task, i) {
- if (task.id === task_id) {
- scope.tasks[i].status = (failed) ? 'failed' : 'successful';
+ if (task.id === id) {
+ scope.tasks[i].status = (changed) ? 'changed' : (failed) ? 'failed' : 'successful';
+ UpdatePlayStatus({
+ scope: scope,
+ failed: failed,
+ changed: changed,
+ play_id: task.parent
+ });
}
});
};
@@ -212,15 +241,12 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
failed: (status === 'failed') ? 1 : 0
});
}
-
- // Mark task failed
- if (status === 'failed') {
- UpdateTaskStatus({
- scope: scope,
- task_id: task_id,
- failed: true
- });
- }
+ UpdateTaskStatus({
+ scope: scope,
+ task_id: task_id,
+ failed: (status === 'failed' || status === 'unreachable') ? true :false,
+ changed: (status === 'changed') ? true : false
+ });
};
}])
@@ -256,8 +282,9 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
id: id,
status: status,
host_id: host_id,
- play_name: play_name,
- task_name : task_name,
+ task_id: event.parent,
+ task_name: task_name,
+ host_name: event.event_data.host,
module_name: module_name,
module_args: module_args,
results: results,
@@ -271,8 +298,29 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
var scope = params.scope,
id = params.id;
scope.plays.forEach(function(play, idx) {
- scope.plays[idx].playActiveClass = (play.id === id) ? 'active' : '';
+ if (play.id === id) {
+ scope.plays[idx].playActiveClass = 'active';
+ }
+ else {
+ scope.plays[idx].playActiveClass = '';
+ }
});
- scope.selectedPlay = id;
+ scope.activePlay = id;
};
}])
+
+.factory('SelectTask', [ function() {
+ return function(params) {
+ var scope = params.scope,
+ id = params.id;
+ scope.tasks.forEach(function(task, idx) {
+ if (task.id === id) {
+ scope.tasks[idx].taskActiveClass = 'active';
+ }
+ else {
+ scope.tasks[idx].taskActiveClass = '';
+ }
+ });
+ scope.activeTask = id;
+ };
+}]);
diff --git a/awx/ui/static/js/helpers/Schedules.js b/awx/ui/static/js/helpers/Schedules.js
index 788aef629c..48cd64af2a 100644
--- a/awx/ui/static/js/helpers/Schedules.js
+++ b/awx/ui/static/js/helpers/Schedules.js
@@ -164,7 +164,12 @@ angular.module('SchedulesHelper', [ 'Utilities', 'RestServices', 'SchedulesHelpe
url = GetBasePath(base),
scheduler;
- url += (!Empty($routeParams.id)) ? $routeParams.id + '/schedules/' : '';
+ if (!Empty($routeParams.template_id)) {
+ url += $routeParams.template_id + '/schedules/';
+ }
+ else if (!Empty($routeParams.id)) {
+ url += $routeParams.id + '/schedules/';
+ }
if (scope.removeDialogReady) {
scope.removeDialogReady();
@@ -596,4 +601,4 @@ angular.module('SchedulesHelper', [ 'Utilities', 'RestServices', 'SchedulesHelpe
scope.search(list.iterator);
};
- }]);
\ No newline at end of file
+ }]);
diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less
index 9123062d50..c4eeb1ecde 100644
--- a/awx/ui/static/less/ansible-ui.less
+++ b/awx/ui/static/less/ansible-ui.less
@@ -7,22 +7,23 @@
*
*/
-@black: #171717;
-@white: #FFF;
-@warning: #FF9900;
-@red: #da4f49;
-@red-hover: #AE3F3A;
-@green: #5bb75b;
-@blue: #1778c3; /* logo blue */
-@blue-link: #1778c3;
-@blue-dark: #2a6496; /* link hover */
-@grey: #A9A9A9;
-@grey-txt: #707070;
-@well: #f5f5f5; /* well background color */
-@well-border: #e3e3e3;
-@info: #d9edf7; /* alert info background color */
-@info-border: #bce8f1; /* alert info border color */
-@info-color: #3a87ad;
+@active-color: #c6e5e5;
+@black: #171717;
+@blue: #1778c3; /* logo blue */
+@blue-link: #1778c3;
+@blue-dark: #2a6496; /* link hover */
+@green: #5bb75b;
+@grey: #A9A9A9;
+@grey-txt: #707070;
+@info: #d9edf7; /* alert info background color */
+@info-border: #bce8f1; /* alert info border color */
+@info-color: #3a87ad;
+@red: #da4f49;
+@red-hover: #AE3F3A;
+@warning: #FF9900;
+@well: #f5f5f5; /* well background color */
+@well-border: #e3e3e3;
+@white: #FFF;
@tip-background: #0088CC;
@tip-color: #fff;
@@ -65,6 +66,7 @@ body.modal-open {
.capitalize { text-transform: capitalize; }
.grey-txt { color: @grey; }
.text-center { text-align: center !important; }
+.cursor-pointer { cursor: pointer }
.red-txt,
a.red-txt:visited,
@@ -899,7 +901,7 @@ input[type="checkbox"].checkbox-no-label {
.table-hover-inverse tbody tr:hover > td,
.table-hover-inverse tbody tr:hover > th {
- background-color: #c6e5e5;
+ background-color: @active-color;
}
.table > thead > tr > td.success,
@@ -914,13 +916,13 @@ input[type="checkbox"].checkbox-no-label {
.table > thead > tr.success > th,
.table > tbody > tr.success > th,
.table > tfoot > tr.success > th {
- background-color: #c6e5e5;
+ background-color: @active-color;
}
.table-hover > tbody > tr > td.success:hover,
.table-hover > tbody > tr > th.success:hover,
.table-hover > tbody > tr.success:hover > td,
.table-hover > tbody > tr.success:hover > th {
- background-color: #c6e5e5;
+ background-color: @active-color;
}
.table-summary thead > tr > th,
@@ -1588,11 +1590,11 @@ tr td button i {
margin-bottom: 0;
}
.table>tbody>tr>td {
- border-top-color: #fff;
+ border-top-color: @well;
padding: 0;
}
.table>thead>tr>th {
- border-bottom-color: #fff;
+ border-bottom-color: @well;
padding: 0;
}
ul {
@@ -1621,7 +1623,23 @@ tr td button i {
}
.job-list li.active {
- background-color: @white;
+ background-color: @active-color;
+}
+
+.job_plays, .job_tasks, .job_hosts {
+ height: 150px;
+ overflow-y: auto;
+ overflow-x: none;
+}
+
+.host_details {
+ pre {
+ border: none;
+ max-height: 100px;
+ overflow: auto;
+ margin: 0;
+ padding: 0;
+ }
}
.scroll-up-indicator {
diff --git a/awx/ui/static/partials/job_detail.html b/awx/ui/static/partials/job_detail.html
index 04db499a5c..d2bc500a11 100644
--- a/awx/ui/static/partials/job_detail.html
+++ b/awx/ui/static/partials/job_detail.html
@@ -3,8 +3,9 @@
+
-
+
+
+
-
-
+
Plays
+
-
Plays
-
-
+
Tasks
+
+
+
Host Details
+
+
{{ activeTaskName }}
+
+
+
+ | Host |
+ Results |
+
+
+
+
+ | {{ result.host_name }} |
+ {{ result.results }} |
+
+
+
+
+
-
Tasks
-
+
+
Hosts Summary
+
- | Status |
- Name |
-
-
-
-
- |
- {{ task.name }} |
-
-
-
-
-
-
Hosts
-
-
-
-
- | Name |
- OK |
- Changed |
- Unreachable |
- Failed |
+ Name |
+ OK |
+ Changed |
+ Unreachable |
+ Failed |
@@ -116,7 +125,12 @@
-
+