fix(client): fix json input component value handling (#2028)
* fix(client): fix json input component value handling * fix(client): fix json input test case * refactor(client): remove format button from json variable component * refactor(client): move json input style to global * test(client): remove unused test case
This commit is contained in:
parent
91d6f09fc3
commit
dd9cb723d4
@ -2,19 +2,52 @@ import { Field } from '@formily/core';
|
||||
import { useField } from '@formily/react';
|
||||
import { Input } from 'antd';
|
||||
import { TextAreaProps } from 'antd/es/input';
|
||||
import React, { Ref } from 'react';
|
||||
import React, { useState, useEffect, Ref } from 'react';
|
||||
import { cx, css } from '@emotion/css';
|
||||
|
||||
export type JSONTextAreaProps = TextAreaProps & { value?: string; space?: number };
|
||||
|
||||
export const Json = React.forwardRef<typeof Input.TextArea, JSONTextAreaProps>(
|
||||
({ value, onChange, space = 2, ...props }: JSONTextAreaProps, ref: Ref<any>) => {
|
||||
const field = useField<Field>();
|
||||
const [text, setText] = useState('');
|
||||
useEffect(() => {
|
||||
try {
|
||||
if (value != null) {
|
||||
setText(JSON.stringify(value, null, space));
|
||||
}
|
||||
} catch (ex) {
|
||||
//
|
||||
}
|
||||
}, [space, value]);
|
||||
return (
|
||||
<Input.TextArea
|
||||
{...props}
|
||||
className={cx(
|
||||
css`
|
||||
font-size: 90%;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
`,
|
||||
props.className,
|
||||
)}
|
||||
ref={ref}
|
||||
defaultValue={value != null ? JSON.stringify(value, null, space) : ''}
|
||||
value={text}
|
||||
onChange={(ev) => {
|
||||
setText(ev.target.value);
|
||||
try {
|
||||
if (ev.target.value.trim() !== '') {
|
||||
JSON.parse(ev.target.value);
|
||||
}
|
||||
field.setFeedback({});
|
||||
} catch (err) {
|
||||
field.setFeedback({
|
||||
type: 'error',
|
||||
code: 'JSONSyntaxError',
|
||||
messages: [err.message],
|
||||
});
|
||||
}
|
||||
}}
|
||||
onBlur={(ev) => {
|
||||
try {
|
||||
const v = ev.target.value.trim() !== '' ? JSON.parse(ev.target.value) : null;
|
||||
field.setFeedback({});
|
||||
|
@ -136,7 +136,8 @@ describe('Input.JSON', () => {
|
||||
const textarea = container.querySelector('textarea') as HTMLTextAreaElement;
|
||||
const pre = container.querySelector('pre') as HTMLPreElement;
|
||||
fireEvent.change(textarea, { target: { value: '{"name":"nocobase"}' } });
|
||||
expect(textarea.value).toBe('{"name":"nocobase"}');
|
||||
fireEvent.blur(textarea, { target: { value: '{"name":"nocobase"}' } });
|
||||
expect(textarea.value).toBe('{\n "name": "nocobase"\n}');
|
||||
expect(pre).toMatchInlineSnapshot(`
|
||||
<pre
|
||||
class="ant-json css-4dta7v"
|
||||
@ -153,6 +154,7 @@ describe('Input.JSON', () => {
|
||||
|
||||
const textarea = container.querySelector('textarea') as HTMLTextAreaElement;
|
||||
fireEvent.change(textarea, { target: { value: '{"name":nocobase}' } });
|
||||
fireEvent.blur(textarea, { target: { value: '{"name":nocobase}' } });
|
||||
expect(screen.getByText(`Unexpected token o in JSON at position 9`).innerHTML).toBe(
|
||||
`Unexpected token o in JSON at position 9`,
|
||||
);
|
||||
|
@ -3,7 +3,6 @@ import { Button } from 'antd';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import { Input } from '../input';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { VariableSelect } from './VariableSelect';
|
||||
|
||||
// NOTE: https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js/46012210#46012210
|
||||
@ -19,25 +18,9 @@ function setNativeInputValue(input, value) {
|
||||
|
||||
export function JSONInput(props) {
|
||||
const inputRef = useRef<any>(null);
|
||||
const { value, space = 2, scope } = props;
|
||||
const { t } = useTranslation();
|
||||
const { scope } = props;
|
||||
const options = typeof scope === 'function' ? scope() : scope ?? [];
|
||||
|
||||
function onFormat() {
|
||||
if (!inputRef.current) {
|
||||
return;
|
||||
}
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { textArea } = inputRef.current.resizableTextArea;
|
||||
const nextValue = JSON.stringify(value, null, space);
|
||||
setNativeInputValue(textArea, nextValue);
|
||||
textArea.setSelectionRange(nextValue.length, nextValue.length);
|
||||
textArea.focus();
|
||||
}
|
||||
|
||||
function onInsert(selected) {
|
||||
if (!inputRef.current) {
|
||||
return;
|
||||
@ -73,7 +56,6 @@ export function JSONInput(props) {
|
||||
}
|
||||
`}
|
||||
>
|
||||
<Button onClick={onFormat}>{t('Prettify')}</Button>
|
||||
<VariableSelect options={options} onInsert={onInsert} />
|
||||
</Button.Group>
|
||||
</div>
|
||||
|
@ -61,7 +61,6 @@ describe('Variable', () => {
|
||||
const variableSelector = document.querySelector('.ant-select-selector') as HTMLElement;
|
||||
expect(input).toBeInTheDocument();
|
||||
expect(variableSelector).toBeInTheDocument();
|
||||
expect(screen.getByText('Prettify')).toBeInTheDocument();
|
||||
|
||||
// https://testing-library.com/docs/user-event/keyboard/
|
||||
await userEvent.type(input, '{{ "a": "');
|
||||
@ -71,13 +70,5 @@ describe('Variable', () => {
|
||||
|
||||
await userEvent.type(input, '" }');
|
||||
expect(input.value).toMatchInlineSnapshot('"{ \\"a\\": \\"{{v1}}\\" }"');
|
||||
|
||||
// 格式化一下
|
||||
await userEvent.click(screen.getByText('Prettify'));
|
||||
expect(input.value).toMatchInlineSnapshot(`
|
||||
"{
|
||||
\\"a\\": \\"{{v1}}\\"
|
||||
}"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { ArrayItems } from '@formily/antd';
|
||||
import { cx, css } from '@emotion/css';
|
||||
|
||||
import { NAMESPACE } from '../locale';
|
||||
import { useWorkflowVariableOptions } from '../variable';
|
||||
@ -146,13 +145,7 @@ export default {
|
||||
minRows: 10,
|
||||
},
|
||||
placeholder: `{{t("Input request data", { ns: "${NAMESPACE}" })}}`,
|
||||
className: cx(
|
||||
'full-width',
|
||||
css`
|
||||
font-size: 90%;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
`,
|
||||
),
|
||||
className: 'full-width',
|
||||
},
|
||||
description: `{{t("Only support standard JSON data", { ns: "${NAMESPACE}" })}}`,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user