Skip to content

Commit 341b3ae

Browse files
badbyecrazywoolagemini-code-assist[bot]
authored
Sync log detail drawer with conversation_id query parameter, so that we can share a specific conversation (#27518)
Co-authored-by: crazywoola <[email protected]> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent f01907a commit 341b3ae

File tree

1 file changed

+103
-17
lines changed

1 file changed

+103
-17
lines changed

web/app/components/app/log/list.tsx

Lines changed: 103 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import timezone from 'dayjs/plugin/timezone'
1414
import { createContext, useContext } from 'use-context-selector'
1515
import { useShallow } from 'zustand/react/shallow'
1616
import { useTranslation } from 'react-i18next'
17+
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
1718
import type { ChatItemInTree } from '../../base/chat/types'
1819
import Indicator from '../../header/indicator'
1920
import VarPanel from './var-panel'
@@ -42,6 +43,10 @@ import cn from '@/utils/classnames'
4243
import { noop } from 'lodash-es'
4344
import PromptLogModal from '../../base/prompt-log-modal'
4445

46+
type AppStoreState = ReturnType<typeof useAppStore.getState>
47+
type ConversationListItem = ChatConversationGeneralDetail | CompletionConversationGeneralDetail
48+
type ConversationSelection = ConversationListItem | { id: string; isPlaceholder?: true }
49+
4550
dayjs.extend(utc)
4651
dayjs.extend(timezone)
4752

@@ -201,7 +206,7 @@ function DetailPanel({ detail, onFeedback }: IDetailPanel) {
201206
const { formatTime } = useTimestamp()
202207
const { onClose, appDetail } = useContext(DrawerContext)
203208
const { notify } = useContext(ToastContext)
204-
const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, showPromptLogModal, setShowPromptLogModal, currentLogModalActiveTab } = useAppStore(useShallow(state => ({
209+
const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, showPromptLogModal, setShowPromptLogModal, currentLogModalActiveTab } = useAppStore(useShallow((state: AppStoreState) => ({
205210
currentLogItem: state.currentLogItem,
206211
setCurrentLogItem: state.setCurrentLogItem,
207212
showMessageLogModal: state.showMessageLogModal,
@@ -893,20 +898,113 @@ const ChatConversationDetailComp: FC<{ appId?: string; conversationId?: string }
893898
const ConversationList: FC<IConversationList> = ({ logs, appDetail, onRefresh }) => {
894899
const { t } = useTranslation()
895900
const { formatTime } = useTimestamp()
901+
const router = useRouter()
902+
const pathname = usePathname()
903+
const searchParams = useSearchParams()
904+
const conversationIdInUrl = searchParams.get('conversation_id') ?? undefined
896905

897906
const media = useBreakpoints()
898907
const isMobile = media === MediaType.mobile
899908

900909
const [showDrawer, setShowDrawer] = useState<boolean>(false) // Whether to display the chat details drawer
901-
const [currentConversation, setCurrentConversation] = useState<ChatConversationGeneralDetail | CompletionConversationGeneralDetail | undefined>() // Currently selected conversation
910+
const [currentConversation, setCurrentConversation] = useState<ConversationSelection | undefined>() // Currently selected conversation
911+
const closingConversationIdRef = useRef<string | null>(null)
912+
const pendingConversationIdRef = useRef<string | null>(null)
913+
const pendingConversationCacheRef = useRef<ConversationSelection | undefined>(undefined)
902914
const isChatMode = appDetail.mode !== 'completion' // Whether the app is a chat app
903915
const isChatflow = appDetail.mode === 'advanced-chat' // Whether the app is a chatflow app
904-
const { setShowPromptLogModal, setShowAgentLogModal, setShowMessageLogModal } = useAppStore(useShallow(state => ({
916+
const { setShowPromptLogModal, setShowAgentLogModal, setShowMessageLogModal } = useAppStore(useShallow((state: AppStoreState) => ({
905917
setShowPromptLogModal: state.setShowPromptLogModal,
906918
setShowAgentLogModal: state.setShowAgentLogModal,
907919
setShowMessageLogModal: state.setShowMessageLogModal,
908920
})))
909921

922+
const activeConversationId = conversationIdInUrl ?? pendingConversationIdRef.current ?? currentConversation?.id
923+
924+
const buildUrlWithConversation = useCallback((conversationId?: string) => {
925+
const params = new URLSearchParams(searchParams.toString())
926+
if (conversationId)
927+
params.set('conversation_id', conversationId)
928+
else
929+
params.delete('conversation_id')
930+
931+
const queryString = params.toString()
932+
return queryString ? `${pathname}?${queryString}` : pathname
933+
}, [pathname, searchParams])
934+
935+
const handleRowClick = useCallback((log: ConversationListItem) => {
936+
if (conversationIdInUrl === log.id) {
937+
if (!showDrawer)
938+
setShowDrawer(true)
939+
940+
if (!currentConversation || currentConversation.id !== log.id)
941+
setCurrentConversation(log)
942+
return
943+
}
944+
945+
pendingConversationIdRef.current = log.id
946+
pendingConversationCacheRef.current = log
947+
if (!showDrawer)
948+
setShowDrawer(true)
949+
950+
if (currentConversation?.id !== log.id)
951+
setCurrentConversation(undefined)
952+
953+
router.push(buildUrlWithConversation(log.id), { scroll: false })
954+
}, [buildUrlWithConversation, conversationIdInUrl, currentConversation, router, showDrawer])
955+
956+
const currentConversationId = currentConversation?.id
957+
958+
useEffect(() => {
959+
if (!conversationIdInUrl) {
960+
if (pendingConversationIdRef.current)
961+
return
962+
963+
if (showDrawer || currentConversationId) {
964+
setShowDrawer(false)
965+
setCurrentConversation(undefined)
966+
}
967+
closingConversationIdRef.current = null
968+
pendingConversationCacheRef.current = undefined
969+
return
970+
}
971+
972+
if (closingConversationIdRef.current === conversationIdInUrl)
973+
return
974+
975+
if (pendingConversationIdRef.current === conversationIdInUrl)
976+
pendingConversationIdRef.current = null
977+
978+
const matchedConversation = logs?.data?.find((item: ConversationListItem) => item.id === conversationIdInUrl)
979+
const nextConversation: ConversationSelection = matchedConversation
980+
?? pendingConversationCacheRef.current
981+
?? { id: conversationIdInUrl, isPlaceholder: true }
982+
983+
if (!showDrawer)
984+
setShowDrawer(true)
985+
986+
if (!currentConversation || currentConversation.id !== conversationIdInUrl || (!('created_at' in currentConversation) && matchedConversation))
987+
setCurrentConversation(nextConversation)
988+
989+
if (pendingConversationCacheRef.current?.id === conversationIdInUrl || matchedConversation)
990+
pendingConversationCacheRef.current = undefined
991+
}, [conversationIdInUrl, currentConversation, isChatMode, logs?.data, showDrawer])
992+
993+
const onCloseDrawer = useCallback(() => {
994+
onRefresh()
995+
setShowDrawer(false)
996+
setCurrentConversation(undefined)
997+
setShowPromptLogModal(false)
998+
setShowAgentLogModal(false)
999+
setShowMessageLogModal(false)
1000+
pendingConversationIdRef.current = null
1001+
pendingConversationCacheRef.current = undefined
1002+
closingConversationIdRef.current = conversationIdInUrl ?? null
1003+
1004+
if (conversationIdInUrl)
1005+
router.replace(buildUrlWithConversation(), { scroll: false })
1006+
}, [buildUrlWithConversation, conversationIdInUrl, onRefresh, router, setShowAgentLogModal, setShowMessageLogModal, setShowPromptLogModal])
1007+
9101008
// Annotated data needs to be highlighted
9111009
const renderTdValue = (value: string | number | null, isEmptyStyle: boolean, isHighlight = false, annotation?: LogAnnotation) => {
9121010
return (
@@ -925,15 +1023,6 @@ const ConversationList: FC<IConversationList> = ({ logs, appDetail, onRefresh })
9251023
)
9261024
}
9271025

928-
const onCloseDrawer = () => {
929-
onRefresh()
930-
setShowDrawer(false)
931-
setCurrentConversation(undefined)
932-
setShowPromptLogModal(false)
933-
setShowAgentLogModal(false)
934-
setShowMessageLogModal(false)
935-
}
936-
9371026
if (!logs)
9381027
return <Loading />
9391028

@@ -960,11 +1049,8 @@ const ConversationList: FC<IConversationList> = ({ logs, appDetail, onRefresh })
9601049
const rightValue = get(log, isChatMode ? 'message_count' : 'message.answer')
9611050
return <tr
9621051
key={log.id}
963-
className={cn('cursor-pointer border-b border-divider-subtle hover:bg-background-default-hover', currentConversation?.id !== log.id ? '' : 'bg-background-default-hover')}
964-
onClick={() => {
965-
setShowDrawer(true)
966-
setCurrentConversation(log)
967-
}}>
1052+
className={cn('cursor-pointer border-b border-divider-subtle hover:bg-background-default-hover', activeConversationId !== log.id ? '' : 'bg-background-default-hover')}
1053+
onClick={() => handleRowClick(log)}>
9681054
<td className='h-4'>
9691055
{!log.read_at && (
9701056
<div className='flex items-center p-3 pr-0.5'>

0 commit comments

Comments
 (0)