diff --git a/awx/ui/static/js/controllers/Groups.js b/awx/ui/static/js/controllers/Groups.js index ef3e64a4c7..d01b884a9b 100644 --- a/awx/ui/static/js/controllers/Groups.js +++ b/awx/ui/static/js/controllers/Groups.js @@ -18,6 +18,7 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP var generator = GenerateForm; var form = InventoryGroupsForm; var defaultUrl=GetBasePath('inventory'); + $('#tree-view').empty(); var scope = generator.inject(form, { mode: 'edit', related: true, buildTree: true }); var base = $location.path().replace(/^\//,'').split('/')[0]; @@ -127,10 +128,13 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP var type = node.attr('type'); var url; + scope['nodeSelectValue'] = n; scope['selectedNode'] = node; scope['selectedNodeName'] = node.attr('name'); scope['grpBtnDisable'] = false; - + scope['flashMessage'] = null; + scope['groupUpdateHide'] = true; + $('#tree-view').jstree('open_node',node); if (type == 'group') { @@ -145,11 +149,13 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP // Load the form GroupsEdit({ "inventory_id": id, group_id: scope.group_id }); - //scope.groupName = n.data; - //scope.groupTitle = '

' + n.data + '

'; - //scope.groupTitle += (node.attr('description')) ? '

' + node.attr('description') + '

' : ''; + + // Slide in the group properties form + $('#tree-form').show(); + $('input:first').focus(); } else if (type == 'inventory') { + $('#tree-form').hide().empty(); url = node.attr('hosts'); scope.groupAddHide = true; scope.groupCreateHide = false; @@ -157,8 +163,6 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP scope.inventoryEditHide=false; scope.groupDeleteHide = true; scope.createButtonShow = false; - //scope.groupName = 'All Hosts'; - //scope.groupTitle = '

All Hosts

'; scope.group_id = null; } @@ -177,14 +181,7 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP scope.editGroup = function() { // Slide in the group properties form - $('#tree-form').show('slide', {direction: 'up'}, 500); - - // Set the focust to the first form field - $('input:first').focus(); - - // Disable all the group related buttons - scope.grpBtnDisable = true; - setTimeout(function() { + $('#tree-form').show('slide', {direction: 'up'}, 500, function() { // Remove any tooltips that might be lingering $('.tooltip').each( function(index) { $(this).remove(); @@ -193,7 +190,19 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP // remove lingering popover
. Seems to be a bug in TB3 RC1 $(this).remove(); }); - }, 1000); + // Set the focust to the first form field + $('input:first').focus(); + }); + + // Disable all the group related buttons + scope.grpBtnDisable = false; + + } + + scope.closeForm = function() { + // Slide in the group properties form + $('#tree-form').hide('slide',{ direction: 'right' }, 500, function() { $('#tree-form').empty(); }); + scope.grpBtnDisable = false; } scope.editInventory = function() { diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index a356afb37e..5a530f3a9a 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -238,54 +238,18 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP } }; - // Related set: Add button - scope.add = function(set) { - $rootScope.flashMessage = null; - $location.path('/' + base + '/' + $routeParams.id + '/groups/' + scope.group_id + '/' + set + '/add'); - }; - - // Related set: Edit button - scope.edit = function(set, id, name) { - $rootScope.flashMessage = null; - $location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id); - }; - if (scope.removeInventorySaved) { scope.removeInventorySaved(); } scope.removeInventorySaved = scope.$on('inventorySaved', function() { $location.path('/inventories'); }); + scope.formSave = function() { generator.clearApiErrors(); SaveInventory({ scope: scope }); } - // Related set: Delete button - scope['delete'] = function(set, itm_id, name, title) { - $rootScope.flashMessage = null; - - var action = function() { - var url = defaultUrl + id + '/' + set + '/'; - Rest.setUrl(url); - Rest.post({ id: itm_id, disassociate: 1 }) - .success( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - }); - }; - - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', - action: action - }); - - }; } InventoriesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', diff --git a/awx/ui/static/js/forms/Groups.js b/awx/ui/static/js/forms/Groups.js index ccf928e9fa..ccd5142616 100644 --- a/awx/ui/static/js/forms/Groups.js +++ b/awx/ui/static/js/forms/Groups.js @@ -11,21 +11,15 @@ angular.module('GroupFormDefinition', []) 'GroupForm', { addTitle: 'Create Group', //Legend in add mode - editTitle: '{{ name }}', //Legend in edit mode + editTitle: 'Group Properties: {{ name }}', //Legend in edit mode + showTitle: true, + cancelButton: false, name: 'group', //Form name attribute well: false, //Wrap the form with TB well - //formLabelSize: 'col-lg-3', - //formFieldSize: 'col-lg-9', + formLabelSize: 'col-lg-3', + formFieldSize: 'col-lg-9', fields: { - /*has_active_failures: { - label: 'Status', - control: '
' + - ' Contains hosts with failed jobs
', - type: 'custom', - ngShow: 'has_active_failures', - readonly: true - },*/ name: { label: 'Name', type: 'text', @@ -44,11 +38,11 @@ angular.module('GroupFormDefinition', []) addRequired: false, editRequird: false, rows: 10, - "class": 'modal-input-xlarge', - "default": "---", + 'default': '---', dataTitle: 'Group Variables', dataPlacement: 'left', - awPopOver: "

Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.

