diff --git a/surfsense_web/components/chat-comments/comment-composer/comment-composer.tsx b/surfsense_web/components/chat-comments/comment-composer/comment-composer.tsx index 0d6c312e4..657cfcade 100644 --- a/surfsense_web/components/chat-comments/comment-composer/comment-composer.tsx +++ b/surfsense_web/components/chat-comments/comment-composer/comment-composer.tsx @@ -86,9 +86,11 @@ export function CommentComposer({ onSubmit, onCancel, autoFocus = false, + initialValue = "", }: CommentComposerProps) { - const [displayContent, setDisplayContent] = useState(""); + const [displayContent, setDisplayContent] = useState(initialValue); const [insertedMentions, setInsertedMentions] = useState([]); + const [mentionsInitialized, setMentionsInitialized] = useState(false); const [mentionState, setMentionState] = useState({ isActive: false, query: "", @@ -200,6 +202,33 @@ export function CommentComposer({ setInsertedMentions([]); }; + // Pre-populate insertedMentions from initialValue when members are loaded + useEffect(() => { + if (mentionsInitialized || !initialValue || members.length === 0) return; + + const mentionPattern = /@([^\s@]+(?:\s+[^\s@]+)*?)(?=\s|$|[.,!?;:]|@)/g; + const foundMentions: InsertedMention[] = []; + let match: RegExpExecArray | null; + + while ((match = mentionPattern.exec(initialValue)) !== null) { + const displayName = match[1]; + const member = members.find( + (m) => m.displayName === displayName || m.email.split("@")[0] === displayName + ); + if (member) { + const exists = foundMentions.some((m) => m.id === member.id); + if (!exists) { + foundMentions.push({ id: member.id, displayName }); + } + } + } + + if (foundMentions.length > 0) { + setInsertedMentions(foundMentions); + } + setMentionsInitialized(true); + }, [initialValue, members, mentionsInitialized]); + useEffect(() => { if (autoFocus && textareaRef.current) { textareaRef.current.focus(); diff --git a/surfsense_web/components/chat-comments/comment-composer/types.ts b/surfsense_web/components/chat-comments/comment-composer/types.ts index c23a96ab9..7e050398f 100644 --- a/surfsense_web/components/chat-comments/comment-composer/types.ts +++ b/surfsense_web/components/chat-comments/comment-composer/types.ts @@ -9,6 +9,7 @@ export interface CommentComposerProps { onSubmit: (content: string) => void; onCancel?: () => void; autoFocus?: boolean; + initialValue?: string; } export interface MentionState { diff --git a/surfsense_web/components/chat-comments/comment-item/comment-item.tsx b/surfsense_web/components/chat-comments/comment-item/comment-item.tsx index 643c8b295..8d2a3dad0 100644 --- a/surfsense_web/components/chat-comments/comment-item/comment-item.tsx +++ b/surfsense_web/components/chat-comments/comment-item/comment-item.tsx @@ -6,6 +6,7 @@ import { currentUserAtom } from "@/atoms/user/user-query.atoms"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; +import { CommentComposer } from "../comment-composer/comment-composer"; import { CommentActions } from "./comment-actions"; import type { CommentItemProps } from "./types"; @@ -67,6 +68,11 @@ function formatTimestamp(dateString: string): string { ); } +function convertRenderedToDisplay(contentRendered: string): string { + // Convert @{DisplayName} format to @DisplayName for editing + return contentRendered.replace(/@\{([^}]+)\}/g, "@$1"); +} + function renderMentions(content: string): React.ReactNode { // Match @{DisplayName} format from backend const mentionPattern = /@\{([^}]+)\}/g; @@ -99,9 +105,15 @@ function renderMentions(content: string): React.ReactNode { export function CommentItem({ comment, onEdit, + onEditSubmit, + onEditCancel, onDelete, onReply, isReply = false, + isEditing = false, + isSubmitting = false, + members = [], + membersLoading = false, }: CommentItemProps) { const [{ data: currentUser }] = useAtom(currentUserAtom); @@ -111,6 +123,10 @@ export function CommentItem({ : comment.author?.displayName || comment.author?.email.split("@")[0] || "Unknown"; const email = comment.author?.email || ""; + const handleEditSubmit = (content: string) => { + onEditSubmit?.(comment.id, content); + }; + return (
@@ -131,21 +147,39 @@ export function CommentItem({ {comment.isEdited && ( (edited) )} -
- onEdit?.(comment.id)} - onDelete={() => onDelete?.(comment.id)} + {!isEditing && ( +
+ onEdit?.(comment.id)} + onDelete={() => onDelete?.(comment.id)} + /> +
+ )} +
+ + {isEditing ? ( +
+
-
+ ) : ( +
+ {renderMentions(comment.contentRendered)} +
+ )} -
- {renderMentions(comment.contentRendered)} -
- - {!isReply && onReply && ( + {!isReply && onReply && !isEditing && (