AC-1146 job relaunch fails after 2 or 3 relaunches in a row. Improved Jobs page search, defaulting all search boxes to Name. Enabled searching jobs by Type. Search drop-down box now sorted alphabetically.

This commit is contained in:
Chris Houseknecht 2014-04-06 01:03:52 -04:00
parent 26211dbcfb
commit a493bd15af
10 changed files with 90 additions and 48 deletions

View File

@ -34,7 +34,16 @@ function JobsListController ($scope, $compile, ClearScope, Breadcrumbs, LoadBrea
$scope.removeBuildJobsList();
}
$scope.removeBuildJobsList = $scope.$on('buildJobsList', function() {
completed_scope = $scope.$new();
if (CompletedJobsList.fields.type) {
CompletedJobsList.fields.type.searchOptions = $scope.type_choices;
}
if (RunningJobsList.fields.type) {
RunningJobsList.fields.type.searchOptions = $scope.type_choices;
}
if (QueuedJobsList.fields.type) {
QueuedJobsList.fields.type.searchOptions = $scope.type_choices;
}
completed_scope = $scope.$new(true);
LoadJobsScope({
parent_scope: $scope,
scope: completed_scope,
@ -42,7 +51,7 @@ function JobsListController ($scope, $compile, ClearScope, Breadcrumbs, LoadBrea
id: 'completed-jobs',
url: GetBasePath('unified_jobs') + '?or__status=successful&or__status=failed&or__status=error&or__status=canceled'
});
running_scope = $scope.$new();
running_scope = $scope.$new(true);
LoadJobsScope({
parent_scope: $scope,
scope: running_scope,
@ -50,7 +59,7 @@ function JobsListController ($scope, $compile, ClearScope, Breadcrumbs, LoadBrea
id: 'active-jobs',
url: GetBasePath('unified_jobs') + '?status=running'
});
queued_scope = $scope.$new();
queued_scope = $scope.$new(true);
LoadJobsScope({
parent_scope: $scope,
scope: queued_scope,
@ -58,7 +67,7 @@ function JobsListController ($scope, $compile, ClearScope, Breadcrumbs, LoadBrea
id: 'queued-jobs',
url: GetBasePath('unified_jobs') + '?or__status=pending&or__status=waiting&or__status=new'
});
scheduled_scope = $scope.$new();
scheduled_scope = $scope.$new(true);
LoadSchedulesScope({
parent_scope: $scope,
scope: scheduled_scope,

View File

@ -140,6 +140,7 @@ function(Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialList) {
}
else {
parent_scope.$emit(callback, acceptedPasswords);
scope.$destroy();
}
};
@ -147,6 +148,7 @@ function(Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialList) {
$('#password-modal').modal('hide');
Alert('Missing Password', 'Required password(s) not provided. Your request will not be submitted.', 'alert-info');
parent_scope.$emit('PasswordsCanceled');
scope.$destroy();
};
promptPassword();
@ -223,7 +225,7 @@ function(Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialList) {
if (scope.removeStartPlaybookRun) {
scope.removeStartPlaybookRun();
}
scope.removeStartJob = scope.$on('StartPlaybookRun', function(e, passwords) {
scope.removeStartPlaybookRun = scope.$on('StartPlaybookRun', function(e, passwords) {
LaunchJob({
scope: scope,
url: launch_url,

View File

@ -57,8 +57,20 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
}
}
// Default the search field to 'defaultSearchField', if one exists
for (fld in list.fields) {
if (list.fields[fld].searchWidget === undefined && widget === 1 ||
list.fields[fld].searchWidget === widget) {
if (list.fields[fld].defaultSearchField) {
scope[iterator + 'SearchField' + modifier] = fld;
scope[iterator + 'SearchFieldLabel' + modifier] = list.fields[fld].label;
}
}
}
// A field marked as key may not be 'searchable', and there might not be a 'defaultSearchField',
// so find the first searchable field.
if (Empty(scope[iterator + 'SearchField' + modifier])) {
// A field marked as key may not be 'searchable'. Find the first searchable field.
for (fld in list.fields) {
if (list.fields[fld].searchWidget === undefined && widget === 1 ||
list.fields[fld].searchWidget === widget) {
@ -203,6 +215,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
list.fields[fld].searchType === 'select' || list.fields[fld].searchType === 'select_or')) {
scope[iterator + 'SelectShow' + modifier] = true;
scope[iterator + 'SearchSelectOpts' + modifier] = list.fields[fld].searchOptions;
scope[iterator + 'SearchType' + modifier] = '';
} else if (list.fields[fld].searchType && list.fields[fld].searchType === 'int') {
//scope[iterator + 'HideSearchType' + modifier] = true;
scope[iterator + 'SearchType' + modifier] = 'int';
@ -366,10 +379,12 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
// handle fields whose source is a related model e.g. inventories.organization
scope[iterator + 'SearchParams'] += '&' + list.fields[scope[iterator + 'SearchField' + modifier]].sourceModel + '__' +
list.fields[scope[iterator + 'SearchField' + modifier]].sourceField + '__';
} else if ((list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
(scope[iterator + 'SearchSelectValue' + modifier].value === '' ||
scope[iterator + 'SearchSelectValue' + modifier].value === null)) {
} else if ( list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select' &&
Empty(scope[iterator + 'SearchSelectValue' + modifier].value) ) {
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
} else if ( list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select' &&
!Empty(scope[iterator + 'SearchSelectValue' + modifier].value) ) {
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier];
} else {
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
}
@ -381,10 +396,9 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
} else if (list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero') {
scope[iterator + 'SearchParams'] += 'gt=0';
} else if ((list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
(scope[iterator + 'SearchSelectValue' + modifier].value === '' ||
scope[iterator + 'SearchSelectValue' + modifier].value === null)) {
scope[iterator + 'SearchParams'] += 'iexact=';
} else if ( (list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
Empty(scope[iterator + 'SearchSelectValue' + modifier].value) ) {
scope[iterator + 'SearchParams'] += '=iexact=';
} else {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType' + modifier] + '=';
}

View File

@ -60,12 +60,15 @@ angular.module('CompletedJobsDefinition', [])
link: false,
columnClass: "col-md-2 hidden-sm hidden-xs",
columnShow: "showJobType",
searchable: false
searchable: true,
searchType: 'select',
searchOptions: [] // populated via GetChoices() in controller
},
name: {
label: 'Name',
columnClass: 'col-md-3 col-xs-5',
ngClick: "viewJobLog(completed_job.id, completed_job.nameHref)"
ngClick: "viewJobLog(completed_job.id, completed_job.nameHref)",
defaultSearchField: true
},
failed: {
label: 'Job failed?',

View File

@ -51,12 +51,15 @@ angular.module('QueuedJobsDefinition', [])
ngBind: 'queued_job.type_label',
link: false,
columnClass: "col-md-2 hidden-sm hidden-xs",
searchable: false
searchable: true,
searchType: 'select',
searchOptions: [] // populated via GetChoices() in controller
},
name: {
label: 'Name',
columnClass: 'col-sm-3 col-xs-5',
ngClick: "viewJobLog(queued_job.id, queued_job.nameHref)"
ngClick: "viewJobLog(queued_job.id, queued_job.nameHref)",
defaultSearchField: true
}
},

View File

@ -51,12 +51,15 @@ angular.module('RunningJobsDefinition', [])
ngBind: 'running_job.type_label',
link: false,
columnClass: "col-md-2 hidden-sm hidden-xs",
searchable: false
searchable: true,
searchType: 'select',
searchOptions: [] // populated via GetChoices() in controller
},
name: {
label: 'Name',
columnClass: 'col-md-3 col-xs-5',
ngClick: "viewJobLog(running_job.id, running_job.nameHref)"
ngClick: "viewJobLog(running_job.id, running_job.nameHref)",
defaultSearchField: true
}
},

View File

@ -56,7 +56,8 @@ angular.module('ScheduledJobsDefinition', [])
sourceField: 'name',
ngClick: "editSchedule(schedule.id)",
awToolTip: "{{ schedule.nameTip }}",
dataPlacement: "top"
dataPlacement: "top",
defaultSearchField: true
}
},

View File

@ -77,14 +77,14 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
*/
.factory('Alert', ['$rootScope', '$compile', function ($rootScope, $compile) {
return function (hdr, msg, cls, action, secondAlert, disableButtons) {
var scope = $rootScope.$new(), e;
var scope = $rootScope.$new(), alertClass, e;
if (secondAlert) {
$('#alert2-modal-msg').attr({ "class": "alert" });
scope.alertHeader2 = hdr;
scope.alertBody2 = msg;
scope.alertClass2 = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
e = angular.element(document.getElementById('alert-modal2'));
$compile(e)(scope);
scope.alertHeader2 = hdr;
scope.alertBody2 = msg;
alertClass = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert2-modal-msg').attr({ "class": "alert " + alertClass });
$('#alert-modal2').modal({
show: true,
keyboard: true,
@ -103,12 +103,12 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
}
});
} else {
$('#alert-modal-msg').attr({ "class": "alert" });
scope.alertHeader = hdr;
scope.alertBody = msg;
scope.alertClass = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
e = angular.element(document.getElementById('alert-modal'));
$compile(e)(scope);
scope.alertHeader = hdr;
scope.alertBody = msg;
alertClass = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal-msg').attr({ "class": "alert " + alertClass });
$('#alert-modal').modal({
show: true,
keyboard: true,

View File

@ -687,10 +687,31 @@ angular.module('GeneratorHelpers', [])
form = params.template,
size = params.size,
includeSize = (params.includeSize === undefined) ? true : params.includeSize,
fld,
i, html = '',
modifier,
searchWidgets = (params.searchWidgets) ? params.searchWidgets : 1;
searchWidgets = (params.searchWidgets) ? params.searchWidgets : 1,
sortedKeys;
function addSearchFields(idx) {
var html = '';
sortedKeys = Object.keys(form.fields).sort();
sortedKeys.forEach(function(fld) {
if ((form.fields[fld].searchable === undefined || form.fields[fld].searchable === true) &&
(((form.fields[fld].searchWidget === undefined || form.fields[fld].searchWidget === 1) && idx === 1) ||
(form.fields[fld].searchWidget === idx))) {
html += "<li><a href=\"\" ng-click=\"setSearchField('" + iterator + "','";
html += fld + "','";
if (form.fields[fld].searchLabel) {
html += form.fields[fld].searchLabel + "', " + idx + ")\">" +
form.fields[fld].searchLabel + "</a></li>\n";
} else {
html += form.fields[fld].label.replace(/<br \/>/g, ' ') + "', " + idx + ")\">" +
form.fields[fld].label.replace(/<br \/>/g, ' ') + "</a></li>\n";
}
}
});
return html;
}
for (i = 1; i <= searchWidgets; i++) {
modifier = (i === 1) ? '' : i;
@ -713,21 +734,7 @@ angular.module('GeneratorHelpers', [])
html += "<span class=\"caret\"></span>\n";
html += "</button>\n";
html += "<ul class=\"dropdown-menu\" id=\"" + iterator + "SearchDropdown" + modifier + "\">\n";
for (fld in form.fields) {
if ((form.fields[fld].searchable === undefined || form.fields[fld].searchable === true) &&
(((form.fields[fld].searchWidget === undefined || form.fields[fld].searchWidget === 1) && i === 1) ||
(form.fields[fld].searchWidget === i))) {
html += "<li><a href=\"\" ng-click=\"setSearchField('" + iterator + "','";
html += fld + "','";
if (form.fields[fld].searchLabel) {
html += form.fields[fld].searchLabel + "', " + i + ")\">" +
form.fields[fld].searchLabel + "</a></li>\n";
} else {
html += form.fields[fld].label.replace(/<br \/>/g, ' ') + "', " + i + ")\">" +
form.fields[fld].label.replace(/<br \/>/g, ' ') + "</a></li>\n";
}
}
}
html += addSearchFields(i);
html += "</ul>\n";
html += "</div><!-- input-group-btn -->\n";

View File

@ -331,7 +331,7 @@
<h3 ng-bind="alertHeader"></h3>
</div>
<div class="modal-body">
<div id="alert-modal-msg" class="alert" ng-class="alertClass" ng-bind-html="alertBody"></div>
<div id="alert-modal-msg" class="alert" ng-bind-html="alertBody"></div>
</div>
<div class="modal-footer">
<a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" id="alert_ok_btn" class="btn btn-primary">OK</a>
@ -349,7 +349,7 @@
<h3 ng-bind="alertHeader2"></h3>
</div>
<div class="modal-body">
<div id="alert2-modal-msg" class="alert" ng-class="alertClass2" ng-bind-html="alertBody2"></div>
<div id="alert2-modal-msg" class="alert" ng-bind-html="alertBody2"></div>
</div>
<div class="modal-footer">
<a href="#" ng-hide="disableButtons2" data-target="#form-modal2" data-dismiss="modal" id="alert2_ok_btn" class="btn btn-primary">OK</a>