" + + awPopOver: "

Variables defined here apply to all child groups and hosts. Enter variables using either JSON or YAML syntax. Use the " + + "radio button to toggle between the two.

" + "JSON:
\n" + "
{
\"somevar\": \"somevalue\",
\"password\": \"magic\"
}
\n" + "YAML:
\n" + @@ -56,10 +50,164 @@ angular.module('GroupFormDefinition', []) '

View JSON examples at www.json.org

' + '

View YAML examples at ansibleworks.com

', dataContainer: 'body' - } + }, + source: { + label: 'Source', + excludeModal: true, + type: 'select', + ngOptions: 'source.label for source in source_type_options', + ngChange: 'sourceChange()', + addRequired: false, + editRequired: false, + 'default': { label: 'Manual', value: null } + }, + source_path: { + label: 'Script Path', + excludeModal: true, + ngShow: "source.value == 'file'", + type: 'text', + awRequiredWhen: {variable: "sourcePathRequired", init: "false" } + }, + source_env: { + label: 'Script Environment Variables', + ngShow: "source.value == 'file'", + type: 'textarea', + addRequired: false, + editRequird: false, + excludeModal: true, + rows: 10, + 'default': '---', + parseTypeName: 'envParseType', + dataTitle: 'Script Environment Variables', + dataPlacement: 'left', + awPopOver: "

Define environment variables here that will be referenced by the inventory script at runtime. " + + "Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.

" + + "JSON:
\n" + + "
{
\"somevar\": \"somevalue\",
\"password\": \"magic\"
}
\n" + + "YAML:
\n" + + "
---
somevar: somevalue
password: magic
\n" + + '

View JSON examples at www.json.org

' + + '

View YAML examples at ansibleworks.com

', + dataContainer: 'body', + awPopOverRight: true + }, + source_username: { + labelBind: 'sourceUsernameLabel', + excludeModal: true, + type: 'text', + ngShow: "source.value == 'rackspace' || source.value == 'ec2'", + awRequiredWhen: {variable: "sourceUsernameRequired", init: "false" } + }, + source_password: { + labelBind: 'sourcePasswordLabel', + excludeModal: true, + type: 'password', + ngShow: "source.value == 'rackspace' || source.value == 'ec2'", + editRequired: false, + addRequired: false, + ngChange: "clearPWConfirm('source_password_confirm')", + ask: true, + clear: true, + associated: 'source_password_confirm', + autocomplete: false + }, + source_password_confirm: { + labelBind: 'sourcePasswordConfirmLabel', + type: 'password', + ngShow: "source.value == 'rackspace' || source.value == 'ec2'", + addRequired: false, + editRequired: false, + awPassMatch: true, + associated: 'source_password', + autocomplete: false + }, + source_regions: { + label: 'Regions', + excludeModal: true, + type: 'text', + ngShow: "source.value == 'rackspace' || source.value == 'ec2'", + addRequired: false, + editRequired: false + }, + source_tags: { + label: 'Tags', + excludeModal: true, + type: 'text', + ngShow: "source.value == 'rackspace' || source.value == 'ec2'", + addRequired: false, + editRequired: false + }, + checkbox_group: { + label: 'Update Options', + type: 'checkbox_group', + ngShow: "source.value !== '' && source.value !== null", + + fields: [ + { + name: 'overwite_hosts', + label: 'Overwrite Hosts', + type: 'checkbox', + ngShow: "source.value !== '' && source.value !== null", + addRequired: false, + editRequired: false, + awPopOver: '

Replace AWX inventory hosts with cloud inventory hosts.

