Skip to content

Commit f0d9c50

Browse files
authored
feat(demo-fixed-layout): add case node for condition branches (bytedance#302)
* refactor: FlowNodeRegistry.addChild depreacted * feat: FlowDocument.toString(true) support showType * feat(demo-fixed-layout): add case node and catch-block node
1 parent b477181 commit f0d9c50

File tree

18 files changed

+144
-34
lines changed

18 files changed

+144
-34
lines changed

apps/demo-fixed-layout-simple/src/components/flow-select.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function FlowSelect() {
1515
clientContext.history.stop(); // Stop redo/undo
1616
clientContext.history.clear(); // Clear redo/undo
1717
clientContext.document.fromJSON(targetDemoJSON); // Reload Data
18-
console.log(clientContext.document.toString()); // Print the document tree
18+
console.log(clientContext.document.toString(true)); // Print the document tree
1919
clientContext.history.start(); // Restart redo/undo
2020
clientContext.document.setLayout(
2121
targetDemoJSON.defaultLayout || FlowLayoutDefault.VERTICAL_FIXED_LAYOUT

apps/demo-fixed-layout/src/components/branch-adder/index.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { type FlowNodeEntity, useClientContext } from '@flowgram.ai/fixed-layout-editor';
22
import { IconPlus } from '@douyinfe/semi-icons';
33

4-
import { BlockNodeRegistry } from '../../nodes/block';
4+
import { CatchBlockNodeRegistry } from '../../nodes/catch-block';
5+
import { CaseNodeRegistry } from '../../nodes/case';
56
import { Container } from './styles';
67

78
interface PropsType {
@@ -17,7 +18,12 @@ export default function BranchAdder(props: PropsType) {
1718
const { isVertical } = node;
1819

1920
function addBranch() {
20-
const block = operation.addBlock(node, BlockNodeRegistry.onAdd!(ctx, node));
21+
const block = operation.addBlock(
22+
node,
23+
node.flowNodeType === 'condition'
24+
? CaseNodeRegistry.onAdd!(ctx, node)
25+
: CatchBlockNodeRegistry.onAdd!(ctx, node)
26+
);
2127

2228
setTimeout(() => {
2329
playground.scrollToView({

apps/demo-fixed-layout/src/hooks/use-editor-props.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useMemo } from 'react';
22

3+
import { debounce } from 'lodash-es';
34
import { createMinimapPlugin } from '@flowgram.ai/minimap-plugin';
45
import { createGroupPlugin } from '@flowgram.ai/group-plugin';
56
import { defaultFixedSemiMaterials } from '@flowgram.ai/fixed-semi-materials';
@@ -139,10 +140,10 @@ export function useEditorProps(
139140
history: {
140141
enable: true,
141142
enableChangeNode: true, // Listen Node engine data change
142-
onApply(ctx, opt) {
143+
onApply: debounce((ctx, opt) => {
143144
// Listen change to trigger auto save
144-
// console.log('auto save: ', ctx.document.toJSON(), opt);
145-
},
145+
console.log('auto save: ', ctx.document.toJSON());
146+
}, 100),
146147
},
147148
/**
148149
* Node engine enable, you can configure formMeta in the FlowNodeRegistry
@@ -201,7 +202,7 @@ export function useEditorProps(
201202
setTimeout(() => {
202203
ctx.playground.config.fitView(ctx.document.root.bounds.pad(30));
203204
}, 10);
204-
console.log(ctx.document.toString()); // Get the document tree
205+
console.log(ctx.document.toString(true)); // Get the document tree
205206
},
206207
/**
207208
* Playground dispose

apps/demo-fixed-layout/src/initial-data.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ export const initialData: FlowDocumentJSON = {
106106
},
107107
blocks: [
108108
{
109-
id: 'branch_0',
110-
type: 'block',
109+
id: 'case_0',
110+
type: 'case',
111111
data: {
112112
title: 'If_0',
113113
inputsValues: {
@@ -126,8 +126,8 @@ export const initialData: FlowDocumentJSON = {
126126
blocks: [],
127127
},
128128
{
129-
id: 'branch_1',
130-
type: 'block',
129+
id: 'case_1',
130+
type: 'case',
131131
data: {
132132
title: 'If_1',
133133
inputsValues: {

apps/demo-fixed-layout/src/nodes/block/index.ts renamed to apps/demo-fixed-layout/src/nodes/case/index.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ import iconIf from '../../assets/icon-if.png';
55
import { formMeta } from './form-meta';
66

77
let id = 2;
8-
export const BlockNodeRegistry: FlowNodeRegistry = {
9-
type: 'block',
8+
export const CaseNodeRegistry: FlowNodeRegistry = {
9+
type: 'case',
10+
/**
11+
* 分支节点需要继承自 block
12+
* Branch nodes need to inherit from 'block'
13+
*/
14+
extend: 'block',
1015
meta: {
1116
copyDisable: true,
1217
},
@@ -15,19 +20,13 @@ export const BlockNodeRegistry: FlowNodeRegistry = {
1520
description: 'Execute the branch when the condition is met.',
1621
},
1722
canAdd: () => false,
18-
canDelete: (ctx, node) => {
19-
if (node.originParent!.flowNodeType === 'tryCatch') {
20-
return node.parent!.blocks.length >= 2;
21-
}
22-
return node.parent!.blocks.length >= 3;
23-
},
23+
canDelete: (ctx, node) => node.parent!.blocks.length >= 3,
2424
onAdd(ctx, from) {
25-
const isTryCatch = from.flowNodeType === 'tryCatch';
2625
return {
2726
id: `if_${nanoid(5)}`,
28-
type: isTryCatch ? 'catchBlock' : 'block',
27+
type: 'case',
2928
data: {
30-
title: isTryCatch ? `Catch Block ${id++}` : `If_${id++}`,
29+
title: `If_${id++}`,
3130
inputs: {
3231
type: 'object',
3332
required: ['condition'],
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { FormRenderProps, FormMeta, ValidateTrigger } from '@flowgram.ai/fixed-layout-editor';
2+
3+
import { FlowNodeJSON } from '../../typings';
4+
import { FormHeader, FormContent, FormInputs, FormOutputs } from '../../form-components';
5+
6+
export const renderForm = ({ form }: FormRenderProps<FlowNodeJSON['data']>) => (
7+
<>
8+
<FormHeader />
9+
<FormContent>
10+
<FormInputs />
11+
<FormOutputs />
12+
</FormContent>
13+
</>
14+
);
15+
16+
export const formMeta: FormMeta<FlowNodeJSON['data']> = {
17+
render: renderForm,
18+
validateTrigger: ValidateTrigger.onChange,
19+
validate: {
20+
'inputsValues.*': ({ value, context, formValues, name }) => {
21+
const valuePropetyKey = name.replace(/^inputsValues\./, '');
22+
const required = formValues.inputs?.required || [];
23+
if (
24+
required.includes(valuePropetyKey) &&
25+
(value === '' || value === undefined || value?.content === '')
26+
) {
27+
return `${valuePropetyKey} is required`;
28+
}
29+
return undefined;
30+
},
31+
},
32+
};
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { nanoid } from 'nanoid';
2+
3+
import { FlowNodeRegistry } from '../../typings';
4+
import iconIf from '../../assets/icon-if.png';
5+
import { formMeta } from './form-meta';
6+
7+
let id = 3;
8+
export const CatchBlockNodeRegistry: FlowNodeRegistry = {
9+
type: 'catchBlock',
10+
meta: {
11+
copyDisable: true,
12+
},
13+
info: {
14+
icon: iconIf,
15+
description: 'Execute the catch branch when the condition is met.',
16+
},
17+
canAdd: () => false,
18+
canDelete: (ctx, node) => node.parent!.blocks.length >= 2,
19+
onAdd(ctx, from) {
20+
return {
21+
id: `Catch_${nanoid(5)}`,
22+
type: 'catchblock',
23+
data: {
24+
title: `Catch Block ${id++}`,
25+
inputs: {
26+
type: 'object',
27+
required: ['condition'],
28+
inputsValues: {
29+
condition: '',
30+
},
31+
properties: {
32+
condition: {
33+
type: 'string',
34+
},
35+
},
36+
},
37+
},
38+
};
39+
},
40+
formMeta,
41+
};

apps/demo-fixed-layout/src/nodes/condition/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const ConditionNodeRegistry: FlowNodeRegistry = {
2727
blocks: [
2828
{
2929
id: nanoid(5),
30-
type: 'block',
30+
type: 'case',
3131
data: {
3232
title: 'If_0',
3333
inputsValues: {
@@ -47,7 +47,7 @@ export const ConditionNodeRegistry: FlowNodeRegistry = {
4747
},
4848
{
4949
id: nanoid(5),
50-
type: 'block',
50+
type: 'case',
5151
data: {
5252
title: 'If_1',
5353
inputsValues: {

apps/demo-fixed-layout/src/nodes/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import { LoopNodeRegistry } from './loop';
55
import { LLMNodeRegistry } from './llm';
66
import { EndNodeRegistry } from './end';
77
import { ConditionNodeRegistry } from './condition';
8-
import { BlockNodeRegistry } from './block';
8+
import { CatchBlockNodeRegistry } from './catch-block';
9+
import { CaseNodeRegistry } from './case';
910

1011
export const FlowNodeRegistries: FlowNodeRegistry[] = [
1112
StartNodeRegistry,
1213
EndNodeRegistry,
1314
ConditionNodeRegistry,
1415
LLMNodeRegistry,
1516
LoopNodeRegistry,
16-
BlockNodeRegistry,
17+
CaseNodeRegistry,
1718
TryCatchNodeRegistry,
19+
CatchBlockNodeRegistry,
1820
];

0 commit comments

Comments
 (0)