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 8d0e8a0219..ffdb158705 100644
--- a/awx/ui/client/src/standard-out/standard-out.block.less
+++ b/awx/ui/client/src/standard-out/standard-out.block.less
@@ -1,28 +1,22 @@
@import "../shared/branding/colors.default.less";
+@import "awx/ui/client/src/shared/layouts/one-plus-two.less";
/** @define StandardOut */
-.StandardOut {
- height: 100%;
- display: flex;
- flex-direction: row;
+.StandardOut-container {
+ .OnePlusTwo-container;
}
.StandardOut-leftPanel {
- flex: 0 0 400px;
- margin-right: 20px;
+ .OnePlusTwo-left--panel(590px);
}
.StandardOut-rightPanel {
- flex: 1 0;
+ .OnePlusTwo-right--panel(590px);
}
.StandardOut-panelHeader {
- color: @default-interface-txt;
- font-size: 14px;
- font-weight: bold;
- text-transform: uppercase;
- display: flex;
+ .OnePlusTwo-panelHeader
}
.StandardOut-consoleOutput {
@@ -30,31 +24,28 @@
min-height: 200px;
background-color: @default-secondary-bg;
border-radius: 5px;
- height: 300px;
+ height: ~"calc(100% - 74px)";
overflow: scroll;
}
.StandardOut-details {
- margin-top: 25px;
+ .OnePlusTwo-left--details;
}
.StandardOut-detailsRow {
- display: flex;
+ .OnePlusTwo-left--detailsRow;
}
-.StandardOut-detailsRow:not(:last-child) {
- margin-bottom: 20px;
+.StandardOut-detailsRow + .StandardOut-detailsRow {
+ margin-top: 20px;
}
.StandardOut-detailsLabel {
- width: 130px;
- flex: 0 0 130px;
- color: @default-interface-txt;
- text-transform: uppercase;
+ .OnePlusTwo-left--detailsLabel;
}
.StandardOut-detailsContent {
- flex: 1 0;
+ .OnePlusTwo-left--detailsContent;
}
.StandardOut-statusText {
@@ -66,7 +57,7 @@
}
.StandardOut-preContainer {
- height: 300px;
+ height: 100%;
}
.StandardOut-panelHeaderText {
@@ -105,14 +96,3 @@
.StandardOut-actionButton + a {
margin-left: 15px;
}
-
-@standardout-breakpoint: 900px;
-
-@media screen and (max-width: @standardout-breakpoint) {
- .StandardOut {
- flex-direction: column;
- }
- .StandardOut-leftPanel {
- margin-right: 0px;
- }
-}
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 152d2a8a5d..b3b363e064 100644
--- a/awx/ui/client/src/standard-out/standard-out.controller.js
+++ b/awx/ui/client/src/standard-out/standard-out.controller.js
@@ -32,118 +32,124 @@ export function JobStdoutController ($rootScope, $scope, $state, $stateParams, C
$scope.job.status = data.status;
}
- // TODO: when the job completes we should refresh the job data so that we pull in the finish
- // timestamp as well as the run time.
+ if (data.status === 'failed' || data.status === 'canceled' || data.status === 'error' || data.status === 'successful') {
+ // Go out and refresh the job details
+ getJobDetails();
+ }
});
- // Go out and get the job details based on the job type. jobType gets defined
- // in the data block of the route declaration for each of the different types
- // of stdout jobs.
- Rest.setUrl(GetBasePath('base') + jobType + '/' + job_id + '/');
- Rest.get()
- .success(function(data) {
- $scope.job = data;
- $scope.job_template_name = data.name;
- $scope.created_by = data.summary_fields.created_by;
- $scope.project_name = (data.summary_fields.project) ? data.summary_fields.project.name : '';
- $scope.inventory_name = (data.summary_fields.inventory) ? data.summary_fields.inventory.name : '';
- $scope.job_template_url = '/#/job_templates/' + data.unified_job_template;
- $scope.inventory_url = ($scope.inventory_name && data.inventory) ? '/#/inventories/' + data.inventory : '';
- $scope.project_url = ($scope.project_name && data.project) ? '/#/projects/' + data.project : '';
- $scope.credential_name = (data.summary_fields.credential) ? data.summary_fields.credential.name : '';
- $scope.credential_url = (data.credential) ? '/#/credentials/' + data.credential : '';
- $scope.cloud_credential_url = (data.cloud_credential) ? '/#/credentials/' + data.cloud_credential : '';
- $scope.playbook = data.playbook;
- $scope.credential = data.credential;
- $scope.cloud_credential = data.cloud_credential;
- $scope.forks = data.forks;
- $scope.limit = data.limit;
- $scope.verbosity = data.verbosity;
- $scope.job_tags = data.job_tags;
+ function getJobDetails() {
- // If we have a source then we have to go get the source choices from the server
- if (!Empty(data.source)) {
- if ($scope.removeChoicesReady) {
- $scope.removeChoicesReady();
- }
- $scope.removeChoicesReady = $scope.$on('ChoicesReady', function() {
- $scope.source_choices.every(function(e) {
- if (e.value === data.source) {
- $scope.source = e.label;
- return false;
- }
- return true;
+ // Go out and get the job details based on the job type. jobType gets defined
+ // in the data block of the route declaration for each of the different types
+ // of stdout jobs.
+ Rest.setUrl(GetBasePath('base') + jobType + '/' + job_id + '/');
+ Rest.get()
+ .success(function(data) {
+ $scope.job = data;
+ $scope.job_template_name = data.name;
+ $scope.created_by = data.summary_fields.created_by;
+ $scope.project_name = (data.summary_fields.project) ? data.summary_fields.project.name : '';
+ $scope.inventory_name = (data.summary_fields.inventory) ? data.summary_fields.inventory.name : '';
+ $scope.job_template_url = '/#/job_templates/' + data.unified_job_template;
+ $scope.inventory_url = ($scope.inventory_name && data.inventory) ? '/#/inventories/' + data.inventory : '';
+ $scope.project_url = ($scope.project_name && data.project) ? '/#/projects/' + data.project : '';
+ $scope.credential_name = (data.summary_fields.credential) ? data.summary_fields.credential.name : '';
+ $scope.credential_url = (data.credential) ? '/#/credentials/' + data.credential : '';
+ $scope.cloud_credential_url = (data.cloud_credential) ? '/#/credentials/' + data.cloud_credential : '';
+ $scope.playbook = data.playbook;
+ $scope.credential = data.credential;
+ $scope.cloud_credential = data.cloud_credential;
+ $scope.forks = data.forks;
+ $scope.limit = data.limit;
+ $scope.verbosity = data.verbosity;
+ $scope.job_tags = data.job_tags;
+
+ // If we have a source then we have to go get the source choices from the server
+ if (!Empty(data.source)) {
+ if ($scope.removeChoicesReady) {
+ $scope.removeChoicesReady();
+ }
+ $scope.removeChoicesReady = $scope.$on('ChoicesReady', function() {
+ $scope.source_choices.every(function(e) {
+ if (e.value === data.source) {
+ $scope.source = e.label;
+ return false;
+ }
+ return true;
+ });
+ });
+ // GetChoices can be found in the helper: StandardOut.js
+ // It attaches the source choices to $scope.source_choices.
+ // Then, when the callback is fired, $scope.source is bound
+ // to the corresponding label.
+ GetChoices({
+ scope: $scope,
+ url: GetBasePath('inventory_sources'),
+ field: 'source',
+ variable: 'source_choices',
+ choice_name: 'choices',
+ callback: 'ChoicesReady'
});
- });
- // GetChoices can be found in the helper: StandardOut.js
- // It attaches the source choices to $scope.source_choices.
- // Then, when the callback is fired, $scope.source is bound
- // to the corresponding label.
- GetChoices({
- scope: $scope,
- url: GetBasePath('inventory_sources'),
- field: 'source',
- variable: 'source_choices',
- choice_name: 'choices',
- callback: 'ChoicesReady'
- });
- }
-
- // LookUpName can be found in the helper: StandardOut.js
- // It attaches the name that it gets (based on the url)
- // to the $scope variable defined by the attribute scope_var.
- if (!Empty(data.credential)) {
- LookUpName({
- scope: $scope,
- scope_var: 'credential',
- url: GetBasePath('credentials') + data.credential + '/'
- });
- }
-
- if (!Empty(data.inventory)) {
- LookUpName({
- scope: $scope,
- scope_var: 'inventory',
- url: GetBasePath('inventory') + data.inventory + '/'
- });
- }
-
- if (!Empty(data.project)) {
- LookUpName({
- scope: $scope,
- scope_var: 'project',
- url: GetBasePath('projects') + data.project + '/'
- });
- }
-
- if (!Empty(data.cloud_credential)) {
- LookUpName({
- scope: $scope,
- scope_var: 'cloud_credential',
- url: GetBasePath('credentials') + data.cloud_credential + '/'
- });
- }
-
- if (!Empty(data.inventory_source)) {
- LookUpName({
- scope: $scope,
- scope_var: 'inventory_source',
- url: GetBasePath('inventory_sources') + data.inventory_source + '/'
- });
- }
-
- // If the job isn't running we want to clear out the interval that goes out and checks for stdout updates.
- // This interval is defined in the standard out log directive controller.
- if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') {
- if ($rootScope.jobStdOutInterval) {
- window.clearInterval($rootScope.jobStdOutInterval);
}
- }
- })
- .error(function(data, status) {
- ProcessErrors($scope, data, status, null, { hdr: 'Error!',
- msg: 'Failed to retrieve job: ' + job_id + '. GET returned: ' + status });
- });
+
+ // LookUpName can be found in the helper: StandardOut.js
+ // It attaches the name that it gets (based on the url)
+ // to the $scope variable defined by the attribute scope_var.
+ if (!Empty(data.credential)) {
+ LookUpName({
+ scope: $scope,
+ scope_var: 'credential',
+ url: GetBasePath('credentials') + data.credential + '/'
+ });
+ }
+
+ if (!Empty(data.inventory)) {
+ LookUpName({
+ scope: $scope,
+ scope_var: 'inventory',
+ url: GetBasePath('inventory') + data.inventory + '/'
+ });
+ }
+
+ if (!Empty(data.project)) {
+ LookUpName({
+ scope: $scope,
+ scope_var: 'project',
+ url: GetBasePath('projects') + data.project + '/'
+ });
+ }
+
+ if (!Empty(data.cloud_credential)) {
+ LookUpName({
+ scope: $scope,
+ scope_var: 'cloud_credential',
+ url: GetBasePath('credentials') + data.cloud_credential + '/'
+ });
+ }
+
+ if (!Empty(data.inventory_source)) {
+ LookUpName({
+ scope: $scope,
+ scope_var: 'inventory_source',
+ url: GetBasePath('inventory_sources') + data.inventory_source + '/'
+ });
+ }
+
+ // If the job isn't running we want to clear out the interval that goes out and checks for stdout updates.
+ // This interval is defined in the standard out log directive controller.
+ if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') {
+ if ($rootScope.jobStdOutInterval) {
+ window.clearInterval($rootScope.jobStdOutInterval);
+ }
+ }
+ })
+ .error(function(data, status) {
+ ProcessErrors($scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to retrieve job: ' + job_id + '. GET returned: ' + status });
+ });
+
+ }
// TODO: this is currently not used but is necessary for cases where sockets
// are not available and a manual refresh trigger is needed.
@@ -156,6 +162,8 @@ export function JobStdoutController ($rootScope, $scope, $state, $stateParams, C
$scope.stdoutFullScreen = !$scope.stdoutFullScreen;
}
+ getJobDetails();
+
}
JobStdoutController.$inject = [ '$rootScope', '$scope', '$state', '$stateParams', 'ClearScope', 'GetBasePath', 'Rest', 'ProcessErrors', 'Empty', 'GetChoices', 'LookUpName'];