From 87965645b5d3d41c85217197f8c0d00d0f501c4e Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Tue, 15 Apr 2014 16:18:07 -0400 Subject: [PATCH] Latest job detail page changes. Fix for AC-1189- job template schedules. --- awx/ui/static/js/controllers/JobDetail.js | 11 ++- awx/ui/static/js/helpers/JobDetail.js | 102 +++++++++++++++------ awx/ui/static/js/helpers/Schedules.js | 9 +- awx/ui/static/less/ansible-ui.less | 62 ++++++++----- awx/ui/static/partials/job_detail.html | 104 ++++++++++++---------- 5 files changed, 190 insertions(+), 98 deletions(-) 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 @@
+
-
+
Options
@@ -52,57 +53,65 @@
- more - more -
-
+ + +
-
-
+
Plays
+
+
    +
  • + {{play.name }} +
      +
    • + {{child.name }} +
    • +
    +
  • +
+
-
Plays
-
-
    -
  • - {{play.name }} -
      -
    • - {{child.name }} -
    • -
    -
  • -
+
Tasks
+
+
    +
  • {{ task.name }}
  • +
+
+ +
Host Details
+
+

{{ activeTaskName }}

+ + + + + + + + + + + + + +
HostResults
{{ result.host_name }}
{{ result.results }}
+
+
-

Tasks

-
+
+
Hosts Summary
+
- - - - - - - - - - -
StatusName
{{ task.name }}
-
- -

Hosts

-
- - - - - - - - + + + + + @@ -116,7 +125,12 @@
NameOKChangedUnreachableFailedNameOKChangedUnreachableFailed
- +