Skip to main content
Glama

Activepieces MCP Server

by eldoonreval
index.tsxβ€’9.27 kB
import { ReactFlow, Background, SelectionMode, OnSelectionChangeParams, useStoreApi, PanOnScrollMode, useKeyPress, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import React, { useCallback, useMemo, useRef, useState } from 'react'; import { ActionType, flowStructureUtil, FlowVersion, isNil, Step, } from '@activepieces/shared'; import { doesSelectionRectangleExist, NODE_SELECTION_RECT_CLASS_NAME, useBuilderStateContext, useFocusedFailedStep, useHandleKeyPressOnCanvas, usePasteActionsInClipboard, useResizeCanvas, } from '../builder-hooks'; import { CanvasContextMenu, ContextMenuType, } from './context-menu/canvas-context-menu'; import { FlowDragLayer } from './flow-drag-layer'; import { flowUtilConsts, SELECTION_RECT_CHEVRON_ATTRIBUTE, STEP_CONTEXT_MENU_ATTRIBUTE, } from './utils/consts'; import { flowCanvasUtils } from './utils/flow-canvas-utils'; import { AboveFlowWidgets } from './widgets'; import { useShowChevronNextToSelection } from './widgets/selection-chevron-button'; const getChildrenKey = (step: Step) => { switch (step.type) { case ActionType.LOOP_ON_ITEMS: return step.firstLoopAction ? step.firstLoopAction.name : ''; case ActionType.ROUTER: return step.children.reduce((routerKey, child) => { const childrenKey = child ? flowStructureUtil .getAllSteps(child) .reduce( (childKey, grandChild) => `${childKey}-${grandChild.name}`, '', ) : 'null'; return `${routerKey}-${childrenKey}`; }, ''); case ActionType.CODE: case ActionType.PIECE: return ''; } }; const createGraphKey = (flowVersion: FlowVersion) => { return flowStructureUtil .getAllSteps(flowVersion.trigger) .reduce((acc, step) => { const branchesNames = step.type === ActionType.ROUTER ? step.settings.branches.map((branch) => branch.branchName).join('-') : '0'; const childrenKey = getChildrenKey(step); return `${acc}-${step.displayName}-${step.type}-${ step.nextAction ? step.nextAction.name : '' }-${ step.type === ActionType.PIECE ? step.settings.pieceName : '' }-${branchesNames}-${childrenKey}`; }, ''); }; export const FlowCanvas = React.memo( ({ setHasCanvasBeenInitialised, lefSideBarContainerWidth, }: { setHasCanvasBeenInitialised: (value: boolean) => void; lefSideBarContainerWidth: number; }) => { const [ flowVersion, readonly, setSelectedNodes, selectedNodes, applyOperation, selectedStep, exitStepSettings, panningMode, setPieceSelectorStep, selectStepByName, ] = useBuilderStateContext((state) => { return [ state.flowVersion, state.readonly, state.setSelectedNodes, state.selectedNodes, state.applyOperation, state.selectedStep, state.exitStepSettings, state.panningMode, state.setPieceSelectorStep, state.selectStepByName, ]; }); const containerRef = useRef<HTMLDivElement>(null); const { actionsToPaste, fetchClipboardOperations } = usePasteActionsInClipboard(); useShowChevronNextToSelection(); useFocusedFailedStep(); useHandleKeyPressOnCanvas(); useResizeCanvas(containerRef, setHasCanvasBeenInitialised); const storeApi = useStoreApi(); const isShiftKeyPressed = useKeyPress('Shift'); const inGrabPanningMode = !isShiftKeyPressed && panningMode === 'grab'; const onSelectionChange = useCallback( (ev: OnSelectionChangeParams) => { const selectedNodes = ev.nodes.map((n) => n.id); if (selectedNodes.length === 0 && selectedStep) { selectedNodes.push(selectedStep); } setSelectedNodes(selectedNodes); }, [setSelectedNodes, selectedStep], ); const graphKey = createGraphKey(flowVersion); const graph = useMemo(() => { return flowCanvasUtils.convertFlowVersionToGraph(flowVersion); }, [graphKey]); const [contextMenuType, setContextMenuType] = useState<ContextMenuType>( ContextMenuType.CANVAS, ); const onContextMenu = useCallback( (ev: React.MouseEvent<HTMLDivElement>) => { fetchClipboardOperations(); if ( ev.target instanceof HTMLElement || ev.target instanceof SVGElement ) { const stepElement = ev.target.closest( `[data-${STEP_CONTEXT_MENU_ATTRIBUTE}]`, ); const stepName = stepElement?.getAttribute( `data-${STEP_CONTEXT_MENU_ATTRIBUTE}`, ); if (stepElement && stepName) { selectStepByName(stepName); storeApi.getState().addSelectedNodes([stepName]); } const targetIsSelectionChevron = ev.target.closest( `[data-${SELECTION_RECT_CHEVRON_ATTRIBUTE}]`, ); const targetIsSelectionRect = ev.target.classList.contains( NODE_SELECTION_RECT_CLASS_NAME, ); if ( stepElement || targetIsSelectionRect || targetIsSelectionChevron ) { setContextMenuType(ContextMenuType.STEP); } else { setContextMenuType(ContextMenuType.CANVAS); } if ( doesSelectionRectangleExist() && !targetIsSelectionRect && !targetIsSelectionChevron ) { document .querySelector(`.${NODE_SELECTION_RECT_CLASS_NAME}`) ?.remove(); } } }, [setSelectedNodes, selectedNodes, doesSelectionRectangleExist], ); const onSelectionEnd = useCallback(() => { if ( !storeApi.getState().userSelectionActive || doesSelectionRectangleExist() ) { return; } const selectedSteps = selectedNodes.map((node) => flowStructureUtil.getStepOrThrow(node, flowVersion.trigger), ); selectedSteps.forEach((step) => { if ( step.type === ActionType.LOOP_ON_ITEMS || step.type === ActionType.ROUTER ) { const childrenNotSelected = flowStructureUtil .getAllChildSteps(step) .filter((c) => isNil(selectedNodes.find((n) => n === c.name))); selectedSteps.push(...childrenNotSelected); } }); const step = selectedStep ? flowStructureUtil.getStep(selectedStep, flowVersion.trigger) : null; if (selectedNodes.length === 0 && step) { selectedSteps.push(step); } storeApi .getState() .addSelectedNodes(selectedSteps.map((step) => step.name)); }, [selectedNodes, storeApi, selectedStep]); const [cursorPosition, setCursorPosition] = useState({ x: 0, y: 0 }); return ( <div ref={containerRef} className="size-full relative overflow-hidden z-50" > <FlowDragLayer cursorPosition={cursorPosition} lefSideBarContainerWidth={lefSideBarContainerWidth} > <CanvasContextMenu selectedNodes={selectedNodes} applyOperation={applyOperation} selectedStep={selectedStep} exitStepSettings={exitStepSettings} flowVersion={flowVersion} readonly={readonly} setPieceSelectorStep={setPieceSelectorStep} actionsToPaste={actionsToPaste} contextMenuType={contextMenuType} > <ReactFlow onContextMenu={onContextMenu} onPaneClick={() => { storeApi.getState().unselectNodesAndEdges(); }} nodeTypes={flowUtilConsts.nodeTypes} nodes={graph.nodes} edgeTypes={flowUtilConsts.edgeTypes} edges={graph.edges} draggable={false} edgesFocusable={false} elevateEdgesOnSelect={false} maxZoom={1.5} minZoom={0.5} panOnDrag={inGrabPanningMode ? [0, 1] : [1]} zoomOnDoubleClick={false} panOnScroll={true} panOnScrollMode={PanOnScrollMode.Free} fitView={false} nodesConnectable={false} elementsSelectable={true} nodesDraggable={false} nodesFocusable={false} onNodeDrag={(event) => { setCursorPosition({ x: event.clientX, y: event.clientY }); }} selectionKeyCode={inGrabPanningMode ? 'Shift' : null} multiSelectionKeyCode={inGrabPanningMode ? 'Shift' : null} selectionOnDrag={inGrabPanningMode ? false : true} selectNodesOnDrag={true} selectionMode={SelectionMode.Partial} onSelectionChange={onSelectionChange} onSelectionEnd={onSelectionEnd} > <AboveFlowWidgets></AboveFlowWidgets> <Background /> </ReactFlow> </CanvasContextMenu> </FlowDragLayer> </div> ); }, ); FlowCanvas.displayName = 'FlowCanvas';

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/eldoonreval/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server