mirror of
https://github.com/ansible/awx.git
synced 2026-03-13 15:09:32 -02:30
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:
@@ -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',
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user