Rolled back comments into separate branch

This commit is contained in:
Emir Karabeg
2025-02-02 21:17:13 -08:00
parent c35cb81caa
commit a040708997
5 changed files with 8 additions and 248 deletions

View File

@@ -1,106 +0,0 @@
import { useState, useEffect, useRef } from 'react'
import { Card } from '@/components/ui/card'
import { Textarea } from '@/components/ui/textarea'
import { X } from 'lucide-react'
import { useCommentStore } from '@/stores/comments/store'
import { NodeProps } from 'reactflow'
import { cn } from '@/lib/utils'
interface CommentBlockData {
id: string
text: string
}
export function CommentBlock({ data }: NodeProps<CommentBlockData>) {
const [text, setText] = useState(data.text)
const [isEditing, setIsEditing] = useState(!data.text)
const [isExpanded, setIsExpanded] = useState(false)
const textareaRef = useRef<HTMLTextAreaElement>(null)
const { updateComment, removeComment } = useCommentStore()
useEffect(() => {
if (isEditing && textareaRef.current) {
textareaRef.current.focus()
}
}, [isEditing])
const handleBlur = () => {
setIsEditing(false)
setIsExpanded(false)
if (text.trim()) {
updateComment(data.id, text)
} else {
removeComment(data.id)
}
}
const handleClick = () => {
setIsExpanded(true)
if (!text) {
setIsEditing(true)
}
}
if (!isExpanded) {
return (
<div
className={cn(
'w-6 h-6 rounded-full bg-white border border-gray-200 shadow-sm cursor-pointer',
'hover:shadow-md transition-all duration-200 ease-in-out transform scale-100',
'flex items-center justify-center'
)}
onClick={handleClick}
onMouseEnter={() => setIsExpanded(true)}
>
<div className="w-2 h-2 rounded-full bg-yellow-500" />
</div>
)
}
return (
<Card
className={cn(
'w-[240px] shadow-md select-none relative cursor-default focus:outline-none focus-visible:ring-0',
'bg-white hover:bg-gray-50/50',
'border border-gray-200',
'transition-all duration-200 ease-in-out transform scale-100',
'animate-in fade-in-0 zoom-in-95'
)}
onMouseLeave={() => !isEditing && setIsExpanded(false)}
>
<div className="flex items-center justify-between p-2 border-b border-gray-200 cursor-grab active:cursor-grabbing">
<div className="text-sm font-medium text-gray-600">Note</div>
<button
className="opacity-0 group-hover:opacity-100 transition-opacity"
onClick={(e) => {
e.stopPropagation()
removeComment(data.id)
}}
>
<X className="h-4 w-4 text-gray-400 hover:text-gray-600" />
</button>
</div>
<div className="p-2.5" onClick={() => setIsEditing(true)}>
{isEditing ? (
<Textarea
ref={textareaRef}
value={text}
onChange={(e) => setText(e.target.value)}
onBlur={handleBlur}
className={cn(
'min-h-[80px] max-h-[240px] resize-none',
'bg-transparent border-0 outline-none focus:outline-none focus-visible:ring-0 focus:ring-0 p-0',
'text-sm text-gray-900 placeholder:text-gray-400'
)}
placeholder="Type your note here..."
/>
) : (
<div className="text-sm text-gray-900 whitespace-pre-wrap cursor-text">
{text}
</div>
)}
</div>
</Card>
)
}

View File

