diff --git a/surfsense_backend/alembic/versions/68_add_comments_permissions_to_roles.py b/surfsense_backend/alembic/versions/68_add_comments_permissions_to_roles.py index 87f3f3cc4..a66ad3404 100644 --- a/surfsense_backend/alembic/versions/68_add_comments_permissions_to_roles.py +++ b/surfsense_backend/alembic/versions/68_add_comments_permissions_to_roles.py @@ -6,9 +6,10 @@ Create Date: 2024-01-16 """ -from alembic import op from sqlalchemy import text +from alembic import op + # revision identifiers, used by Alembic. revision = "68" down_revision = "67" diff --git a/surfsense_web/app/preview/chat-comments/page.tsx b/surfsense_web/app/preview/chat-comments/page.tsx deleted file mode 100644 index a99040b77..000000000 --- a/surfsense_web/app/preview/chat-comments/page.tsx +++ /dev/null @@ -1,657 +0,0 @@ -"use client"; - -import { useState } from "react"; -import { CommentComposer } from "@/components/chat-comments/comment-composer/comment-composer"; -import { CommentItem } from "@/components/chat-comments/comment-item/comment-item"; -import type { CommentData } from "@/components/chat-comments/comment-item/types"; -import { CommentPanel } from "@/components/chat-comments/comment-panel/comment-panel"; -import { CommentThread } from "@/components/chat-comments/comment-thread/comment-thread"; -import type { CommentThreadData } from "@/components/chat-comments/comment-thread/types"; -import { CommentTrigger } from "@/components/chat-comments/comment-trigger/comment-trigger"; -import { MemberMentionPicker } from "@/components/chat-comments/member-mention-picker/member-mention-picker"; -import type { MemberOption } from "@/components/chat-comments/member-mention-picker/types"; - -const fakeMembersData: MemberOption[] = [ - { - id: "550e8400-e29b-41d4-a716-446655440001", - displayName: "Alice Smith", - email: "alice@example.com", - avatarUrl: null, - }, - { - id: "550e8400-e29b-41d4-a716-446655440002", - displayName: "Bob Johnson", - email: "bob.johnson@example.com", - avatarUrl: null, - }, - { - id: "550e8400-e29b-41d4-a716-446655440003", - displayName: "Charlie Brown", - email: "charlie@example.com", - avatarUrl: null, - }, - { - id: "550e8400-e29b-41d4-a716-446655440004", - displayName: null, - email: "david.wilson@example.com", - avatarUrl: null, - }, - { - id: "550e8400-e29b-41d4-a716-446655440005", - displayName: "Emma Davis", - email: "emma@example.com", - avatarUrl: null, - }, -]; - -const fakeCommentsData: CommentData[] = [ - { - id: 1, - content: "This is a great response! @Alice Smith can you review?", - contentRendered: "This is a great response! @Alice Smith can you review?", - author: { - id: "550e8400-e29b-41d4-a716-446655440002", - displayName: "Bob Johnson", - email: "bob.johnson@example.com", - avatarUrl: null, - }, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - isEdited: false, - canEdit: true, - canDelete: true, - }, - { - id: 2, - content: "I checked this yesterday and it looks good.", - contentRendered: "I checked this yesterday and it looks good.", - author: { - id: "550e8400-e29b-41d4-a716-446655440001", - displayName: "Alice Smith", - email: "alice@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 86400000).toISOString(), - updatedAt: new Date(Date.now() - 3600000).toISOString(), - isEdited: true, - canEdit: false, - canDelete: true, - }, - { - id: 3, - content: "Thanks @Bob Johnson and @Alice Smith for the quick turnaround!", - contentRendered: "Thanks @Bob Johnson and @Alice Smith for the quick turnaround!", - author: { - id: "550e8400-e29b-41d4-a716-446655440004", - displayName: null, - email: "david.wilson@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 3600000 * 3).toISOString(), - updatedAt: new Date(Date.now() - 3600000 * 3).toISOString(), - isEdited: false, - canEdit: true, - canDelete: false, - }, -]; - -const fakeThreadsData: CommentThreadData[] = [ - { - id: 1, - messageId: 101, - content: "This is a great response! @Alice Smith can you review?", - contentRendered: "This is a great response! @Alice Smith can you review?", - author: { - id: "550e8400-e29b-41d4-a716-446655440002", - displayName: "Bob Johnson", - email: "bob.johnson@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 3600000).toISOString(), - updatedAt: new Date(Date.now() - 3600000).toISOString(), - isEdited: false, - canEdit: true, - canDelete: true, - replyCount: 2, - replies: [ - { - id: 2, - content: "I checked this yesterday and it looks good.", - contentRendered: "I checked this yesterday and it looks good.", - author: { - id: "550e8400-e29b-41d4-a716-446655440001", - displayName: "Alice Smith", - email: "alice@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 1800000).toISOString(), - updatedAt: new Date(Date.now() - 1800000).toISOString(), - isEdited: false, - canEdit: false, - canDelete: true, - }, - { - id: 3, - content: "Thanks @Alice Smith!", - contentRendered: "Thanks @Alice Smith!", - author: { - id: "550e8400-e29b-41d4-a716-446655440002", - displayName: "Bob Johnson", - email: "bob.johnson@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 900000).toISOString(), - updatedAt: new Date(Date.now() - 900000).toISOString(), - isEdited: false, - canEdit: true, - canDelete: true, - }, - ], - }, - { - id: 4, - messageId: 101, - content: "Can we also add some documentation for this feature?", - contentRendered: "Can we also add some documentation for this feature?", - author: { - id: "550e8400-e29b-41d4-a716-446655440003", - displayName: "Charlie Brown", - email: "charlie@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 7200000).toISOString(), - updatedAt: new Date(Date.now() - 7200000).toISOString(), - isEdited: false, - canEdit: false, - canDelete: true, - replyCount: 1, - replies: [ - { - id: 5, - content: "Good idea @Charlie Brown, I'll create a ticket for that.", - contentRendered: "Good idea @Charlie Brown, I'll create a ticket for that.", - author: { - id: "550e8400-e29b-41d4-a716-446655440002", - displayName: "Bob Johnson", - email: "bob.johnson@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 6000000).toISOString(), - updatedAt: new Date(Date.now() - 6000000).toISOString(), - isEdited: false, - canEdit: true, - canDelete: true, - }, - ], - }, - { - id: 6, - messageId: 101, - content: "I think we should also consider edge cases here. What happens if the input is empty?", - contentRendered: "I think we should also consider edge cases here. What happens if the input is empty?", - author: { - id: "550e8400-e29b-41d4-a716-446655440001", - displayName: "Alice Smith", - email: "alice@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 10800000).toISOString(), - updatedAt: new Date(Date.now() - 10800000).toISOString(), - isEdited: false, - canEdit: false, - canDelete: true, - replyCount: 3, - replies: [ - { - id: 7, - content: "Good point! We should add validation.", - contentRendered: "Good point! We should add validation.", - author: { - id: "550e8400-e29b-41d4-a716-446655440002", - displayName: "Bob Johnson", - email: "bob.johnson@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 10000000).toISOString(), - updatedAt: new Date(Date.now() - 10000000).toISOString(), - isEdited: false, - canEdit: true, - canDelete: true, - }, - { - id: 8, - content: "I'll handle the validation logic @Alice Smith", - contentRendered: "I'll handle the validation logic @Alice Smith", - author: { - id: "550e8400-e29b-41d4-a716-446655440003", - displayName: "Charlie Brown", - email: "charlie@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 9500000).toISOString(), - updatedAt: new Date(Date.now() - 9500000).toISOString(), - isEdited: false, - canEdit: false, - canDelete: true, - }, - { - id: 9, - content: "Thanks @Charlie Brown!", - contentRendered: "Thanks @Charlie Brown!", - author: { - id: "550e8400-e29b-41d4-a716-446655440001", - displayName: "Alice Smith", - email: "alice@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 9000000).toISOString(), - updatedAt: new Date(Date.now() - 9000000).toISOString(), - isEdited: false, - canEdit: false, - canDelete: true, - }, - ], - }, - { - id: 10, - messageId: 101, - content: "The performance looks great in the benchmarks. Nice work everyone!", - contentRendered: "The performance looks great in the benchmarks. Nice work everyone!", - author: { - id: "550e8400-e29b-41d4-a716-446655440005", - displayName: "Emma Davis", - email: "emma@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 14400000).toISOString(), - updatedAt: new Date(Date.now() - 14400000).toISOString(), - isEdited: false, - canEdit: false, - canDelete: true, - replyCount: 0, - replies: [], - }, - { - id: 11, - messageId: 101, - content: "Should we schedule a review meeting for this?", - contentRendered: "Should we schedule a review meeting for this?", - author: { - id: "550e8400-e29b-41d4-a716-446655440004", - displayName: null, - email: "david.wilson@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 18000000).toISOString(), - updatedAt: new Date(Date.now() - 18000000).toISOString(), - isEdited: true, - canEdit: true, - canDelete: true, - replyCount: 2, - replies: [ - { - id: 12, - content: "Yes, let's do it tomorrow at 10am", - contentRendered: "Yes, let's do it tomorrow at 10am", - author: { - id: "550e8400-e29b-41d4-a716-446655440002", - displayName: "Bob Johnson", - email: "bob.johnson@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 17000000).toISOString(), - updatedAt: new Date(Date.now() - 17000000).toISOString(), - isEdited: false, - canEdit: true, - canDelete: true, - }, - { - id: 13, - content: "Works for me!", - contentRendered: "Works for me!", - author: { - id: "550e8400-e29b-41d4-a716-446655440005", - displayName: "Emma Davis", - email: "emma@example.com", - avatarUrl: null, - }, - createdAt: new Date(Date.now() - 16000000).toISOString(), - updatedAt: new Date(Date.now() - 16000000).toISOString(), - isEdited: false, - canEdit: false, - canDelete: true, - }, - ], - }, -]; - -export default function ChatCommentsPreviewPage() { - const [highlightedIndex, setHighlightedIndex] = useState(0); - const [selectedMember, setSelectedMember] = useState(null); - const [submittedContent, setSubmittedContent] = useState(null); - const [isPanelOpen, setIsPanelOpen] = useState(false); - const [isEmptyPanelOpen, setIsEmptyPanelOpen] = useState(false); - - return ( -
-
-
-

Chat Comments UI Preview

-

- Preview page for chat comments components with fake data -

-
- - {/* Full Integration Simulation */} -
-
-

🎯 Full Integration Simulation

-

- Two scenarios: no comments (hover to see trigger) and with comments (always visible). -

-
- - {/* Scenario 1: No comments yet */} -
-

No comments yet — hover to see trigger, click to add first comment

-
-
-
-
-
- AI Assistant -
-

- This is an AI response with no comments yet. Hover over this message to reveal the comment trigger icon on the right. Click to open the panel and add the first comment. -

-
-
- setIsEmptyPanelOpen(!isEmptyPanelOpen)} - /> - {isEmptyPanelOpen && ( - alert(`Create first comment: ${content}`)} - onCreateReply={() => {}} - onEditComment={() => {}} - onDeleteComment={() => {}} - maxHeight={300} - /> - )} -
-
- - {/* Scenario 2: Has comments */} -
-

Has comments — trigger always visible, click to toggle panel

-
-
-
-
-
- AI Assistant -
-

- Based on my analysis, the quarterly revenue increased by 15% compared to the previous period. - The main drivers were the expansion into new markets and improved customer retention rates. - I recommend focusing on the following areas for continued growth... -

-
-
- setIsPanelOpen(!isPanelOpen)} - /> - {isPanelOpen && ( - alert(`Create comment: ${content}`)} - onCreateReply={(id, content) => alert(`Reply to ${id}: ${content}`)} - onEditComment={(id) => alert(`Edit ${id}`)} - onDeleteComment={(id) => alert(`Delete ${id}`)} - maxHeight={350} - /> - )} -
-
-
- - {/* Comment Composer Section */} -
-

Comment Composer

-

- Type @ to trigger mention picker. Use Tab/Shift+Tab/Arrow keys to navigate, Enter to - select. -

- -
- setSubmittedContent(content)} - onCancel={() => setSubmittedContent(null)} - autoFocus - /> -
- - {submittedContent && ( -
- Submitted content: - - {submittedContent} - -
- )} -
- - {/* Comment Trigger Section */} -
-

Comment Trigger

-

- Toggle button on AI messages. Clicking opens/closes the comment panel. -

- -
-
-

No comments yet

-

Hidden until hover

-
- AI response... - {}} /> -
-
- -
-

5 comments exist

-

Always visible with count

-
- AI response... - {}} /> -
-
- -
-

Panel is open

-

Active/pressed state

-
- AI response... - {}} /> -
-
-
-
- - {/* Comment Panel Section */} -
-

Comment Panel

-

- Full panel with scrollable threads and composer. Shows alongside AI responses. -

- -
-
-

With comments

- alert(`Create: ${content}`)} - onCreateReply={(id, content) => alert(`Reply ${id}: ${content}`)} - onEditComment={(id) => alert(`Edit ${id}`)} - onDeleteComment={(id) => alert(`Delete ${id}`)} - /> -
- -
-

Empty state

- alert(`Create: ${content}`)} - onCreateReply={(id, content) => alert(`Reply ${id}: ${content}`)} - onEditComment={(id) => alert(`Edit ${id}`)} - onDeleteComment={(id) => alert(`Delete ${id}`)} - /> -
- -
-

Loading

- {}} - onCreateReply={() => {}} - onEditComment={() => {}} - onDeleteComment={() => {}} - /> -
-
-
- - {/* Comment Thread Section */} -
-

Comment Thread

-

- Two top-level comments with replies. Click Reply to open composer. Click the replies - count to collapse/expand. -

- -
- {fakeThreadsData.map((thread) => ( - alert(`Reply to ${commentId}: ${content}`)} - onEditComment={(commentId) => alert(`Edit comment ${commentId}`)} - onDeleteComment={(commentId) => alert(`Delete comment ${commentId}`)} - /> - ))} -
-
- - {/* Comment Item Section */} -
-

Comment Item (Standalone)

-

- Individual comment components. Hover to see action menu. -

- -
- alert(`Edit comment ${id}`)} - onDelete={(id) => alert(`Delete comment ${id}`)} - onReply={(id) => alert(`Reply to comment ${id}`)} - /> -
-
- - {/* Member Mention Picker Section */} -
-

- Member Mention Picker (Standalone) -

- -
-
-

After typing @

-

Shows all members

-
- setSelectedMember(member)} - onHighlightChange={setHighlightedIndex} - /> -
- {selectedMember && ( -
- Selected: - - @[{selectedMember.id.slice(0, 8)}...] - -
- )} -
- -
-

After typing @ali

-

Filtered to matching members

-
- {}} - onHighlightChange={() => {}} - /> -
-
- -
-

Loading State

-

While fetching members

-
- {}} - onHighlightChange={() => {}} - /> -
-
- -
-

No Results

-

After typing @xyz (no match)

-
- {}} - onHighlightChange={() => {}} - /> -
-
-
-
-
-
- ); -} diff --git a/surfsense_web/atoms/chat-comments/comments-query.atoms.ts b/surfsense_web/atoms/chat-comments/comments-query.atoms.ts deleted file mode 100644 index d79c7ea30..000000000 --- a/surfsense_web/atoms/chat-comments/comments-query.atoms.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { atomWithQuery } from "jotai-tanstack-query"; -import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms"; -import { chatCommentsApiService } from "@/lib/apis/chat-comments-api.service"; -import { cacheKeys } from "@/lib/query-client/cache-keys"; - -export const mentionsAtom = atomWithQuery((get) => { - const searchSpaceId = get(activeSearchSpaceIdAtom); - - return { - queryKey: cacheKeys.mentions.all(searchSpaceId ? Number(searchSpaceId) : undefined), - queryFn: async () => { - return chatCommentsApiService.getMentions({ - search_space_id: searchSpaceId ? Number(searchSpaceId) : undefined, - }); - }, - }; -}); diff --git a/surfsense_web/lib/query-client/cache-keys.ts b/surfsense_web/lib/query-client/cache-keys.ts index 37a38c4de..72f2bbd54 100644 --- a/surfsense_web/lib/query-client/cache-keys.ts +++ b/surfsense_web/lib/query-client/cache-keys.ts @@ -75,7 +75,4 @@ export const cacheKeys = { comments: { byMessage: (messageId: number) => ["comments", "message", messageId] as const, }, - mentions: { - all: (searchSpaceId?: number) => ["mentions", searchSpaceId] as const, - }, };