mirror of
https://gitee.com/ByteDance/flowgram.ai.git
synced 2025-07-07 17:43:29 +08:00
chore(demo): remove sync-variable-plugin in demo-nextjs-antd (#442)
This commit is contained in:
parent
d8e2b4a838
commit
522bc0770d
@ -18,7 +18,7 @@ import { createContainerNodePlugin } from '@flowgram.ai/free-container-plugin';
|
|||||||
|
|
||||||
import { onDragLineEnd } from '@editor/utils';
|
import { onDragLineEnd } from '@editor/utils';
|
||||||
import { FlowNodeRegistry } from '@editor/typings';
|
import { FlowNodeRegistry } from '@editor/typings';
|
||||||
import { createContextMenuPlugin, createSyncVariablePlugin } from '@editor/plugins';
|
import { createContextMenuPlugin } from '@editor/plugins';
|
||||||
import { defaultFormMeta } from '@editor/nodes/default-form-meta';
|
import { defaultFormMeta } from '@editor/nodes/default-form-meta';
|
||||||
import { WorkflowNodeType } from '@editor/nodes';
|
import { WorkflowNodeType } from '@editor/nodes';
|
||||||
import { BaseNode } from '@editor/components/base-node';
|
import { BaseNode } from '@editor/components/base-node';
|
||||||
@ -156,11 +156,6 @@ export const useEditorProps = (initialData: WorkflowJSON, nodeRegistries: FlowNo
|
|||||||
},
|
},
|
||||||
inactiveDebounceTime: 1,
|
inactiveDebounceTime: 1,
|
||||||
}),
|
}),
|
||||||
/**
|
|
||||||
* Variable plugin
|
|
||||||
* 变量插件
|
|
||||||
*/
|
|
||||||
createSyncVariablePlugin({}),
|
|
||||||
/**
|
/**
|
||||||
* Snap plugin
|
* Snap plugin
|
||||||
* 自动对齐及辅助线插件
|
* 自动对齐及辅助线插件
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { FormMeta, FormRenderProps, ValidateTrigger } from '@flowgram.ai/free-layout-editor';
|
import { FormMeta, FormRenderProps, ValidateTrigger } from '@flowgram.ai/free-layout-editor';
|
||||||
import { autoRenameRefEffect } from '@flowgram.ai/form-antd-materials';
|
import { autoRenameRefEffect, syncVariableTitle, provideJsonSchemaOutputs } from '@flowgram.ai/form-antd-materials';
|
||||||
|
|
||||||
import { FormContent, FormHeader, FormInputs, FormOutputs } from '@editor/form-components';
|
import { FormContent, FormHeader, FormInputs, FormOutputs } from '@editor/form-components';
|
||||||
import { FlowNodeJSON } from '../typings';
|
import { FlowNodeJSON } from '../typings';
|
||||||
@ -37,6 +37,8 @@ export const defaultFormMeta: FormMeta<FlowNodeJSON> = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
effect: {
|
effect: {
|
||||||
|
title: syncVariableTitle,
|
||||||
|
outputs: provideJsonSchemaOutputs,
|
||||||
inputsValues: autoRenameRefEffect,
|
inputsValues: autoRenameRefEffect,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
FormRenderProps,
|
FormRenderProps,
|
||||||
ValidateTrigger,
|
ValidateTrigger,
|
||||||
} from '@flowgram.ai/free-layout-editor';
|
} from '@flowgram.ai/free-layout-editor';
|
||||||
import { JsonSchemaEditor } from '@flowgram.ai/form-antd-materials';
|
import { JsonSchemaEditor, syncVariableTitle, provideJsonSchemaOutputs } from '@flowgram.ai/form-antd-materials';
|
||||||
|
|
||||||
import { FlowNodeJSON, JsonSchema } from '@editor/typings';
|
import { FlowNodeJSON, JsonSchema } from '@editor/typings';
|
||||||
import { useIsSidebar } from '@editor/hooks';
|
import { useIsSidebar } from '@editor/hooks';
|
||||||
@ -57,4 +57,8 @@ export const formMeta: FormMeta<FlowNodeJSON> = {
|
|||||||
validate: {
|
validate: {
|
||||||
title: ({ value }: { value: string }) => (value ? undefined : 'Title is required'),
|
title: ({ value }: { value: string }) => (value ? undefined : 'Title is required'),
|
||||||
},
|
},
|
||||||
|
effect: {
|
||||||
|
title: syncVariableTitle,
|
||||||
|
outputs: provideJsonSchemaOutputs,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,5 +3,4 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export { createSyncVariablePlugin } from './sync-variable-plugin/sync-variable-plugin';
|
|
||||||
export { createContextMenuPlugin } from './context-menu-plugin';
|
export { createContextMenuPlugin } from './context-menu-plugin';
|
||||||
|
|||||||
@ -1,85 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use client';
|
|
||||||
|
|
||||||
import {
|
|
||||||
ASTFactory,
|
|
||||||
FlowNodeVariableData,
|
|
||||||
FreeLayoutPluginContext,
|
|
||||||
PluginCreator,
|
|
||||||
definePluginCreator,
|
|
||||||
getNodeForm,
|
|
||||||
} from '@flowgram.ai/free-layout-editor';
|
|
||||||
import { JsonSchemaUtils } from '@flowgram.ai/form-antd-materials';
|
|
||||||
|
|
||||||
export interface SyncVariablePluginOptions {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a plugin to synchronize output data to the variable engine when nodes are created or updated.
|
|
||||||
* @param ctx - The plugin context, containing the document and other relevant information.
|
|
||||||
* @param options - Plugin options, currently an empty object.
|
|
||||||
*/
|
|
||||||
export const createSyncVariablePlugin: PluginCreator<SyncVariablePluginOptions> =
|
|
||||||
definePluginCreator<SyncVariablePluginOptions, FreeLayoutPluginContext>({
|
|
||||||
onInit(ctx, options) {
|
|
||||||
const flowDocument = ctx.document;
|
|
||||||
|
|
||||||
// Listen for node creation events
|
|
||||||
flowDocument.onNodeCreate(({ node }) => {
|
|
||||||
const form = getNodeForm(node);
|
|
||||||
const variableData = node.getData(FlowNodeVariableData);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronizes output data to the variable engine.
|
|
||||||
* @param value - The output data to synchronize.
|
|
||||||
*/
|
|
||||||
const syncOutputs = (value: any) => {
|
|
||||||
if (!value) {
|
|
||||||
// If the output data is empty, clear the variable
|
|
||||||
variableData?.clearVar();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create an Type AST from the output data's JSON schema
|
|
||||||
// NOTICE: You can create a new function to generate an AST based on YOUR CUSTOM DSL
|
|
||||||
const typeAST = JsonSchemaUtils.schemaToAST(value);
|
|
||||||
|
|
||||||
if (typeAST) {
|
|
||||||
// Use the node's title or its ID as the title for the variable
|
|
||||||
const title = form?.getValueIn('title') || node.id;
|
|
||||||
|
|
||||||
// Set the variable in the variable engine
|
|
||||||
variableData?.setVar(
|
|
||||||
ASTFactory.createVariableDeclaration({
|
|
||||||
meta: {
|
|
||||||
title: `${title}`,
|
|
||||||
icon: node.getNodeRegistry()?.info?.icon,
|
|
||||||
// NOTICE: You can add more metadata here as needed
|
|
||||||
},
|
|
||||||
key: `${node.id}`,
|
|
||||||
type: typeAST,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// If the AST cannot be created, clear the variable
|
|
||||||
variableData?.clearVar();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (form) {
|
|
||||||
// Initially synchronize the output data
|
|
||||||
syncOutputs(form.getValueIn('outputs'));
|
|
||||||
|
|
||||||
// Listen for changes in the form values and re-synchronize when outputs change
|
|
||||||
form.onFormValuesChange((props) => {
|
|
||||||
if (props.name.match(/^outputs/) || props.name.match(/^title/)) {
|
|
||||||
syncOutputs(form.getValueIn('outputs'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@ -6,3 +6,5 @@
|
|||||||
export * from './provide-batch-input';
|
export * from './provide-batch-input';
|
||||||
export * from './provide-batch-outputs';
|
export * from './provide-batch-outputs';
|
||||||
export * from './auto-rename-ref';
|
export * from './auto-rename-ref';
|
||||||
|
export * from './provide-json-schema-outputs';
|
||||||
|
export * from './sync-variable-title';
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import {
|
|||||||
import { IFlowRefValue } from '../../typings';
|
import { IFlowRefValue } from '../../typings';
|
||||||
|
|
||||||
export const provideBatchOutputsEffect: EffectOptions[] = createEffectFromVariableProvider({
|
export const provideBatchOutputsEffect: EffectOptions[] = createEffectFromVariableProvider({
|
||||||
private: true,
|
|
||||||
parse: (value: Record<string, IFlowRefValue>, ctx) => [
|
parse: (value: Record<string, IFlowRefValue>, ctx) => [
|
||||||
ASTFactory.createVariableDeclaration({
|
ASTFactory.createVariableDeclaration({
|
||||||
key: `${ctx.node.id}`,
|
key: `${ctx.node.id}`,
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "provide-json-schema-outputs",
|
||||||
|
"depMaterials": [
|
||||||
|
"typings/json-schema",
|
||||||
|
"utils/json-schema"
|
||||||
|
],
|
||||||
|
"depPackages": []
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
ASTFactory,
|
||||||
|
EffectOptions,
|
||||||
|
FlowNodeRegistry,
|
||||||
|
createEffectFromVariableProvider,
|
||||||
|
getNodeForm,
|
||||||
|
} from '@flowgram.ai/editor';
|
||||||
|
|
||||||
|
import { JsonSchemaUtils } from '../../utils';
|
||||||
|
import { IJsonSchema } from '../../typings';
|
||||||
|
|
||||||
|
export const provideJsonSchemaOutputs: EffectOptions[] = createEffectFromVariableProvider({
|
||||||
|
parse: (value: IJsonSchema, ctx) => [
|
||||||
|
ASTFactory.createVariableDeclaration({
|
||||||
|
key: `${ctx.node.id}`,
|
||||||
|
meta: {
|
||||||
|
title: getNodeForm(ctx.node)?.getValueIn('title') || ctx.node.id,
|
||||||
|
icon: ctx.node.getNodeRegistry<FlowNodeRegistry>().info?.icon,
|
||||||
|
},
|
||||||
|
type: JsonSchemaUtils.schemaToAST(value),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "sync-variable-title",
|
||||||
|
"depMaterials": [],
|
||||||
|
"depPackages": []
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
DataEvent,
|
||||||
|
Effect,
|
||||||
|
EffectOptions,
|
||||||
|
FlowNodeRegistry,
|
||||||
|
FlowNodeVariableData,
|
||||||
|
} from '@flowgram.ai/editor';
|
||||||
|
|
||||||
|
export const syncVariableTitle: EffectOptions[] = [
|
||||||
|
{
|
||||||
|
event: DataEvent.onValueChange,
|
||||||
|
effect: (({ value, context }) => {
|
||||||
|
context.node.getData(FlowNodeVariableData).allScopes.forEach((_scope) => {
|
||||||
|
_scope.output.variables.forEach((_var) => {
|
||||||
|
_var.updateMeta({
|
||||||
|
title: value || context.node.id,
|
||||||
|
icon: context.node.getNodeRegistry<FlowNodeRegistry>().info?.icon,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}) as Effect,
|
||||||
|
},
|
||||||
|
];
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "batch-outputs-plugin",
|
||||||
|
"depMaterials": [
|
||||||
|
"flow-value"
|
||||||
|
],
|
||||||
|
"depPackages": []
|
||||||
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
ASTFactory,
|
||||||
|
createEffectFromVariableProvider,
|
||||||
|
defineFormPluginCreator,
|
||||||
|
FlowNodeRegistry,
|
||||||
|
getNodeForm,
|
||||||
|
getNodePrivateScope,
|
||||||
|
getNodeScope,
|
||||||
|
ScopeChainTransformService,
|
||||||
|
type EffectOptions,
|
||||||
|
type FormPluginCreator,
|
||||||
|
FlowNodeScopeType,
|
||||||
|
} from '@flowgram.ai/editor';
|
||||||
|
|
||||||
|
import { IFlowRefValue } from '../../typings';
|
||||||
|
|
||||||
|
export const provideBatchOutputsEffect: EffectOptions[] = createEffectFromVariableProvider({
|
||||||
|
parse: (value: Record<string, IFlowRefValue>, ctx) => [
|
||||||
|
ASTFactory.createVariableDeclaration({
|
||||||
|
key: `${ctx.node.id}`,
|
||||||
|
meta: {
|
||||||
|
title: getNodeForm(ctx.node)?.getValueIn('title'),
|
||||||
|
icon: ctx.node.getNodeRegistry<FlowNodeRegistry>().info?.icon,
|
||||||
|
},
|
||||||
|
type: ASTFactory.createObject({
|
||||||
|
properties: Object.entries(value).map(([_key, value]) =>
|
||||||
|
ASTFactory.createProperty({
|
||||||
|
key: _key,
|
||||||
|
initializer: ASTFactory.createWrapArrayExpression({
|
||||||
|
wrapFor: ASTFactory.createKeyPathExpression({
|
||||||
|
keyPath: value?.content || [],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free Layout only right now
|
||||||
|
*/
|
||||||
|
export const createBatchOutputsFormPlugin: FormPluginCreator<{ outputKey: string }> =
|
||||||
|
defineFormPluginCreator({
|
||||||
|
name: 'batch-outputs-plugin',
|
||||||
|
onSetupFormMeta({ mergeEffect }, { outputKey }) {
|
||||||
|
mergeEffect({
|
||||||
|
[outputKey]: provideBatchOutputsEffect,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onInit(ctx, { outputKey }) {
|
||||||
|
const chainTransformService = ctx.node.getService(ScopeChainTransformService);
|
||||||
|
|
||||||
|
const batchNodeType = ctx.node.flowNodeType;
|
||||||
|
|
||||||
|
const transformerId = `${batchNodeType}-outputs`;
|
||||||
|
|
||||||
|
if (chainTransformService.hasTransformer(transformerId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chainTransformService.registerTransformer(transformerId, {
|
||||||
|
transformCovers: (covers, ctx) => {
|
||||||
|
const node = ctx.scope.meta?.node;
|
||||||
|
|
||||||
|
// Child Node's variable can cover parent
|
||||||
|
if (node?.parent?.flowNodeType === batchNodeType) {
|
||||||
|
return [...covers, getNodeScope(node.parent)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return covers;
|
||||||
|
},
|
||||||
|
transformDeps(scopes, ctx) {
|
||||||
|
const scopeMeta = ctx.scope.meta;
|
||||||
|
|
||||||
|
if (scopeMeta?.type === FlowNodeScopeType.private) {
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const node = scopeMeta?.node;
|
||||||
|
|
||||||
|
// Public of Loop Node depends on child Node
|
||||||
|
if (node?.flowNodeType === batchNodeType) {
|
||||||
|
// Get all child blocks
|
||||||
|
const childBlocks = node.blocks;
|
||||||
|
|
||||||
|
// public scope of all child blocks
|
||||||
|
return [
|
||||||
|
getNodePrivateScope(node),
|
||||||
|
...childBlocks.map((_childBlock) => getNodeScope(_childBlock)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return scopes;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -3,4 +3,4 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './sync-variable-plugin';
|
export { createBatchOutputsFormPlugin } from './batch-outputs-plugin';
|
||||||
@ -7,3 +7,4 @@ export * from './components';
|
|||||||
export * from './effects';
|
export * from './effects';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
export * from './typings';
|
export * from './typings';
|
||||||
|
export * from './form-plugins';
|
||||||
|
|||||||
@ -4,5 +4,5 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './format-legacy-refs';
|
export * from './format-legacy-refs';
|
||||||
export * from './json-schema';
|
|
||||||
export * from './svg-icon';
|
export * from './svg-icon';
|
||||||
|
export * from './json-schema';
|
||||||
|
|||||||
@ -42,7 +42,10 @@ export namespace JsonSchemaUtils {
|
|||||||
.map(([key, _property]) => ({
|
.map(([key, _property]) => ({
|
||||||
key,
|
key,
|
||||||
type: schemaToAST(_property),
|
type: schemaToAST(_property),
|
||||||
meta: { description: _property.description },
|
meta: {
|
||||||
|
title: _property.title,
|
||||||
|
description: _property.description,
|
||||||
|
},
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
case 'array':
|
case 'array':
|
||||||
@ -114,7 +117,18 @@ export namespace JsonSchemaUtils {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: drilldown
|
properties: drilldown
|
||||||
? Object.fromEntries(
|
? Object.fromEntries(
|
||||||
Object.entries(typeAST.properties).map(([key, value]) => [key, astToSchema(value)!])
|
typeAST.properties.map((property) => {
|
||||||
|
const schema = astToSchema(property.type);
|
||||||
|
|
||||||
|
if (property.meta?.title && schema) {
|
||||||
|
schema.title = property.meta.title;
|
||||||
|
}
|
||||||
|
if (property.meta?.description && schema) {
|
||||||
|
schema.description = property.meta.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [property.key, schema!];
|
||||||
|
})
|
||||||
)
|
)
|
||||||
: {},
|
: {},
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user