From 3d0d75e8974c6bc9600d69122c5b2d86953f07ce Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Wed, 26 Mar 2014 16:33:41 -0400 Subject: [PATCH] Wired schedule edit to Jobs page. Fixed issues with modal dialogs. On inventory hosts focus is now set to first field rather than help icon. ESC key no longer closes jqueryui dialogs as it conflicts with clicking ESC to close help pop-over. Resizing a dialog no longer causes button pane (the dialog footer) to appear to grow taller and taller. --- awx/ui/static/js/app.js | 4 +- awx/ui/static/js/controllers/Jobs.js | 19 +++++++-- awx/ui/static/js/controllers/Schedules.js | 45 +++++++++++++-------- awx/ui/static/js/helpers/Groups.js | 5 +++ awx/ui/static/js/helpers/Hosts.js | 2 + awx/ui/static/js/helpers/Jobs.js | 12 +++++- awx/ui/static/js/helpers/Schedules.js | 38 +++++++++++++++-- awx/ui/static/less/ansible-ui.less | 2 +- awx/ui/static/less/jquery-ui-overrides.less | 1 + awx/ui/static/lib/ansible/Modal.js | 5 +++ awx/ui/static/lib/ansible/directives.js | 2 +- awx/ui/static/partials/jobs.html | 3 +- awx/ui/static/partials/schedule_detail.html | 14 +------ awx/ui/static/partials/schedule_dialog.html | 13 ++++++ 14 files changed, 123 insertions(+), 42 deletions(-) create mode 100644 awx/ui/static/partials/schedule_dialog.html diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js index 4c70cdca4b..732a6625d6 100644 --- a/awx/ui/static/js/app.js +++ b/awx/ui/static/js/app.js @@ -147,7 +147,7 @@ angular.module('ansible', [ when('/job_templates/:id/schedules', { templateUrl: urlPrefix + 'partials/schedule_detail.html', - controller: 'ScheduleEdit' + controller: 'ScheduleEditController' }). when('/projects', { @@ -167,7 +167,7 @@ angular.module('ansible', [ when('/projects/:id/schedules', { templateUrl: urlPrefix + 'partials/schedule_detail.html', - controller: 'ScheduleEdit' + controller: 'ScheduleEditController' }). when('/projects/:project_id/organizations', { diff --git a/awx/ui/static/js/controllers/Jobs.js b/awx/ui/static/js/controllers/Jobs.js index 6c659aebdb..9323b37404 100644 --- a/awx/ui/static/js/controllers/Jobs.js +++ b/awx/ui/static/js/controllers/Jobs.js @@ -11,7 +11,8 @@ 'use strict'; function JobsListController ($scope, $compile, ClearScope, Breadcrumbs, LoadBreadCrumbs, LoadScope, RunningJobsList, CompletedJobsList, QueuedJobsList, - ScheduledJobsList, GetChoices, GetBasePath, Wait, DeleteJob, Find, DeleteSchedule, ToggleSchedule, RelaunchInventory, RelaunchPlaybook, RelaunchSCM) { + ScheduledJobsList, GetChoices, GetBasePath, Wait, DeleteJob, Find, DeleteSchedule, ToggleSchedule, RelaunchInventory, RelaunchPlaybook, RelaunchSCM, + LoadDialogPartial, ScheduledJobEdit) { ClearScope(); @@ -140,6 +141,10 @@ function JobsListController ($scope, $compile, ClearScope, Breadcrumbs, LoadBrea }); }; + scheduled_scope.editSchedule = function(id) { + ScheduledJobEdit({ scope: scheduled_scope, id: id }); + }; + completed_scope.relaunch = function(id) { var job = Find({ list: completed_scope.completed_jobs, key: 'id', val: id }), type_id = getTypeId(job); @@ -165,7 +170,7 @@ function JobsListController ($scope, $compile, ClearScope, Breadcrumbs, LoadBrea } $scope.removeChoicesReady = $scope.$on('choicesReady', function() { choicesCount++; - if (choicesCount === 2) { + if (choicesCount === 3) { $scope.$emit('buildJobsList'); } }); @@ -188,11 +193,16 @@ function JobsListController ($scope, $compile, ClearScope, Breadcrumbs, LoadBrea callback: 'choicesReady' }); + LoadDialogPartial({ + scope: $scope, + element_id: 'schedule-dialog-target', + callback: 'choicesReady' + }); } JobsListController.$inject = ['$scope', '$compile', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'LoadScope', 'RunningJobsList', 'CompletedJobsList', 'QueuedJobsList', 'ScheduledJobsList', 'GetChoices', 'GetBasePath', 'Wait', 'DeleteJob', 'Find', 'DeleteSchedule', 'ToggleSchedule', 'RelaunchInventory', - 'RelaunchPlaybook', 'RelaunchSCM']; + 'RelaunchPlaybook', 'RelaunchSCM', 'LoadDialogPartial', 'ScheduledJobEdit']; function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, JobTemplateForm, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, @@ -464,6 +474,7 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J 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' + 'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait', 'Empty', 'ParseVariableString', 'GetChoices', + 'LoadDialogPartial' ]; diff --git a/awx/ui/static/js/controllers/Schedules.js b/awx/ui/static/js/controllers/Schedules.js index 962b1d3f37..cda9f9cd45 100644 --- a/awx/ui/static/js/controllers/Schedules.js +++ b/awx/ui/static/js/controllers/Schedules.js @@ -10,8 +10,9 @@ 'use strict'; -function ScheduleEdit($scope, $compile, $location, $routeParams, SchedulesList, GenerateList, Rest, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, -GetBasePath, LookUpInit, Wait, SchedulerInit, Breadcrumbs, SearchInit, PaginateInit, PageRangeSetup, EditSchedule, AddSchedule, Find, ToggleSchedule, DeleteSchedule) { +function ScheduleEditController($scope, $compile, $location, $routeParams, SchedulesList, GenerateList, Rest, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, +GetBasePath, LookUpInit, Wait, SchedulerInit, Breadcrumbs, SearchInit, PaginateInit, PageRangeSetup, EditSchedule, AddSchedule, Find, ToggleSchedule, DeleteSchedule, +LoadDialogPartial) { ClearScope(); @@ -156,21 +157,33 @@ GetBasePath, LookUpInit, Wait, SchedulerInit, Breadcrumbs, SearchInit, PaginateI }); }; - // Load the parent object - id = $routeParams.id; - Rest.setUrl(GetBasePath(base) + id); - Rest.get() - .success(function(data) { - parentObject = data; - $scope.$emit('ParentLoaded'); - }) - .error(function(status) { - ProcessErrors($scope, null, status, null, { hdr: 'Error!', - msg: 'Call to ' + url + ' failed. GET returned: ' + status }); - }); + if ($scope.removeLoadParent) { + $scope.removeLoadParent(); + } + $scope.removeLoadParent = $scope.$on('LoadParent', function() { + // Load the parent object + id = $routeParams.id; + url = GetBasePath(base) + id; + Rest.setUrl(url); + Rest.get() + .success(function(data) { + parentObject = data; + $scope.$emit('ParentLoaded'); + }) + .error(function(status) { + ProcessErrors($scope, null, status, null, { hdr: 'Error!', + msg: 'Call to ' + url + ' failed. GET returned: ' + status }); + }); + }); + + LoadDialogPartial({ + scope: $scope, + element_id: 'schedule-dialog-target', + callback: 'LoadParent', + }); } -ScheduleEdit.$inject = ['$scope', '$compile', '$location', '$routeParams', 'SchedulesList', 'GenerateList', 'Rest', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', +ScheduleEditController.$inject = ['$scope', '$compile', '$location', '$routeParams', 'SchedulesList', 'GenerateList', 'Rest', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath', 'LookUpInit', 'Wait', 'SchedulerInit', 'Breadcrumbs', 'SearchInit', 'PaginateInit', 'PageRangeSetup', 'EditSchedule', 'AddSchedule', -'Find', 'ToggleSchedule', 'DeleteSchedule' +'Find', 'ToggleSchedule', 'DeleteSchedule', 'LoadDialogPartial' ]; \ No newline at end of file diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index 833283b3cf..05d58c2d20 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -678,6 +678,7 @@ function(SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize) { autoOpen: false, minWidth: 440, title: 'Edit Group', + closeOnEscape: false, create: function () { $('.ui-dialog[aria-describedby="group-modal-dialog"]').find('.ui-dialog-titlebar button').empty().attr({'class': 'close'}).text('x'); $('.ui-dialog[aria-describedby="group-modal-dialog"]').find('.ui-dialog-buttonset button').each(function () { @@ -705,9 +706,13 @@ function(SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize) { resizeStop: function () { // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100% var dialog = $('.ui-dialog[aria-describedby="group-modal-dialog"]'), + titleHeight = dialog.find('.ui-dialog-titlebar').outerHeight(), + buttonHeight = dialog.find('.ui-dialog-buttonpane').outerHeight(), content = dialog.find('#group-modal-dialog'), w; content.width(dialog.width() - 28); + content.css({ height: (dialog.height() - titleHeight - buttonHeight - 10) }); + if ($('#group_tabs .active a').text() === 'Properties') { textareaResize('group_variables', properties_scope); } diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js index 93efd6f655..d8a49ebf7d 100644 --- a/awx/ui/static/js/helpers/Hosts.js +++ b/awx/ui/static/js/helpers/Hosts.js @@ -470,6 +470,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener minWidth: 400, title: 'Host Properties', id: 'host-modal-dialog', + clonseOnEscape: false, onClose: function() { Wait('stop'); scope.codeMirror.destroy(); @@ -485,6 +486,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener }); }, onOpen: function() { + $('#host_name').focus(); setTimeout(function() { TextareaResize({ scope: scope, diff --git a/awx/ui/static/js/helpers/Jobs.js b/awx/ui/static/js/helpers/Jobs.js index 11567cfae4..4732c69887 100644 --- a/awx/ui/static/js/helpers/Jobs.js +++ b/awx/ui/static/js/helpers/Jobs.js @@ -10,7 +10,7 @@ 'use strict'; angular.module('JobsHelper', ['Utilities', 'RestServices', 'FormGenerator', 'JobSummaryDefinition', 'InventoryHelper', 'GeneratorHelpers', - 'JobSubmissionHelper']) + 'JobSubmissionHelper', 'SchedulesHelper']) .factory('JobStatusToolTip', [ function () { @@ -370,5 +370,15 @@ function(Find, Wait, Rest, InventoryUpdate, ProcessErrors, GetBasePath) { id = params.id; ProjectUpdate({ scope: scope, id: id }); }; +}]) + +.factory('ScheduledJobEdit', ['Find', 'EditSchedule', 'GetBasePath', function(Find, EditSchedule, GetBasePath) { + return function(params) { + var scope = params.scope, + id = params.id, + url = GetBasePath('schedules'), + schedule = Find({ list: scope.scheduled_jobs, key: 'id', val: id }); + EditSchedule({ scope: scope, schedule: schedule, url: url }); + }; }]); diff --git a/awx/ui/static/js/helpers/Schedules.js b/awx/ui/static/js/helpers/Schedules.js index aebdb14151..3a4245a2b8 100644 --- a/awx/ui/static/js/helpers/Schedules.js +++ b/awx/ui/static/js/helpers/Schedules.js @@ -52,6 +52,7 @@ angular.module('SchedulesHelper', ['Utilities', 'SchedulesHelper']) width: x, height: y, autoOpen: false, + closeOnEscape: false, create: function () { $('.ui-dialog[aria-describedby="scheduler-modal-dialog"]').find('.ui-dialog-titlebar button').empty().attr({'class': 'close'}).text('x'); $('.ui-dialog[aria-describedby="scheduler-modal-dialog"]').find('.ui-dialog-buttonset button').each(function () { @@ -79,9 +80,12 @@ angular.module('SchedulesHelper', ['Utilities', 'SchedulesHelper']) }, resizeStop: function () { // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100% - var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'), - content = dialog.find('#scheduler-modal-dialog'); + var dialog = $('.ui-dialog[aria-describedby="scheduler-modal-dialog"]'), + titleHeight = dialog.find('.ui-dialog-titlebar').outerHeight(), + buttonHeight = dialog.find('.ui-dialog-buttonpane').outerHeight(), + content = dialog.find('#scheduler-modal-dialog'); content.width(dialog.width() - 28); + content.css({ height: (dialog.height() - titleHeight - buttonHeight - 10) }); }, close: function () { // Destroy on close @@ -114,7 +118,6 @@ angular.module('SchedulesHelper', ['Utilities', 'SchedulesHelper']) schedule = params.schedule, url = params.url, scheduler; - Wait('start'); $('#form-container').empty(); scheduler = SchedulerInit({ scope: scope, requireFutureStartTime: false }); @@ -124,6 +127,10 @@ angular.module('SchedulesHelper', ['Utilities', 'SchedulesHelper']) ShowSchedulerModal({ scope: scope }); scope.showRRuleDetail = false; + if (!/DTSTART/.test(schedule.rrule)) { + schedule.rrule += ";DTSTART=" + schedule.dtstart; + } + setTimeout(function(){ $('#scheduler-modal-dialog').dialog('open'); scope.$apply(function() { @@ -216,6 +223,31 @@ angular.module('SchedulesHelper', ['Utilities', 'SchedulesHelper']) }; }]) + .factory('LoadDialogPartial', ['Rest', '$compile', 'ProcessErrors', function(Rest, $compile, ProcessErrors) { + return function(params) { + + var scope = params.scope, + element_id = params.element_id, + callback = params.callback, + url; + + // Add the schedule_dialog.html partial + url = '/static/partials/schedule_dialog.html'; + Rest.setUrl(url); + Rest.get() + .success(function(data) { + var e = angular.element(document.getElementById(element_id)); + e.append(data); + $compile(e)(scope); + scope.$emit(callback); + }) + .error(function(data, status) { + ProcessErrors(scope, null, status, null, { hdr: 'Error!', + msg: 'Call to ' + url + ' failed. GET returned: ' + status }); + }); + }; + }]) + /** * Flip a schedule's enable flag * diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index 6d4f924322..b1ba03e777 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -733,7 +733,7 @@ select.page-size { .nav-path { padding: 5px 0 10px 0; margin-right: 5px; - margin-bottom: 25px; + margin-bottom: 20px; font-size: 14px; font-weight: bold; background-color: #f5f5f5; diff --git a/awx/ui/static/less/jquery-ui-overrides.less b/awx/ui/static/less/jquery-ui-overrides.less index 5d0882fc73..bcb1d8de1e 100644 --- a/awx/ui/static/less/jquery-ui-overrides.less +++ b/awx/ui/static/less/jquery-ui-overrides.less @@ -76,6 +76,7 @@ table.ui-datepicker-calendar { text-decoration: none; font-weight: normal; } + max-height: 48px; } .ui-widget-overlay.ui-front { diff --git a/awx/ui/static/lib/ansible/Modal.js b/awx/ui/static/lib/ansible/Modal.js index be43142756..58e9ab147d 100644 --- a/awx/ui/static/lib/ansible/Modal.js +++ b/awx/ui/static/lib/ansible/Modal.js @@ -45,6 +45,7 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper']) onClose = params.onClose, onOpen = params.onOpen, callback = params.callback, + closeOnEscape = (params.closeOnEscape === undefined) ? false : params.closeOnEscape, buttons, id = params.id, x, y, wh, ww; @@ -82,6 +83,7 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper']) autoOpen: false, minWidth: minWidth, title: title, + closeOnEscape: closeOnEscape, create: function () { // Fix the close button $('.ui-dialog[aria-describedby="' + id + '"]').find('.ui-dialog-titlebar button').empty().attr({'class': 'close'}).text('x'); @@ -108,8 +110,11 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper']) resizeStop: function () { // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100% var dialog = $('.ui-dialog[aria-describedby="' + id + '"]'), + titleHeight = dialog.find('.ui-dialog-titlebar').outerHeight(), + buttonHeight = dialog.find('.ui-dialog-buttonpane').outerHeight(), content = dialog.find('#' + id); content.width(dialog.width() - 28); + content.css({ height: (dialog.height() - titleHeight - buttonHeight - 10) }); if (onResizeStop) { onResizeStop(); } diff --git a/awx/ui/static/lib/ansible/directives.js b/awx/ui/static/lib/ansible/directives.js index ca7858ef5d..d3b934de74 100644 --- a/awx/ui/static/lib/ansible/directives.js +++ b/awx/ui/static/lib/ansible/directives.js @@ -287,7 +287,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job var placement = (attrs.placement !== undefined && attrs.placement !== null) ? attrs.placement : 'left', title = (attrs.title !== undefined && attrs.title !== null) ? attrs.title : 'Help', container = (attrs.container !== undefined) ? attrs.container : false, - trigger = (attrs.trigger !== undefined) ? attrs.trigger : 'manua'; + trigger = (attrs.trigger !== undefined) ? attrs.trigger : 'manual'; $(element).popover({ placement: placement, delay: 0, title: title, content: attrs.awPopOver, trigger: trigger, html: true, container: container }); $(element).click(function() { diff --git a/awx/ui/static/partials/jobs.html b/awx/ui/static/partials/jobs.html index 3180521f4f..94a2addb39 100644 --- a/awx/ui/static/partials/jobs.html +++ b/awx/ui/static/partials/jobs.html @@ -32,6 +32,7 @@ - + +
\ No newline at end of file diff --git a/awx/ui/static/partials/schedule_detail.html b/awx/ui/static/partials/schedule_detail.html index 103ac7207a..01d9947b3e 100644 --- a/awx/ui/static/partials/schedule_detail.html +++ b/awx/ui/static/partials/schedule_detail.html @@ -8,16 +8,4 @@ -
- -
-
-
-
-
-
-
-
\ No newline at end of file +
\ No newline at end of file diff --git a/awx/ui/static/partials/schedule_dialog.html b/awx/ui/static/partials/schedule_dialog.html new file mode 100644 index 0000000000..d9feaf4e38 --- /dev/null +++ b/awx/ui/static/partials/schedule_dialog.html @@ -0,0 +1,13 @@ +
+ +
+
+
+
+
+
+
+
\ No newline at end of file