mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2025-04-12 21:50:23 +08:00
Merge pull request #229 from webzard-io/fix/windlike-patch
fix(editor): make the form update correctly
This commit is contained in:
commit
87e6289747
@ -5,7 +5,7 @@ import { simple as simpleWalk } from 'acorn-walk';
|
||||
import { flattenDeep, isArray, isObject } from 'lodash-es';
|
||||
import { ComponentId, IFieldModel, ModuleId } from './IAppModel';
|
||||
|
||||
const regExp = new RegExp('.*{{.*}}.*');
|
||||
const regExp = /.*{{.*}}.*/;
|
||||
|
||||
export class FieldModel implements IFieldModel {
|
||||
isDynamic = false;
|
||||
@ -32,21 +32,39 @@ export class FieldModel implements IFieldModel {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
update(value: unknown) {
|
||||
private updateValue(value: unknown, shouldExtendValues = true) {
|
||||
if (isObject(value)) {
|
||||
if (!isObject(this.value)) {
|
||||
this.value = isArray(value) ? [] : {};
|
||||
}
|
||||
const isArrayValue = isArray(value);
|
||||
const isOldValueObject = isObject(this.value);
|
||||
|
||||
for (const key in value) {
|
||||
const val = (value as Record<string, unknown>)[key];
|
||||
const _thisValue = this.value as Record<string, IFieldModel>;
|
||||
if (!_thisValue[key]) {
|
||||
_thisValue[key] = new FieldModel(val);
|
||||
} else {
|
||||
_thisValue[key].update(val);
|
||||
}
|
||||
}
|
||||
this.value = (Object.keys(value) as Array<keyof typeof value>).reduce(
|
||||
(result, key) => {
|
||||
const oldValue: IFieldModel | null = isObject(this.value)
|
||||
? this.value[key]
|
||||
: null;
|
||||
let newValue: FieldModel;
|
||||
|
||||
if (oldValue) {
|
||||
(oldValue as FieldModel).updateValue(value[key], false);
|
||||
newValue = oldValue;
|
||||
} else {
|
||||
newValue = new FieldModel(value[key]);
|
||||
}
|
||||
|
||||
if (isArray(result)) {
|
||||
result.push(newValue);
|
||||
} else {
|
||||
result[key] = newValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
(isArrayValue
|
||||
? []
|
||||
: shouldExtendValues && isOldValueObject
|
||||
? this.value
|
||||
: {}) as Record<string, IFieldModel>
|
||||
);
|
||||
} else {
|
||||
this.value = value;
|
||||
}
|
||||
@ -54,6 +72,10 @@ export class FieldModel implements IFieldModel {
|
||||
this.parseReferences();
|
||||
}
|
||||
|
||||
update(value: unknown) {
|
||||
this.updateValue(value);
|
||||
}
|
||||
|
||||
getProperty(key: string | number): FieldModel | undefined {
|
||||
if (typeof this.value === 'object') {
|
||||
return (this.value as any)[key];
|
||||
@ -62,7 +84,7 @@ export class FieldModel implements IFieldModel {
|
||||
}
|
||||
|
||||
getValue() {
|
||||
return this.value
|
||||
return this.value;
|
||||
}
|
||||
|
||||
traverse(cb: (f: IFieldModel, key: string) => void) {
|
||||
@ -102,7 +124,7 @@ export class FieldModel implements IFieldModel {
|
||||
const str = exp.slice(node.start, node.end);
|
||||
let path = str.replace(lastIdentifier, '');
|
||||
if (path.startsWith('.')) {
|
||||
path = path.slice(1, path.length)
|
||||
path = path.slice(1, path.length);
|
||||
}
|
||||
this.refs[lastIdentifier].push(path);
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { flatten } from 'lodash-es';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FormControl, FormLabel, Input, Textarea, VStack } from '@chakra-ui/react';
|
||||
@ -29,30 +29,50 @@ export const renderField = (properties: {
|
||||
services: EditorServices;
|
||||
}) => {
|
||||
const { value, type, fullKey, selectedComponentId, index, services } = properties;
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const [textareaValue, setTextareaValue] = useState(value as string);
|
||||
const { eventBus, registry } = services;
|
||||
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
useEffect(() => {
|
||||
if (typeof value !== 'object') {
|
||||
setTextareaValue(value as string);
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
if (typeof value !== 'object') {
|
||||
const ref = React.createRef<HTMLTextAreaElement>();
|
||||
const onBlur = () => {
|
||||
const operation = type
|
||||
? genOperation(registry, 'modifyTraitProperty', {
|
||||
componentId: selectedComponentId,
|
||||
traitIndex: index,
|
||||
properties: {
|
||||
[fullKey]: ref.current?.value,
|
||||
},
|
||||
})
|
||||
: genOperation(registry, 'modifyComponentProperty', {
|
||||
componentId: selectedComponentId,
|
||||
properties: {
|
||||
[fullKey]: ref.current?.value,
|
||||
},
|
||||
});
|
||||
const operation = type ? genOperation(
|
||||
registry,
|
||||
'modifyTraitProperty',
|
||||
{
|
||||
componentId: selectedComponentId,
|
||||
traitIndex: index,
|
||||
properties: {
|
||||
[fullKey]: ref.current?.value,
|
||||
},
|
||||
}
|
||||
) : genOperation(
|
||||
registry,
|
||||
'modifyComponentProperty',
|
||||
{
|
||||
componentId: selectedComponentId,
|
||||
properties: {
|
||||
[fullKey]: ref.current?.value,
|
||||
},
|
||||
}
|
||||
);
|
||||
eventBus.send('operation', operation);
|
||||
};
|
||||
const onChange = (event: any) => {
|
||||
setTextareaValue(event.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormControl key={`${selectedComponentId}-${fullKey}`}>
|
||||
<FormLabel>{fullKey}</FormLabel>
|
||||
<Textarea ref={ref} onBlur={onBlur} defaultValue={value as string} />
|
||||
<Textarea ref={ref} onChange={onChange} onBlur={onBlur} value={textareaValue} />
|
||||
</FormControl>
|
||||
);
|
||||
} else {
|
||||
|
@ -36,6 +36,13 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
const { components } = editorStore;
|
||||
const [methods, setMethods] = useState<string[]>([]);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: handler,
|
||||
onSubmit: values => {
|
||||
onChange(values);
|
||||
},
|
||||
});
|
||||
|
||||
const updateMethods = useCallback(
|
||||
(componentId: string) => {
|
||||
if (componentId === GLOBAL_UTILS_ID) {
|
||||
@ -57,6 +64,10 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
[components, registry]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
formik.setValues(handler);
|
||||
}, [handler]);
|
||||
|
||||
useEffect(() => {
|
||||
if (handler.componentId) {
|
||||
updateMethods(handler.componentId);
|
||||
@ -67,21 +78,14 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
updateMethods(e.target.value);
|
||||
};
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: handler,
|
||||
onSubmit: values => {
|
||||
onChange(values);
|
||||
},
|
||||
});
|
||||
|
||||
const typeField = (
|
||||
<FormControl>
|
||||
<FormLabel>Event Type</FormLabel>
|
||||
<Select
|
||||
name="type"
|
||||
placeholder="Select Event Type"
|
||||
onChange={formik.handleChange}
|
||||
onBlur={() => formik.submitForm()}
|
||||
onChange={formik.handleChange}
|
||||
placeholder="Select Event Type"
|
||||
value={formik.values.type}
|
||||
>
|
||||
{eventTypes.map(e => (
|
||||
@ -97,12 +101,12 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
<FormLabel>Target Component</FormLabel>
|
||||
<Select
|
||||
name="componentId"
|
||||
placeholder="Select Target Component"
|
||||
onBlur={() => formik.submitForm()}
|
||||
onChange={e => {
|
||||
onTargetComponentChange(e);
|
||||
formik.handleChange(e);
|
||||
}}
|
||||
onBlur={() => formik.submitForm()}
|
||||
placeholder="Select Target Component"
|
||||
value={formik.values.componentId}
|
||||
>
|
||||
{[{ id: GLOBAL_UTILS_ID }].concat(components).map(c => (
|
||||
@ -118,9 +122,9 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
<FormLabel>Method</FormLabel>
|
||||
<Select
|
||||
name="method.name"
|
||||
placeholder="Select Method"
|
||||
onChange={formik.handleChange}
|
||||
onBlur={() => formik.submitForm()}
|
||||
onChange={formik.handleChange}
|
||||
placeholder="Select Method"
|
||||
value={formik.values.method.name}
|
||||
>
|
||||
{methods.map(m => (
|
||||
@ -136,7 +140,7 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
<FormControl>
|
||||
<FormLabel>Parameters</FormLabel>
|
||||
<KeyValueEditor
|
||||
initValue={formik.values.method.parameters}
|
||||
value={formik.values.method.parameters}
|
||||
onChange={json => {
|
||||
formik.setFieldValue('method.parameters', json);
|
||||
formik.submitForm();
|
||||
@ -150,8 +154,8 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
<FormLabel>Wait Type</FormLabel>
|
||||
<Select
|
||||
name="wait.type"
|
||||
onChange={formik.handleChange}
|
||||
onBlur={() => formik.submitForm()}
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.wait?.type}
|
||||
>
|
||||
<option value="delay">delay</option>
|
||||
@ -166,8 +170,8 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
<FormLabel>Wait Time</FormLabel>
|
||||
<Input
|
||||
name="wait.time"
|
||||
onChange={formik.handleChange}
|
||||
onBlur={() => formik.submitForm()}
|
||||
onChange={formik.handleChange}
|
||||
value={formik.values.wait?.time}
|
||||
/>
|
||||
</FormControl>
|
||||
@ -177,10 +181,10 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
<FormControl>
|
||||
<FormLabel>Disabled</FormLabel>
|
||||
<Switch
|
||||
name="disabled"
|
||||
isChecked={formik.values.disabled}
|
||||
onChange={formik.handleChange}
|
||||
name="disabled"
|
||||
onBlur={() => formik.submitForm()}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
@ -197,15 +201,15 @@ export const EventHandlerForm: React.FC<Props> = observer(props => {
|
||||
{disabledField}
|
||||
</VStack>
|
||||
<IconButton
|
||||
position="absolute"
|
||||
right="4"
|
||||
top="4"
|
||||
aria-label="remove event handler"
|
||||
variant="ghost"
|
||||
colorScheme="red"
|
||||
size="xs"
|
||||
icon={<CloseIcon />}
|
||||
onClick={onRemove}
|
||||
position="absolute"
|
||||
right="4"
|
||||
size="xs"
|
||||
top="4"
|
||||
variant="ghost"
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
@ -93,7 +93,7 @@ export const FetchTraitForm: React.FC<Props> = props => {
|
||||
<FormControl>
|
||||
<FormLabel>Body</FormLabel>
|
||||
<KeyValueEditor
|
||||
initValue={formik.values.body}
|
||||
value={formik.values.body}
|
||||
onChange={json => {
|
||||
formik.setFieldValue('body', json);
|
||||
formik.submitForm();
|
||||
@ -106,7 +106,7 @@ export const FetchTraitForm: React.FC<Props> = props => {
|
||||
<FormControl>
|
||||
<FormLabel>Headers</FormLabel>
|
||||
<KeyValueEditor
|
||||
initValue={formik.values.headers}
|
||||
value={formik.values.headers}
|
||||
onChange={json => {
|
||||
formik.setFieldValue('headers', json);
|
||||
formik.submitForm();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { FieldProps } from './fields';
|
||||
import {
|
||||
NumberInput,
|
||||
@ -14,6 +14,10 @@ const NumberField: React.FC<Props> = props => {
|
||||
const { formData, onChange } = props;
|
||||
const [value, setValue] = useState(String(formData));
|
||||
|
||||
useEffect(() => {
|
||||
setValue(String(formData));
|
||||
}, [formData]);
|
||||
|
||||
return (
|
||||
<NumberInput
|
||||
value={value}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { FieldProps } from './fields';
|
||||
import { Input, Select } from '@chakra-ui/react';
|
||||
|
||||
@ -8,6 +8,10 @@ const StringField: React.FC<Props> = props => {
|
||||
const { schema, formData, onChange } = props;
|
||||
const [value, setValue] = useState(formData);
|
||||
|
||||
useEffect(() => {
|
||||
setValue(formData);
|
||||
}, [formData]);
|
||||
|
||||
// enum
|
||||
if (Array.isArray(schema.enum)) {
|
||||
return (
|
||||
|
@ -52,7 +52,7 @@ export const ModuleMetaDataForm: React.FC<ModuleMetaDataFormProps> = observer(
|
||||
<FormControl>
|
||||
<FormLabel>Module StateMap</FormLabel>
|
||||
<KeyValueEditor
|
||||
initValue={formik.values.stateMap}
|
||||
value={formik.values.stateMap}
|
||||
onChange={json => {
|
||||
formik.setFieldValue('stateMap', json);
|
||||
formik.submitForm();
|
||||
|
@ -2,18 +2,22 @@ import { CloseIcon } from '@chakra-ui/icons';
|
||||
import { Button, HStack, IconButton, Input, VStack } from '@chakra-ui/react';
|
||||
import produce from 'immer';
|
||||
import { fromPairs, toPairs } from 'lodash-es';
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
type Props = {
|
||||
onChange: (json: Record<string, string>) => void;
|
||||
initValue?: Record<string, string>;
|
||||
value?: Record<string, string>;
|
||||
};
|
||||
|
||||
export const KeyValueEditor: React.FC<Props> = props => {
|
||||
const [rows, setRows] = useState<Array<[string, string]>>(() => {
|
||||
return toPairs(props.initValue);
|
||||
return toPairs(props.value);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setRows(toPairs(props.value));
|
||||
}, [props.value]);
|
||||
|
||||
const emitDataChange = (newRows: Array<[string, string]>) => {
|
||||
const json = fromPairs(newRows);
|
||||
props.onChange(json);
|
||||
|
Loading…
x
Reference in New Issue
Block a user