Selaa lähdekoodia

feat(demo-free-layout): context-menu-plugin (#329)

xiamidaxia 7 kuukautta sitten
vanhempi
commit
b87c3e918c

+ 1 - 1
apps/demo-free-layout/src/components/node-menu/index.tsx

@@ -83,7 +83,7 @@ export const NodeMenu: FC<NodeMenuProps> = ({ node, deleteNode, updateTitleEdit
   }, [updateTitleEdit]);
 
   if (!visible) {
-    return;
+    return <></>;
   }
 
   return (

+ 15 - 3
apps/demo-free-layout/src/hooks/use-editor-props.tsx

@@ -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 } from '@flowgram.ai/free-layout-editor';
+import { FreeLayoutProps, WorkflowNodeLinesData } from '@flowgram.ai/free-layout-editor';
 import { createFreeGroupPlugin } from '@flowgram.ai/free-group-plugin';
 import { createContainerNodePlugin } from '@flowgram.ai/free-container-plugin';
 
@@ -14,7 +14,7 @@ import { onDragLineEnd } from '../utils';
 import { FlowNodeRegistry, FlowDocumentJSON } from '../typings';
 import { shortcuts } from '../shortcuts';
 import { CustomService, RunningService } from '../services';
-import { createSyncVariablePlugin } from '../plugins';
+import { createSyncVariablePlugin, createContextMenuPlugin } from '../plugins';
 import { defaultFormMeta } from '../nodes/default-form-meta';
 import { WorkflowNodeType } from '../nodes';
 import { SelectorBoxPopover } from '../components/selector-box-popover';
@@ -92,7 +92,11 @@ export function useEditorProps(
         if (fromPort.node === toPort.node) {
           return false;
         }
-        return true;
+        /**
+         * 线条环检测,不允许连接到前面的节点
+         * Line loop detection, which is not allowed to connect to the node in front of it
+         */
+        return !fromPort.node.getData(WorkflowNodeLinesData).allInputNodes.includes(toPort.node);
       },
       /**
        * Check whether the line can be deleted, this triggers on the default shortcut `Bakspace` or `Delete`
@@ -157,6 +161,7 @@ export function useEditorProps(
        * Running line
        */
       isFlowingLine: (ctx, line) => ctx.get(RunningService).isFlowingLine(line),
+
       /**
        * Shortcuts
        */
@@ -249,9 +254,16 @@ export function useEditorProps(
          * 这个用于 loop 节点子画布的渲染
          */
         createContainerNodePlugin({}),
+        /**
+         * Group plugin
+         */
         createFreeGroupPlugin({
           groupNodeRender: GroupNodeRender,
         }),
+        /**
+         * ContextMenu plugin
+         */
+        createContextMenuPlugin({}),
       ],
     }),
     []

+ 52 - 0
apps/demo-free-layout/src/plugins/context-menu-plugin/context-menu-layer.tsx

@@ -0,0 +1,52 @@
+import { NodePanelResult, WorkflowNodePanelService } from '@flowgram.ai/free-node-panel-plugin';
+import {
+  Layer,
+  injectable,
+  inject,
+  FreeLayoutPluginContext,
+  WorkflowHoverService,
+  WorkflowNodeEntity,
+  WorkflowNodeJSON,
+} from '@flowgram.ai/free-layout-editor';
+
+@injectable()
+export class ContextMenuLayer extends Layer {
+  @inject(FreeLayoutPluginContext) ctx: FreeLayoutPluginContext;
+
+  @inject(WorkflowNodePanelService) nodePanelService: WorkflowNodePanelService;
+
+  @inject(WorkflowHoverService) hoverService: WorkflowHoverService;
+
+  onReady() {
+    this.listenPlaygroundEvent('contextmenu', (e) => {
+      this.openNodePanel(e);
+      e.preventDefault();
+      e.stopPropagation();
+    });
+  }
+
+  openNodePanel(e: MouseEvent) {
+    const pos = this.getPosFromMouseEvent(e);
+    this.nodePanelService.callNodePanel({
+      position: pos,
+      panelProps: {},
+      // handle node selection from panel - 处理从面板中选择节点
+      onSelect: async (panelParams?: NodePanelResult) => {
+        if (!panelParams) {
+          return;
+        }
+        const { nodeType, nodeJSON } = panelParams;
+        // create new workflow node based on selected type - 根据选择的类型创建新的工作流节点
+        const node: WorkflowNodeEntity = this.ctx.document.createWorkflowNodeByType(
+          nodeType,
+          pos,
+          nodeJSON ?? ({} as WorkflowNodeJSON)
+        );
+        // select the newly created node - 选择新创建的节点
+        this.ctx.selection.selection = [node];
+      },
+      // handle panel close - 处理面板关闭
+      onClose: () => {},
+    });
+  }
+}

+ 23 - 0
apps/demo-free-layout/src/plugins/context-menu-plugin/context-menu-plugin.ts

@@ -0,0 +1,23 @@
+import {
+  definePluginCreator,
+  PluginCreator,
+  FreeLayoutPluginContext,
+} from '@flowgram.ai/free-layout-editor';
+
+import { ContextMenuLayer } from './context-menu-layer';
+
+export interface ContextMenuPluginOptions {}
+
+/**
+ * Creates a plugin of contextmenu
+ * @param ctx - The plugin context, containing the document and other relevant information.
+ * @param options - Plugin options, currently an empty object.
+ */
+export const createContextMenuPlugin: PluginCreator<ContextMenuPluginOptions> = definePluginCreator<
+  ContextMenuPluginOptions,
+  FreeLayoutPluginContext
+>({
+  onInit(ctx, options) {
+    ctx.playground.registerLayer(ContextMenuLayer);
+  },
+});

+ 1 - 0
apps/demo-free-layout/src/plugins/context-menu-plugin/index.ts

@@ -0,0 +1 @@
+export { createContextMenuPlugin } from './context-menu-plugin';

+ 1 - 0
apps/demo-free-layout/src/plugins/index.ts

@@ -1 +1,2 @@
 export { createSyncVariablePlugin } from './sync-variable-plugin/sync-variable-plugin';
+export { createContextMenuPlugin } from './context-menu-plugin';