feat: enhance canvas and layout components with new features and improvements
- Added remote image patterns to the Next.js configuration for enhanced image handling. - Updated TypeScript configuration to exclude the 'implement' directory. - Refactored layout component to fetch initial authentication token and pass it to Providers. - Replaced CanvasToolbar with CanvasSidebar for improved UI layout and functionality. - Enhanced Canvas component with new drag-and-drop file upload capabilities and batch node movement. - Updated various node components to support new status handling and improved user interactions. - Added debounced saving for note and prompt nodes to optimize performance.
This commit is contained in:
@@ -1,15 +1,68 @@
|
||||
"use client";
|
||||
|
||||
import { type Node, type NodeProps } from "@xyflow/react";
|
||||
|
||||
import { useState, useCallback, useEffect } from "react";
|
||||
import { type NodeProps, type Node } from "@xyflow/react";
|
||||
import { useMutation } from "convex/react";
|
||||
import { api } from "@/convex/_generated/api";
|
||||
import type { Id } from "@/convex/_generated/dataModel";
|
||||
import BaseNodeWrapper from "./base-node-wrapper";
|
||||
|
||||
export type GroupNode = Node<{ label?: string }, "group">;
|
||||
type GroupNodeData = {
|
||||
label?: string;
|
||||
_status?: string;
|
||||
_statusMessage?: string;
|
||||
};
|
||||
|
||||
export type GroupNode = Node<GroupNodeData, "group">;
|
||||
|
||||
export default function GroupNode({ id, data, selected }: NodeProps<GroupNode>) {
|
||||
const updateData = useMutation(api.nodes.updateData);
|
||||
const [label, setLabel] = useState(data.label ?? "Gruppe");
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEditing) {
|
||||
setLabel(data.label ?? "Gruppe");
|
||||
}
|
||||
}, [data.label, isEditing]);
|
||||
|
||||
const handleBlur = useCallback(() => {
|
||||
setIsEditing(false);
|
||||
if (label !== data.label) {
|
||||
updateData({
|
||||
nodeId: id as Id<"nodes">,
|
||||
data: {
|
||||
...data,
|
||||
label,
|
||||
_status: undefined,
|
||||
_statusMessage: undefined,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [label, data, id, updateData]);
|
||||
|
||||
export default function GroupNode({ data, selected }: NodeProps<GroupNode>) {
|
||||
return (
|
||||
<BaseNodeWrapper selected={selected} className="min-h-[150px] min-w-[200px] border-dashed p-3">
|
||||
<div className="text-xs font-medium text-muted-foreground">{data.label || "Gruppe"}</div>
|
||||
<BaseNodeWrapper
|
||||
selected={selected}
|
||||
className="min-w-[200px] min-h-[150px] p-3 border-dashed"
|
||||
>
|
||||
{isEditing ? (
|
||||
<input
|
||||
value={label}
|
||||
onChange={(e) => setLabel(e.target.value)}
|
||||
onBlur={handleBlur}
|
||||
onKeyDown={(e) => e.key === "Enter" && handleBlur()}
|
||||
autoFocus
|
||||
className="nodrag text-xs font-medium text-muted-foreground bg-transparent border-0 outline-none w-full"
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
onDoubleClick={() => setIsEditing(true)}
|
||||
className="text-xs font-medium text-muted-foreground cursor-text"
|
||||
>
|
||||
📁 {label}
|
||||
</div>
|
||||
)}
|
||||
</BaseNodeWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user