diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index 32380a0bf9..500591135b 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -236,11 +236,12 @@ function InventoriesAdd($scope, $rootScope, $compile, $location, $log, $routePar generator.inject(form, { mode: 'add', related: false, scope: $scope }); - $scope.inventoryParseType = 'yaml'; - generator.reset(); LoadBreadCrumbs(); - ParseTypeChange( $scope, 'inventory_variables', 'inventoryParseType'); + + $scope.inventoryParseType = 'yaml'; + ParseTypeChange({ scope: $scope, variable: 'inventory_variables', parse_variable: 'inventoryParseType', + field_id: 'inventory_inventory_variables' }); LookUpInit({ scope: $scope, diff --git a/awx/ui/static/js/controllers/JobTemplates.js b/awx/ui/static/js/controllers/JobTemplates.js index c2b807e8a5..5d1d417dec 100644 --- a/awx/ui/static/js/controllers/JobTemplates.js +++ b/awx/ui/static/js/controllers/JobTemplates.js @@ -118,12 +118,18 @@ function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routePa generator = GenerateForm, master = {}, CloudCredentialList = {}, - selectPlaybook, checkSCMStatus; + selectPlaybook, checkSCMStatus, + callback; generator.inject(form, { mode: 'add', related: false, scope: $scope }); + callback = function() { + // Make sure the form controller knows there was a change + $scope[form.name + '_form'].setDirty(); + }; + $scope.parseType = 'yaml'; - ParseTypeChange($scope); + ParseTypeChange({ scope: $scope, field_id: 'job_templates_variables', onChange: callback }); $scope.job_type_options = [ { value: 'run', label: 'Run' }, @@ -131,9 +137,9 @@ function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routePa ]; $scope.verbosity_options = [ - { value: '0', label: 'Default' }, - { value: '1', label: 'Verbose' }, - { value: '3', label: 'Debug' } + { value: 0, label: 'Default' }, + { value: 1, label: 'Verbose' }, + { value: 3, label: 'Debug' } ]; $scope.playbook_options = []; @@ -258,6 +264,24 @@ function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routePa field: 'project' }); + function saveCompleted() { + setTimeout(function() { $scope.$apply(function() { $location.path('/job_templates'); }); }, 500); + } + + if ($scope.removeTemplateSaveSuccess) { + $scope.removeTemplateSaveSuccess(); + } + $scope.removeTemplateSaveSuccess = $scope.$on('templateSaveSuccess', function(e, data) { + Wait('stop'); + if (data.related && data.related.callback) { + Alert('Callback URL', '

Host callbacks are enabled for this template. The callback URL is: ' + data.related.callback + + '

The host configuration key is: ' + data.host_config_key + '

', 'alert-info', saveCompleted); + } + else { + saveCompleted(); + } + }); + // Save $scope.formSave = function () { generator.clearApiErrors(); @@ -293,16 +317,10 @@ function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routePa Rest.setUrl(defaultUrl); Rest.post(data) - .success(function () { - Wait('stop'); - var base = $location.path().replace(/^\//, '').split('/')[0]; - if (base === 'job_templates') { - ReturnToCaller(); - } - ReturnToCaller(1); + .success(function(data) { + $scope.$emit('templateSaveSuccess', data); }) .error(function (data, status) { - Wait('stop'); ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to add new job template. POST returned status: ' + status }); @@ -347,13 +365,12 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP master = {}, id = $routeParams.id, relatedSets = {}, - checkSCMStatus, getPlaybooks; + checkSCMStatus, getPlaybooks, callback; generator.inject(form, { mode: 'edit', related: true, scope: $scope }); $scope.parseType = 'yaml'; - ParseTypeChange($scope); - + // Our job type options $scope.job_type_options = [ { value: 'run', label: 'Run' }, @@ -361,10 +378,15 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP ]; $scope.verbosity_options = [ - { value: '0', label: 'Default' }, - { value: '1', label: 'Verbose' }, - { value: '3', label: 'Debug' } + { value: 0, label: 'Default' }, + { value: 1, label: 'Verbose' }, + { value: 3, label: 'Debug' } ]; + + callback = function() { + // Make sure the form controller knows there was a change + $scope[form.name + '_form'].$setDirty(); + }; $scope.playbook_options = null; $scope.playbook = null; @@ -524,6 +546,8 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP default_val: dft }); + ParseTypeChange({ scope: $scope, field_id: 'job_templates_variables', onChange: callback }); + if (related_cloud_credential) { Rest.setUrl(related_cloud_credential); Rest.get() @@ -642,6 +666,24 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP }); }); + function saveCompleted() { + setTimeout(function() { $scope.$apply(function() { $location.path('/job_templates'); }); }, 500); + } + + if ($scope.removeTemplateSaveSuccess) { + $scope.removeTemplateSaveSuccess(); + } + $scope.removeTemplateSaveSuccess = $scope.$on('templateSaveSuccess', function(e, data) { + Wait('stop'); + if (Empty(master.callback_url) && data.related && data.related.callback) { + Alert('Callback URL', '

Host callbacks are enabled for this template. The callback URL is: ' + data.related.callback + + '

The host configuration key is: ' + data.host_config_key + '

', 'alert-info', saveCompleted); + } + else { + saveCompleted(); + } + }); + // Save changes to the parent $scope.formSave = function () { generator.clearApiErrors(); @@ -677,19 +719,12 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP Rest.setUrl(defaultUrl + id + '/'); Rest.put(data) - .success(function () { - Wait('stop'); - var base = $location.path().replace(/^\//, '').split('/')[0]; - if (base === 'job_templates') { - ReturnToCaller(); - } - ReturnToCaller(1); + .success(function (data) { + $scope.$emit('templateSaveSuccess', data); }) .error(function (data, status) { - ProcessErrors($scope, data, status, form, { - hdr: 'Error!', - msg: 'Failed to update job template. PUT returned status: ' + status - }); + ProcessErrors($scope, data, status, form, { hdr: 'Error!', + msg: 'Failed to update job template. PUT returned status: ' + status }); }); } catch (err) { @@ -711,6 +746,7 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP $scope[fld] = master[fld]; } $scope.parseType = 'yaml'; + ParseTypeChange({ scope: $scope, field_id: 'job_templates_variables', onChange: callback }); $('#forks-slider').slider("option", "value", $scope.forks); }; diff --git a/awx/ui/static/js/controllers/Projects.js b/awx/ui/static/js/controllers/Projects.js index 31509867c1..c474bf70fb 100644 --- a/awx/ui/static/js/controllers/Projects.js +++ b/awx/ui/static/js/controllers/Projects.js @@ -444,10 +444,11 @@ function ProjectsAdd($scope, $rootScope, $compile, $location, $log, $routeParams if (base === 'projects') { ReturnToCaller(); } - ReturnToCaller(1); + else { + ReturnToCaller(1); + } }) .error(function (data, status) { - Wait('stop'); ProcessErrors($scope, data, status, ProjectsForm, { hdr: 'Error!', msg: 'Failed to add organization to project. POST returned status: ' + status }); }); diff --git a/awx/ui/static/js/controllers/Teams.js b/awx/ui/static/js/controllers/Teams.js index fe897dd8ef..01353d9a8c 100644 --- a/awx/ui/static/js/controllers/Teams.js +++ b/awx/ui/static/js/controllers/Teams.js @@ -285,7 +285,9 @@ function TeamsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, if (base === 'teams') { ReturnToCaller(); } - ReturnToCaller(1); + else { + ReturnToCaller(1); + } }) .error(function (data, status) { Wait('stop'); diff --git a/awx/ui/static/js/controllers/Users.js b/awx/ui/static/js/controllers/Users.js index 0680fae82e..33326753a6 100644 --- a/awx/ui/static/js/controllers/Users.js +++ b/awx/ui/static/js/controllers/Users.js @@ -166,7 +166,9 @@ function UsersAdd($scope, $rootScope, $compile, $location, $log, $routeParams, U $rootScope.flashMessage = 'New user successfully created!'; $location.path('/users/' + data.id); } - ReturnToCaller(1); + else { + ReturnToCaller(1); + } }) .error(function (data, status) { ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to add new user. POST returned status: ' + status }); @@ -307,7 +309,9 @@ function UsersEdit($scope, $rootScope, $compile, $location, $log, $routeParams, if (base === 'users') { ReturnToCaller(); } - ReturnToCaller(1); + else { + ReturnToCaller(1); + } }) .error(function (data, status) { ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to update users: ' + $routeParams.id + diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index b0cf82a2c3..1c358ac180 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -178,13 +178,13 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G } ]) -.factory('SourceChange', ['GetBasePath', 'CredentialList', 'LookUpInit', 'Empty', - function (GetBasePath, CredentialList, LookUpInit, Empty) { +.factory('SourceChange', ['GetBasePath', 'CredentialList', 'LookUpInit', 'Empty', 'Wait', 'ParseTypeChange', + function (GetBasePath, CredentialList, LookUpInit, Empty, Wait, ParseTypeChange) { return function (params) { var scope = params.scope, form = params.form, - kind, url; + kind, url, callback; if (!Empty(scope.source)) { if (scope.source.value === 'file') { @@ -220,6 +220,13 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G list: CredentialList, field: 'credential' }); + + if ($('#group_tabs .active a').text() === 'Source' && scope.source.value === 'ec2') { + callback = function(){ Wait('stop'); }; + Wait('start'); + ParseTypeChange({ scope: scope, variable: 'source_vars', parse_variable: form.fields.source_vars.parseTypeName, + field_id: 'group_source_vars', onReady: callback }); + } } } }; @@ -314,10 +321,10 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G ]) .factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', - 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'Wait', 'GetChoices', + 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'Wait', 'GetChoices', 'GetSourceTypeOptions', 'LookUpInit', 'BuildTree', 'SourceChange', 'WatchInventoryWindowResize', function ($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, - GetBasePath, ParseTypeChange, GroupsEdit, Wait, GetChoices, GetSourceTypeOptions, LookUpInit, BuildTree, + GetBasePath, ParseTypeChange, Wait, GetChoices, GetSourceTypeOptions, LookUpInit, BuildTree, SourceChange, WatchInventoryWindowResize) { return function (params) { @@ -333,12 +340,28 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G scope.formModalActionLabel = 'Save'; scope.formModalCancelShow = true; - scope.parseType = 'yaml'; scope.source = null; - ParseTypeChange(scope); - generator.reset(); + scope[form.fields.source_vars.parseTypeName] = 'yaml'; + scope.parseType = 'yaml'; + ParseTypeChange({ scope: scope, field_id: 'group_variables' }); + + $('#group_tabs a[data-toggle="tab"]').on('show.bs.tab', function (e) { + var callback = function(){ Wait('stop'); }; + if ($(e.target).text() === 'Properties') { + Wait('start'); + ParseTypeChange({ scope: scope, field_id: 'group_variables', onReady: callback }); + } + else { + if (scope.source && scope.source.value === 'ec2') { + Wait('start'); + ParseTypeChange({ scope: scope, variable: 'source_vars', parse_variable: form.fields.source_vars.parseTypeName, + field_id: 'group_source_vars', onReady: callback }); + } + } + }); + if (scope.removeAddTreeRefreshed) { scope.removeAddTreeRefreshed(); } @@ -586,12 +609,33 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G scope.formModalHeader = 'Group'; scope.formModalCancelShow = true; scope.source = form.fields.source['default']; - scope.parseType = 'yaml'; - scope[form.fields.source_vars.parseTypeName] = 'yaml'; scope.sourcePathRequired = false; - ParseTypeChange(scope); - ParseTypeChange(scope, 'source_vars', form.fields.source_vars.parseTypeName); + $('#group_tabs a[data-toggle="tab"]').on('show.bs.tab', function (e) { + var callback = function(){ Wait('stop'); }; + if ($(e.target).text() === 'Properties') { + Wait('start'); + ParseTypeChange({ scope: scope, field_id: 'group_variables', onReady: callback }); + } + else { + if (scope.source && scope.source.value === 'ec2') { + Wait('start'); + ParseTypeChange({ scope: scope, variable: 'source_vars', parse_variable: form.fields.source_vars.parseTypeName, + field_id: 'group_source_vars', onReady: callback }); + } + } + }); + + scope[form.fields.source_vars.parseTypeName] = 'yaml'; + scope.parseType = 'yaml'; + + if (scope.groupVariablesLoadedRemove) { + scope.groupVariablesLoadedRemove(); + } + scope.groupVariablesLoadedRemove = scope.$on('groupVariablesLoaded', function () { + var callback = function() { Wait('stop'); }; + ParseTypeChange({ scope: scope, field_id: 'group_variables', onReady: callback }); + }); // After the group record is loaded, retrieve related data if (scope.groupLoadedRemove) { @@ -608,18 +652,16 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G } else { scope.variables = jsyaml.safeDump(data); } - Wait('stop'); + scope.$emit('groupVariablesLoaded'); }) .error(function (data, status) { scope.variables = null; - Wait('stop'); - ProcessErrors(scope, data, status, form, { - hdr: 'Error!', - msg: 'Failed to retrieve group variables. GET returned status: ' + status - }); + ProcessErrors(scope, data, status, form, { hdr: 'Error!', + msg: 'Failed to retrieve group variables. GET returned status: ' + status }); }); } else { scope.variables = "---"; + scope.$emit('groupVariablesLoaded'); } master.variables = scope.variables; @@ -714,11 +756,10 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G }]; } scope.group_update_url = data.related.update; - Wait('stop'); + //Wait('stop'); }) .error(function (data, status) { scope.source = ""; - Wait('stop'); ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to retrieve inventory source. GET status: ' + status }); }); diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js index 104bd7e0ec..eb0c5587bc 100644 --- a/awx/ui/static/js/helpers/Hosts.js +++ b/awx/ui/static/js/helpers/Hosts.js @@ -336,8 +336,9 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener scope.formModalActionLabel = 'Save'; scope.formModalHeader = 'Create New Host'; scope.formModalCancelShow = true; + scope.parseType = 'yaml'; - ParseTypeChange(scope); + ParseTypeChange({ scope: scope, field_id: 'host_variables' }); if (scope.removeHostsReload) { scope.removeHostsReload(); @@ -466,7 +467,15 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener scope.formModalHeader = 'Host Properties'; scope.formModalCancelShow = true; scope.parseType = 'yaml'; - ParseTypeChange(scope); + + if (scope.hostVariablesLoadedRemove) { + scope.hostVariablesLoadedRemove(); + } + scope.hostVariablesLoadedRemove = scope.$on('hostVariablesLoaded', function() { + var callback = function() { Wait('stop'); }; + $('#form-modal').modal('show'); + ParseTypeChange({ scope: scope, field_id: 'host_variables', onReady: callback }); + }); if (scope.hostLoadedRemove) { scope.hostLoadedRemove(); @@ -483,8 +492,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener else { scope.variables = jsyaml.safeDump(data); } - Wait('stop'); - $('#form-modal').modal('show'); + scope.$emit('hostVariablesLoaded'); }) .error( function(data, status) { scope.variables = null; @@ -494,8 +502,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener } else { scope.variables = "---"; - Wait('stop'); - $('#form-modal').modal('show'); + scope.$emit('hostVariablesLoaded'); } master.variables = scope.variables; }); diff --git a/awx/ui/static/js/helpers/Parse.js b/awx/ui/static/js/helpers/Parse.js index a5cd1ecb39..432de6d8b0 100644 --- a/awx/ui/static/js/helpers/Parse.js +++ b/awx/ui/static/js/helpers/Parse.js @@ -3,8 +3,8 @@ * * ParseHelper * - * Routines for parsing variable data and toggling - * between JSON and YAML. + * Show the CodeMirror variable editor and allow + * toggle between JSON and YAML * */ @@ -12,32 +12,41 @@ angular.module('ParseHelper', ['Utilities', 'AngularCodeMirrorModule']) .factory('ParseTypeChange', ['Alert', 'AngularCodeMirror', function (Alert, AngularCodeMirror) { - return function (scope, varName, parseTypeName) { + return function (params) { + + var scope = params.scope, + field_id = params.field_id, + fld = (params.variable) ? params.variable : 'variables', + pfld = (params.parse_variable) ? params.parse_variable : 'parseType', + onReady = params.onReady, + onChange = params.onChange, + codeMirror; + + function removeField() { + //set our model to the last change in CodeMirror and then destroy CodeMirror + scope[fld] = codeMirror.getValue(); + codeMirror.destroy(); + } + + function createField(onChange, onReady) { + //hide the textarea and show a fresh CodeMirror with the current mode (json or yaml) + codeMirror = AngularCodeMirror(); + codeMirror.addModes($AnsibleConfig.variable_edit_modes); + codeMirror.showTextArea({ scope: scope, model: fld, element: field_id, mode: scope[pfld], onReady: onReady, onChange: onChange }); + } + + + // Hide the textarea and show a CodeMirror editor + createField(onChange, onReady); + // Toggle displayed variable string between JSON and YAML - - var fld = (varName) ? varName : 'variables', - pfld = (parseTypeName) ? parseTypeName : 'parseType', - codeMirror = AngularCodeMirror(); - codeMirror.addModes($AnsibleConfig.variable_edit_modes); - - scope.showCodeEditor = function() { - var title = 'Edit ' + scope[pfld].toUpperCase(), - container = document.getElementById('main-view'); - codeMirror.show({ - scope: scope, - container: container, - mode: scope[pfld], - model: fld, - title: title - }); - }; - scope.parseTypeChange = function() { var json_obj; if (scope[pfld] === 'json') { // converting yaml to json try { + removeField(); json_obj = jsyaml.load(scope[fld]); if ($.isEmptyObject(json_obj)) { scope[fld] = "{}"; @@ -45,15 +54,17 @@ angular.module('ParseHelper', ['Utilities', 'AngularCodeMirrorModule']) else { scope[fld] = JSON.stringify(json_obj, null, " "); } + createField(); } catch (e) { Alert('Parse Error', 'Failed to parse valid YAML. ' + e.message); - setTimeout( function() { scope.$apply( function() { scope[pfld] = 'yaml'; }); }, 500); + setTimeout( function() { scope.$apply( function() { scope[pfld] = 'yaml'; createField(); }); }, 500); } } else { // convert json to yaml try { + removeField(); json_obj = JSON.parse(scope[fld]); if ($.isEmptyObject(json_obj)) { scope[fld] = '---'; @@ -61,10 +72,11 @@ angular.module('ParseHelper', ['Utilities', 'AngularCodeMirrorModule']) else { scope[fld] = jsyaml.safeDump(json_obj); } + createField(); } catch (e) { Alert('Parse Error', 'Failed to parse valid JSON. ' + e.message); - setTimeout( function() { scope.$apply( function() { scope[pfld] = 'json'; }); }, 500 ); + setTimeout( function() { scope.$apply( function() { scope[pfld] = 'json'; createField(); }); }, 500 ); } } }; diff --git a/awx/ui/static/js/helpers/inventory.js b/awx/ui/static/js/helpers/inventory.js index 7ec7ef82d7..0a9f618a55 100644 --- a/awx/ui/static/js/helpers/inventory.js +++ b/awx/ui/static/js/helpers/inventory.js @@ -8,8 +8,6 @@ * */ - /* globals console:false */ - 'use strict'; angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService', @@ -131,8 +129,14 @@ angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationLis /* Reset form properties. Otherwise it screws up future requests of the Inventories detail page */ form.well = true; - ParseTypeChange(scope, 'inventory_variables', 'inventoryParseType'); - scope.inventoryParseType = 'yaml'; + scope.$on('inventoryPropertiesLoaded', function() { + var callback = function() { Wait('stop'); }; + $('#form-modal').modal('show'); + scope.inventoryParseType = 'yaml'; + ParseTypeChange({ scope: scope, variable: 'inventory_variables', parse_variable: 'inventoryParseType', + field_id: 'inventory_inventory_variables', onReady: callback }); + }); + scope.formModalActionLabel = 'Save'; scope.formModalCancelShow = true; scope.formModalInfo = false; @@ -156,11 +160,6 @@ angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationLis } catch (err) { Alert('Variable Parse Error', 'Attempted to parse variables for inventory: ' + inventory_id + '. Parse returned: ' + err); - if (console) { - console.log(err); - console.log('data:'); - console.log(data.variables); - } scope.inventory_variables = '---'; } } @@ -193,15 +192,12 @@ angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationLis field: 'organization' }); - Wait('stop'); - $('#form-modal').modal('show'); + scope.$emit('inventoryPropertiesLoaded'); }) .error(function (data, status) { - ProcessErrors(scope, data, status, null, { - hdr: 'Error!', - msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status - }); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', + msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status }); }); if (scope.removeInventorySaved) { @@ -242,11 +238,9 @@ angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationLis }; scope.formModalAction = function () { - parent_scope.inventory_id = inventory_id; + scope.inventory_id = inventory_id; parent_scope.inventory_name = scope.inventory_name; - SaveInventory({ - scope: scope - }); + SaveInventory({ scope: scope }); }; }; diff --git a/awx/ui/static/js/helpers/md5.js b/awx/ui/static/js/helpers/md5.js index 8939039ace..b200449f32 100644 --- a/awx/ui/static/js/helpers/md5.js +++ b/awx/ui/static/js/helpers/md5.js @@ -10,8 +10,8 @@ 'use strict'; -angular.module('md5Helper', ['RestServices', 'Utilities']) - .factory('md5Setup', [ function () { +angular.module('md5Helper', ['RestServices', 'Utilities', 'angular-md5']) + .factory('md5Setup', ['md5', function (md5) { return function (params) { var scope = params.scope, @@ -24,7 +24,7 @@ angular.module('md5Helper', ['RestServices', 'Utilities']) scope.genMD5 = function (fld) { var now = new Date(); - scope[fld] = $.md5('AnsibleWorks' + now.getTime()); + scope[fld] = md5.createHash('AnsibleWorks' + now.getTime()); }; scope.toggleCallback = function (fld) { diff --git a/awx/ui/static/less/codemirror.less b/awx/ui/static/less/codemirror.less index 9c01f50542..785d50d4a9 100644 --- a/awx/ui/static/less/codemirror.less +++ b/awx/ui/static/less/codemirror.less @@ -8,6 +8,9 @@ .CodeMirror { height: auto; + overflow-x: scroll; + overflow-y: hidden; + border: 1px solid #ccc; } .CodeMirror-activeline-background { diff --git a/awx/ui/static/lib/angular-codemirror/.bower.json b/awx/ui/static/lib/angular-codemirror/.bower.json index f00a892537..194a61b513 100644 --- a/awx/ui/static/lib/angular-codemirror/.bower.json +++ b/awx/ui/static/lib/angular-codemirror/.bower.json @@ -20,6 +20,7 @@ "commit": "94b7aac548b036f4fbd94e56129ed9574e472616" }, "_source": "git://github.com/chouseknecht/angular-codemirror.git", - "_target": "~1.0.0", - "_originalSource": "angular-codemirror" + "_target": "~1.0.2", + "_originalSource": "angular-codemirror", + "_direct": true } \ No newline at end of file diff --git a/awx/ui/static/lib/angular-codemirror/lib/AngularCodeMirror.js b/awx/ui/static/lib/angular-codemirror/lib/AngularCodeMirror.js index 557eca31ee..e4b9e5e02e 100644 --- a/awx/ui/static/lib/angular-codemirror/lib/AngularCodeMirror.js +++ b/awx/ui/static/lib/angular-codemirror/lib/AngularCodeMirror.js @@ -32,16 +32,94 @@ angular.module('AngularCodeMirrorModule', []) .factory('AngularCodeMirror', [ function() { return function() { var fn = function() { - - this.show = function(params) { + + this.myCodeMirror = null; + this.element = null; + + this.showTextArea = function(params) { + var self = this, + element = (typeof params.element === "object") ? params.element : document.getElementById(params.element), + scope = params.scope, + model = params.model, + mode = params.mode, + onReady = params.onReady, + onChange = params.onChange, + height = 0; + + self.element = $(element); - var scope = params.scope, + // We don't want to touch the original textarea. Angular likely has a model and other listeners + // attached to it. In prior iterations attaching CodeMirror to it seemed to go bad, so we'll insert a + //
under it, hide the textarea and let CodeMirror attach to the
. + if ($('#cm-' + model + '-container').length > 0) { + $('#cm-' + model + '-container').empty(); + } + else { + self.element.after("
"); + } + + // Calc the height of the text area- our CodeMirror should match. + height += self.element.attr('rows') * parseInt($(self.element).css('line-height').replace(/px/,''),10); + height += parseInt(self.element.css('padding-top').replace(/px|%/,''),10) + + parseInt(self.element.css('padding-bottom').replace(/px|%/,''),10); + height += 2; //for the border + + // hide + self.element.hide(); + + // Initialize CodeMirror + self.modes[mode].value = scope[model]; + self.myCodeMirror = CodeMirror(document.getElementById('cm-' + model + '-container'), self.modes[mode]); + + // Adjust the height + $('.CodeMirror').css({ 'min-height': height, 'max-height': height }); + self.myCodeMirror.setSize(null, height); + + // This doesn't work without a setTimeout + setTimeout(function() { + self.myCodeMirror.refresh(); + if (onReady) { + onReady(); + } + }, 500); + + // Update the model on change + self.myCodeMirror.on('change', function() { + setTimeout(function() { + scope.$apply(function(){ + scope[model] = self.myCodeMirror.getValue(); + if (onChange) { + onChange(); + } + }); + }, 500); + }); + }; + + this.getValue = function() { + var self = this; + return self.myCodeMirror.getValue(); + }; + + this.destroy = function() { + // Intended for use with showTextArea. This will get ride of CM and put the + // textarea back to normal + var self = this; + $('.CodeMirror').empty().remove(); + if (self.element) { + self.element.show(); + } + }; + + this.showModal = function(params) { + + var self = this, + scope = params.scope, target = (typeof params.container === "string") ? document.getElementById(params.container) : params.container, mode = params.mode, model = params.model, title = params.title || 'Code Editor', - modes = this.modes, - myCodeMirror; + modes = self.modes; this.html = "
\n
\n"; if ($('#af-code-editor-modal').length === 0) { @@ -66,7 +144,7 @@ angular.module('AngularCodeMirrorModule', []) { text: "Cancel", id: "af-code-edit-cancel", click: function() { $(this).dialog('close'); } }, { text: "OK", id: "af-code-edit-ok", click: function() { - scope.$apply(function() { scope[model] = myCodeMirror.getValue(); }); + scope.$apply(function() { scope[model] = self.myCodeMirror.getValue(); }); $(this).dialog('close'); } } @@ -87,7 +165,7 @@ angular.module('AngularCodeMirrorModule', []) // initialize CodeMirror options = modes[mode]; options.value = scope[model]; - myCodeMirror = CodeMirror(document.getElementById('af-code'), options); + self.myCodeMirror = CodeMirror(document.getElementById('af-code'), options); } }); }; diff --git a/awx/ui/static/lib/ansible/Utilities.js b/awx/ui/static/lib/ansible/Utilities.js index f805c17c7a..c05b81c5b9 100644 --- a/awx/ui/static/lib/ansible/Utilities.js +++ b/awx/ui/static/lib/ansible/Utilities.js @@ -85,7 +85,7 @@ angular.module('Utilities', ['RestServices', 'Utilities']) }); $rootScope.disableButtons2 = (disableButtons) ? true : false; if (action) { - $('#alert-modal2').on('hidden', function () { + $('#alert-modal2').on('hidden.bs.modal', function () { action(); }); } @@ -107,6 +107,14 @@ angular.module('Utilities', ['RestServices', 'Utilities']) backdrop: 'static' }); + $('#alert-modal').on('hidden.bs.modal', function () { + console.log('modal closed'); + if (action) { + console.log('attempting callback'); + action(); + } + }); + $(document).bind('keydown', function (e) { if (e.keyCode === 27) { $('#alert-modal').modal('hide'); @@ -117,11 +125,7 @@ angular.module('Utilities', ['RestServices', 'Utilities']) }); $rootScope.disableButtons = (disableButtons) ? true : false; - if (action) { - $('#alert-modal').on('hidden', function () { - action(); - }); - } + } }; } @@ -630,6 +634,7 @@ angular.module('Utilities', ['RestServices', 'Utilities']) var form = params.form, scope = params.scope, fld; + console.log('here'); for (fld in form.fields) { if (scope[form.name + '_form'][fld]) { console.log(fld + ' valid: ' + scope[form.name + '_form'][fld].$valid); diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index e901fa6c42..a17f941303 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -688,8 +688,6 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) html += " JSON\n"; - html += " Editor"; html += "
\n"; }