mirror of
https://github.com/ansible/awx.git
synced 2026-02-12 23:24:48 -03:30
Fixed Loading message and Pagination widget fouc. Start of new job detail page.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
var urlPrefix = $basePath;
|
||||
|
||||
angular.module('ansible', [
|
||||
angular.module('Tower', [
|
||||
'ngRoute',
|
||||
'ngSanitize',
|
||||
'ngCookies',
|
||||
@@ -97,7 +97,8 @@ angular.module('ansible', [
|
||||
'JobsListDefinition',
|
||||
'LogViewerStatusDefinition',
|
||||
'LogViewerHelper',
|
||||
'LogViewerOptionsDefinition'
|
||||
'LogViewerOptionsDefinition',
|
||||
'JobDetailHelper'
|
||||
])
|
||||
|
||||
.constant('AngularScheduler.partials', $basePath + 'lib/angular-scheduler/lib/')
|
||||
@@ -107,11 +108,18 @@ angular.module('ansible', [
|
||||
|
||||
.config(['$routeProvider',
|
||||
function ($routeProvider) {
|
||||
|
||||
$routeProvider.
|
||||
|
||||
when('/jobs', {
|
||||
templateUrl: urlPrefix + 'partials/jobs.html',
|
||||
controller: 'JobsListController'
|
||||
}).
|
||||
|
||||
when('/jobs/:id', {
|
||||
templateUrl: urlPrefix + 'partials/job_detail.html',
|
||||
controller: 'JobDetailController'
|
||||
}).
|
||||
|
||||
when('/job_events/:id', {
|
||||
templateUrl: urlPrefix + 'partials/job_events.html',
|
||||
@@ -405,7 +413,6 @@ angular.module('ansible', [
|
||||
$rootScope.sessionTimer = Timer.init();
|
||||
|
||||
$rootScope.$on("$routeChangeStart", function (event, next) {
|
||||
|
||||
// Before navigating away from current tab, make sure the primary view is visible
|
||||
if ($('#stream-container').is(':visible')) {
|
||||
HideStream();
|
||||
|
||||
@@ -23,7 +23,7 @@ function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
mode = (base === 'credentials') ? 'edit' : 'select',
|
||||
url;
|
||||
|
||||
|
||||
view.inject(list, { mode: mode, scope: $scope });
|
||||
|
||||
$scope.selected = [];
|
||||
|
||||
88
awx/ui/static/js/controllers/JobDetail.js
Normal file
88
awx/ui/static/js/controllers/JobDetail.js
Normal file
@@ -0,0 +1,88 @@
|
||||
/************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobDetail.js
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest, ProcessErrors, DigestEvents) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
var job_id = $routeParams.id,
|
||||
job;
|
||||
|
||||
/*LoadBreadCrumbs();
|
||||
|
||||
e = angular.element(document.getElementById('breadcrumbs'));
|
||||
e.html(Breadcrumbs({ list: { editTitle: 'Jobs' } , mode: 'edit' }));
|
||||
$compile(e)($scope);
|
||||
*/
|
||||
|
||||
$scope.plays = [];
|
||||
$scope.tasks = [];
|
||||
|
||||
// Apply each event to the view
|
||||
if ($scope.removeEventsReady) {
|
||||
$scope.removeEventsReady();
|
||||
}
|
||||
$scope.removeEventsReady = $scope.$on('EventsReady', function(e, events) {
|
||||
DigestEvents({
|
||||
scope: $scope,
|
||||
events: events
|
||||
});
|
||||
});
|
||||
|
||||
// Get events, page size 50
|
||||
if ($scope.removeJobReady) {
|
||||
$scope.removeJobReady();
|
||||
}
|
||||
$scope.removeJobReady = $scope.$on('JobReady', function(e, next) {
|
||||
if (next) {
|
||||
Rest.setUrl(next);
|
||||
Rest.get()
|
||||
.success(function(data) {
|
||||
$scope.$emit('EventsReady', data.results);
|
||||
if (data.next) {
|
||||
$scope.$emit('JobReady', data.next);
|
||||
}
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Failed to retrieve job events: ' + next + ' GET returned: ' + status });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Load the job record
|
||||
Rest.setUrl(GetBasePath('jobs') + job_id + '/');
|
||||
Rest.get()
|
||||
.success(function(data) {
|
||||
job = data;
|
||||
$scope.job_template_name = data.name;
|
||||
$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.job_type = data.job_type;
|
||||
$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;
|
||||
$scope.$emit('JobReady', data.related.job_events + '?page_size=50&order_by=id');
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Failed to retrieve job: ' + $routeParams.id + '. GET returned: ' + status });
|
||||
});
|
||||
}
|
||||
|
||||
JobDetailController.$inject = [ '$scope', '$compile', '$routeParams', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath', 'Wait',
|
||||
'Rest', 'ProcessErrors', 'DigestEvents'
|
||||
];
|
||||
@@ -209,7 +209,7 @@ function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateI
|
||||
scope[list.iterator + 'SearchFieldLabel'] = list.fields.has_active_failures.label;
|
||||
scope[list.iterator + 'SearchSelectValue'] = { value: 1 };
|
||||
}
|
||||
scope.search(list.iterator);
|
||||
scope.search(list.iterator, null, true);
|
||||
};
|
||||
}])
|
||||
|
||||
|
||||
108
awx/ui/static/js/helpers/JobDetail.js
Normal file
108
awx/ui/static/js/helpers/JobDetail.js
Normal file
@@ -0,0 +1,108 @@
|
||||
/************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobDetail.js
|
||||
*
|
||||
* Helper moduler for JobDetails controller
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
# Playbook events will be structured to form the following hierarchy:
|
||||
# - playbook_on_start (once for each playbook file)
|
||||
# - playbook_on_vars_prompt (for each play, but before play starts, we
|
||||
# currently don't handle responding to these prompts)
|
||||
# - playbook_on_play_start (once for each play)
|
||||
# - playbook_on_import_for_host
|
||||
# - playbook_on_not_import_for_host
|
||||
# - playbook_on_no_hosts_matched
|
||||
# - playbook_on_no_hosts_remaining
|
||||
# - playbook_on_setup
|
||||
# - runner_on*
|
||||
# - playbook_on_task_start (once for each task within a play)
|
||||
# - runner_on_failed
|
||||
# - runner_on_ok
|
||||
# - runner_on_error
|
||||
# - runner_on_skipped
|
||||
# - runner_on_unreachable
|
||||
# - runner_on_no_hosts
|
||||
# - runner_on_async_poll
|
||||
# - runner_on_async_ok
|
||||
# - runner_on_async_failed
|
||||
# - runner_on_file_diff
|
||||
# - playbook_on_notify (once for each notification from the play)
|
||||
# - playbook_on_stats
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('JobDetailHelper', ['Utilities', 'RestServices'])
|
||||
|
||||
.factory('DigestEvents', ['UpdatePlayStatus', 'UpdatePlayNoHostsMatched', function(UpdatePlayStatus, UpdatePlayNoHostsMatched) {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
events = params.events;
|
||||
events.forEach(function(event) {
|
||||
if (event.event === 'playbook_on_play_start') {
|
||||
scope.plays.push({
|
||||
id: event.id,
|
||||
name: event.play,
|
||||
status: (event.failed) ? 'failed' : 'successful'
|
||||
});
|
||||
}
|
||||
if (event.event === 'playbook_on_task_start') {
|
||||
scope.tasks.push({
|
||||
id: event.id,
|
||||
name: event.task,
|
||||
play_id: event.parent,
|
||||
status: (event.failed) ? 'failed' : 'successful'
|
||||
});
|
||||
UpdatePlayStatus({ scope: scope, play_id: event.parent, status: event.status });
|
||||
}
|
||||
if (event.event === 'playbook_on_no_hosts_matched') {
|
||||
UpdatePlayNoHostsMatched({ scope: scope, play_id: event.parent });
|
||||
}
|
||||
if (event.event === 'runner_on_failed') {
|
||||
|
||||
}
|
||||
if (event.event === 'playbook_on_stats') {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
}])
|
||||
|
||||
// Update the status of a play
|
||||
.factory('UpdatePlayStatus', [ function() {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
status = params.status,
|
||||
id = params.play_id;
|
||||
scope.plays.every(function(play,idx) {
|
||||
if (play.id === id) {
|
||||
scope.plays[idx].status = (status) ? 'failed' : 'successful';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
}])
|
||||
|
||||
.factory('UpdatePlayNoHostsMatched', [ function() {
|
||||
return function(params) {
|
||||
var scope = params.scope,
|
||||
id = params.play_id;
|
||||
scope.plays.every(function(play,idx) {
|
||||
if (play.id === id) {
|
||||
scope.plays[idx].status = 'none';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
||||
|
||||
|
||||
@@ -86,10 +86,15 @@ angular.module('JobsHelper', ['Utilities', 'RestServices', 'FormGenerator', 'Job
|
||||
list = scope.queued_jobs;
|
||||
}
|
||||
job = Find({ list: list, key: 'id', val: id });
|
||||
LogViewer({
|
||||
scope: scope,
|
||||
url: job.url
|
||||
});
|
||||
if (job.type === 'job') {
|
||||
$location.url('/jobs/' + job.id);
|
||||
}
|
||||
else {
|
||||
LogViewer({
|
||||
scope: scope,
|
||||
url: job.url
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities', 'PaginationHelpers
|
||||
iterator = params.iterator,
|
||||
url = params.url;
|
||||
|
||||
scope[iterator + 'Loading'] = true;
|
||||
//scope[iterator + 'Loading'] = true;
|
||||
scope.current_url = url;
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
@@ -45,6 +45,7 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities', 'PaginationHelpers
|
||||
}
|
||||
scope[set] = data.results;
|
||||
scope[iterator + 'Loading'] = false;
|
||||
scope[iterator + "HidePaginator"] = false;
|
||||
Wait('stop');
|
||||
scope.$emit('PostRefresh');
|
||||
})
|
||||
|
||||
@@ -1569,17 +1569,17 @@ tr td button i {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
.activity-btn {
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
padding-bottom: 2px;
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
/* New job detail page */
|
||||
|
||||
.job-detail-tables {
|
||||
.table>tbody>tr>td {
|
||||
border-top-color: #fff;
|
||||
}
|
||||
}
|
||||
*/
|
||||
.table>thead>tr>th {
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ng-cloak directive */
|
||||
|
||||
|
||||
@@ -792,7 +792,7 @@ angular.module('GeneratorHelpers', [])
|
||||
html += "<!-- Paginate Widget -->\n";
|
||||
html += "<div class=\"row page-row\">\n";
|
||||
html += "<div class=\"col-lg-8 col-md-8\">\n";
|
||||
html += "<ul class=\"pagination\" ng-hide=\"" + iterator + "Loading || " + iterator + "_num_pages <= 1\">\n";
|
||||
html += "<ul class=\"pagination\" ng-hide=\"" + iterator + "HidePaginator || " + iterator + "_num_pages <= 1\">\n";
|
||||
html += "<li ng-hide=\"" + iterator + "_page -5 <= 1 \"><a href ng-click=\"getPage(1,'" + set + "','" + iterator + "')\">" +
|
||||
"<i class=\"fa fa-angle-double-left\"></i></a></li>\n";
|
||||
html += "<li ng-hide=\"" + iterator + "_page -1 <= 0\"><a href " +
|
||||
|
||||
@@ -82,6 +82,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
|
||||
// Reset the scope to prevent displaying old data from our last visit to this list
|
||||
//this.scope[list.name] = null;
|
||||
this.scope[list.iterator] = [];
|
||||
this.scope[list.iterator + "HidePaginator"] = true;
|
||||
|
||||
// Remove any lingering tooltip and popover <div> elements
|
||||
$('.tooltip').each(function() {
|
||||
|
||||
143
awx/ui/static/partials/job_detail.html
Normal file
143
awx/ui/static/partials/job_detail.html
Normal file
@@ -0,0 +1,143 @@
|
||||
<div class="tab-pane" id="jobs">
|
||||
<div ng-cloak id="htmlTemplate">
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="breadcrumbs"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h4>Job Options</h4>
|
||||
<div class="job_options">
|
||||
<table class="table table-condensed">
|
||||
<tbody>
|
||||
<tr ng-show="job_template_url">
|
||||
<td class="col-md-3 col-sm-2">Job Template</td>
|
||||
<td><a ng-href="{{ job_template_url }}">{{ job_template_name }}</a></td>
|
||||
</tr>
|
||||
<tr ng-show="project_url">
|
||||
<td class="col-md-3 col-sm-2">Project</td>
|
||||
<td><a ng-href="{{ project_url }}">{{ project_name }}</a></td>
|
||||
</tr>
|
||||
<tr ng-show="inventory_url">
|
||||
<td class="col-md-3 col-sm-2">Inventory</td>
|
||||
<td><a ng-href="{{ inventory_url }}">{{ inventory_name }}</a></td>
|
||||
</tr>
|
||||
<tr ng-show="playbook">
|
||||
<td class="col-md-3 col-sm-2">Playbook</td>
|
||||
<td>{{ playbook }}</td>
|
||||
</tr>
|
||||
<tr ng-show="job_type">
|
||||
<td class="col-md-3 col-sm-2">Run Type</td>
|
||||
<td>{{ job_type }}</td>
|
||||
</tr>
|
||||
<tr ng-show="credential">
|
||||
<td class="col-md-3 col-sm-2">Machine Credential</td>
|
||||
<td>{{ credential }}</td>
|
||||
</tr>
|
||||
<tr ng-show="forks">
|
||||
<td class="col-md-3 col-sm-2">Forks</td>
|
||||
<td>{{ forks }}</td>
|
||||
</tr>
|
||||
<tr ng-show="limit">
|
||||
<td class="col-md-3 col-sm-2">Limit</td>
|
||||
<td>{{ limit }}</td>
|
||||
</tr>
|
||||
<tr ng-show="verbosity !== undefined">
|
||||
<td class="col-md-3 col-sm-2">Verbosity</td>
|
||||
<td>{{ verbosity }}</td>
|
||||
</tr>
|
||||
<tr ng-show="job_tags">
|
||||
<td class="col-md-3 col-sm-2">Job Tags</td>
|
||||
<td>{{ job_tags }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- row -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 job-detail-tables">
|
||||
|
||||
<h4>Plays</h4>
|
||||
<div class="job_plays">
|
||||
<table class="table table-condensed job-detail-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-1">Status</th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="play in plays">
|
||||
<td><i class="fa icon-job-{{ play.status }}"></i></td>
|
||||
<td>{{ play.name }}</td>
|
||||
<td>{{ play.state }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h4>Tasks</h4>
|
||||
<div class="job_tasks">
|
||||
<table class="table table-condensed job-detail-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-1">Status</th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="task in tasks">
|
||||
<td><i class="fa icon-job-{{ task.status }}"></i></td>
|
||||
<td>{{ task.name }}</td>
|
||||
<td>{{ task.state }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h4>Hosts</h4>
|
||||
<div class="job_hosts">
|
||||
<table class="table table-condensed job-detail-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-1">Status</th>
|
||||
<th>Name</th>
|
||||
<th>OK</th>
|
||||
<th>Changed</th>
|
||||
<th>Unreachable</th>
|
||||
<th>Failed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="host in hosts">
|
||||
<td><i class="fa icon-job-{{ task.status }}"></i></td>
|
||||
<td>{{ host.name }}</td>
|
||||
<td>{{ host.ok }}</td>
|
||||
<td>{{ host.changed }}</td>
|
||||
<td>{{ host.unreachable }}</td>
|
||||
<td>{{ host.failed }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" ng-app="ansible">
|
||||
<html lang="en" ng-app="Tower">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Ansible Tower</title>
|
||||
@@ -74,6 +74,7 @@
|
||||
<script src="{{ STATIC_URL }}js/controllers/JobTemplates.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/controllers/Projects.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/controllers/Jobs.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/controllers/JobDetail.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/controllers/JobEvents.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/controllers/JobHosts.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/controllers/Permissions.js"></script>
|
||||
@@ -150,6 +151,7 @@
|
||||
<script src="{{ STATIC_URL }}js/helpers/Variables.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/helpers/Schedules.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/helpers/LogViewer.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/helpers/JobDetail.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/widgets/JobStatus.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/widgets/InventorySyncStatus.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/widgets/SCMSyncStatus.js"></script>
|
||||
@@ -355,7 +357,7 @@
|
||||
<div id="push"></div>
|
||||
</div>
|
||||
|
||||
<div class="navbar navbar-inverse site-footer">
|
||||
<div class="navbar navbar-inverse site-footer fade-in">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 text-left help">
|
||||
|
||||
Reference in New Issue
Block a user