mirror of
https://gitee.com/ByteDance/flowgram.ai.git
synced 2025-07-07 17:43:29 +08:00
feat(material): auto rename effect (#261)
This commit is contained in:
parent
e9218afcaa
commit
dd727c8d63
@ -1,3 +1,4 @@
|
||||
import { autoRenameRefEffect } from '@flowgram.ai/form-materials';
|
||||
import { FormRenderProps, FormMeta, ValidateTrigger } from '@flowgram.ai/fixed-layout-editor';
|
||||
|
||||
import { FlowNodeJSON } from '../typings';
|
||||
@ -27,4 +28,7 @@ export const defaultFormMeta: FormMeta<FlowNodeJSON['data']> = {
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
effect: {
|
||||
inputsValues: autoRenameRefEffect,
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { FormRenderProps, FormMeta, ValidateTrigger } from '@flowgram.ai/free-layout-editor';
|
||||
import { autoRenameRefEffect } from '@flowgram.ai/form-materials';
|
||||
|
||||
import { FlowNodeJSON } from '../typings';
|
||||
import { FormHeader, FormContent, FormInputs, FormOutputs } from '../form-components';
|
||||
@ -27,4 +28,7 @@ export const defaultFormMeta: FormMeta<FlowNodeJSON> = {
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
effect: {
|
||||
inputsValues: autoRenameRefEffect,
|
||||
},
|
||||
};
|
||||
|
||||
7
common/config/rush/pnpm-lock.yaml
generated
7
common/config/rush/pnpm-lock.yaml
generated
@ -1916,6 +1916,9 @@ importers:
|
||||
commander:
|
||||
specifier: ^11.0.0
|
||||
version: 11.1.0
|
||||
immer:
|
||||
specifier: ~10.1.1
|
||||
version: 10.1.1
|
||||
inquirer:
|
||||
specifier: ^9.2.7
|
||||
version: 9.3.7
|
||||
@ -11746,6 +11749,10 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/immer@10.1.1:
|
||||
resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==}
|
||||
dev: false
|
||||
|
||||
/immutable@5.0.3:
|
||||
resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
|
||||
|
||||
|
||||
@ -40,7 +40,8 @@
|
||||
"nanoid": "^4.0.2",
|
||||
"commander": "^11.0.0",
|
||||
"chalk": "^5.3.0",
|
||||
"inquirer": "^9.2.7"
|
||||
"inquirer": "^9.2.7",
|
||||
"immer": "~10.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@flowgram.ai/eslint-config": "workspace:*",
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import Input, { InputProps } from '@douyinfe/semi-ui/lib/es/input';
|
||||
|
||||
export function BlurInput(props: InputProps) {
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
setValue(props.value as string);
|
||||
}, [props.value]);
|
||||
|
||||
return (
|
||||
<Input
|
||||
{...props}
|
||||
value={value}
|
||||
onChange={(value) => {
|
||||
setValue(value);
|
||||
}}
|
||||
onBlur={(e) => props.onChange?.(value, e)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
|
||||
import { Button, Checkbox, IconButton, Input } from '@douyinfe/semi-ui';
|
||||
import { Button, Checkbox, IconButton } from '@douyinfe/semi-ui';
|
||||
import {
|
||||
IconExpand,
|
||||
IconShrink,
|
||||
@ -31,6 +31,7 @@ import {
|
||||
import { UIName } from './styles';
|
||||
import { UIRow } from './styles';
|
||||
import { usePropertiesEdit } from './hooks';
|
||||
import { BlurInput } from './components/blur-input';
|
||||
|
||||
export function JsonSchemaEditor(props: {
|
||||
value?: IJsonSchema;
|
||||
@ -109,7 +110,7 @@ function PropertyEdit(props: {
|
||||
<UIPropertyMain $expand={expand}>
|
||||
<UIRow>
|
||||
<UIName>
|
||||
<Input
|
||||
<BlurInput
|
||||
placeholder={config?.placeholder ?? 'Input Variable Name'}
|
||||
size="small"
|
||||
value={name}
|
||||
@ -162,7 +163,7 @@ function PropertyEdit(props: {
|
||||
{expand && (
|
||||
<UIExpandDetail>
|
||||
<UILabel>{config?.descTitle ?? 'Description'}</UILabel>
|
||||
<Input
|
||||
<BlurInput
|
||||
size="small"
|
||||
value={description}
|
||||
onChange={(value) => onChange('description', value)}
|
||||
|
||||
@ -100,7 +100,7 @@ export const VariableSelector = ({
|
||||
);
|
||||
}}
|
||||
showClear={false}
|
||||
arrowIcon={value ? null : <IconChevronDownStroked size="small" />}
|
||||
arrowIcon={<IconChevronDownStroked size="small" />}
|
||||
triggerRender={triggerRender}
|
||||
placeholder={config?.placeholder ?? 'Select Variable...'}
|
||||
/>
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "auto-rename-ref",
|
||||
"depMaterials": ["flow-value"],
|
||||
"depPackages": ["lodash"]
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
import { isArray, isObject } from 'lodash';
|
||||
import {
|
||||
DataEvent,
|
||||
Effect,
|
||||
EffectOptions,
|
||||
VariableFieldKeyRenameService,
|
||||
} from '@flowgram.ai/editor';
|
||||
|
||||
import { IFlowRefValue } from '../../typings';
|
||||
|
||||
/**
|
||||
* Auto rename ref when form item's key is renamed
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* formMeta: {
|
||||
* effects: {
|
||||
* "inputsValues": autoRenameRefEffect,
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export const autoRenameRefEffect: EffectOptions[] = [
|
||||
{
|
||||
event: DataEvent.onValueInit,
|
||||
effect: ((params) => {
|
||||
const { context, form, name } = params;
|
||||
|
||||
const renameService = context.node.getService(VariableFieldKeyRenameService);
|
||||
|
||||
const disposable = renameService.onRename(({ before, after }) => {
|
||||
const beforeKeyPath = [
|
||||
...before.parentFields.map((_field) => _field.key).reverse(),
|
||||
before.key,
|
||||
];
|
||||
const afterKeyPath = [
|
||||
...after.parentFields.map((_field) => _field.key).reverse(),
|
||||
after.key,
|
||||
];
|
||||
|
||||
// traverse rename refs inside form item 'name'
|
||||
traverseRef(name, form.getValueIn(name), (_drilldownName, _v) => {
|
||||
if (isRefMatch(_v, beforeKeyPath)) {
|
||||
_v.content = [...afterKeyPath, ...(_v.content || [])?.slice(beforeKeyPath.length)];
|
||||
form.setValueIn(_drilldownName, _v);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}) as Effect,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* If ref value's keyPath is the under as targetKeyPath
|
||||
* @param value
|
||||
* @param targetKeyPath
|
||||
* @returns
|
||||
*/
|
||||
function isRefMatch(value: IFlowRefValue, targetKeyPath: string[]) {
|
||||
return targetKeyPath.every((_key, index) => _key === value.content?.[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* If value is ref
|
||||
* @param value
|
||||
* @returns
|
||||
*/
|
||||
function isRef(value: any): value is IFlowRefValue {
|
||||
return (
|
||||
value?.type === 'ref' && Array.isArray(value?.content) && typeof value?.content[0] === 'string'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse value to find ref
|
||||
* @param value
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
function traverseRef(name: string, value: any, cb: (name: string, _v: IFlowRefValue) => void) {
|
||||
if (isObject(value)) {
|
||||
if (isRef(value)) {
|
||||
cb(name, value);
|
||||
return;
|
||||
}
|
||||
|
||||
Object.entries(value).forEach(([_key, _value]) => {
|
||||
traverseRef(`${name}.${_key}`, _value, cb);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (isArray(value)) {
|
||||
value.forEach((_value, idx) => {
|
||||
traverseRef(`${name}[${idx}]`, _value, cb);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './provide-batch-input';
|
||||
export * from './provide-batch-outputs';
|
||||
export * from './auto-rename-ref';
|
||||
|
||||
@ -13,7 +13,12 @@ import {
|
||||
ObjectType,
|
||||
StringType,
|
||||
} from './type';
|
||||
import { EnumerateExpression, KeyPathExpression, WrapArrayExpression } from './expression';
|
||||
import {
|
||||
EnumerateExpression,
|
||||
// KeyPathExpression,
|
||||
KeyPathExpressionV2,
|
||||
WrapArrayExpression,
|
||||
} from './expression';
|
||||
import { Property, VariableDeclaration, VariableDeclarationList } from './declaration';
|
||||
import { DataNode, MapNode } from './common';
|
||||
import { ASTNode, ASTNodeRegistry } from './ast-node';
|
||||
@ -41,7 +46,9 @@ export class ASTRegisters {
|
||||
this.registerAST(Property);
|
||||
this.registerAST(VariableDeclaration);
|
||||
this.registerAST(VariableDeclarationList);
|
||||
this.registerAST(KeyPathExpression);
|
||||
// this.registerAST(KeyPathExpression);
|
||||
this.registerAST(KeyPathExpressionV2);
|
||||
|
||||
this.registerAST(EnumerateExpression);
|
||||
this.registerAST(WrapArrayExpression);
|
||||
this.registerAST(MapNode);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user