diff --git a/awx/ui/client/src/job-results/job-results.block.less b/awx/ui/client/src/job-results/job-results.block.less
index e5ed7beddc..c05d872b74 100644
--- a/awx/ui/client/src/job-results/job-results.block.less
+++ b/awx/ui/client/src/job-results/job-results.block.less
@@ -232,3 +232,13 @@ job-results-standard-out {
margin-left: 10px;
color: @default-icon;
}
+
+.JobResults-seeMoreLess {
+ color: #337AB7;
+ margin: 4px 0px;
+ text-transform: uppercase;
+ padding: 2px 0px;
+ cursor: pointer;
+ border-radius: 5px;
+ font-size: 11px;
+}
diff --git a/awx/ui/client/src/job-results/job-results.controller.js b/awx/ui/client/src/job-results/job-results.controller.js
index e880994a71..95d500b05c 100644
--- a/awx/ui/client/src/job-results/job-results.controller.js
+++ b/awx/ui/client/src/job-results/job-results.controller.js
@@ -22,6 +22,8 @@ function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTy
var currentContext = 1;
$scope.firstCounterFromSocket = -1;
+ $scope.explanationLimit = 150;
+
// if the user enters the page mid-run, reset the search to include a param
// to only grab events less than the first counter from the websocket events
toDestroy.push($scope.$watch('firstCounterFromSocket', function(counter) {
diff --git a/awx/ui/client/src/job-results/job-results.partial.html b/awx/ui/client/src/job-results/job-results.partial.html
index ded3071ed5..7f5d653bca 100644
--- a/awx/ui/client/src/job-results/job-results.partial.html
+++ b/awx/ui/client/src/job-results/job-results.partial.html
@@ -75,6 +75,22 @@
+
+
diff --git a/awx/ui/client/src/standard-out/inventory-sync/standard-out-inventory-sync.partial.html b/awx/ui/client/src/standard-out/inventory-sync/standard-out-inventory-sync.partial.html
index 9907c3df64..4cd0ec3d82 100644
--- a/awx/ui/client/src/standard-out/inventory-sync/standard-out-inventory-sync.partial.html
+++ b/awx/ui/client/src/standard-out/inventory-sync/standard-out-inventory-sync.partial.html
@@ -41,6 +41,19 @@
+
+
LICENSE ERROR
diff --git a/awx/ui/client/src/standard-out/standard-out.block.less b/awx/ui/client/src/standard-out/standard-out.block.less
index 3ceb1f695e..bf0ca8727b 100644
--- a/awx/ui/client/src/standard-out/standard-out.block.less
+++ b/awx/ui/client/src/standard-out/standard-out.block.less
@@ -158,3 +158,13 @@ standard-out-log {
.StandardOut-actionButton + a {
margin-left: 15px;
}
+
+.StandardOut-seeMoreLess {
+ color: #337AB7;
+ margin: 4px 0px;
+ text-transform: uppercase;
+ padding: 2px 0px;
+ cursor: pointer;
+ border-radius: 5px;
+ font-size: 11px;
+}
diff --git a/awx/ui/client/src/standard-out/standard-out.controller.js b/awx/ui/client/src/standard-out/standard-out.controller.js
index 1b2743f4f8..97b85f68b2 100644
--- a/awx/ui/client/src/standard-out/standard-out.controller.js
+++ b/awx/ui/client/src/standard-out/standard-out.controller.js
@@ -12,7 +12,8 @@
export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
GetBasePath, Rest, ProcessErrors, Empty, GetChoices, LookUpName,
- ParseTypeChange, ParseVariableString, RelaunchJob, DeleteJob, Wait, i18n) {
+ ParseTypeChange, ParseVariableString, RelaunchJob, DeleteJob, Wait, i18n,
+ fieldChoices, fieldLabels) {
var job_id = $stateParams.id,
jobType = $state.current.data.jobType;
@@ -22,6 +23,8 @@ export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
$scope.stdoutFullScreen = false;
$scope.toggleStdoutFullscreenTooltip = i18n._("Expand Output");
+ $scope.explanationLimit = 150;
+
// Listen for job status updates that may come across via sockets. We need to check the payload
// to see whethere the updated job is the one that we're currently looking at.
$scope.$on(`ws-jobs`, function(e, data) {
@@ -35,6 +38,37 @@ export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
}
});
+ $scope.previousTaskFailed = false;
+
+ $scope.$watch('job.job_explanation', function(explanation) {
+ if (explanation && explanation.split(":")[0] === "Previous Task Failed") {
+ $scope.previousTaskFailed = true;
+
+ var taskObj = JSON.parse(explanation.substring(explanation.split(":")[0].length + 1));
+ // return a promise from the options request with the permission type choices (including adhoc) as a param
+ var fieldChoice = fieldChoices({
+ $scope: $scope,
+ url: GetBasePath('unified_jobs'),
+ field: 'type'
+ });
+
+ // manipulate the choices from the options request to be set on
+ // scope and be usable by the list form
+ fieldChoice.then(function (choices) {
+ choices =
+ fieldLabels({
+ choices: choices
+ });
+ $scope.explanation_fail_type = choices[taskObj.job_type];
+ $scope.explanation_fail_name = taskObj.job_name;
+ $scope.explanation_fail_id = taskObj.job_id;
+ $scope.task_detail = $scope.explanation_fail_type + " failed for " + $scope.explanation_fail_name + " with ID " + $scope.explanation_fail_id + ".";
+ });
+ } else {
+ $scope.previousTaskFailed = false;
+ }
+ });
+
// Set the parse type so that CodeMirror knows how to display extra params YAML/JSON
$scope.parseType = 'yaml';
@@ -242,4 +276,5 @@ export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
JobStdoutController.$inject = [ '$rootScope', '$scope', '$state',
'$stateParams', 'GetBasePath', 'Rest', 'ProcessErrors',
'Empty', 'GetChoices', 'LookUpName', 'ParseTypeChange',
- 'ParseVariableString', 'RelaunchJob', 'DeleteJob', 'Wait', 'i18n'];
+ 'ParseVariableString', 'RelaunchJob', 'DeleteJob', 'Wait', 'i18n',
+ 'fieldChoices', 'fieldLabels'];