mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-28 08:49:42 +02:00
Initial Commit 🚀 🚀
This commit is contained in:
commit
4f2a629340
444 changed files with 76863 additions and 0 deletions
44
ui/src/components/flow/nodes/common/NodeContent.tsx
Normal file
44
ui/src/components/flow/nodes/common/NodeContent.tsx
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { Position } from "@xyflow/react";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { BaseHandle } from "@/components/flow/nodes/BaseHandle";
|
||||
import { BaseNode } from "@/components/flow/nodes/BaseNode";
|
||||
import { NodeHeader, NodeHeaderIcon, NodeHeaderTitle } from "@/components/flow/nodes/NodeHeader";
|
||||
|
||||
interface NodeContentProps {
|
||||
selected: boolean;
|
||||
invalid?: boolean;
|
||||
title: string;
|
||||
icon: ReactNode;
|
||||
bgColor: string;
|
||||
hasSourceHandle?: boolean;
|
||||
hasTargetHandle?: boolean;
|
||||
children?: ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const NodeContent = ({
|
||||
selected,
|
||||
invalid,
|
||||
title,
|
||||
icon,
|
||||
bgColor,
|
||||
hasSourceHandle = false,
|
||||
hasTargetHandle = false,
|
||||
children,
|
||||
className = "",
|
||||
}: NodeContentProps) => {
|
||||
return (
|
||||
<BaseNode selected={selected} invalid={invalid} className={`p-0 overflow-hidden ${className}`}>
|
||||
{hasTargetHandle && <BaseHandle type="target" position={Position.Top} />}
|
||||
<NodeHeader className={`px-3 py-2 border-b ${bgColor}`}>
|
||||
<NodeHeaderIcon>{icon}</NodeHeaderIcon>
|
||||
<NodeHeaderTitle>{title}</NodeHeaderTitle>
|
||||
</NodeHeader>
|
||||
<div className="p-3">
|
||||
{children}
|
||||
</div>
|
||||
{hasSourceHandle && <BaseHandle type="source" position={Position.Bottom} />}
|
||||
</BaseNode>
|
||||
);
|
||||
};
|
||||
63
ui/src/components/flow/nodes/common/NodeEditDialog.tsx
Normal file
63
ui/src/components/flow/nodes/common/NodeEditDialog.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { AlertCircle } from "lucide-react";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { FlowNodeData } from "@/components/flow/types";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
|
||||
interface NodeEditDialogProps {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
nodeData: FlowNodeData;
|
||||
title: string;
|
||||
children: ReactNode;
|
||||
onSave?: () => void;
|
||||
}
|
||||
|
||||
export const NodeEditDialog = ({
|
||||
open,
|
||||
onOpenChange,
|
||||
nodeData,
|
||||
title,
|
||||
children,
|
||||
onSave
|
||||
}: NodeEditDialogProps) => {
|
||||
const handleClose = () => onOpenChange(false);
|
||||
|
||||
const handleSave = () => {
|
||||
if (onSave) {
|
||||
onSave();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent
|
||||
className="max-h-[85vh] overflow-y-auto"
|
||||
style={{ maxWidth: "1200px", width: "95vw" }}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogDescription>
|
||||
Configure the settings for this node in your workflow.
|
||||
</DialogDescription>
|
||||
{nodeData.invalid && nodeData.validationMessage && (
|
||||
<div className="mt-2 flex items-center gap-2 rounded-md bg-red-50 p-2 text-sm text-red-500 border border-red-200">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<span>{nodeData.validationMessage}</span>
|
||||
</div>
|
||||
)}
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
{children}
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="outline" onClick={handleClose}>Cancel</Button>
|
||||
<Button onClick={handleSave}>Save</Button>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
39
ui/src/components/flow/nodes/common/useNodeHandlers.ts
Normal file
39
ui/src/components/flow/nodes/common/useNodeHandlers.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { useReactFlow } from "@xyflow/react";
|
||||
import { useCallback, useState } from "react";
|
||||
|
||||
import { FlowEdge, FlowNode, FlowNodeData } from "@/components/flow/types";
|
||||
|
||||
interface UseNodeHandlersProps {
|
||||
id: string;
|
||||
additionalData?: Record<string, string | boolean>;
|
||||
}
|
||||
|
||||
export const useNodeHandlers = ({ id, additionalData = {} }: UseNodeHandlersProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { setNodes } = useReactFlow<FlowNode, FlowEdge>();
|
||||
|
||||
const handleSaveNodeData = useCallback(
|
||||
(updatedData: FlowNodeData) => {
|
||||
setNodes((nodes) => {
|
||||
const updatedNodes = nodes.map((node) =>
|
||||
node.id === id
|
||||
? { ...node, data: { ...node.data, ...updatedData, ...additionalData } }
|
||||
: node
|
||||
);
|
||||
return updatedNodes;
|
||||
});
|
||||
},
|
||||
[id, setNodes, additionalData]
|
||||
);
|
||||
|
||||
const handleDeleteNode = useCallback(() => {
|
||||
setNodes((nodes) => nodes.filter((node) => node.id !== id));
|
||||
}, [id, setNodes]);
|
||||
|
||||
return {
|
||||
open,
|
||||
setOpen,
|
||||
handleSaveNodeData,
|
||||
handleDeleteNode,
|
||||
};
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue