Don't unecessarily expand YAML expressions

If the user toggles a VariablesField to JSON then back to YAML without
editing the field content, revert to the initial YAML value to maintain
any shorthand expressions
This commit is contained in:
Keith J. Grant 2021-03-15 16:07:36 -07:00
parent 634c9892df
commit 1bd71024e3
2 changed files with 81 additions and 14 deletions

View File

@ -73,8 +73,29 @@ 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 [isExpanded, setIsExpanded] = useState(false);
const handleModeChange = newMode => {
if (newMode === YAML_MODE && !isEdited && initialYamlValue) {
helpers.setValue(initialYamlValue);
setMode(newMode);
return;
}
try {
const newVal =
newMode === YAML_MODE
? jsonToYaml(field.value)
: yamlToJson(field.value);
helpers.setValue(newVal);
setMode(newMode);
} catch (err) {
helpers.setError(err.message);
}
};
return (
<>
<VariablesFieldInternals
@ -87,7 +108,8 @@ function VariablesField({
tooltip={tooltip}
onExpand={() => setIsExpanded(true)}
mode={mode}
setMode={setMode}
setMode={handleModeChange}
setIsEdited={setIsEdited}
setShouldValidate={setShouldValidate}
/>
<Modal
@ -118,7 +140,8 @@ function VariablesField({
tooltip={tooltip}
fullHeight
mode={mode}
setMode={setMode}
setMode={handleModeChange}
setIsEdited={setIsEdited}
setShouldValidate={setShouldValidate}
/>
</div>
@ -155,6 +178,7 @@ function VariablesFieldInternals({
mode,
setMode,
onExpand,
setIsEdited,
setShouldValidate,
}) {
const [field, meta, helpers] = useField(name);
@ -176,18 +200,7 @@ function VariablesFieldInternals({
[JSON_MODE, 'JSON'],
]}
value={mode}
onChange={newMode => {
try {
const newVal =
newMode === YAML_MODE
? jsonToYaml(field.value)
: yamlToJson(field.value);
helpers.setValue(newVal);
setMode(newMode);
} catch (err) {
helpers.setError(err.message);
}
}}
onChange={setMode}
/>
</SplitItem>
</Split>
@ -214,6 +227,7 @@ function VariablesFieldInternals({
readOnly={readOnly}
{...field}
onChange={newVal => {
setIsEdited(true);
helpers.setValue(newVal);
}}
fullHeight={fullHeight}

View File

@ -51,6 +51,59 @@ describe('VariablesField', () => {
});
wrapper.update();
expect(wrapper.find('CodeEditor').prop('mode')).toEqual('yaml');
expect(wrapper.find('CodeEditor').prop('value')).toEqual(
'---\nfoo: bar\nbaz: 3'
);
});
it('should retain non-expanded yaml if value not 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>
);
const buttons = wrapper.find('Button');
expect(buttons).toHaveLength(2);
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(value);
});
it('should retain expanded yaml if 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>
);
const buttons = wrapper.find('Button');
expect(buttons).toHaveLength(2);
await act(async () => {
buttons.at(1).simulate('click');
});
wrapper.update();
wrapper.find('CodeEditor').invoke('onChange')(
'{\n "foo": "bar",\n "baz": 3\n}'
);
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(
'foo: bar\nbaz: 3\n'
);