mirror of
https://gitee.com/ByteDance/flowgram.ai.git
synced 2025-07-07 17:43:29 +08:00
feat(demo-fixed-layout): add case-default/break-loop/if nodes,condition -> switch (#336)
* feat(demo-fixed-layout): add case-default/break-loop/if nodes * feat(demo-fixed-layout): condition -> switch * chore: e2e fixed
This commit is contained in:
parent
bb623e9fe6
commit
de863df6fb
1
apps/demo-fixed-layout/src/assets/icon-break.svg
Normal file
1
apps/demo-fixed-layout/src/assets/icon-break.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" focusable="false" aria-hidden="true"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.56066 2.43934C10.1464 3.02513 10.1464 3.97487 9.56066 4.56066L7.12132 7H14.75C18.8353 7 22 10.5796 22 14.5C22 18.4204 18.8353 22 14.75 22H11.5C10.6716 22 10 21.3284 10 20.5C10 19.6716 10.6716 19 11.5 19H14.75C17.016 19 19 16.9308 19 14.5C19 12.0692 17.016 10 14.75 10H7.12132L9.56066 12.4393C10.1464 13.0251 10.1464 13.9749 9.56066 14.5607C8.97487 15.1464 8.02513 15.1464 7.43934 14.5607L2.43934 9.56066C1.85355 8.97487 1.85355 8.02513 2.43934 7.43934L7.43934 2.43934C8.02513 1.85355 8.97487 1.85355 9.56066 2.43934Z" fill="#54A9FF"></path></svg>
|
||||
|
After Width: | Height: | Size: 733 B |
BIN
apps/demo-fixed-layout/src/assets/icon-case.png
Normal file
BIN
apps/demo-fixed-layout/src/assets/icon-case.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
@ -53,7 +53,8 @@ export const BaseNode = ({ node }: { node: FlowNodeEntity }) => {
|
||||
* isBlockIcon: 整个 condition 分支的 头部节点
|
||||
* isBlockOrderIcon: 分支的第一个节点
|
||||
*/
|
||||
...(nodeRender.isBlockOrderIcon || nodeRender.isBlockIcon ? { width: 260 } : {}),
|
||||
...(nodeRender.isBlockOrderIcon || nodeRender.isBlockIcon ? {} : {}),
|
||||
...nodeRender.node.getNodeRegistry().meta.style,
|
||||
outline: form?.state.invalid ? '1px solid red' : 'none',
|
||||
}}
|
||||
>
|
||||
|
||||
@ -20,9 +20,12 @@ export default function BranchAdder(props: PropsType) {
|
||||
function addBranch() {
|
||||
const block = operation.addBlock(
|
||||
node,
|
||||
node.flowNodeType === 'condition'
|
||||
node.flowNodeType === 'switch'
|
||||
? CaseNodeRegistry.onAdd!(ctx, node)
|
||||
: CatchBlockNodeRegistry.onAdd!(ctx, node)
|
||||
: CatchBlockNodeRegistry.onAdd!(ctx, node),
|
||||
{
|
||||
index: 0,
|
||||
}
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
@ -55,7 +55,7 @@ export function NodeList(props: { onSelect: (meta: any) => void; from: FlowNodeE
|
||||
};
|
||||
return (
|
||||
<NodesWrap style={{ width: 80 * 2 + 20 }}>
|
||||
{FlowNodeRegistries.map((registry) => (
|
||||
{FlowNodeRegistries.filter((registry) => !registry.meta?.addDisable).map((registry) => (
|
||||
<Node
|
||||
key={registry.type}
|
||||
disabled={!(registry.canAdd?.(context, props.from) ?? true)}
|
||||
|
||||
@ -63,8 +63,8 @@ export const SidebarRenderer = () => {
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
const { disableSideBar = false } = node.getNodeMeta<FlowNodeMeta>();
|
||||
return !disableSideBar;
|
||||
const { sidebarDisable = false } = node.getNodeMeta<FlowNodeMeta>();
|
||||
return !sidebarDisable;
|
||||
}, [node]);
|
||||
|
||||
if (playground.config.readonly) {
|
||||
@ -73,7 +73,8 @@ export const SidebarRenderer = () => {
|
||||
/**
|
||||
* Add "key" to rerender the sidebar when the node changes
|
||||
*/
|
||||
const content = node ? (
|
||||
const content =
|
||||
node && visible ? (
|
||||
<PlaygroundEntityContext.Provider key={node.id} value={node}>
|
||||
<SidebarNodeRenderer node={node} />
|
||||
</PlaygroundEntityContext.Provider>
|
||||
|
||||
@ -87,6 +87,40 @@ export const initialData: FlowDocumentJSON = {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'if_0',
|
||||
type: 'if',
|
||||
data: {
|
||||
title: 'If',
|
||||
inputsValues: {
|
||||
condition: { type: 'constant', content: true },
|
||||
},
|
||||
inputs: {
|
||||
type: 'object',
|
||||
required: ['condition'],
|
||||
properties: {
|
||||
condition: {
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
id: 'if_true',
|
||||
type: 'ifBlock',
|
||||
data: {
|
||||
title: 'true',
|
||||
},
|
||||
blocks: [],
|
||||
},
|
||||
{
|
||||
id: 'if_false',
|
||||
type: 'ifBlock',
|
||||
data: {
|
||||
title: 'false',
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
id: 'loop_0',
|
||||
type: 'loop',
|
||||
@ -99,17 +133,17 @@ export const initialData: FlowDocumentJSON = {
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
id: 'condition_0',
|
||||
type: 'condition',
|
||||
id: 'switch_0',
|
||||
type: 'switch',
|
||||
data: {
|
||||
title: 'Condition',
|
||||
title: 'Switch',
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
id: 'case_0',
|
||||
type: 'case',
|
||||
data: {
|
||||
title: 'If_0',
|
||||
title: 'Case_0',
|
||||
inputsValues: {
|
||||
condition: { type: 'constant', content: true },
|
||||
},
|
||||
@ -129,7 +163,7 @@ export const initialData: FlowDocumentJSON = {
|
||||
id: 'case_1',
|
||||
type: 'case',
|
||||
data: {
|
||||
title: 'If_1',
|
||||
title: 'Case_1',
|
||||
inputsValues: {
|
||||
condition: { type: 'constant', content: true },
|
||||
},
|
||||
@ -143,8 +177,26 @@ export const initialData: FlowDocumentJSON = {
|
||||
},
|
||||
},
|
||||
},
|
||||
meta: {},
|
||||
blocks: [],
|
||||
},
|
||||
{
|
||||
id: 'case_default_1',
|
||||
type: 'caseDefault',
|
||||
data: {
|
||||
title: 'Default',
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
id: 'break_0',
|
||||
type: 'breakLoop',
|
||||
data: {
|
||||
title: 'BreakLoop',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
13
apps/demo-fixed-layout/src/nodes/break-loop/form-meta.tsx
Normal file
13
apps/demo-fixed-layout/src/nodes/break-loop/form-meta.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import { FormMeta } from '@flowgram.ai/fixed-layout-editor';
|
||||
|
||||
import { FormHeader } from '../../form-components';
|
||||
|
||||
export const renderForm = () => (
|
||||
<>
|
||||
<FormHeader />
|
||||
</>
|
||||
);
|
||||
|
||||
export const formMeta: FormMeta = {
|
||||
render: renderForm,
|
||||
};
|
||||
42
apps/demo-fixed-layout/src/nodes/break-loop/index.ts
Normal file
42
apps/demo-fixed-layout/src/nodes/break-loop/index.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
import { FlowNodeRegistry } from '../../typings';
|
||||
import iconBreak from '../../assets/icon-break.svg';
|
||||
import { formMeta } from './form-meta';
|
||||
|
||||
/**
|
||||
* Break 节点用于在 loop 中根据条件终止并跳出
|
||||
*/
|
||||
export const BreakLoopNodeRegistry: FlowNodeRegistry = {
|
||||
type: 'breakLoop',
|
||||
extend: 'end',
|
||||
info: {
|
||||
icon: iconBreak,
|
||||
description: 'Break in current Loop.',
|
||||
},
|
||||
meta: {
|
||||
style: {
|
||||
width: 240,
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Render node via formMeta
|
||||
*/
|
||||
formMeta,
|
||||
canAdd(ctx, from) {
|
||||
while (from.parent) {
|
||||
if (from.parent.flowNodeType === 'loop') return true;
|
||||
from = from.parent;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
onAdd(ctx, from) {
|
||||
return {
|
||||
id: `break_${nanoid()}`,
|
||||
type: 'breakLoop',
|
||||
data: {
|
||||
title: 'BreakLoop',
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
32
apps/demo-fixed-layout/src/nodes/case-default/form-meta.tsx
Normal file
32
apps/demo-fixed-layout/src/nodes/case-default/form-meta.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { FormRenderProps, FormMeta, ValidateTrigger } from '@flowgram.ai/fixed-layout-editor';
|
||||
|
||||
import { FlowNodeJSON } from '../../typings';
|
||||
import { FormHeader, FormContent, FormInputs, FormOutputs } from '../../form-components';
|
||||
|
||||
export const renderForm = ({ form }: FormRenderProps<FlowNodeJSON['data']>) => (
|
||||
<>
|
||||
<FormHeader />
|
||||
<FormContent>
|
||||
<FormInputs />
|
||||
<FormOutputs />
|
||||
</FormContent>
|
||||
</>
|
||||
);
|
||||
|
||||
export const formMeta: FormMeta<FlowNodeJSON['data']> = {
|
||||
render: renderForm,
|
||||
validateTrigger: ValidateTrigger.onChange,
|
||||
validate: {
|
||||
'inputsValues.*': ({ value, context, formValues, name }) => {
|
||||
const valuePropetyKey = name.replace(/^inputsValues\./, '');
|
||||
const required = formValues.inputs?.required || [];
|
||||
if (
|
||||
required.includes(valuePropetyKey) &&
|
||||
(value === '' || value === undefined || value?.content === '')
|
||||
) {
|
||||
return `${valuePropetyKey} is required`;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
};
|
||||
31
apps/demo-fixed-layout/src/nodes/case-default/index.ts
Normal file
31
apps/demo-fixed-layout/src/nodes/case-default/index.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { FlowNodeRegistry } from '../../typings';
|
||||
import iconCase from '../../assets/icon-case.png';
|
||||
import { formMeta } from './form-meta';
|
||||
|
||||
export const CaseDefaultNodeRegistry: FlowNodeRegistry = {
|
||||
type: 'caseDefault',
|
||||
/**
|
||||
* 分支节点需要继承自 block
|
||||
* Branch nodes need to inherit from 'block'
|
||||
*/
|
||||
extend: 'case',
|
||||
meta: {
|
||||
copyDisable: true,
|
||||
addDisable: true,
|
||||
/**
|
||||
* caseDefault 永远在最后一个分支,所以不允许拖拽排序
|
||||
* "caseDefault" is always in the last branch, so dragging and sorting is not allowed.
|
||||
*/
|
||||
draggable: false,
|
||||
deleteDisable: true,
|
||||
style: {
|
||||
width: 240,
|
||||
},
|
||||
},
|
||||
info: {
|
||||
icon: iconCase,
|
||||
description: 'Switch default branch',
|
||||
},
|
||||
canDelete: (ctx, node) => false,
|
||||
formMeta,
|
||||
};
|
||||
@ -1,7 +1,7 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
import { FlowNodeRegistry } from '../../typings';
|
||||
import iconIf from '../../assets/icon-if.png';
|
||||
import iconCase from '../../assets/icon-case.png';
|
||||
import { formMeta } from './form-meta';
|
||||
|
||||
let id = 2;
|
||||
@ -14,19 +14,19 @@ export const CaseNodeRegistry: FlowNodeRegistry = {
|
||||
extend: 'block',
|
||||
meta: {
|
||||
copyDisable: true,
|
||||
addDisable: true,
|
||||
},
|
||||
info: {
|
||||
icon: iconIf,
|
||||
icon: iconCase,
|
||||
description: 'Execute the branch when the condition is met.',
|
||||
},
|
||||
canAdd: () => false,
|
||||
canDelete: (ctx, node) => node.parent!.blocks.length >= 3,
|
||||
onAdd(ctx, from) {
|
||||
return {
|
||||
id: `if_${nanoid(5)}`,
|
||||
id: `Case_${nanoid(5)}`,
|
||||
type: 'case',
|
||||
data: {
|
||||
title: `If_${id++}`,
|
||||
title: `Case_${id++}`,
|
||||
inputs: {
|
||||
type: 'object',
|
||||
required: ['condition'],
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
import { FlowNodeRegistry } from '../../typings';
|
||||
import iconIf from '../../assets/icon-if.png';
|
||||
import iconCase from '../../assets/icon-case.png';
|
||||
import { formMeta } from './form-meta';
|
||||
|
||||
let id = 3;
|
||||
@ -9,9 +9,10 @@ export const CatchBlockNodeRegistry: FlowNodeRegistry = {
|
||||
type: 'catchBlock',
|
||||
meta: {
|
||||
copyDisable: true,
|
||||
addDisable: true,
|
||||
},
|
||||
info: {
|
||||
icon: iconIf,
|
||||
icon: iconCase,
|
||||
description: 'Execute the catch branch when the condition is met.',
|
||||
},
|
||||
canAdd: () => false,
|
||||
|
||||
28
apps/demo-fixed-layout/src/nodes/if-block/form-meta.tsx
Normal file
28
apps/demo-fixed-layout/src/nodes/if-block/form-meta.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import { FormRenderProps, FormMeta, Field } from '@flowgram.ai/fixed-layout-editor';
|
||||
|
||||
import { FlowNodeJSON } from '../../typings';
|
||||
import { useNodeRenderContext } from '../../hooks';
|
||||
|
||||
export const renderForm = (props: FormRenderProps<FlowNodeJSON['data']>) => {
|
||||
const { node } = useNodeRenderContext();
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: node.index === 0 ? 'green' : 'red',
|
||||
color: 'white',
|
||||
display: 'flex',
|
||||
pointerEvents: 'none',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Field name="title">{({ field }) => <>{field.value}</>}</Field>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const formMeta: FormMeta<FlowNodeJSON['data']> = {
|
||||
render: renderForm,
|
||||
};
|
||||
30
apps/demo-fixed-layout/src/nodes/if-block/index.ts
Normal file
30
apps/demo-fixed-layout/src/nodes/if-block/index.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { FlowNodeRegistry } from '../../typings';
|
||||
import iconIf from '../../assets/icon-if.png';
|
||||
import { formMeta } from './form-meta';
|
||||
|
||||
export const IFBlockNodeRegistry: FlowNodeRegistry = {
|
||||
type: 'ifBlock',
|
||||
/**
|
||||
* 分支节点需要继承自 block
|
||||
* Branch nodes need to inherit from 'block'
|
||||
*/
|
||||
extend: 'block',
|
||||
meta: {
|
||||
copyDisable: true,
|
||||
addDisable: true,
|
||||
sidebarDisable: true,
|
||||
defaultExpanded: false,
|
||||
style: {
|
||||
width: 66,
|
||||
height: 20,
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
info: {
|
||||
icon: iconIf,
|
||||
description: '',
|
||||
},
|
||||
canAdd: () => false,
|
||||
canDelete: (ctx, node) => false,
|
||||
formMeta,
|
||||
};
|
||||
57
apps/demo-fixed-layout/src/nodes/if/index.ts
Normal file
57
apps/demo-fixed-layout/src/nodes/if/index.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
import { FlowNodeSplitType } from '@flowgram.ai/fixed-layout-editor';
|
||||
|
||||
import { defaultFormMeta } from '../default-form-meta';
|
||||
import { FlowNodeRegistry } from '../../typings';
|
||||
import iconIf from '../../assets/icon-if.png';
|
||||
|
||||
export const IFNodeRegistry: FlowNodeRegistry = {
|
||||
extend: FlowNodeSplitType.STATIC_SPLIT,
|
||||
type: 'if',
|
||||
info: {
|
||||
icon: iconIf,
|
||||
description: 'Only the corresponding branch will be executed if the set conditions are met.',
|
||||
},
|
||||
meta: {
|
||||
expandable: false, // disable expanded
|
||||
},
|
||||
formMeta: defaultFormMeta,
|
||||
onAdd() {
|
||||
return {
|
||||
id: `if_${nanoid(5)}`,
|
||||
type: 'if',
|
||||
data: {
|
||||
title: 'If',
|
||||
inputsValues: {
|
||||
condition: { type: 'constant', content: true },
|
||||
},
|
||||
inputs: {
|
||||
type: 'object',
|
||||
required: ['condition'],
|
||||
properties: {
|
||||
condition: {
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
id: nanoid(5),
|
||||
type: 'ifBlock',
|
||||
data: {
|
||||
title: 'true',
|
||||
},
|
||||
blocks: [],
|
||||
},
|
||||
{
|
||||
id: nanoid(5),
|
||||
type: 'ifBlock',
|
||||
data: {
|
||||
title: 'false',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
@ -1,20 +1,28 @@
|
||||
import { type FlowNodeRegistry } from '../typings';
|
||||
import { TryCatchNodeRegistry } from './trycatch';
|
||||
import { SwitchNodeRegistry } from './switch';
|
||||
import { StartNodeRegistry } from './start';
|
||||
import { LoopNodeRegistry } from './loop';
|
||||
import { LLMNodeRegistry } from './llm';
|
||||
import { IFBlockNodeRegistry } from './if-block';
|
||||
import { IFNodeRegistry } from './if';
|
||||
import { EndNodeRegistry } from './end';
|
||||
import { ConditionNodeRegistry } from './condition';
|
||||
import { CatchBlockNodeRegistry } from './catch-block';
|
||||
import { CaseDefaultNodeRegistry } from './case-default';
|
||||
import { CaseNodeRegistry } from './case';
|
||||
import { BreakLoopNodeRegistry } from './break-loop';
|
||||
|
||||
export const FlowNodeRegistries: FlowNodeRegistry[] = [
|
||||
StartNodeRegistry,
|
||||
EndNodeRegistry,
|
||||
ConditionNodeRegistry,
|
||||
SwitchNodeRegistry,
|
||||
LLMNodeRegistry,
|
||||
LoopNodeRegistry,
|
||||
CaseNodeRegistry,
|
||||
TryCatchNodeRegistry,
|
||||
CatchBlockNodeRegistry,
|
||||
IFNodeRegistry,
|
||||
IFBlockNodeRegistry,
|
||||
BreakLoopNodeRegistry,
|
||||
CaseDefaultNodeRegistry,
|
||||
];
|
||||
|
||||
@ -10,6 +10,7 @@ export const StartNodeRegistry: FlowNodeRegistry = {
|
||||
selectable: false, // Start node cannot select
|
||||
copyDisable: true, // Start node cannot copy
|
||||
expandable: false, // disable expanded
|
||||
addDisable: true, // Start Node cannot be added
|
||||
},
|
||||
info: {
|
||||
icon: iconStart,
|
||||
@ -20,10 +21,4 @@ export const StartNodeRegistry: FlowNodeRegistry = {
|
||||
* Render node via formMeta
|
||||
*/
|
||||
formMeta,
|
||||
/**
|
||||
* Start Node cannot be added
|
||||
*/
|
||||
canAdd() {
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
@ -5,9 +5,9 @@ import { defaultFormMeta } from '../default-form-meta';
|
||||
import { FlowNodeRegistry } from '../../typings';
|
||||
import iconCondition from '../../assets/icon-condition.svg';
|
||||
|
||||
export const ConditionNodeRegistry: FlowNodeRegistry = {
|
||||
export const SwitchNodeRegistry: FlowNodeRegistry = {
|
||||
extend: FlowNodeSplitType.DYNAMIC_SPLIT,
|
||||
type: 'condition',
|
||||
type: 'switch',
|
||||
info: {
|
||||
icon: iconCondition,
|
||||
description:
|
||||
@ -19,17 +19,17 @@ export const ConditionNodeRegistry: FlowNodeRegistry = {
|
||||
formMeta: defaultFormMeta,
|
||||
onAdd() {
|
||||
return {
|
||||
id: `condition_${nanoid(5)}`,
|
||||
type: 'condition',
|
||||
id: `switch_${nanoid(5)}`,
|
||||
type: 'switch',
|
||||
data: {
|
||||
title: 'Condition',
|
||||
title: 'Switch',
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
id: nanoid(5),
|
||||
type: 'case',
|
||||
data: {
|
||||
title: 'If_0',
|
||||
title: 'Case_0',
|
||||
inputsValues: {
|
||||
condition: { type: 'constant', content: '' },
|
||||
},
|
||||
@ -49,7 +49,7 @@ export const ConditionNodeRegistry: FlowNodeRegistry = {
|
||||
id: nanoid(5),
|
||||
type: 'case',
|
||||
data: {
|
||||
title: 'If_1',
|
||||
title: 'Case_1',
|
||||
inputsValues: {
|
||||
condition: { type: 'constant', content: '' },
|
||||
},
|
||||
@ -64,6 +64,14 @@ export const ConditionNodeRegistry: FlowNodeRegistry = {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: nanoid(5),
|
||||
type: 'caseDefault',
|
||||
data: {
|
||||
title: 'Default',
|
||||
},
|
||||
blocks: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
@ -43,14 +43,15 @@ export interface FlowNodeJSON extends FlowNodeJSONDefault {
|
||||
* 你可以自定义节点的meta
|
||||
*/
|
||||
export interface FlowNodeMeta extends FlowNodeMetaDefault {
|
||||
disableSideBar?: boolean;
|
||||
sidebarDisable?: boolean;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
/**
|
||||
* You can customize your own node registry
|
||||
* 你可以自定义节点的注册器
|
||||
*/
|
||||
export interface FlowNodeRegistry extends FlowNodeRegistryDefault {
|
||||
meta: FlowNodeMeta;
|
||||
meta?: FlowNodeMeta;
|
||||
info: {
|
||||
icon: string;
|
||||
description: string;
|
||||
|
||||
@ -63,8 +63,8 @@ export const SidebarRenderer = () => {
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
const { disableSideBar = false } = node.getNodeMeta<FlowNodeMeta>();
|
||||
return !disableSideBar;
|
||||
const { sidebarDisable = false } = node.getNodeMeta<FlowNodeMeta>();
|
||||
return !sidebarDisable;
|
||||
}, [node]);
|
||||
|
||||
if (playground.config.readonly) {
|
||||
@ -73,7 +73,8 @@ export const SidebarRenderer = () => {
|
||||
/**
|
||||
* Add "key" to rerender the sidebar when the node changes
|
||||
*/
|
||||
const content = node ? (
|
||||
const content =
|
||||
node && visible ? (
|
||||
<PlaygroundEntityContext.Provider key={node.id} value={node}>
|
||||
<SidebarNodeRenderer node={node} />
|
||||
</PlaygroundEntityContext.Provider>
|
||||
|
||||
@ -6,7 +6,7 @@ import { createMinimapPlugin } from '@flowgram.ai/minimap-plugin';
|
||||
import { createFreeSnapPlugin } from '@flowgram.ai/free-snap-plugin';
|
||||
import { createFreeNodePanelPlugin } from '@flowgram.ai/free-node-panel-plugin';
|
||||
import { createFreeLinesPlugin } from '@flowgram.ai/free-lines-plugin';
|
||||
import { FreeLayoutProps, WorkflowNodeLinesData } from '@flowgram.ai/free-layout-editor';
|
||||
import { FreeLayoutProps, WorkflowNodeLinesData, Form } from '@flowgram.ai/free-layout-editor';
|
||||
import { createFreeGroupPlugin } from '@flowgram.ai/free-group-plugin';
|
||||
import { createContainerNodePlugin } from '@flowgram.ai/free-container-plugin';
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import { FlowNodeRegistry } from '../../typings';
|
||||
export const CommentNodeRegistry: FlowNodeRegistry = {
|
||||
type: WorkflowNodeType.Comment,
|
||||
meta: {
|
||||
disableSideBar: true,
|
||||
sidebarDisable: true,
|
||||
defaultPorts: [],
|
||||
renderKey: WorkflowNodeType.Comment,
|
||||
size: {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { FormRenderProps, FlowNodeJSON, Field } from '@flowgram.ai/free-layout-editor';
|
||||
import { SubCanvasRender } from '@flowgram.ai/free-container-plugin';
|
||||
import { BatchVariableSelector, IFlowRefValue } from '@flowgram.ai/form-materials';
|
||||
|
||||
import { useIsSidebar, useNodeRenderContext } from '../../hooks';
|
||||
@ -48,7 +47,6 @@ export const LoopFormRender = ({ form }: FormRenderProps<LoopNodeJSON>) => {
|
||||
<FormHeader />
|
||||
<FormContent>
|
||||
{batchFor}
|
||||
<SubCanvasRender />
|
||||
<FormOutputs />
|
||||
</FormContent>
|
||||
</>
|
||||
|
||||
@ -44,7 +44,7 @@ export interface FlowNodeJSON extends FlowNodeJSONDefault {
|
||||
* 你可以自定义节点的meta
|
||||
*/
|
||||
export interface FlowNodeMeta extends WorkflowNodeMeta {
|
||||
disableSideBar?: boolean;
|
||||
sidebarDisable?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -25,7 +25,7 @@ class FixedLayoutModel {
|
||||
}
|
||||
|
||||
public async isConditionNodeExist() {
|
||||
return await this.page.locator('[data-node-id="$blockIcon$condition_0"]').count();
|
||||
return await this.page.locator('[data-node-id="$blockIcon$switch_0"]').count();
|
||||
}
|
||||
|
||||
public async insert(searchText: string, { from, to }: InsertEdgeOptions) {
|
||||
|
||||
@ -21,11 +21,11 @@ test.describe('node operations', () => {
|
||||
|
||||
test('add node', async () => {
|
||||
const prevCount = await editorPage.getNodeCount();
|
||||
await editorPage.insert('condition', {
|
||||
await editorPage.insert('switch', {
|
||||
from: 'llm_0',
|
||||
to: 'loop_0',
|
||||
to: 'if_0',
|
||||
});
|
||||
const defaultNodeCount = await editorPage.getNodeCount();
|
||||
expect(defaultNodeCount).toEqual(prevCount + 3);
|
||||
expect(defaultNodeCount).toEqual(prevCount + 4);
|
||||
});
|
||||
});
|
||||
|
||||
@ -174,7 +174,7 @@ export class FlowNodeEntity extends Entity<FlowNodeEntityConfig> {
|
||||
return this.document.renderTree.getParent(this);
|
||||
}
|
||||
|
||||
getNodeRegistry<M extends FlowNodeRegistry = FlowNodeRegistry>(): M {
|
||||
getNodeRegistry<M extends FlowNodeRegistry = FlowNodeRegistry & { meta: FlowNodeMeta }>(): M {
|
||||
if (this._registerCache) return this._registerCache as M;
|
||||
this._registerCache = this.document.getNodeRegistry(this.flowNodeType, this.originParent);
|
||||
return this._registerCache as M;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user