add more robust handling of JSON/YAML toggle to prevent expanding YAML expressions

This commit is contained in:
Keith J. Grant 2021-03-16 11:54:13 -07:00
parent 1bd71024e3
commit dff3103d96
3 changed files with 53 additions and 16 deletions

View File

@ -11,7 +11,6 @@ import 'ace-builds/src-noconflict/theme-github';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import styled from 'styled-components';
import debounce from '../../util/debounce';
config.set('loadWorkerFromBlob', false);
@ -140,7 +139,8 @@ function CodeEditor({
mode={aceModes[mode] || 'text'}
className={`pf-c-form-control ${className}`}
theme="github"
onChange={debounce(onChange, 250)}
onChange={onChange}
debounceChangePeriod={250}
value={value}
onFocus={onFocus}
onBlur={onBlur}

View File

@ -73,13 +73,15 @@ function VariablesField({
},
[shouldValidate, validate] // eslint-disable-line react-hooks/exhaustive-deps
);
const [initialYamlValue] = useState(mode === YAML_MODE ? field.value : null);
const [isEdited, setIsEdited] = useState(false);
const [lastYamlValue, setLastYamlValue] = useState(
mode === YAML_MODE ? field.value : null
);
const [isJsonEdited, setIsJsonEdited] = useState(false);
const [isExpanded, setIsExpanded] = useState(false);
const handleModeChange = newMode => {
if (newMode === YAML_MODE && !isEdited && initialYamlValue) {
helpers.setValue(initialYamlValue);
if (newMode === YAML_MODE && !isJsonEdited && lastYamlValue !== null) {
helpers.setValue(lastYamlValue);
setMode(newMode);
return;
}
@ -96,6 +98,16 @@ function VariablesField({
}
};
const handleChange = newVal => {
helpers.setValue(newVal);
if (mode === JSON_MODE) {
setIsJsonEdited(true);
} else {
setLastYamlValue(newVal);
setIsJsonEdited(false);
}
};
return (
<>
<VariablesFieldInternals
@ -109,8 +121,8 @@ function VariablesField({
onExpand={() => setIsExpanded(true)}
mode={mode}
setMode={handleModeChange}
setIsEdited={setIsEdited}
setShouldValidate={setShouldValidate}
handleChange={handleChange}
/>
<Modal
variant="xlarge"
@ -141,8 +153,8 @@ function VariablesField({
fullHeight
mode={mode}
setMode={handleModeChange}
setIsEdited={setIsEdited}
setShouldValidate={setShouldValidate}
handleChange={handleChange}
/>
</div>
</Modal>
@ -178,10 +190,10 @@ function VariablesFieldInternals({
mode,
setMode,
onExpand,
setIsEdited,
setShouldValidate,
handleChange,
}) {
const [field, meta, helpers] = useField(name);
const [field, meta] = useField(name);
return (
<div className="pf-c-form__group">
@ -226,10 +238,7 @@ function VariablesFieldInternals({
mode={mode}
readOnly={readOnly}
{...field}
onChange={newVal => {
setIsEdited(true);
helpers.setValue(newVal);
}}
onChange={handleChange}
fullHeight={fullHeight}
onFocus={() => setShouldValidate(false)}
onBlur={() => setShouldValidate(true)}

View File

@ -56,7 +56,7 @@ describe('VariablesField', () => {
);
});
it('should retain non-expanded yaml if value not edited', async () => {
it('should retain non-expanded yaml if JSON value not edited', async () => {
const value = '---\na: &aa [a,b,c]\nb: *aa';
const wrapper = mountWithContexts(
<Formik initialValues={{ variables: value }}>
@ -80,7 +80,7 @@ describe('VariablesField', () => {
expect(wrapper.find('CodeEditor').prop('value')).toEqual(value);
});
it('should retain expanded yaml if value is edited', async () => {
it('should retain expanded yaml if JSON value is edited', async () => {
const value = '---\na: &aa [a,b,c]\nb: *aa';
const wrapper = mountWithContexts(
<Formik initialValues={{ variables: value }}>
@ -109,6 +109,34 @@ describe('VariablesField', () => {
);
});
it('should retain non-expanded yaml if YAML value is edited', async () => {
const value = '---\na: &aa [a,b,c]\nb: *aa';
const wrapper = mountWithContexts(
<Formik initialValues={{ variables: value }}>
{() => (
<VariablesField id="the-field" name="variables" label="Variables" />
)}
</Formik>
);
wrapper.find('CodeEditor').invoke('onChange')(
'---\na: &aa [a,b,c]\nb: *aa\n'
);
const buttons = wrapper.find('Button');
await act(async () => {
buttons.at(1).simulate('click');
});
wrapper.update();
const buttons2 = wrapper.find('Button');
await act(async () => {
buttons2.at(0).simulate('click');
});
wrapper.update();
expect(wrapper.find('CodeEditor').prop('mode')).toEqual('yaml');
expect(wrapper.find('CodeEditor').prop('value')).toEqual(
'---\na: &aa [a,b,c]\nb: *aa\n'
);
});
it('should set Formik error if yaml is invalid', async () => {
const value = '---\nfoo bar\n';
const wrapper = mountWithContexts(