diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js
index 29100b2547..9887476c5f 100644
--- a/awx/ui/static/js/app.js
+++ b/awx/ui/static/js/app.js
@@ -411,7 +411,7 @@ angular.module('Tower', [
function ($compile, $cookieStore, $rootScope, $log, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense,
Timer, ClearScope, HideStream, Socket) {
- var e, html, sock;
+ var e, html, sock, checkCount;
LoadBasePaths();
@@ -468,13 +468,17 @@ angular.module('Tower', [
HideStream();
}
+ // remove any lingering intervals
if ($rootScope.jobDetailInterval) {
window.clearInterval($rootScope.jobDetailInterval);
}
-
if ($rootScope.jobStdOutInterval) {
window.clearInterval($rootScope.jobStdOutInterval);
}
+ if ($rootScope.checkSocketConnectionInterval) {
+ // use to monitor and restart socket connections
+ window.clearInterval($rootScope.checkSocketConnectionInterval);
+ }
// On each navigation request, check that the user is logged in
if (!/^\/(login|logout)/.test($location.path())) {
@@ -541,33 +545,37 @@ angular.module('Tower', [
function openSocket() {
sock = Socket({ scope: $rootScope, endpoint: "jobs" });
sock.init();
- setTimeout(function() {
- $rootScope.$apply(function() {
- sock.checkStatus();
- $log.debug('socket status: ' + $rootScope.socketStatus);
- });
- },2000);
sock.on("status_changed", function(data) {
$log.debug('Job ' + data.unified_job_id + ' status changed to ' + data.status);
$rootScope.$emit('JobStatusChange', data);
});
}
+
openSocket();
- /*
- $rootScope.socketToggle = function() {
- switch($rootScope.socketStatus) {
- case 'ok':
- case 'connecting':
- sock = null;
- $rootScope.socketStatus = 'error';
- $rootScope.socketTip = 'Disconnected. Click to connect.';
- break;
- case 'error':
- sock = null;
- $rootScope.socketStatus = '';
- $rootScope.socketTip = '';
- setTimeout(openSocket, 500);
+
+ setTimeout(function() {
+ $rootScope.$apply(function() {
+ sock.checkStatus();
+ $log.debug('socket status: ' + $rootScope.socketStatus);
+ });
+ },2000);
+
+ // monitor socket status
+ checkCount = 0;
+ setInterval(function() {
+ if (sock.checkStatus() === 'error' || checkCount > 2) {
+ // there's an error or we're stuck in a 'connecting' state. attempt to reconnect
+ sock = null;
+ $log.debug('attempting new socket connection');
+ openSocket();
+ checkCount = 0;
}
- };*/
+ else if (sock.checkStatus() === 'connecting') {
+ checkCount++;
+ }
+ else {
+ checkCount = 0;
+ }
+ }, 3000);
}
]);
diff --git a/awx/ui/static/js/config.js b/awx/ui/static/js/config.js
index 66255cf4da..8b82bc3da5 100644
--- a/awx/ui/static/js/config.js
+++ b/awx/ui/static/js/config.js
@@ -14,7 +14,7 @@ var $AnsibleConfig = {
tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips
- debug_mode: false, // Enable console logging messages
+ debug_mode: true, // Enable console logging messages
password_strength: 45, // User password strength. Integer between 0 and 100, 100 being impossibly strong.
// This value controls progress bar colors:
diff --git a/awx/ui/static/js/controllers/Jobs.js b/awx/ui/static/js/controllers/Jobs.js
index 5d41f5b9f5..b94018505c 100644
--- a/awx/ui/static/js/controllers/Jobs.js
+++ b/awx/ui/static/js/controllers/Jobs.js
@@ -10,8 +10,8 @@
'use strict';
-function JobsListController ($log, $scope, $compile, $routeParams, ClearScope, Breadcrumbs, LoadBreadCrumbs, LoadSchedulesScope, LoadJobsScope, RunningJobsList, CompletedJobsList, QueuedJobsList,
- ScheduledJobsList, GetChoices, GetBasePath, Wait, Socket) {
+function JobsListController ($rootScope, $log, $scope, $compile, $routeParams, ClearScope, Breadcrumbs, LoadBreadCrumbs, LoadSchedulesScope,
+ LoadJobsScope, RunningJobsList, CompletedJobsList, QueuedJobsList, ScheduledJobsList, GetChoices, GetBasePath, Wait, Socket) {
ClearScope();
@@ -21,104 +21,70 @@ function JobsListController ($log, $scope, $compile, $routeParams, ClearScope, B
api_complete = false,
schedule_socket,
job_socket,
- event_queue = [],
- expecting = 0,
- max_rows;
+ max_rows, checkCount;
- job_socket = Socket({
- scope: $scope,
- endpoint: "jobs"
- });
+ function openSockets() {
+ job_socket = Socket({
+ scope: $scope,
+ endpoint: "jobs"
+ });
+ job_socket.init();
+ job_socket.on("status_changed", function(data) {
+ if (api_complete) {
+ processEvent(data);
+ }
+ });
+ schedule_socket = Socket({
+ scope: $scope,
+ endpoint: "schedules"
+ });
+ schedule_socket.init();
+ schedule_socket.on("schedule_changed", function() {
+ if (api_complete) {
+ scheduled_scope.search('schedule');
+ }
+ });
+ }
+ openSockets();
- job_socket.init();
-
- job_socket.on("status_changed", function(data) {
- if (api_complete) {
- processEvent(data);
+ $rootScope.checkSocketConnectionInterval = setInterval(function() {
+ if (job_socket.checkStatus() === 'error' || checkCount > 2) {
+ // there's an error or we're stuck in a 'connecting' state. attempt to reconnect
+ $log.debug('jobs page: initializing and restarting socket connections');
+ job_socket = null;
+ schedule_socket = null;
+ openSockets();
+ checkCount = 0;
+ }
+ else if (job_socket.checkStatus() === 'connecting') {
+ checkCount++;
}
else {
- event_queue.push(data);
+ checkCount = 0;
}
- });
-
- schedule_socket = Socket({
- scope: $scope,
- endpoint: "schedules"
- });
-
- schedule_socket.init();
- schedule_socket.on("status_change", function() {
- if (api_complete) {
- scheduled_scope.search('schedule');
- }
- });
+ }, 3000);
function processEvent(event) {
- expecting = 0;
switch(event.status) {
case 'running':
- if (!inList(running_scope[RunningJobsList.name], event.unified_job_id)) {
- expecting = 2;
- running_scope.search('running_job');
- queued_scope.search('queued_job');
- }
+ running_scope.search('running_job');
+ queued_scope.search('queued_job');
break;
case 'new':
case 'pending':
case 'waiting':
- if (!inList(queued_scope[QueuedJobsList.name], event.unified_job_id)) {
- expecting = 1;
- queued_scope.search('queued_job');
- }
+ queued_scope.search('queued_job');
break;
case 'successful':
case 'failed':
case 'error':
case 'canceled':
- if (!inList(completed_scope[CompletedJobsList.name], event.unified_job_id)) {
- expecting = 2;
- completed_scope.search('completed_job');
- running_scope.search('running_job');
- }
+ completed_scope.search('completed_job');
+ running_scope.search('running_job');
break;
}
}
- function inList(list, id) {
- var found = false;
- list.every( function(row) {
- if (row.id === id) {
- found = true;
- return false;
- }
- return true;
- });
- return found;
- }
-
-
- if ($scope.removeProcessQueue) {
- $scope.removeProcessQueue();
- }
- $scope.removeProcessQueue = $scope.$on('ProcessQueue', function() {
- var event;
- listCount=0;
- if (event_queue.length > 0) {
- event = event_queue[0];
- processEvent(event);
- event_queue.splice(0,1);
- if ($scope.removeListLoaded) {
- $scope.removeListLoaded();
- }
- $scope.removeListLoaded = $scope.$on('listLoaded', function() {
- listCount++;
- if (listCount === expecting) {
- $scope.$emit('ProcessQueue');
- }
- });
- }
- });
-
LoadBreadCrumbs();
if ($scope.removeListLoaded) {
@@ -128,7 +94,6 @@ function JobsListController ($log, $scope, $compile, $routeParams, ClearScope, B
listCount++;
if (listCount === 4) {
api_complete = true;
- $scope.$emit('ProcessQueue');
}
});
@@ -286,280 +251,5 @@ function JobsListController ($log, $scope, $compile, $routeParams, ClearScope, B
}
}
-JobsListController.$inject = [ '$log', '$scope', '$compile', '$routeParams', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'LoadSchedulesScope', 'LoadJobsScope', 'RunningJobsList', 'CompletedJobsList',
- 'QueuedJobsList', 'ScheduledJobsList', 'GetChoices', 'GetBasePath', 'Wait', 'Socket'];
-
-function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, JobTemplateForm, GenerateForm, Rest,
- Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList,
- CredentialList, ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, FormatDate, JobStatusToolTip, Wait, Empty,
- ParseVariableString, GetChoices) {
-
- ClearScope();
-
- var defaultUrl = GetBasePath('jobs'),
- generator = GenerateForm,
- id = $routeParams.id,
- loadingFinishedCount = 0,
- templateForm = {},
- choicesCount = 0;
-
- generator.inject(JobForm, { mode: 'edit', related: true, scope: $scope });
-
- $scope.job_id = id;
- $scope.parseType = 'yaml';
- $scope.statusSearchSpin = false;
- $scope.disableParseSelection = true;
-
- function getPlaybooks(project, playbook) {
- if (!Empty(project)) {
- var url = GetBasePath('projects') + project + '/playbooks/';
- Rest.setUrl(url);
- Rest.get()
- .success(function (data) {
- var i;
- $scope.playbook_options = [];
- for (i = 0; i < data.length; i++) {
- $scope.playbook_options.push(data[i]);
- }
- for (i = 0; i < $scope.playbook_options.length; i++) {
- if ($scope.playbook_options[i] === playbook) {
- $scope.playbook = $scope.playbook_options[i];
- }
- }
- $scope.$emit('jobTemplateLoadFinished');
- })
- .error(function () {
- $scope.$emit('jobTemplateLoadFinished');
- });
- } else {
- $scope.$emit('jobTemplateLoadFinished');
- }
- }
-
-
- // Retrieve each related set and populate the playbook list
- if ($scope.jobLoadedRemove) {
- $scope.jobLoadedRemove();
- }
- $scope.jobLoadedRemove = $scope.$on('jobLoaded', function (e, related_cloud_credential, project, playbook) {
-
- getPlaybooks(project, playbook);
- if (related_cloud_credential) {
- //Get the name of the cloud credential
- Rest.setUrl(related_cloud_credential);
- Rest.get()
- .success(function (data) {
- $scope.cloud_credential_name = data.name;
- $scope.$emit('jobTemplateLoadFinished');
- })
- .error(function (data, status) {
- ProcessErrors($scope, data, status, null, { hdr: 'Error!',
- msg: 'Failed to related cloud credential. GET returned status: ' + status });
- });
- } else {
- $scope.$emit('jobTemplateLoadFinished');
- }
-
- });
-
- // Turn off 'Wait' after both cloud credential and playbook list come back
- if ($scope.removeJobTemplateLoadFinished) {
- $scope.removeJobTemplateLoadFinished();
- }
- $scope.removeJobTemplateLoadFinished = $scope.$on('jobTemplateLoadFinished', function () {
- loadingFinishedCount++;
- if (loadingFinishedCount >= 2) {
- // The initial template load finished. Now load related jobs, which
- // will turn off the 'working' spinner.
- Wait('stop');
- }
- });
-
- $scope.verbosity_options = [{
- value: 0,
- label: 'Default'
- }, {
- value: 1,
- label: 'Verbose'
- }, {
- value: 3,
- label: 'Debug'
- }];
-
- $scope.playbook_options = null;
- $scope.playbook = null;
-
- function calcRows(content) {
- var n = content.match(/\n/g),
- rows = (n) ? n.length : 1;
- return (rows > 15) ? 15 : rows;
- }
-
- if ($scope.removeLoadJobTemplate) {
- $scope.removeLoadJobTemplate();
- }
- $scope.removeLoadJobTemplate = $scope.$on('loadJobTemplate', function() {
- // Retrieve the job detail record and prepopulate the form
- Rest.setUrl(defaultUrl + ':id/');
- Rest.get({ params: { id: id } })
- .success(function (data) {
-
- var i, fld;
-
- LoadBreadCrumbs();
-
- $scope.status = data.status;
- $scope.created = FormatDate(data.created);
- $scope.modified = FormatDate(data.modified);
- $scope.result_stdout = data.result_stdout;
- $scope.result_traceback = data.result_traceback;
- $scope.stdout_rows = calcRows($scope.result_stdout);
- $scope.traceback_rows = calcRows($scope.result_traceback);
- $scope.job_explanation = data.job_explanation || 'Things may have ended badly or gone swimingly well';
-
- // Now load the job template form
- templateForm.addTitle = 'Create Job Templates';
- templateForm.editTitle = '{{ name }}';
- templateForm.name = 'job_templates';
- templateForm.twoColumns = true;
- templateForm.fields = angular.copy(JobTemplateForm.fields);
- for (fld in templateForm.fields) {
- templateForm.fields[fld].readonly = true;
- }
-
- if (data.type === "playbook_run") {
- $('#ui-accordion-jobs-collapse-0-panel-1').empty();
- generator.inject(templateForm, {
- mode: 'edit',
- id: 'ui-accordion-jobs-collapse-0-panel-1',
- related: false,
- scope: $scope,
- breadCrumbs: false
- });
- }
- else {
- $('#ui-accordion-jobs-collapse-0-header-1').hide();
- $('#ui-accordion-jobs-collapse-0-panel-1').empty().hide();
- $('#jobs-collapse-0').accordion( "option", "collapsible", false );
- }
-
- for (fld in templateForm.fields) {
- if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
- if (JobTemplateForm.fields[fld].type === 'select') {
- if ($scope[fld + '_options'] && $scope[fld + '_options'].length > 0) {
- for (i = 0; i < $scope[fld + '_options'].length; i++) {
- if (data[fld] === $scope[fld + '_options'][i].value) {
- $scope[fld] = $scope[fld + '_options'][i];
- }
- }
- } else {
- $scope[fld] = data[fld];
- }
- } else {
- $scope[fld] = data[fld];
- }
- }
- if (fld === 'variables') {
- $scope.variables = ParseVariableString(data.extra_vars);
- }
- if (JobTemplateForm.fields[fld].type === 'lookup' && data.summary_fields[JobTemplateForm.fields[fld].sourceModel]) {
- $scope[JobTemplateForm.fields[fld].sourceModel + '_' + JobTemplateForm.fields[fld].sourceField] =
- data.summary_fields[JobTemplateForm.fields[fld].sourceModel][JobTemplateForm.fields[fld].sourceField];
- }
- }
-
- $scope.id = data.id;
- $scope.name = (data.summary_fields && data.summary_fields.job_template) ? data.summary_fields.job_template.name : '';
- $scope.statusToolTip = JobStatusToolTip(data.status);
- $scope.url = data.url;
- $scope.project = data.project;
- $scope.launch_type = data.launch_type;
-
- // set the type
- data.type = 'playbook_run'; //temporary
- $scope.type_choices.every( function(choice) {
- if (choice.value === data.type) {
- $scope.type = choice.label;
- return false;
- }
- return true;
- });
-
- $scope.$emit('jobLoaded', data.related.cloud_credential, data.project, data.playbook);
- })
- .error(function (data, status) {
- ProcessErrors($scope, data, status, null, { hdr: 'Error!',
- msg: 'Failed to retrieve job: ' + $routeParams.id + '. GET status: ' + status });
- });
- });
-
- Wait('start');
-
- if ($scope.removeChoicesReady) {
- $scope.removeChoicesReady();
- }
- $scope.removeChoicesReady = $scope.$on('choicesReady', function() {
- choicesCount++;
- if (choicesCount === 2) {
- $scope.$emit('loadJobTemplate');
- }
- });
-
- GetChoices({
- scope: $scope,
- url: GetBasePath('unified_jobs'),
- field: 'job_type',
- variable: 'job_type_options',
- callback: 'choicesReady'
- });
-
- /*GetChoices({
- scope: $scope,
- url: GetBasePath('jobs'),
- field: 'status',
- variable: 'status_choices',
- callback: 'choicesReady'
- });*/
-
- GetChoices({
- scope: $scope,
- url: GetBasePath('unified_jobs'), //'/static/sample/data/types/data.json'
- field: 'type',
- variable: 'type_choices',
- callback: 'choicesReady'
- });
-
- $scope.refresh = function () {
- Wait('start');
- Rest.setUrl(defaultUrl + id + '/');
- Rest.get()
- .success(function (data) {
- $scope.status = data.status;
- $scope.result_stdout = data.result_stdout;
- $scope.result_traceback = data.result_traceback;
- $scope.stdout_rows = calcRows($scope.result_stdout);
- $scope.traceback_rows = calcRows($scope.result_traceback);
- Wait('stop');
- })
- .error(function (data, status) {
- ProcessErrors($scope, data, status, null, { hdr: 'Error!',
- msg: 'Attempt to load job failed. GET returned status: ' + status });
- });
- };
-
- $scope.jobSummary = function () {
- $location.path('/jobs/' + id + '/job_host_summaries');
- };
-
- $scope.jobEvents = function () {
- $location.path('/jobs/' + id + '/job_events');
- };
-}
-
-JobsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm', 'JobTemplateForm',
- 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
- 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', 'PromptPasswords',
- 'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait', 'Empty', 'ParseVariableString', 'GetChoices',
- 'LoadDialogPartial'
-];
-
+JobsListController.$inject = ['$rootScope', '$log', '$scope', '$compile', '$routeParams', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'LoadSchedulesScope', 'LoadJobsScope', 'RunningJobsList', 'CompletedJobsList',
+ 'QueuedJobsList', 'ScheduledJobsList', 'GetChoices', 'GetBasePath', 'Wait', 'Socket'];
\ No newline at end of file
diff --git a/awx/ui/static/js/controllers/Projects.js b/awx/ui/static/js/controllers/Projects.js
index ba881e5744..b1619b515a 100644
--- a/awx/ui/static/js/controllers/Projects.js
+++ b/awx/ui/static/js/controllers/Projects.js
@@ -63,7 +63,7 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
if (type.value === project.scm_type) {
$scope.projects[i].scm_type = type.label;
if (type.label === 'Manual') {
- $scope.projects[i].scm_update_tooltip = 'Manaul projects do not require an SCM update';
+ $scope.projects[i].scm_update_tooltip = 'Manual projects do not require an SCM update';
$scope.projects[i].scm_schedule_tooltip = 'Manual projects do not require a schedule';
$scope.projects[i].scm_type_class = 'btn-disabled';
$scope.projects[i].statusTip = 'Not configured for SCM';
@@ -284,7 +284,7 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
Rest.setUrl(url);
Rest.post()
.success(function () {
- Alert('SCM Update Cancel', 'Your request to cancel the update was submitted to the task maanger.', 'alert-info');
+ Alert('SCM Update Cancel', 'Your request to cancel the update was submitted to the task manager.', 'alert-info');
$scope.refresh();
})
.error(function (data, status) {
diff --git a/awx/ui/static/js/helpers/JobSubmission.js b/awx/ui/static/js/helpers/JobSubmission.js
index c829467826..3e0670bb66 100644
--- a/awx/ui/static/js/helpers/JobSubmission.js
+++ b/awx/ui/static/js/helpers/JobSubmission.js
@@ -551,15 +551,14 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
}
scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function() {
// Refresh the project list after update request submitted
- if (scope.refreshJobs) {
- Wait('stop');
+ Wait('stop');
+ if (scope.socketStatus === 'error') {
Alert('Update Started', 'The request to start the SCM update process was submitted. ' +
- 'To monitor the update status, refresh the page by clicking the button.', 'alert-info');
- scope.refreshJobs();
+ 'To monitor the update status, refresh the page by clicking the button.', 'alert-info');
+ if (scope.refresh) {
+ scope.refresh();
+ }
}
- //else if (scope.refresh) {
- // scope.refresh();
- //}
});
if (scope.removePromptForPasswords) {
@@ -619,8 +618,17 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
}
scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function () {
Wait('stop');
- // No need to do anything else. The caller should be connected to the socket server and
- // handling real-time updates
+ if (scope.socketStatus === 'error') {
+ Alert('Sync Started', 'The request to start the inventory sync process was submitted. ' +
+ 'To monitor the status refresh the page by clicking the button.', 'alert-info');
+ if (scope.refreshGroups) {
+ // inventory detail page
+ scope.refreshGroups();
+ }
+ else if (scope.refresh) {
+ scope.refresh();
+ }
+ }
});
if (scope.removePromptForPasswords) {
diff --git a/awx/ui/static/lib/ansible/Socket.js b/awx/ui/static/lib/ansible/Socket.js
index 02c6fc2393..cb550f38fd 100644
--- a/awx/ui/static/lib/ansible/Socket.js
+++ b/awx/ui/static/lib/ansible/Socket.js
@@ -127,15 +127,12 @@ angular.module('SocketIO', ['AuthService', 'Utilities'])
// Check connection status
var self = this;
if (self.socket.socket.connected) {
- $log.debug('Socket connected');
self.scope.socketStatus = 'ok';
}
else if (self.socket.socket.connecting || self.socket.socket.reconnecting) {
- $log.debug('Socket connecting...');
self.scope.socketStatus = 'connecting';
}
else {
- $log.debug('Socket error: connection refused');
self.scope.socketStatus = 'error';
}
self.scope.socketTip = getSocketTip(self.scope.socketStatus);
diff --git a/awx/ui/static/lib/ansible/Utilities.js b/awx/ui/static/lib/ansible/Utilities.js
index 5afd01eaa3..e2ec43225c 100644
--- a/awx/ui/static/lib/ansible/Utilities.js
+++ b/awx/ui/static/lib/ansible/Utilities.js
@@ -16,30 +16,30 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
* Place to remove things that might be lingering from a prior tab or view.
* This used to destroy the scope, but that causes issues in angular 1.2.x
*/
-.factory('ClearScope', [
- function () {
- return function () {
+.factory('ClearScope', [ '$rootScope', function ($rootScope) {
+ return function () {
- $('#form-modal .modal-body').empty();
- $('#form-modal2 .modal-body').empty();
+ $rootScope.flashMessage = null;
- $('.tooltip').each(function () {
- $(this).remove();
- });
+ $('#form-modal .modal-body').empty();
+ $('#form-modal2 .modal-body').empty();
- $('.popover').each(function () {
- $(this).remove();
- });
+ $('.tooltip').each(function () {
+ $(this).remove();
+ });
- try {
- $('#help-modal').dialog('close');
- } catch (e) {
- // ignore
- }
- $(window).unbind('resize');
- };
- }
-])
+ $('.popover').each(function () {
+ $(this).remove();
+ });
+
+ try {
+ $('#help-modal').dialog('close');
+ } catch (e) {
+ // ignore
+ }
+ $(window).unbind('resize');
+ };
+}])
/* Empty()
diff --git a/awx/ui/static/lib/socket.io-client/dist/socket.io.js b/awx/ui/static/lib/socket.io-client/dist/socket.io.js
index 9e11e3ef92..88ac893599 100644
--- a/awx/ui/static/lib/socket.io-client/dist/socket.io.js
+++ b/awx/ui/static/lib/socket.io-client/dist/socket.io.js
@@ -1651,7 +1651,7 @@ var io = ('undefined' === typeof module ? {} : module.exports);
} else if (xhr.status == 403) {
self.onError(xhr.responseText);
} else {
- self.connecting = false;
+ self.connecting = false;
!self.reconnecting && self.onError(xhr.responseText);
}
}
@@ -1695,7 +1695,7 @@ var io = ('undefined' === typeof module ? {} : module.exports);
var self = this;
self.connecting = true;
-
+
this.handshake(function (sid, heartbeat, close, transports) {
self.sessionid = sid;
self.closeTimeout = close * 1000;
@@ -1817,7 +1817,7 @@ var io = ('undefined' === typeof module ? {} : module.exports);
this.transport.payload(this.buffer);
this.buffer = [];
};
-
+
/**
* Disconnect the established connect.
@@ -1877,7 +1877,7 @@ var io = ('undefined' === typeof module ? {} : module.exports);
var port = global.location.port ||
('https:' == global.location.protocol ? 443 : 80);
- return this.options.host !== global.location.hostname
+ return this.options.host !== global.location.hostname
|| this.options.port != port;
};
@@ -2158,7 +2158,7 @@ var io = ('undefined' === typeof module ? {} : module.exports);
*
* @api public
*/
-
+
SocketNamespace.prototype.emit = function (name) {
var args = Array.prototype.slice.call(arguments, 1)
, lastArg = args[args.length - 1]
@@ -2396,8 +2396,8 @@ var io = ('undefined' === typeof module ? {} : module.exports);
* @api public
*/
- // Do to a bug in the current IDevices browser, we need to wrap the send in a
- // setTimeout, when they resume from sleeping the browser will crash if
+ // Do to a bug in the current IDevices browser, we need to wrap the send in a
+ // setTimeout, when they resume from sleeping the browser will crash if
// we don't allow the browser time to detect the socket has been closed
if (io.util.ua.iDevice) {
WS.prototype.send = function (data) {
@@ -2543,8 +2543,8 @@ var io = ('undefined' === typeof module ? {} : module.exports);
Flashsocket.prototype.name = 'flashsocket';
/**
- * Disconnect the established `FlashSocket` connection. This is done by adding a
- * new task to the FlashSocket. The rest will be handled off by the `WebSocket`
+ * Disconnect the established `FlashSocket` connection. This is done by adding a
+ * new task to the FlashSocket. The rest will be handled off by the `WebSocket`
* transport.
*
* @returns {Transport}
@@ -2560,10 +2560,10 @@ var io = ('undefined' === typeof module ? {} : module.exports);
});
return this;
};
-
+
/**
* Sends a message to the Socket.IO server. This is done by adding a new
- * task to the FlashSocket. The rest will be handled off by the `WebSocket`
+ * task to the FlashSocket. The rest will be handled off by the `WebSocket`
* transport.
*
* @returns {Transport}
@@ -2657,7 +2657,7 @@ var io = ('undefined' === typeof module ? {} : module.exports);
};
/**
- * Check if the FlashSocket transport can be used as cross domain / cross origin
+ * Check if the FlashSocket transport can be used as cross domain / cross origin
* transport. Because we can't see which type (secure or insecure) of .swf is used
* we will just return true.
*
@@ -2688,8 +2688,8 @@ var io = ('undefined' === typeof module ? {} : module.exports);
'undefined' != typeof io ? io.Transport : module.exports
, 'undefined' != typeof io ? io : module.parent.exports
);
-/* SWFObject v2.2
- is released under the MIT License
+/* SWFObject v2.2
+ is released under the MIT License
*/
if ('undefined' != typeof window) {
var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O[(['Active'].concat('Object').join('X'))]!=D){try{var ad=new window[(['Active'].concat('Object').join('X'))](W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab= 10.0.0 is required.");
return;
@@ -2846,7 +2846,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
if ("protocol" in flashEvent) {
this.protocol = flashEvent.protocol;
}
-
+
var jsEvent;
if (flashEvent.type == "open" || flashEvent.type == "error") {
jsEvent = this.__createSimpleEvent(flashEvent.type);
@@ -2859,10 +2859,10 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
} else {
throw "unknown event type: " + flashEvent.type;
}
-
+
this.dispatchEvent(jsEvent);
};
-
+
WebSocket.prototype.__createSimpleEvent = function(type) {
if (document.createEvent && window.Event) {
var event = document.createEvent("Event");
@@ -2872,7 +2872,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
return {type: type, bubbles: false, cancelable: false};
}
};
-
+
WebSocket.prototype.__createMessageEvent = function(type, data) {
if (document.createEvent && window.MessageEvent && !window.opera) {
var event = document.createEvent("MessageEvent");
@@ -2883,7 +2883,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
return {type: type, data: data, bubbles: false, cancelable: false};
}
};
-
+
/**
* Define the WebSocket readyState enumeration.
*/
@@ -2896,7 +2896,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
WebSocket.__instances = {};
WebSocket.__tasks = [];
WebSocket.__nextId = 0;
-
+
/**
* Load a new flash security policy file.
* @param {string} url
@@ -2912,7 +2912,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
*/
WebSocket.__initialize = function() {
if (WebSocket.__flash) return;
-
+
if (WebSocket.__swfLocation) {
// For backword compatibility.
window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;
@@ -2958,7 +2958,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
}
});
};
-
+
/**
* Called by Flash to notify JS that it's fully loaded and ready
* for communication.
@@ -2976,7 +2976,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
WebSocket.__tasks = [];
}, 0);
};
-
+
/**
* Called by Flash to notify WebSockets events are fired.
*/
@@ -2996,17 +2996,17 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
}, 0);
return true;
};
-
+
// Called by Flash.
WebSocket.__log = function(message) {
console.log(decodeURIComponent(message));
};
-
+
// Called by Flash.
WebSocket.__error = function(message) {
console.error(decodeURIComponent(message));
};
-
+
WebSocket.__addTask = function(task) {
if (WebSocket.__flash) {
task();
@@ -3014,7 +3014,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
WebSocket.__tasks.push(task);
}
};
-
+
/**
* Test if the browser is running flash lite.
* @return {boolean} True if flash lite is running, false otherwise.
@@ -3029,7 +3029,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
}
return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false;
};
-
+
if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {
if (window.addEventListener) {
window.addEventListener("load", function(){
@@ -3041,7 +3041,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
});
}
}
-
+
})();
/**
@@ -3276,7 +3276,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
/**
* The HTMLFile transport creates a `forever iframe` based transport
- * for Internet Explorer. Regular forever iframe implementations will
+ * for Internet Explorer. Regular forever iframe implementations will
* continuously trigger the browsers buzy indicators. If the forever iframe
* is created inside a `htmlfile` these indicators will not be trigged.
*
@@ -3490,7 +3490,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
return false;
};
- /**
+ /**
* Establish a connection, for iPhone and Android this will be done once the page
* is loaded.
*
@@ -3542,7 +3542,7 @@ var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="Sho
function onerror () {
self.retryCounter ++;
if(!self.retryCounter || self.retryCounter > 3) {
- self.onClose();
+ self.onClose();
} else {
self.get();
}
diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html
index 70922a6a98..bb77e5a131 100644
--- a/awx/ui/templates/ui/index.html
+++ b/awx/ui/templates/ui/index.html
@@ -436,7 +436,7 @@
-
+