diff --git a/awx/ui/client/src/configuration/forms/settings-form.controller.js b/awx/ui/client/src/configuration/forms/settings-form.controller.js index 7fe61999ba..907f978a93 100644 --- a/awx/ui/client/src/configuration/forms/settings-form.controller.js +++ b/awx/ui/client/src/configuration/forms/settings-form.controller.js @@ -304,6 +304,10 @@ export default [ $scope[fld + '_api_error'] = ''; $('[name="' + fld + '"]').removeClass('ng-invalid'); } + if (currentForm.fields[fld].codeMirror) { + $('label[for="' + fld + '"] span').removeClass('error-color'); + $(`#cm-${fld}-container .CodeMirror`).removeClass('error-border'); + } } if (!$scope.$$phase) { $scope.$digest(); @@ -316,6 +320,8 @@ export default [ var getFormPayload = function() { var keys = _.keys(formDefs[formTracker.getCurrent()].fields); var payload = {}; + const errors = {}; + _.each(keys, function(key) { if (key === 'ACCESS_TOKEN_EXPIRE_SECONDS' || key === 'REFRESH_TOKEN_EXPIRE_SECONDS' || key === 'AUTHORIZATION_CODE_EXPIRE_SECONDS') { // These two values need to be POSTed nested under the OAUTH2_PROVIDER key @@ -350,7 +356,12 @@ export default [ } } else if($scope.configDataResolve[key].type === 'list' && $scope[key] !== null) { // Parse lists - payload[key] = SettingsUtils.listToArray($scope[key], key); + try { + payload[key] = SettingsUtils.listToArray($scope[key], key); + } catch (error) { + errors[key] = error; + payload[key] = []; + } } else if($scope.configDataResolve[key].type === 'nested object') { if(!$scope[key]) { @@ -371,15 +382,22 @@ export default [ } } }); - return payload; + return [payload, errors]; }; vm.formSave = function() { var saveDeferred = $q.defer(); clearApiErrors(); Wait('start'); - const payload = getFormPayload(); - SettingsService.patchConfiguration(getFormPayload()) + + const [payload, errors] = getFormPayload(); + if (!SettingsUtils.isEmpty(errors)) { + ProcessErrors($scope, errors, null, formDefs[formTracker.getCurrent()], {}); + return; + } + + const [payloadCopy] = getFormPayload(); + SettingsService.patchConfiguration(payloadCopy) .then(function(data) { loginUpdate(); diff --git a/awx/ui/client/src/configuration/settingsUtils.service.js b/awx/ui/client/src/configuration/settingsUtils.service.js index e9d448aff5..bf6b354177 100644 --- a/awx/ui/client/src/configuration/settingsUtils.service.js +++ b/awx/ui/client/src/configuration/settingsUtils.service.js @@ -12,13 +12,9 @@ export default ['$q', var payload; if (input.indexOf('[') !== -1) { - try { - payload = JSON.parse(input); + payload = JSON.parse(input); - if (!Array.isArray(payload)) { - payload = []; - } - } catch(err) { + if (!Array.isArray(payload)) { payload = []; } } else if (input.indexOf('\n') !== -1) { diff --git a/awx/ui/client/src/shared/Utilities.js b/awx/ui/client/src/shared/Utilities.js index aa019bcbc3..39ee42cda5 100644 --- a/awx/ui/client/src/shared/Utilities.js +++ b/awx/ui/client/src/shared/Utilities.js @@ -212,7 +212,11 @@ angular.module('Utilities', ['RestServices', 'Utilities']) } } else { if (data[fld]) { - scope[fld + '_api_error'] = data[fld][0]; + if (data[fld].message) { + scope[fld + '_api_error'] = data[fld].message; + } else { + scope[fld + '_api_error'] = data[fld][0]; + } $('[name="' + fld + '"]').addClass('ng-invalid'); $('label[for="' + fld + '"] span').addClass('error-color'); $('html, body').animate({scrollTop: $('[name="' + fld + '"]').offset().top}, 0);