', + dataTitle: 'Overwrite Hosts', + dataContainer: 'body', + dataPlacement: 'left', + labelClass: 'checkbox-options', + inline: false + }, + { + name: 'overwite_vars', + label: 'Overwrite Variables', + type: 'checkbox', + ngShow: "source.value !== '' && source.value !== null", + addRequired: false, + editRequired: false, + awPopOver: '

', + dataTitle: 'Overwrite Variables', + dataContainer: 'body', + dataPlacement: 'left', + labelClass: 'checkbox-options', + inline: false + }, + { + name: 'keep_vars', + label: 'Keep Variables', + type: 'checkbox', + ngShow: "source.value !== '' && source.value !== null", + addRequired: false, + editRequired: false, + awPopOver: '

', + dataTitle: 'Keep Variables', + dataContainer: 'body', + dataPlacement: 'left', + labelClass: 'checkbox-options', + inline: false + }, + { + name: 'update_on_launch', + label: 'Update on Launch', + type: 'checkbox', + ngShow: "source.value !== '' && source.value !== null", + addRequired: false, + editRequired: false, + awPopOver: '

Each time a job runs using this inventory, refresh the inventory from the selected source

', + dataTitle: 'Update on Launch', + dataContainer: 'body', + dataPlacement: 'left', + labelClass: 'checkbox-options', + inline: false + } + ] + } }, buttons: { //for now always generates
\n"; html += "
\n"; + html += "\n
\n"; if (field.ask) { html += "' + "\n"; + html += (field.awPopOver && field.awPopOverRight) ? this.attr(field, 'awPopOver', fld) : ""; html += "\n"; html += "
Parse as: " + " YAML\n"; html += " JSON\n
\n"; } @@ -604,7 +607,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) //select field if (field.type == 'select') { - html += "
" + field.label + "\n"; - html += "
\n"; } + // Add a title and optionally a close button (used on Inventory->Groups) + if ( (!options.modal) && this.form.showTitle ) { + html += "
"; + html += (options.mode == 'edit') ? this.form.editTitle : this.form.addTitle; + if (this.form.cancelButton) { + html += "\n"; + } + html += "
\n"; + html += "
\n"; + } + html += "
\n"; @@ -1001,31 +1018,30 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) var group = ''; for (var fld in this.form.fields) { var field = this.form.fields[fld]; - - if (field.group && field.group != group) { - if (group !== '') { - html += "
\n"; - } - html += "
\n"; - html += "
" + field.group + "
\n"; - group = field.group; + if (!(options.modal && field.excludeModal)) { + if (field.group && field.group != group) { + if (group !== '') { + html += "
\n"; + } + html += "
\n"; + html += "
" + field.group + "
\n"; + group = field.group; + } + if (field.section && field.section != section) { + if (section !== '') { + html += "
\n"; + } + else { + html += "
\n"; + html += "
\n"; + } + var sectionShow = (this.form[field.section + 'Show']) ? " ng-show=\"" + this.form[field.section + 'Show'] + "\"" : ""; + html += "" + field.section + "\n"; + html += "\n"; + section = field.section; + } + html += this.buildField(fld, field, options, this.form); } - - if (field.section && field.section != section) { - if (section !== '') { - html += "
\n"; - } - else { - html += "\n"; - html += "
\n"; - } - var sectionShow = (this.form[field.section + 'Show']) ? " ng-show=\"" + this.form[field.section + 'Show'] + "\"" : ""; - html += "" + field.section + "\n"; - html += "\n"; - section = field.section; - } - - html += this.buildField(fld, field, options, this.form); } if (section !== '') { html += "
\n\n"; @@ -1038,44 +1054,53 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) //buttons if (!this.modal) { if (this.has('buttons')) { + if (this.form.twoColumns) { - html += "
\n"; - html += "
\n"; - html += "
\n"; + html += "
\n"; + html += "
\n"; + html += "
\n"; } + html += "
\n"; - html += "
\n"; + html += "\n"; + html += "
\n"; for (var btn in this.form.buttons) { - var button = this.form.buttons[btn]; - //button - html += "\n"; } html += "
\n"; html += "
\n"; @@ -1180,22 +1205,33 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) html += "
\n"; html += "
\n"; html += "
\n"; - html += "
\n"; + html += "
\n"; + html += "
\n"; html += "
\n"; - html += "\n"; + */ html += "\n"; html += "\n"; + html += "\n"; html += "\n"; + html += "
\n"; + html += "
\n"; html += "
\n"; + html += "
\n"; html += "
\n"; - html += "
\n"; - html += "
\n
\n
\n
\n"; + html += "
\n"; + html += "
\n
\n
\n
\n"; html += "
\n"; html += "
\n"; html += "
\n";