mirror of
https://github.com/ansible/awx.git
synced 2026-05-19 14:57:39 -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': '---',
|
'default': '---',
|
||||||
dataTitle: 'Group Variables',
|
dataTitle: 'Group Variables',
|
||||||
dataPlacement: 'right',
|
dataPlacement: 'right',
|
||||||
|
parseTypeName: 'parseType',
|
||||||
awPopOver: "<p>Variables defined here apply to all child groups and hosts.</p>" +
|
awPopOver: "<p>Variables defined here apply to all child groups and hosts.</p>" +
|
||||||
"<p>Enter variables using either JSON or YAML syntax. Use the " +
|
"<p>Enter variables using either JSON or YAML syntax. Use the " +
|
||||||
"radio button to toggle between the two.</p>" +
|
"radio button to toggle between the two.</p>" +
|
||||||
@@ -158,7 +159,7 @@ export default
|
|||||||
addRequired: false,
|
addRequired: false,
|
||||||
editRequired: false,
|
editRequired: false,
|
||||||
rows: 6,
|
rows: 6,
|
||||||
'default': null,
|
'default': '---',
|
||||||
parseTypeName: 'envParseType',
|
parseTypeName: 'envParseType',
|
||||||
dataTitle: "Environment Variables",
|
dataTitle: "Environment Variables",
|
||||||
dataPlacement: 'right',
|
dataPlacement: 'right',
|
||||||
@@ -181,7 +182,7 @@ export default
|
|||||||
addRequired: false,
|
addRequired: false,
|
||||||
editRequird: false,
|
editRequird: false,
|
||||||
rows: 6,
|
rows: 6,
|
||||||
'default': null,
|
'default': '---',
|
||||||
parseTypeName: 'envParseType',
|
parseTypeName: 'envParseType',
|
||||||
dataTitle: "Source Variables",
|
dataTitle: "Source Variables",
|
||||||
dataPlacement: 'right',
|
dataPlacement: 'right',
|
||||||
@@ -207,7 +208,7 @@ export default
|
|||||||
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
|
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
|
||||||
editRequird: false,
|
editRequird: false,
|
||||||
rows: 6,
|
rows: 6,
|
||||||
'default': null,
|
'default': '---',
|
||||||
parseTypeName: 'envParseType',
|
parseTypeName: 'envParseType',
|
||||||
dataTitle: "Source Variables",
|
dataTitle: "Source Variables",
|
||||||
dataPlacement: 'right',
|
dataPlacement: 'right',
|
||||||
@@ -233,7 +234,7 @@ export default
|
|||||||
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
|
class: 'Form-textAreaLabel Form-formGroup--fullWidth',
|
||||||
editRequird: false,
|
editRequird: false,
|
||||||
rows: 6,
|
rows: 6,
|
||||||
'default': null,
|
'default': '---',
|
||||||
parseTypeName: 'envParseType',
|
parseTypeName: 'envParseType',
|
||||||
dataTitle: "Source Variables",
|
dataTitle: "Source Variables",
|
||||||
dataPlacement: 'right',
|
dataPlacement: 'right',
|
||||||
|
|||||||
@@ -27,51 +27,39 @@ export default
|
|||||||
onReady = params.onReady,
|
onReady = params.onReady,
|
||||||
onChange = params.onChange;
|
onChange = params.onChange;
|
||||||
|
|
||||||
function removeField() {
|
function removeField(fld) {
|
||||||
//set our model to the last change in CodeMirror and then destroy CodeMirror
|
//set our model to the last change in CodeMirror and then destroy CodeMirror
|
||||||
scope[fld] = scope.codeMirror.getValue();
|
scope[fld] = scope[fld + 'codeMirror'].getValue();
|
||||||
|
$('#cm-' + fld + '-container > .CodeMirror').empty().remove();
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createField(onChange, onReady) {
|
function createField(onChange, onReady, fld) {
|
||||||
//hide the textarea and show a fresh CodeMirror with the current mode (json or yaml)
|
//hide the textarea and show a fresh CodeMirror with the current mode (json or yaml)
|
||||||
$rootScope.loginConfig.promise.then(function () {
|
|
||||||
scope.codeMirror = AngularCodeMirror();
|
scope[fld + 'codeMirror'] = AngularCodeMirror();
|
||||||
scope.codeMirror.addModes($AnsibleConfig.variable_edit_modes);
|
scope[fld + 'codeMirror'].addModes($AnsibleConfig.variable_edit_modes);
|
||||||
scope.codeMirror.showTextArea({
|
scope[fld + 'codeMirror'].showTextArea({
|
||||||
scope: scope,
|
scope: scope,
|
||||||
model: fld,
|
model: fld,
|
||||||
element: field_id,
|
element: field_id,
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: scope[pfld],
|
mode: scope[pfld],
|
||||||
onReady: onReady,
|
onReady: onReady,
|
||||||
onChange: onChange
|
onChange: onChange
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide the textarea and show a CodeMirror editor
|
// Hide the textarea and show a CodeMirror editor
|
||||||
createField(onChange, onReady);
|
createField(onChange, onReady, fld);
|
||||||
|
|
||||||
|
|
||||||
// Toggle displayed variable string between JSON and YAML
|
// Toggle displayed variable string between JSON and YAML
|
||||||
scope.parseTypeChange = function() {
|
scope.parseTypeChange = function(model, fld) {
|
||||||
var json_obj;
|
var json_obj;
|
||||||
if (scope[pfld] === 'json') {
|
if (scope[model] === 'json') {
|
||||||
// converting yaml to json
|
// converting yaml to json
|
||||||
try {
|
try {
|
||||||
removeField();
|
removeField(fld);
|
||||||
json_obj = jsyaml.load(scope[fld]);
|
json_obj = jsyaml.load(scope[fld]);
|
||||||
if ($.isEmptyObject(json_obj)) {
|
if ($.isEmptyObject(json_obj)) {
|
||||||
scope[fld] = "{}";
|
scope[fld] = "{}";
|
||||||
@@ -79,17 +67,17 @@ export default
|
|||||||
else {
|
else {
|
||||||
scope[fld] = JSON.stringify(json_obj, null, " ");
|
scope[fld] = JSON.stringify(json_obj, null, " ");
|
||||||
}
|
}
|
||||||
createField();
|
createField(onReady, onChange, fld);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
Alert('Parse Error', 'Failed to parse valid YAML. ' + e.message);
|
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 {
|
else {
|
||||||
// convert json to yaml
|
// convert json to yaml
|
||||||
try {
|
try {
|
||||||
removeField();
|
removeField(fld);
|
||||||
json_obj = JSON.parse(scope[fld]);
|
json_obj = JSON.parse(scope[fld]);
|
||||||
if ($.isEmptyObject(json_obj)) {
|
if ($.isEmptyObject(json_obj)) {
|
||||||
scope[fld] = '---';
|
scope[fld] = '---';
|
||||||
@@ -97,11 +85,11 @@ export default
|
|||||||
else {
|
else {
|
||||||
scope[fld] = jsyaml.safeDump(json_obj);
|
scope[fld] = jsyaml.safeDump(json_obj);
|
||||||
}
|
}
|
||||||
createField();
|
createField(onReady, onChange, fld);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
Alert('Parse Error', 'Failed to parse valid JSON. ' + e.message);
|
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
|
// inventory_source fields
|
||||||
params = {
|
params = {
|
||||||
instance_filters: $scope.instance_filters,
|
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_script: $scope.inventory_script,
|
||||||
source: $scope.source.value,
|
source: $scope.source.value,
|
||||||
credential: $scope.credential,
|
credential: $scope.credential,
|
||||||
@@ -114,6 +114,14 @@
|
|||||||
input_type: "radio"
|
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
|
// reset fields
|
||||||
$scope.group_by_choices = source === 'ec2' ? $scope.ec2_group_by : null;
|
$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
|
// azure_rm regions choices are keyed as "azure" in an OPTIONS request to the inventory_sources endpoint
|
||||||
@@ -203,7 +211,7 @@
|
|||||||
});
|
});
|
||||||
var init = function(){
|
var init = function(){
|
||||||
$scope.parseType = 'yaml';
|
$scope.parseType = 'yaml';
|
||||||
$scope.variables = '---';
|
$scope.envParseType = 'yaml';
|
||||||
generator.inject(form, {mode: 'add', related: false, id: 'Inventory-groupManage--panel', scope: $scope});
|
generator.inject(form, {mode: 'add', related: false, id: 'Inventory-groupManage--panel', scope: $scope});
|
||||||
ParseTypeChange({
|
ParseTypeChange({
|
||||||
scope: $scope,
|
scope: $scope,
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
export default
|
export default
|
||||||
['$state', '$stateParams', '$scope', 'GroupForm', 'CredentialList', 'inventoryScriptsListObject', 'ToggleNotification',
|
['$state', '$stateParams', '$scope', 'GroupForm', 'CredentialList', 'inventoryScriptsListObject', 'ToggleNotification', 'ParseVariableString',
|
||||||
'ParseTypeChange', 'GenerateForm', 'LookUpInit', 'RelatedSearchInit', 'RelatedPaginateInit', 'NotificationsListInit',
|
'ParseTypeChange', 'GenerateForm', 'LookUpInit', 'RelatedSearchInit', 'RelatedPaginateInit', 'NotificationsListInit',
|
||||||
'GroupManageService','GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions', 'groupData', 'inventorySourceData',
|
'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,
|
ParseTypeChange, GenerateForm, LookUpInit, RelatedSearchInit, RelatedPaginateInit, NotificationsListInit,
|
||||||
GroupManageService, GetChoices, GetBasePath, CreateSelect2, GetSourceTypeOptions, groupData, inventorySourceData){
|
GroupManageService, GetChoices, GetBasePath, CreateSelect2, GetSourceTypeOptions, groupData, inventorySourceData){
|
||||||
var generator = GenerateForm,
|
var generator = GenerateForm,
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
group_by: _.map($scope.group_by, 'value').join(','),
|
group_by: _.map($scope.group_by, 'value').join(','),
|
||||||
source_regions: _.map($scope.source_regions, 'value').join(','),
|
source_regions: _.map($scope.source_regions, 'value').join(','),
|
||||||
instance_filters: $scope.instance_filters,
|
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;
|
source = $scope.source.value;
|
||||||
}
|
}
|
||||||
@@ -112,6 +112,16 @@
|
|||||||
input_type: "radio"
|
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
|
// reset fields
|
||||||
// azure_rm regions choices are keyed as "azure" in an OPTIONS request to the inventory_sources endpoint
|
// 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'];
|
$scope.source_region_choices = source.value === 'azure_rm' ? $scope.azure_regions : $scope[source.value + '_regions'];
|
||||||
@@ -122,6 +132,7 @@
|
|||||||
$scope.credential_name = null;
|
$scope.credential_name = null;
|
||||||
initRegionSelect();
|
initRegionSelect();
|
||||||
};
|
};
|
||||||
|
|
||||||
var initRegionSelect = function(){
|
var initRegionSelect = function(){
|
||||||
CreateSelect2({
|
CreateSelect2({
|
||||||
element: '#group_source_regions',
|
element: '#group_source_regions',
|
||||||
@@ -138,6 +149,19 @@
|
|||||||
element: '#group_source',
|
element: '#group_source',
|
||||||
multiple: false
|
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 initRegionData = function(){
|
||||||
var source = $scope.source.value === 'azure_rm' ? 'azure' : $scope.source.value;
|
var source = $scope.source.value === 'azure_rm' ? 'azure' : $scope.source.value;
|
||||||
@@ -230,15 +254,11 @@
|
|||||||
{instance_filters: inventorySourceData.instance_filters},
|
{instance_filters: inventorySourceData.instance_filters},
|
||||||
{inventory_script: inventorySourceData.source_script}
|
{inventory_script: inventorySourceData.source_script}
|
||||||
);
|
);
|
||||||
if(inventorySourceData.source === ('ec2' || 'openstack' || 'custom' || 'vmware')){
|
|
||||||
$scope[inventorySourceData.source + '_variables'] = inventorySourceData.source_vars;
|
|
||||||
}
|
|
||||||
if (inventorySourceData.credential){
|
if (inventorySourceData.credential){
|
||||||
GroupManageService.getCredential(inventorySourceData.credential).then(res => $scope.credential_name = res.data.name);
|
GroupManageService.getCredential(inventorySourceData.credential).then(res => $scope.credential_name = res.data.name);
|
||||||
}
|
}
|
||||||
$scope = angular.extend($scope, groupData);
|
$scope = angular.extend($scope, groupData);
|
||||||
$scope.variables = $scope.variables === (null || '') ? '---' : $scope.variables;
|
|
||||||
$scope.parseType = 'yaml';
|
|
||||||
// instantiate lookup fields
|
// instantiate lookup fields
|
||||||
if (inventorySourceData.source !== 'custom'){
|
if (inventorySourceData.source !== 'custom'){
|
||||||
LookUpInit({
|
LookUpInit({
|
||||||
@@ -272,11 +292,17 @@
|
|||||||
input_type: "radio"
|
input_type: "radio"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// init codemirror(s)
|
||||||
|
$scope.variables = $scope.variables === null || $scope.variables === '' ? '---' : ParseVariableString($scope.variables);
|
||||||
|
$scope.parseType = 'yaml';
|
||||||
|
$scope.envParseType = 'yaml';
|
||||||
|
|
||||||
ParseTypeChange({
|
ParseTypeChange({
|
||||||
scope: $scope,
|
scope: $scope,
|
||||||
field_id: 'group_variables',
|
field_id: 'group_variables',
|
||||||
variable: 'variables',
|
variable: 'variables',
|
||||||
});
|
});
|
||||||
|
|
||||||
NotificationsListInit({
|
NotificationsListInit({
|
||||||
scope: $scope,
|
scope: $scope,
|
||||||
url: GetBasePath('inventory_sources'),
|
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.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>" : "";
|
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
|
// 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\">" +
|
html += "<div class=\"parse-selection\" id=\"" + form.name + "_" + fld + "_parse_type\">" +
|
||||||
"<input type=\"radio\" ng-disabled=\"disableParseSelection\" ng-model=\"";
|
"<input type=\"radio\" ng-disabled=\"disableParseSelection\" ng-model=\"";
|
||||||
html += (field.parseTypeName) ? field.parseTypeName : 'parseType';
|
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 += "<input type=\"radio\" ng-disabled=\"disableParseSelection\" ng-model=\"";
|
||||||
html += (field.parseTypeName) ? field.parseTypeName : 'parseType';
|
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";
|
html += "</div>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user