@@ -16,13 +16,10 @@ import { NotificationList } from '@/app/w/components/notifications/notifications
import { WorkflowNode } from '../workflow-node/workflow-node'
import { CustomEdge } from '../custom-edge/custom-edge'
import { initializeStateLogger } from '@/stores/workflow/logger'
import { useCommentStore } from '@/stores/comments/store'
import { CommentBlock } from '../comment-block/comment-block'
// Define custom node and edge types for ReactFlow
const nodeTypes: NodeTypes = {
workflowBlock: WorkflowNode,
commentBlock: CommentBlock,
}
const edgeTypes: EdgeTypes = { custom: CustomEdge }
@@ -48,8 +45,6 @@ export function WorkflowCanvas() {
} = useWorkflowStore()
const { addNotification } = useNotificationStore()
const { project } = useReactFlow()
const { comments, isCommentMode, addComment, updateCommentPosition } =
useCommentStore()
// Transform blocks into ReactFlow node format
const nodes = Object.values(blocks).map((block) => ({
@@ -70,16 +65,11 @@ export function WorkflowCanvas() {
(changes: any) => {
changes.forEach((change: any) => {
if (change.type === 'position' && change.position) {
if (change.id.startsWith('comment-')) {
const commentId = change.id.replace('comment-', '')
updateCommentPosition(commentId, change.position)
} else {
updateBlockPosition(change.id, change.position)
}
updateBlockPosition(change.id, change.position)
}
})
},
[updateBlockPosition, updateCommentPosition]
[updateBlockPosition]
)
// Handle edge removal and updates
@@ -147,23 +137,11 @@ export function WorkflowCanvas() {
setSelectedEdgeId(null)
}, [])
// Update onPaneClick to handle comment mode
const onPaneClick = useCallback(
(event: React.MouseEvent) => {
setSelectedBlockId(null)
setSelectedEdgeId(null)
if (isCommentMode) {
const reactFlowBounds = event.currentTarget.getBoundingClientRect()
const position = project({
x: event.clientX - reactFlowBounds.left,
y: event.clientY - reactFlowBounds.top,
})
addComment(position)
}
},
[isCommentMode, project, addComment]
)
// Update onPaneClick to clear selections
const onPaneClick = useCallback((event: React.MouseEvent) => {
setSelectedBlockId(null)
setSelectedEdgeId(null)
}, [])
// Update selected edge when clicking on connections
const onEdgeClick = useCallback((event: React.MouseEvent, edge: any) => {
@@ -204,20 +182,11 @@ export function WorkflowCanvas() {
},
}))
// Create comment nodes
const commentNodes = Object.values(comments).map((comment) => ({
id: `comment-${comment.id}`,
type: 'commentBlock',
position: comment.position,
data: { id: comment.id, text: comment.text },
draggable: true,
}))
return (
<div className="relative w-full h-[calc(100vh-4rem)]">
<NotificationList />
<ReactFlow
nodes={[...nodes, ...commentNodes]}
nodes={nodes}
edges={edgesWithSelection}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}

View File

@@ -33,7 +33,6 @@ import {
AlertDialogTitle,
AlertDialogTrigger,
} from '@/components/ui/alert-dialog'
import { useCommentStore } from '@/stores/comments/store'
export function ControlBar() {
const { notifications, getWorkflowNotifications } = useNotificationStore()
@@ -45,7 +44,6 @@ export function ControlBar() {
const [, forceUpdate] = useState({})
const { isExecuting, handleRunWorkflow } = useWorkflowExecution()
const router = useRouter()
const { isCommentMode, toggleCommentMode } = useCommentStore()
// Use client-side only rendering for the timestamp
const [mounted, setMounted] = useState(false)
@@ -165,22 +163,6 @@ export function ControlBar() {
<TooltipContent>Delete Workflow</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant={isCommentMode ? 'secondary' : 'ghost'}
size="icon"
onClick={toggleCommentMode}
>
<MessageSquare className="h-5 w-5" />
<span className="sr-only">Toggle Comment Mode</span>
</Button>
</TooltipTrigger>
<TooltipContent>
{isCommentMode ? 'Exit Comment Mode' : 'Add Comments'}
</TooltipContent>
</Tooltip>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete Workflow</AlertDialogTitle>

View File

@@ -1,85 +0,0 @@
import { create } from 'zustand'
import { devtools, persist } from 'zustand/middleware'
export interface Comment {
id: string
text: string
position: { x: number; y: number }
createdAt: number
}
interface CommentStore {
comments: Record<string, Comment>
isCommentMode: boolean
addComment: (position: { x: number; y: number }) => void
updateComment: (id: string, text: string) => void
updateCommentPosition: (id: string, position: { x: number; y: number }) => void
removeComment: (id: string) => void
toggleCommentMode: () => void
}
export const useCommentStore = create<CommentStore>()(
devtools(
persist(
(set) => ({
comments: {},
isCommentMode: false,
addComment: (position) => {
const id = crypto.randomUUID()
set((state) => ({
comments: {
...state.comments,
[id]: {
id,
text: '',
position,
createdAt: Date.now(),
},
},
isCommentMode: false,
}))
},
updateComment: (id, text) => {
set((state) => ({
comments: {
...state.comments,
[id]: {
...state.comments[id],
text,
},
},
}))
},
updateCommentPosition: (id, position) => {
set((state) => ({
comments: {
...state.comments,
[id]: {
...state.comments[id],
position,
},
},
}))
},
removeComment: (id) => {
set((state) => {
const newComments = { ...state.comments }
delete newComments[id]
return { comments: newComments }
})
},
toggleCommentMode: () => {
set((state) => ({ isCommentMode: !state.isCommentMode }))
},
}),
{
name: 'comments-storage',
}
)
)
)