From 5c42b88e27788ab63bfdbbb4f620e7449afa977c Mon Sep 17 00:00:00 2001
From: Chris Houseknecht
Date: Sat, 28 Dec 2013 19:45:51 +0000
Subject: [PATCH] Finished icon cleanup from FontAwesome upgrade. Changed
default form style to basic rather than horizontal for a much cleaner,
uncluttered look, especially in dialog boxes. Group Edit dialog is starting
to function. Added support for Tabs in form generator.
---
awx/ui/static/js/controllers/Credentials.js | 5 +
awx/ui/static/js/controllers/Inventories.js | 13 +-
awx/ui/static/js/forms/Credentials.js | 17 +-
awx/ui/static/js/forms/Groups.js | 87 +---
awx/ui/static/js/forms/JobTemplates.js | 10 +-
awx/ui/static/js/forms/Jobs.js | 16 +-
awx/ui/static/js/forms/Projects.js | 4 +-
awx/ui/static/js/forms/Users.js | 14 +-
awx/ui/static/js/helpers/Events.js | 5 +-
awx/ui/static/js/helpers/Groups.js | 112 ++---
awx/ui/static/js/helpers/search.js | 2 +-
awx/ui/static/js/lists/Inventories.js | 4 +-
awx/ui/static/js/lists/InventoryGroups.js | 22 +-
awx/ui/static/js/lists/InventoryHosts.js | 4 +-
awx/ui/static/js/lists/JobEvents.js | 2 +-
awx/ui/static/js/lists/JobHosts.js | 2 +-
awx/ui/static/js/lists/Jobs.js | 4 +-
awx/ui/static/less/ansible-ui.less | 39 +-
awx/ui/static/lib/ansible/InventoryTree.js | 17 +-
awx/ui/static/lib/ansible/form-generator.js | 467 +++++++++++-------
.../static/lib/ansible/generator-helpers.js | 8 +-
awx/ui/static/lib/ansible/list-generator.js | 6 +-
22 files changed, 487 insertions(+), 373 deletions(-)
diff --git a/awx/ui/static/js/controllers/Credentials.js b/awx/ui/static/js/controllers/Credentials.js
index 1c8d514830..3ca88de934 100644
--- a/awx/ui/static/js/controllers/Credentials.js
+++ b/awx/ui/static/js/controllers/Credentials.js
@@ -195,6 +195,11 @@ function CredentialsAdd ($scope, $rootScope, $compile, $location, $log, $routePa
{ hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status });
});
}
+ else {
+ // default type of owner to a user
+ scope['owner'] = 'user';
+ OwnerChange({ scope: scope });
+ }
// Handle Kind change
scope.kindChange = function () {
diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js
index 887e000459..4e01f20ce1 100644
--- a/awx/ui/static/js/controllers/Inventories.js
+++ b/awx/ui/static/js/controllers/Inventories.js
@@ -316,7 +316,7 @@ InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$lo
function InventoriesEdit ($scope, $location, $routeParams, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait,
- UpdateStatusMsg, InjectHosts, HostsReload)
+ UpdateStatusMsg, InjectHosts, HostsReload, GroupsAdd, GroupsEdit)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
@@ -347,14 +347,21 @@ function InventoriesEdit ($scope, $location, $routeParams, GenerateList, ClearSc
$scope.showHosts = function(group_id) {
// Clicked on group
- console.log('here');
HostsReload({ scope: $scope, group_id: group_id, inventory_id: $scope.inventory_id });
}
+ $scope.createGroup = function() {
+ GroupsAdd({ scope: $scope, inventory_id: $scope.inventory_id, group_id: null });
+ }
+
+ $scope.editGroup = function(group_id) {
+ GroupsEdit({ scope: $scope, inventory_id: $scope.inventory_id, group_id: group_id });
+ }
+
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id });
}
InventoriesEdit.$inject = [ '$scope','$location', '$routeParams', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts', 'BuildTree',
- 'Wait', 'UpdateStatusMsg', 'InjectHosts', 'HostsReload'
+ 'Wait', 'UpdateStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsAdd', 'GroupsEdit'
];
diff --git a/awx/ui/static/js/forms/Credentials.js b/awx/ui/static/js/forms/Credentials.js
index 1875dcd6f3..d975907135 100644
--- a/awx/ui/static/js/forms/Credentials.js
+++ b/awx/ui/static/js/forms/Credentials.js
@@ -39,13 +39,11 @@ angular.module('CredentialFormDefinition', [])
editRequired: false
},
owner: {
- label: 'Owned By?',
- type: 'radio',
+ label: "Does this credential belong to a team or user?",
+ type: 'radio_group',
ngChange: "ownerChange()",
- addRequired: true,
- editRequired: true,
options: [
- { label: 'User', value: 'user' },
+ { label: 'User', value: 'user', selected: true },
{ label: 'Team', value: 'team' }
],
awPopOver: "A credential must be associated with either a user or a team. Choosing a user allows only the selected user access " +
@@ -55,7 +53,7 @@ angular.module('CredentialFormDefinition', [])
dataContainer: "body"
},
user: {
- label: 'User',
+ label: 'User that owns this credential',
type: 'lookup',
sourceModel: 'user',
sourceField: 'username',
@@ -64,7 +62,7 @@ angular.module('CredentialFormDefinition', [])
awRequiredWhen: { variable: "user_required", init: "false" }
},
team: {
- label: 'Team',
+ label: 'Team that owns this credential',
type: 'lookup',
sourceModel: 'team',
sourceField: 'name',
@@ -81,9 +79,8 @@ angular.module('CredentialFormDefinition', [])
addRequired: true,
editRequired: true,
helpCollapse: [
- { hdr: 'Credential Type',
- content: '
Choose a type for this credential: ' +
- '
\n' +
+ { hdr: 'Select a Credential Type',
+ content: '\n' +
'AWS \n' +
'Access keys for Amazon Web Services used for inventory management or deployment. \n' +
'Machine \n' +
diff --git a/awx/ui/static/js/forms/Groups.js b/awx/ui/static/js/forms/Groups.js
index d503b56f6f..d737a7b811 100644
--- a/awx/ui/static/js/forms/Groups.js
+++ b/awx/ui/static/js/forms/Groups.js
@@ -10,70 +10,34 @@ angular.module('GroupFormDefinition', [])
.value(
'GroupForm', {
- addTitle: 'Create Group', //Legend in add mode
- editTitle: '{{ name }}', //Legend in edit mode
+ addTitle: 'Create Group',
+ editTitle: 'Edit Group',
showTitle: true,
cancelButton: false,
- name: 'group', //Form name attribute
- well: true, //Wrap the form with TB well
+ name: 'group',
+ well: true,
formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',
- titleActions: {
- copy_action: {
- 'class': 'btn-success btn-xs',
- ngClick: "addGroup()",
- ngHide: "groupAddHide",
- awToolTip: "\{\{ addGroupHelp \}\}",
- dataPlacement: 'top',
- ngDisabled: "grpBtnDisable",
- icon: "icon-check",
- label: 'Copy'
- },
- create_action: {
- 'class': 'btn-success btn-xs',
- ngClick: "createGroup()",
- ngHide: "groupCreateHide",
- awToolTip: "\{\{ createGroupHelp \}\}",
- dataPlacement: "top",
- ngDisabled: "grpBtnDisable",
- icon: "icon-plus",
- label: "Create New"
- },
- update_action: {
- 'class': 'btn-success btn-xs',
- ngClick: "updateGroup()",
- ngHide: "groupUpdateHide",
- awToolTip: "\{\{ updateGroupHelp \}\}",
- dataPlacement: "top",
- ngDisabled: "grpBtnDisable",
- icon: "icon-cloud-download",
- label: 'Update'
- },
- delete_action: {
- 'class': "btn-danger btn-xs",
- ngClick: "deleteGroup()",
- ngHide: "groupDeleteHide",
- awToolTip: "\{\{ deleteGroupHelp \}\}",
- dataPlacement: "top",
- ngDisabled: "grpBtnDisable",
- icon: "icon-trash",
- label: "Delete"
- }
- },
-
+ tabs: [
+ { name: 'properties', label: 'Properties'},
+ { name: 'source', label: 'Source' }
+ ],
+
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
- editRequired: true
+ editRequired: true,
+ tab: 'properties'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
- editRequired: false
+ editRequired: false,
+ tab: 'properties'
},
variables: {
label: 'Variables',
@@ -93,24 +57,25 @@ angular.module('GroupFormDefinition', [])
"--- somevar: somevalue password: magic \n" +
'View JSON examples at www.json.org
' +
'View YAML examples at ansibleworks.com
',
- dataContainer: 'body'
+ dataContainer: 'body',
+ tab: 'properties'
},
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: '' }
+ 'default': { label: 'Manual', value: '' },
+ tab: 'source'
},
source_path: {
label: 'Script Path',
- excludeModal: true,
ngShow: "source.value == 'file'",
type: 'text',
- awRequiredWhen: {variable: "sourcePathRequired", init: "false" }
+ awRequiredWhen: {variable: "sourcePathRequired", init: "false" },
+ tab: 'source'
},
credential: {
label: 'Cloud Credential',
@@ -120,11 +85,11 @@ angular.module('GroupFormDefinition', [])
sourceField: 'name',
ngClick: 'lookUpCredential()',
addRequired: false,
- editRequired: false
+ editRequired: false,
+ tab: 'source'
},
source_regions: {
label: 'Regions',
- excludeModal: true,
type: 'text',
ngShow: "source.value == 'rax' || source.value == 'ec2'",
addRequired: false,
@@ -135,7 +100,8 @@ angular.module('GroupFormDefinition', [])
awPopOver: "Click on the regions field to see a list of regions for your cloud provider. You can select multiple regions, " +
"or choose All to include all regions. AWX will only be updated with Hosts associated with the selected regions." +
"
",
- dataContainer: 'body'
+ dataContainer: 'body',
+ tab: 'source'
},
source_vars: {
label: 'Source Variables',
@@ -143,7 +109,6 @@ angular.module('GroupFormDefinition', [])
type: 'textarea',
addRequired: false,
editRequird: false,
- excludeModal: true,
rows: 10,
'default': '---',
parseTypeName: 'envParseType',
@@ -159,7 +124,8 @@ angular.module('GroupFormDefinition', [])
"--- somevar: somevalue password: magic \n" +
'View JSON examples at www.json.org
' +
'View YAML examples at ansibleworks.com
',
- dataContainer: 'body'
+ dataContainer: 'body',
+ tab: 'source'
},
/*update_interval: {
label: 'Update Interval',
@@ -180,6 +146,7 @@ angular.module('GroupFormDefinition', [])
label: 'Update Options',
type: 'checkbox_group',
ngShow: "source.value !== '' && source.value !== null",
+ tab: 'source',
fields: [
{
@@ -249,5 +216,5 @@ angular.module('GroupFormDefinition', [])
}
- }); //UserForm
+ });
diff --git a/awx/ui/static/js/forms/JobTemplates.js b/awx/ui/static/js/forms/JobTemplates.js
index 6222d70cb3..786c832c95 100644
--- a/awx/ui/static/js/forms/JobTemplates.js
+++ b/awx/ui/static/js/forms/JobTemplates.js
@@ -187,7 +187,7 @@ angular.module('JobTemplateFormDefinition', [])
"YAML: \n" +
"--- somevar: somevalue password: magic \n",
dataTitle: 'Extra Variables',
- dataPlacement: 'left',
+ dataPlacement: 'right',
dataContainer: "body"
},
job_tags: {
@@ -206,7 +206,7 @@ angular.module('JobTemplateFormDefinition', [])
"in the Job Tags field:<\p>\n" +
"configuration,packages \n",
dataTitle: "Job Tags",
- dataPlacement: "left",
+ dataPlacement: "right",
dataContainer: "body"
},
allow_callbacks: {
@@ -227,7 +227,7 @@ angular.module('JobTemplateFormDefinition', [])
"Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.
" +
"Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.
",
- detailPlacement: 'left',
+ dataPlacement: 'right',
dataTitle: 'Callback URL',
dataContainer: "body"
},
@@ -247,7 +247,7 @@ angular.module('JobTemplateFormDefinition', [])
"Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.
" +
"Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.
",
- detailPlacement: 'left',
+ dataPlacement: 'right',
dataTitle: 'Callback URL',
dataContainer: "body"
},
@@ -261,7 +261,7 @@ angular.module('JobTemplateFormDefinition', [])
"this key in the POST data of the request. Here's an example using curl:
\n" +
"curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/
\n",
- detailPlacement: 'left',
+ dataPlacement: 'right',
dataContainer: "body"
}
},
diff --git a/awx/ui/static/js/forms/Jobs.js b/awx/ui/static/js/forms/Jobs.js
index 862a8f17f8..009217de3e 100644
--- a/awx/ui/static/js/forms/Jobs.js
+++ b/awx/ui/static/js/forms/Jobs.js
@@ -202,7 +202,7 @@ angular.module('JobFormDefinition', [])
"--- somevar: somevalue password: magic \n",
dataTitle: 'Extra Variables',
dataContainer: 'body',
- dataPlacement: 'left'
+ dataPlacement: 'right'
},
job_tags: {
label: 'Job Tags',
@@ -221,7 +221,7 @@ angular.module('JobFormDefinition', [])
"configuration,packages \n",
dataTitle: "Job Tags",
dataContainer: 'body',
- dataPlacement: "left"
+ dataPlacement: "right"
},
allow_callbacks: {
label: 'Allow Callbacks',
@@ -242,7 +242,7 @@ angular.module('JobFormDefinition', [])
"Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.
" +
"Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.
",
- detailPlacement: 'left',
+ dataPlacement: 'right',
dataContainer: 'body',
dataTitle: 'Callback URL'
},
@@ -262,7 +262,7 @@ angular.module('JobFormDefinition', [])
"Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.
" +
"Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.
",
- detailPlacement: 'left',
+ dataPlacement: 'right',
dataContainer: 'body',
dataTitle: 'Callback URL'
},
@@ -276,7 +276,7 @@ angular.module('JobFormDefinition', [])
"this key in the POST data of the request. Here's an example using curl:\n" +
"curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/
\n",
- detailPlacement: 'left',
+ dataPlacement: 'right',
dataContainer: 'body'
}
},
@@ -300,13 +300,13 @@ angular.module('JobFormDefinition', [])
statusFields: {
status: {
- label: 'Job Status',
+ //label: 'Job Status',
type: 'custom',
- control: ' \{\{ status \}\}
',
+ control: 'Status \{\{ status \}\}
',
readonly: true
},
created: {
- label: 'Date',
+ label: 'Created On',
type: 'text',
readonly: true
},
diff --git a/awx/ui/static/js/forms/Projects.js b/awx/ui/static/js/forms/Projects.js
index 5ebc7b7ddc..a023a9b285 100644
--- a/awx/ui/static/js/forms/Projects.js
+++ b/awx/ui/static/js/forms/Projects.js
@@ -83,7 +83,7 @@ angular.module('ProjectFormDefinition', [])
base_dir: {
label: 'Project Base Path',
type: 'textarea',
- "class": 'col-lg-6',
+ //"class": 'col-lg-6',
showonly: true,
ngShow: "scm_type.value == ''",
awPopOver: 'Base path used for locating playbooks. Directories found inside this path will be listed in the playbook directory drop-down. ' +
@@ -153,7 +153,7 @@ angular.module('ProjectFormDefinition', [])
editRequired: false
},
checkbox_group: {
- label: 'SCM Options',
+ label: 'SCM Update Options',
type: 'checkbox_group',
ngShow: "scm_type && scm_type.value !== ''",
fields: [
diff --git a/awx/ui/static/js/forms/Users.js b/awx/ui/static/js/forms/Users.js
index b7d09fbcba..e59be33dd1 100644
--- a/awx/ui/static/js/forms/Users.js
+++ b/awx/ui/static/js/forms/Users.js
@@ -66,11 +66,6 @@ angular.module('UserFormDefinition', [])
awRequiredWhen: { variable: "not_ldap_user", init: true },
autocomplete: false
},
- ldap_user: {
- label: 'Created by LDAP?',
- type: 'checkbox',
- readonly: true
- },
password: {
label: 'Password',
type: 'password',
@@ -91,13 +86,18 @@ angular.module('UserFormDefinition', [])
autocomplete: false
},
is_superuser: {
- label: 'Superuser?',
+ label: 'Superuser (User has full system administration privileges.)',
type: 'checkbox',
trueValue: 'true',
falseValue: 'false',
"default": 'false',
ngShow: "current_user['is_superuser'] == true"
- }
+ },
+ ldap_user: {
+ label: 'Created by LDAP',
+ type: 'checkbox',
+ readonly: true
+ },
},
buttons: { //for now always generates tags
diff --git a/awx/ui/static/js/helpers/Events.js b/awx/ui/static/js/helpers/Events.js
index e8cc0185bb..01fabf0309 100644
--- a/awx/ui/static/js/helpers/Events.js
+++ b/awx/ui/static/js/helpers/Events.js
@@ -27,10 +27,9 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
fields: {
status: {
labelClass: 'job-\{\{ status \}\}',
- icon: 'icon-job-\{\{ status \}\}',
type: 'custom',
section: 'Event',
- control: '\{\{ status \}\}
'
+ control: ' \{\{ status \}\}
'
},
id: {
label: 'ID',
@@ -40,7 +39,7 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
'class': 'span1'
},
created: {
- label: 'Created',
+ label: 'Created On',
type: 'text',
section: 'Event',
readonly: true
diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js
index caf68d7d20..d268d7ff40 100644
--- a/awx/ui/static/js/helpers/Groups.js
+++ b/awx/ui/static/js/helpers/Groups.js
@@ -6,7 +6,9 @@
* Routines that handle group add/edit/delete on the Inventory tree widget.
*
*/
-
+
+'use strict';
+
angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'GroupListDefinition',
'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService', 'GroupsHelper',
'InventoryHelper', 'SelectionHelper', 'JobSubmissionHelper', 'RefreshHelper',
@@ -26,7 +28,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
var choices = data.actions.GET.source.choices
for (var i=0; i < choices.length; i++) {
if (choices[i][0] !== 'file') {
- scope[variable].push({ label: [ (choices[i][0] == "") ? 'Manual' : choices[i][1] ], value: choices[i][0] });
+ scope[variable].push({ label: (choices[i][0] == "") ? 'Manual' : choices[i][1] , value: choices[i][0] });
}
}
})
@@ -601,7 +603,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
var groupCreated = false;
scope.formModalActionLabel = 'Save';
- scope.formModalHeader = 'Create New Group';
scope.formModalCancelShow = true;
scope.parseType = 'yaml';
scope.source = null;
@@ -704,17 +705,14 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, GetUpdateIntervalOptions, ClickNode,
LookUpInit, CredentialList, Empty, Wait, GetChoices) {
return function(params) {
-
- $('#tree-form').hide().empty();
-
+
var group_id = params.group_id;
var inventory_id = params.inventory_id;
var generator = GenerateForm;
var form = GroupForm;
var defaultUrl = GetBasePath('groups') + group_id + '/';
- var scope = generator.inject(form,
- { mode: 'edit', modal: false, related: false, id: 'tree-form', breadCrumbs: false });
+ var scope = generator.inject(form, { mode: 'edit', modal: true, related: false });
generator.reset();
var master = {};
@@ -722,7 +720,9 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
GetSourceTypeOptions({ scope: scope, variable: 'source_type_options' });
- scope.update_interval_options = GetUpdateIntervalOptions();
+ //scope.update_interval_options = GetUpdateIntervalOptions();
+ scope.formModalActionLabel = 'Save';
+ scope.formModalCancelShow = true;
scope.source = form.fields.source['default'];
scope.parseType = 'yaml';
scope[form.fields['source_vars'].parseTypeName] = 'yaml';
@@ -945,8 +945,11 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}
scope.removeSaveComplete = scope.$on('SaveComplete', function(e, error) {
if (!error) {
- scope['flashMessage'] = 'Your changes to ' + scope['name'] + ' were saved.';
- ClickNode({ selector: '#inventory-root-node' });
+ //scope['flashMessage'] = 'Your changes to ' + scope['name'] + ' were saved.';
+ //ClickNode({ selector: '#inventory-root-node' });
+ scope.formModalActionDisabled = false;
+ scope.showGroupHelp = false; //get rid of the Hint
+ $('#form-modal').modal('hide');
}
});
@@ -955,15 +958,18 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}
scope.removeFormSaveSuccess = scope.$on('formSaveSuccess', function(e, group_id) {
+ // Source data gets stored separately from the group. Validate and store Source
+ // related fields, then call SaveComplete to wrap things up.
+
var parseError = false;
var saveError = false;
// Update the selector tree with new group name, descr
- SetNodeName({ scope: scope['selectedNode'], group_id: group_id,
- name: scope.name, description: scope.description });
+ //SetNodeName({ scope: scope['selectedNode'], group_id: group_id,
+ // name: scope.name, description: scope.description });
if (scope.source.value !== null && scope.source.value !== '') {
- var data = { group: group_id,
+ var data = { group: group_id,
source: scope['source'].value,
source_path: scope['source_path'],
credential: scope['credential'],
@@ -972,46 +978,42 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
update_on_launch: scope['update_on_launch']
//update_interval: scope['update_interval'].value
};
-
- // Get the select list of regions
- var regions = $('#s2id_group_source_regions').select2("data");
- data['source_regions'] = '';
- for (var i=0; i < regions.length; i++) {
- data['source_regions'] += regions[i].id + ',';
- }
- data['source_regions'] = data['source_regions'].replace(/\,$/,'');
- if (scope['source'].value == 'ec2') {
- try {
- // Make sure we have valid variable data
- if (scope.envParseType == 'json') {
- var json_data = JSON.parse(scope.source_vars); //make sure JSON parses
- }
- else {
- var json_data = jsyaml.load(scope.source_vars); //parse yaml
- }
-
- // Make sure our JSON is actually an object
- if (typeof json_data !== 'object') {
- throw "failed to return an object!";
- }
-
- // Send JSON as a string
- if ($.isEmptyObject(json_data)) {
- data.source_vars = "";
- }
- else {
- data.source_vars = JSON.stringify(json_data, undefined, '\t');
- }
- }
- catch(err) {
- parseError = true;
- scope.$emit('SaveComplete', true);
- Alert("Error", "Error parsing extra variables. Parser returned: " + err);
- }
- }
+ // Create a string out of selected list of regions
+ var regions = $('#s2id_group_source_regions').select2("data");
+ data['source_regions'] = regions.join();
+
+ if (scope['source'].value == 'ec2') {
+ // for ec2, validate variable data
+ try {
+ if (scope.envParseType == 'json') {
+ var json_data = JSON.parse(scope.source_vars); //make sure JSON parses
+ }
+ else {
+ var json_data = jsyaml.load(scope.source_vars); //parse yaml
+ }
+
+ // Make sure our JSON is actually an object
+ if (typeof json_data !== 'object') {
+ throw "failed to return an object!";
+ }
+
+ // Send JSON as a string
+ if ($.isEmptyObject(json_data)) {
+ data.source_vars = "";
+ }
+ else {
+ data.source_vars = JSON.stringify(json_data, undefined, '\t');
+ }
+ }
+ catch(err) {
+ parseError = true;
+ scope.$emit('SaveComplete', true);
+ Alert("Error", "Error parsing extra variables. Parser returned: " + err);
+ }
+ }
- if (!parseError) {
+ if (!parseError) {
Rest.setUrl(scope.source_url)
Rest.put(data)
.success( function(data, status, headers, config) {
@@ -1022,7 +1024,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update group inventory source. PUT status: ' + status });
});
- }
+ }
}
else {
// No source value
@@ -1030,8 +1032,8 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}
});
- // Save changes to the parent
- scope.formSave = function() {
+ // Save
+ scope.formModalAction = function() {
Wait('start');
try {
var refreshHosts = false;
diff --git a/awx/ui/static/js/helpers/search.js b/awx/ui/static/js/helpers/search.js
index 721955fbf5..237897796b 100644
--- a/awx/ui/static/js/helpers/search.js
+++ b/awx/ui/static/js/helpers/search.js
@@ -459,7 +459,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
$('.list-header').each(function(index) {
if ($(this).attr('id') != fld + '-header') {
var icon = $(this).find('i');
- icon.attr('class','fa-sort');
+ icon.attr('class','fa fa-sort');
}
});
diff --git a/awx/ui/static/js/lists/Inventories.js b/awx/ui/static/js/lists/Inventories.js
index b77a38010f..015e8ae3d5 100644
--- a/awx/ui/static/js/lists/Inventories.js
+++ b/awx/ui/static/js/lists/Inventories.js
@@ -34,7 +34,7 @@ angular.module('InventoriesListDefinition', [])
failed_hosts: {
label: 'Failed Hosts',
ngHref: "\{\{ inventory.failed_hosts_link \}\}",
- badgeIcon: "\{\{ 'icon-failures-' + inventory.failed_hosts_class \}\}",
+ badgeIcon: "\{\{ 'fa icon-failures-' + inventory.failed_hosts_class \}\}",
badgeNgHref: "\{\{ inventory.failed_hosts_link \}\}",
badgePlacement: 'left',
badgeToolTip: "\{\{ inventory.failed_hosts_tip \}\}",
@@ -48,7 +48,7 @@ angular.module('InventoriesListDefinition', [])
status: {
label: 'Status',
ngHref: "\{\{ inventory.status_link \}\}",
- badgeIcon: "\{\{ 'icon-cloud-' + inventory.status_class \}\}",
+ badgeIcon: "\{\{ 'fa icon-cloud-' + inventory.status_class \}\}",
badgeNgHref: "\{\{ inventory.status_link \}\}",
badgePlacement: 'left',
badgeTipPlacement: 'top',
diff --git a/awx/ui/static/js/lists/InventoryGroups.js b/awx/ui/static/js/lists/InventoryGroups.js
index 39622af9c1..f0e6fca589 100644
--- a/awx/ui/static/js/lists/InventoryGroups.js
+++ b/awx/ui/static/js/lists/InventoryGroups.js
@@ -32,7 +32,7 @@ angular.module('InventoryGroupsDefinition', [])
label: 'Sync Status',
ngClick: "viewUpdateStatus(\{\{ group.id \}\})",
searchType: 'select',
- badgeIcon: "\{\{ 'icon-cloud-' + group.status_badge_class \}\}",
+ badgeIcon: "\{\{ 'fa icon-cloud-' + group.status_badge_class \}\}",
badgeToolTip: "\{\{ group.status_badge_tooltip \}\}",
awToolTip: "\{\{ group.status_badge_tooltip \}\}",
dataPlacement: 'top',
@@ -50,7 +50,7 @@ angular.module('InventoryGroupsDefinition', [])
failed_hosts: {
label: 'Failed Hosts',
ngHref: "\{\{ group.failed_hosts_link \}\}",
- badgeIcon: "\{\{ 'icon-failures-' + group.failed_hosts_class \}\}",
+ badgeIcon: "\{\{ 'fa icon-failures-' + group.failed_hosts_class \}\}",
badgeNgHref: "\{\{ group.failed_hosts_link \}\}",
badgePlacement: 'left',
badgeToolTip: "\{\{ group.failed_hosts_tip \}\}",
@@ -137,34 +137,26 @@ angular.module('InventoryGroupsDefinition', [])
fieldActions: {
group_update: {
label: 'Sync',
- icon: 'icon-cloud-download',
- "class": 'btn-xs btn-primary',
- ngClick: 'updateGroup(\{\{ group.id \}\})',
+ ngClick: 'updateGroup(\{\{ group.group_id \}\})',
awToolTip: "\{\{ group.update_tooltip \}\}",
ngClass: "group.update_class",
awToolTip: "Start inventory sync"
},
cancel: {
label: 'Cancel',
- icon: 'icon-minus-sign',
- ngClick: "cancelUpdate(\{\{ group.id \}\}, '\{\{ group.name \}\}')",
- "class": 'btn-xs btn-primary',
+ ngClick: "cancelUpdate(\{\{ group.group_id \}\}, '\{\{ group.name \}\}')",
awToolTip: "\{\{ group.cancel_tooltip \}\}",
ngClass: "group.cancel_class",
ngShow: "group.status == 'running' || group.status == 'pending'"
},
- edit: {
+ edit: {
label: 'Edit',
- ngClick: "editGroup(\{\{ group.id \}\})",
- icon: 'icon-edit',
- "class": 'btn-xs btn-primary',
+ ngClick: "editGroup(\{\{ group.group_id \}\})",
awToolTip: 'Edit group'
},
"delete": {
label: 'Delete',
- ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')",
- icon: 'icon-trash',
- "class": 'btn-xs btn-primary',
+ ngClick: "deleteGroup(\{\{ group.group_id \}\},'\{\{ group.name \}\}')",
awToolTip: 'Delete group'
}
}
diff --git a/awx/ui/static/js/lists/InventoryHosts.js b/awx/ui/static/js/lists/InventoryHosts.js
index 9517dab8eb..5d7ec94d2b 100644
--- a/awx/ui/static/js/lists/InventoryHosts.js
+++ b/awx/ui/static/js/lists/InventoryHosts.js
@@ -32,7 +32,7 @@ angular.module('InventoryHostsDefinition', [])
awToolTip: "\{\{ host.badgeToolTip \}\}",
dataPlacement: 'top',
badgeNgHref: '\{\{ host.activeFailuresLink \}\}',
- badgeIcon: "\{\{ 'icon-failures-' + host.has_active_failures \}\}",
+ badgeIcon: "\{\{ 'fa icon-failures-' + host.has_active_failures \}\}",
badgePlacement: 'left',
badgeToolTip: "\{\{ host.badgeToolTip \}\}",
badgeTipPlacement: 'top',
@@ -41,7 +41,7 @@ angular.module('InventoryHostsDefinition', [])
},
enabled_flag: {
label: 'Enabled',
- badgeIcon: "\{\{ 'icon-enabled-' + host.enabled \}\}",
+ badgeIcon: "\{\{ 'fa icon-enabled-' + host.enabled \}\}",
badgePlacement: 'left',
badgeToolTip: "\{\{ host.enabledToolTip \}\}",
badgeTipPlacement: "top",
diff --git a/awx/ui/static/js/lists/JobEvents.js b/awx/ui/static/js/lists/JobEvents.js
index 608c4edd17..ffebd798b2 100644
--- a/awx/ui/static/js/lists/JobEvents.js
+++ b/awx/ui/static/js/lists/JobEvents.js
@@ -57,7 +57,7 @@ angular.module('JobEventsListDefinition', [])
ngClick: "viewJobEvent(\{\{ jobevent.id \}\})",
awToolTip: "\{\{ jobevent.statusBadgeToolTip \}\}",
dataPlacement: 'top',
- badgeIcon: 'icon-job-\{\{ jobevent.status \}\}',
+ badgeIcon: 'fa icon-job-\{\{ jobevent.status \}\}',
badgePlacement: 'left',
badgeToolTip: "\{\{ jobevent.statusBadgeToolTip \}\}",
badgeTipPlacement: 'top',
diff --git a/awx/ui/static/js/lists/JobHosts.js b/awx/ui/static/js/lists/JobHosts.js
index efe529a3ff..bf884e61e3 100644
--- a/awx/ui/static/js/lists/JobHosts.js
+++ b/awx/ui/static/js/lists/JobHosts.js
@@ -56,7 +56,7 @@ angular.module('JobHostDefinition', [])
status: {
label: 'Status',
badgeNgHref: "\{\{ jobhost.statusLinkTo \}\}",
- badgeIcon: 'icon-job-\{\{ jobhost.status \}\}',
+ badgeIcon: 'fa icon-job-\{\{ jobhost.status \}\}',
badgePlacement: 'left',
badgeToolTip: "\{\{ jobhost.statusBadgeToolTip \}\}",
badgeTipPlacement: 'top',
diff --git a/awx/ui/static/js/lists/Jobs.js b/awx/ui/static/js/lists/Jobs.js
index aba8dde7c9..b18a4905c1 100644
--- a/awx/ui/static/js/lists/Jobs.js
+++ b/awx/ui/static/js/lists/Jobs.js
@@ -30,7 +30,7 @@ angular.module('JobsListDefinition', [])
searchOnly: true
},
created: {
- label: 'Date',
+ label: 'Create On',
link: false,
searchable: false
},
@@ -64,7 +64,7 @@ angular.module('JobsListDefinition', [])
{ name: "error", value: "error" },
{ name: "failed", value: "failed" },
{ name: "canceled", value: "canceled" } ],
- badgeIcon: 'icon-job-\{\{ job.status \}\}',
+ badgeIcon: 'fa icon-job-\{\{ job.status \}\}',
badgePlacement: 'left',
badgeToolTip: "\{\{ job.statusBadgeToolTip \}\}",
badgeTipPlacement: 'top',
diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less
index f44e378b7b..7c62853fd8 100644
--- a/awx/ui/static/less/ansible-ui.less
+++ b/awx/ui/static/less/ansible-ui.less
@@ -393,19 +393,27 @@ a:hover {
margin-bottom: 10px;
}
+.form-group {
+ margin-bottom: 25px;
+}
+
.form-cancel {
- float: right;
- margin-right: 10px;
+ float: right;
+ margin-right: 10px;
}
.form-title-hr {
- margin-bottom: 20px;
+ margin-bottom: 20px;
}
.form-horizontal .buttons {
margin-top: 25px;
}
+.label-text {
+ padding-right: 10px;
+}
+
/* Outline required fields in Red when focused */
.form-control[required]:focus {
@@ -659,9 +667,6 @@ input[type="checkbox"].checkbox-no-label {
/* End Display list actions */
-.well {
- padding-bottom: 0;
-}
/* Enable table-hover to work when table is in a well */
@@ -695,8 +700,8 @@ input[type="checkbox"].checkbox-no-label {
.icon-failures-true,
.active-failures-true a,
.active-failures-true a:active,
- input[type="text"].job-failed,
- input[type="text"].job-error {
+ .job-failed,
+ .job-error {
color: #da4f49;
}
@@ -715,15 +720,15 @@ input[type="checkbox"].checkbox-no-label {
}
- input[type="text"].job-new,
- input[type="text"].job-canceled {
+ .job-new,
+ .job-canceled {
color: #778899;
}
.icon-failures-false,
.license-valid,
- input[type="text"].job-success,
- input[type="text"].job-successful {
+ .job-success,
+ .job-successful {
color: @green;
}
@@ -756,7 +761,8 @@ input[type="checkbox"].checkbox-no-label {
color: @grey;
}
- .icon-job-changed {
+ .icon-job-changed,
+ .job-changed {
color: @warning;
}
@@ -1227,7 +1233,7 @@ input[type="checkbox"].checkbox-no-label {
/* job_events syles */
-tr td i {
+#jobevents_table tr td i {
float: none;
padding-top: 3px;
padding-left: 0;
@@ -1235,6 +1241,11 @@ tr td i {
margin-left: 0;
}
+#jobevents_table .actions i {
+ padding-top: 0;
+ margin-right: 0;
+}
+
tr td button i {
padding-top: 0;
margin-right: 0;
diff --git a/awx/ui/static/lib/ansible/InventoryTree.js b/awx/ui/static/lib/ansible/InventoryTree.js
index c21b4eca30..44b4c2dea0 100644
--- a/awx/ui/static/lib/ansible/InventoryTree.js
+++ b/awx/ui/static/lib/ansible/InventoryTree.js
@@ -183,9 +183,9 @@ angular.module('InventoryTree', ['Utilities', 'RestServices'])
function buildGroups(tree_data, parent, level) {
var sorted = SortNodes(tree_data);
- for(var i=0; i < sorted.length; i++) {
- var currentId= id;
- var group = {
+ for (var i=0; i < sorted.length; i++) {
+ var currentId= id;
+ var group = {
name: sorted[i].name,
has_active_failures: sorted[i].has_active_failures,
total_hosts: sorted[i].total_hosts,
@@ -195,16 +195,17 @@ angular.module('InventoryTree', ['Utilities', 'RestServices'])
parent: parent,
has_children: (sorted[i].children.length > 0) ? true : false,
id: id,
+ group_id: sorted[i].id,
event_level: level,
ngicon: (sorted[i].children.length > 0) ? 'icon-collapse-alt' : null,
related: { children: (sorted[i].children.length > 0) ? sorted[i].related.children : '' },
status: sorted[i].summary_fields.inventory_source.status
}
- groups.push(group);
- id++;
- if (sorted[i].children.length > 0) {
- buildGroups(sorted[i].children, currentId, level + 1);
- }
+ groups.push(group);
+ id++;
+ if (sorted[i].children.length > 0) {
+ buildGroups(sorted[i].children, currentId, level + 1);
+ }
}
}
diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js
index 878118518f..7f6806ff20 100644
--- a/awx/ui/static/lib/ansible/form-generator.js
+++ b/awx/ui/static/lib/ansible/form-generator.js
@@ -33,7 +33,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
inject: function(form, options) {
//
- // Use to inject the form as html into the view. View MUST have an ng-bind for 'htmlTemplate'.
+ // Use to inject the form as html into the view. View MUST have an ng-bind for 'htmlTemplate'.t
// Returns scope of form.
//
@@ -311,7 +311,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
}
html += " \n";
return html;
},
@@ -412,7 +412,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
}
html += " ';
+ //html += (field.awPopOver && !field.awPopOverRight) ? Attr(field, 'awPopOver', fld) : "";
+ html += (field.icon) ? this.icon(field.icon) : "";
+ html += "" + field.label + " ";
+ html += (field.awPopOver && !field.awPopOverRight) ? Attr(field, 'awPopOver', fld) : "";
+ html += "\n";
+ }
+ return html;
+ }
var html = '';
-
+ var horizontal = (this.form.horizontal) ? true : false;
+
if (field.type == 'alertblock') {
html += "\n";
- html += (field.awPopOver && !field.awPopOverRight) ? this.attr(field, 'awPopOver', fld) : "";
- html += "';
- html += (field.icon) ? this.icon(field.icon) : "";
- html += "" + field.label + ' ' + "\n";
- html += (field.awPopOver && field.awPopOverRight) ? this.attr(field, 'awPopOver', fld) : "";
- html += "
\n";
+ //html += "\n";
+ //html += (field.awPopOver && !field.awPopOverRight) ? this.attr(field, 'awPopOver', fld) : "";
+ //html += "';
+ //html += (field.icon) ? this.icon(field.icon) : "";
+ //html += "" + field.label + ' ' + "\n";
+ //html += (field.awPopOver && field.awPopOverRight) ? this.attr(field, 'awPopOver', fld) : "";
+ //html += "
\n";
+
+ html += label();
+
html += "\n";
+ html += (horizontal) ? "class=\"" + getFieldWidth() + "\"" : "";
+ html += ">\n";
+
html += (field.clear || field.genMD5) ? "