Fixes 2 instances of CodeMirror on one $scope & use CodeMirror for inventory source vars (#2410)

* fix azure regions multiselect, resolves #2289

* fix 2 simultaneous instances of CodeMirror inside one $scope, CodeMirror-ify inventory source vars, resolves #2333
This commit is contained in:
Leigh
2016-06-15 12:56:00 -04:00
committed by GitHub
parent 19c8fe915f
commit 2aa18e394b
5 changed files with 76 additions and 53 deletions

View File

@@ -45,6 +45,7 @@ export default
'default': '---',
dataTitle: 'Group Variables',
dataPlacement: 'right',
parseTypeName: 'parseType',
awPopOver: "<p>Variables defined here apply to all child groups and hosts.</p>" +
"<p>Enter variables using either JSON or YAML syntax. Use the " +
"radio button to toggle between the two.</p>" +
@@ -158,7 +159,7 @@ export default
addRequired: false,
editRequired: false,
rows: 6,
'default': null,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Environment Variables",
dataPlacement: 'right',
@@ -181,7 +182,7 @@ export default
addRequired: false,
editRequird: false,
rows: 6,
'default': null,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Source Variables",
dataPlacement: 'right',
@@ -207,7 +208,7 @@ export default
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
editRequird: false,
rows: 6,
'default': null,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Source Variables",
dataPlacement: 'right',
@@ -233,7 +234,7 @@ export default
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
editRequird: false,
rows: 6,
'default': null,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Source Variables",
dataPlacement: 'right',

View File

@@ -27,51 +27,39 @@ export default
onReady = params.onReady,
onChange = params.onChange;
function removeField() {
function removeField(fld) {
//set our model to the last change in CodeMirror and then destroy CodeMirror
scope[fld] = scope.codeMirror.getValue();
// codeMirror.destroy looks for anything with a CodeMirror class and destroys it, so if there are multiple codeMirror editor instances, it will delete them all,
// // which was the case if launching a job from the job template form. I had to add a check to see if there were multiple instances and only remove the second one found on the modal.
// if( $(".CodeMirror").length >1) {
// var self = scope.codeMirror;
// $('.CodeMirror:eq(1)').empty().remove();
// if (self.element) {
// self.element.show();
// }
// }
// else
scope.codeMirror.destroy();
scope[fld] = scope[fld + 'codeMirror'].getValue();
$('#cm-' + fld + '-container > .CodeMirror').empty().remove();
}
function createField(onChange, onReady) {
function createField(onChange, onReady, fld) {
//hide the textarea and show a fresh CodeMirror with the current mode (json or yaml)
$rootScope.loginConfig.promise.then(function () {
scope.codeMirror = AngularCodeMirror();
scope.codeMirror.addModes($AnsibleConfig.variable_edit_modes);
scope.codeMirror.showTextArea({
scope: scope,
model: fld,
element: field_id,
lineNumbers: true,
mode: scope[pfld],
onReady: onReady,
onChange: onChange
});
scope[fld + 'codeMirror'] = AngularCodeMirror();
scope[fld + 'codeMirror'].addModes($AnsibleConfig.variable_edit_modes);
scope[fld + 'codeMirror'].showTextArea({
scope: scope,
model: fld,
element: field_id,
lineNumbers: true,
mode: scope[pfld],
onReady: onReady,
onChange: onChange
});
}
// Hide the textarea and show a CodeMirror editor
createField(onChange, onReady);
createField(onChange, onReady, fld);
// Toggle displayed variable string between JSON and YAML
scope.parseTypeChange = function() {
scope.parseTypeChange = function(model, fld) {
var json_obj;
if (scope[pfld] === 'json') {
if (scope[model] === 'json') {
// converting yaml to json
try {
removeField();
removeField(fld);
json_obj = jsyaml.load(scope[fld]);
if ($.isEmptyObject(json_obj)) {
scope[fld] = "{}";
@@ -79,17 +67,17 @@ export default
else {
scope[fld] = JSON.stringify(json_obj, null, " ");
}
createField();
createField(onReady, onChange, fld);
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid YAML. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'yaml'; createField(); }); }, 500);
setTimeout( function() { scope.$apply( function() { scope[model] = 'yaml'; createField(); }); }, 500);
}
}
else {
// convert json to yaml
try {
removeField();
removeField(fld);
json_obj = JSON.parse(scope[fld]);
if ($.isEmptyObject(json_obj)) {
scope[fld] = '---';
@@ -97,11 +85,11 @@ export default
else {
scope[fld] = jsyaml.safeDump(json_obj);
}
createField();
createField(onReady, onChange, fld);
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid JSON. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'json'; createField(); }); }, 500 );
setTimeout( function() { scope.$apply( function() { scope[model] = 'json'; createField(); }); }, 500 );
}
}
};

View File

@@ -28,7 +28,7 @@
// inventory_source fields
params = {
instance_filters: $scope.instance_filters,
source_vars: $scope[$scope.source.value + '_variables'] === null ? null : $scope[$scope.source.value + '_variables'],
source_vars: $scope[$scope.source.value + '_variables'] === '---' || $scope[$scope.source.value + '_variables'] === '{}' ? null : $scope[$scope.source.value + '_variables'],
source_script: $scope.inventory_script,
source: $scope.source.value,
credential: $scope.credential,
@@ -114,6 +114,14 @@
input_type: "radio"
});
}
if (source === 'ec2' || source === 'custom' || source === 'vmware' || source === 'openstack'){
ParseTypeChange({
scope: $scope,
field_id: source + '_variables',
variable: source + '_variables',
parse_variable: 'envParseType'
});
}
// reset fields
$scope.group_by_choices = source === 'ec2' ? $scope.ec2_group_by : null;
// azure_rm regions choices are keyed as "azure" in an OPTIONS request to the inventory_sources endpoint
@@ -203,7 +211,7 @@
});
var init = function(){
$scope.parseType = 'yaml';
$scope.variables = '---';
$scope.envParseType = 'yaml';
generator.inject(form, {mode: 'add', related: false, id: 'Inventory-groupManage--panel', scope: $scope});
ParseTypeChange({
scope: $scope,

View File

@@ -5,10 +5,10 @@
*************************************************/
export default
['$state', '$stateParams', '$scope', 'GroupForm', 'CredentialList', 'inventoryScriptsListObject', 'ToggleNotification',
['$state', '$stateParams', '$scope', 'GroupForm', 'CredentialList', 'inventoryScriptsListObject', 'ToggleNotification', 'ParseVariableString',
'ParseTypeChange', 'GenerateForm', 'LookUpInit', 'RelatedSearchInit', 'RelatedPaginateInit', 'NotificationsListInit',
'GroupManageService','GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions', 'groupData', 'inventorySourceData',
function($state, $stateParams, $scope, GroupForm, CredentialList, InventoryScriptsList, ToggleNotification,
function($state, $stateParams, $scope, GroupForm, CredentialList, InventoryScriptsList, ToggleNotification, ParseVariableString,
ParseTypeChange, GenerateForm, LookUpInit, RelatedSearchInit, RelatedPaginateInit, NotificationsListInit,
GroupManageService, GetChoices, GetBasePath, CreateSelect2, GetSourceTypeOptions, groupData, inventorySourceData){
var generator = GenerateForm,
@@ -41,7 +41,7 @@
group_by: _.map($scope.group_by, 'value').join(','),
source_regions: _.map($scope.source_regions, 'value').join(','),
instance_filters: $scope.instance_filters,
source_vars: $scope[$scope.source.value + '_variables'] === '' ? null : $scope[$scope.source.value + '_variables']
source_vars: $scope[$scope.source.value + '_variables'] === '---' || $scope[$scope.source.value + '_variables'] === '{}' ? null : $scope[$scope.source.value + '_variables']
};
source = $scope.source.value;
}
@@ -112,6 +112,16 @@
input_type: "radio"
});
}
if (source.value === 'ec2' || source.value === 'custom' ||
source.value === 'vmware' || source.value === 'openstack'){
$scope[source.value + '_variables'] = $scope[source.value + '_variables'] === null ? '---' : $scope[source.value + '_variables'];
ParseTypeChange({
scope: $scope,
field_id: source.value + '_variables',
variable: source.value + '_variables',
parse_variable: 'envParseType',
});
}
// reset fields
// azure_rm regions choices are keyed as "azure" in an OPTIONS request to the inventory_sources endpoint
$scope.source_region_choices = source.value === 'azure_rm' ? $scope.azure_regions : $scope[source.value + '_regions'];
@@ -122,6 +132,7 @@
$scope.credential_name = null;
initRegionSelect();
};
var initRegionSelect = function(){
CreateSelect2({
element: '#group_source_regions',
@@ -138,6 +149,19 @@
element: '#group_source',
multiple: false
});
// After the source is set, conditional fields will be visible
// CodeMirror is buggy if you instantiate it in a not-visible element
// So we initialize it here instead of the init() routine
if(inventorySourceData.source === 'ec2' || inventorySourceData.source === 'openstack' ||
inventorySourceData.source === 'custom' || inventorySourceData.source === 'vmware'){
$scope[inventorySourceData.source + '_variables'] = inventorySourceData.source_vars === null || inventorySourceData.source_vars === '' ? '---' : ParseVariableString(inventorySourceData.source_vars);
ParseTypeChange({
scope: $scope,
field_id: inventorySourceData.source + '_variables',
variable: inventorySourceData.source + '_variables',
parse_variable: 'envParseType',
});
}
};
var initRegionData = function(){
var source = $scope.source.value === 'azure_rm' ? 'azure' : $scope.source.value;
@@ -230,15 +254,11 @@
{instance_filters: inventorySourceData.instance_filters},
{inventory_script: inventorySourceData.source_script}
);
if(inventorySourceData.source === ('ec2' || 'openstack' || 'custom' || 'vmware')){
$scope[inventorySourceData.source + '_variables'] = inventorySourceData.source_vars;
}
if (inventorySourceData.credential){
GroupManageService.getCredential(inventorySourceData.credential).then(res => $scope.credential_name = res.data.name);
}
$scope = angular.extend($scope, groupData);
$scope.variables = $scope.variables === (null || '') ? '---' : $scope.variables;
$scope.parseType = 'yaml';
// instantiate lookup fields
if (inventorySourceData.source !== 'custom'){
LookUpInit({
@@ -272,11 +292,17 @@
input_type: "radio"
});
}
// init codemirror(s)
$scope.variables = $scope.variables === null || $scope.variables === '' ? '---' : ParseVariableString($scope.variables);
$scope.parseType = 'yaml';
$scope.envParseType = 'yaml';
ParseTypeChange({
scope: $scope,
field_id: 'group_variables',
variable: 'variables',
});
NotificationsListInit({
scope: $scope,
url: GetBasePath('inventory_sources'),

View File

@@ -729,14 +729,14 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
html += (field.awPopOver && !field.awPopOverRight) ? Attr(field, 'awPopOver', fld) : "";
html += (field.hintText) ? "\n\t\t<span class=\"label-hint-text\">\n\t\t\t<i class=\"fa fa-info-circle\">\n\t\t\t</i>\n\t\t\tHint: " + field.hintText + "\n\t\t</span>" : "";
// Variable editing
if (fld === "variables" || fld === "extra_vars" || fld === 'inventory_variables' || fld === 'source_vars') {
if (fld === "variables" || fld === "extra_vars" || _.last(fld.split('_')) === 'variables' || fld === 'source_vars') {
html += "<div class=\"parse-selection\" id=\"" + form.name + "_" + fld + "_parse_type\">" +
"<input type=\"radio\" ng-disabled=\"disableParseSelection\" ng-model=\"";
html += (field.parseTypeName) ? field.parseTypeName : 'parseType';
html += "\" value=\"yaml\" ng-change=\"parseTypeChange()\"> <span class=\"parse-label\">YAML</span>\n";
html += "\" value=\"yaml\" ng-change=\"parseTypeChange('" + ((field.parseTypeName) ? field.parseTypeName : 'parseType') + "', '" + fld + "'" + ")\"> <span class=\"parse-label\">YAML</span>\n";
html += "<input type=\"radio\" ng-disabled=\"disableParseSelection\" ng-model=\"";
html += (field.parseTypeName) ? field.parseTypeName : 'parseType';
html += "\" value=\"json\" ng-change=\"parseTypeChange()\"> <span class=\"parse-label\">JSON</span>\n";
html += "\" value=\"json\" ng-change=\"parseTypeChange('" + ((field.parseTypeName) ? field.parseTypeName : 'parseType')+ "', '" + fld + "'" + ")\"> <span class=\"parse-label\">JSON</span>\n";
html += "</div>\n";
}