From 207be8c4c12aaaf3eca9e3b9895d5cd9b66b8e0f Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Wed, 1 Oct 2025 13:40:12 -0600 Subject: [PATCH 1/4] open on click --- .../inputs/MentionInputSuggestions/MentionInputSuggestions.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx index 9d33a67fa..54ff9ceb4 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx @@ -193,6 +193,9 @@ export const MentionInputSuggestions = forwardRef< )} shouldFilter={shouldFilter} filter={filter || customFilter} + onClick={() => { + setIsInteracting(true); + }} > Date: Wed, 1 Oct 2025 13:44:16 -0600 Subject: [PATCH 2/4] prevent focus capture from segmented --- .../features/input/BusterChatInput/BusterChatInputButtons.tsx | 1 + .../MentionInputSuggestions/MentionInputSuggestions.tsx | 1 + apps/web/src/components/ui/popover/Popover.tsx | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/features/input/BusterChatInput/BusterChatInputButtons.tsx b/apps/web/src/components/features/input/BusterChatInput/BusterChatInputButtons.tsx index 99b87ce17..f6b81cfb9 100644 --- a/apps/web/src/components/features/input/BusterChatInput/BusterChatInputButtons.tsx +++ b/apps/web/src/components/features/input/BusterChatInput/BusterChatInputButtons.tsx @@ -166,6 +166,7 @@ const ModePopoverContent = ({ side="bottom" sideOffset={10} className="p-0" + onOpenAutoFocus={(e) => e.preventDefault()} content={
diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx index 54ff9ceb4..b55292cb6 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx @@ -95,6 +95,7 @@ export const MentionInputSuggestions = forwardRef< const onSelectItem = useMemoizedFn( ({ onClick, ...params }: MentionInputSuggestionsOnSelectParams) => { const { addValueToInput, loading, label, disabled, inputValue } = params; + console.log('onSelectItem', params); if (disabled) { console.warn('Item is disabled', params); return; diff --git a/apps/web/src/components/ui/popover/Popover.tsx b/apps/web/src/components/ui/popover/Popover.tsx index 9a4a1a27f..d0661c02b 100644 --- a/apps/web/src/components/ui/popover/Popover.tsx +++ b/apps/web/src/components/ui/popover/Popover.tsx @@ -9,7 +9,7 @@ import { export interface PopoverProps extends React.ComponentProps, - Pick, 'align' | 'side'> { + Pick, 'align' | 'side' | 'onOpenAutoFocus'> { children: React.ReactNode; content: React.ReactNode; className?: string; @@ -28,6 +28,7 @@ export const Popover = React.memo( trigger = 'click', size = 'default', sideOffset, + onOpenAutoFocus, ...props }) => { return ( @@ -41,6 +42,7 @@ export const Popover = React.memo( className={className} size={size} sideOffset={sideOffset} + onOpenAutoFocus={onOpenAutoFocus} > {content} From 8a4a05660389dfd0445568a5ba07871987144a10 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Wed, 1 Oct 2025 13:52:19 -0600 Subject: [PATCH 3/4] on select items submit --- .../BusterChatInput/BusterChatInputBase.tsx | 5 ++++ .../MentionInputSuggestions.tsx | 16 +++++------ .../MentionInputSuggestionsItem.tsx | 27 ++++++++++++------- apps/web/src/context/Chats/useChat.ts | 5 +++- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/apps/web/src/components/features/input/BusterChatInput/BusterChatInputBase.tsx b/apps/web/src/components/features/input/BusterChatInput/BusterChatInputBase.tsx index a900141ff..ba5812b1e 100644 --- a/apps/web/src/components/features/input/BusterChatInput/BusterChatInputBase.tsx +++ b/apps/web/src/components/features/input/BusterChatInput/BusterChatInputBase.tsx @@ -104,6 +104,10 @@ export const BusterChatInputBase: React.FC = React.memo( onSubmit({ ...value, mode }); }; + const onSuggestionItemClick = useMemoizedFn(() => { + onSubmitPreflight(); + }); + const onCloseCreateShortcutModal = useMemoizedFn(() => { setOpenCreateShortcutModal(false); }); @@ -123,6 +127,7 @@ export const BusterChatInputBase: React.FC = React.memo( 0 : isInteracting && suggestionItems.length > 0; + // biome-ignore lint/style/noNonNullAssertion: we know the ref is not null + const getValue = mentionsInputRef.current?.getValue!; + // biome-ignore lint/style/noNonNullAssertion: we know the ref is not null + const addMentionToInput = mentionsInputRef.current?.addMentionToInput!; + const mounted = useMounted(); + const onChangeInputValue: MentionInputProps['onChange'] = useCallback( (d) => { const { transformedValue } = d; @@ -95,7 +101,6 @@ export const MentionInputSuggestions = forwardRef< const onSelectItem = useMemoizedFn( ({ onClick, ...params }: MentionInputSuggestionsOnSelectParams) => { const { addValueToInput, loading, label, disabled, inputValue } = params; - console.log('onSelectItem', params); if (disabled) { console.warn('Item is disabled', params); return; @@ -114,17 +119,12 @@ export const MentionInputSuggestions = forwardRef< setValue(stringValue); } onClick?.(); - if (closeSuggestionOnSelect && params.closeOnSelect !== false) setHasClickedSelect(true); onSuggestionItemClick?.(params); + + if (closeSuggestionOnSelect && params.closeOnSelect !== false) setHasClickedSelect(true); } ); - // biome-ignore lint/style/noNonNullAssertion: we know the ref is not null - const getValue = mentionsInputRef.current?.getValue!; - // biome-ignore lint/style/noNonNullAssertion: we know the ref is not null - const addMentionToInput = mentionsInputRef.current?.addMentionToInput!; - const mounted = useMounted(); - const onBlur = useMemoizedFn(() => { setIsInteracting(false); }); diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItem.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItem.tsx index b60e2f028..b6cedd62b 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItem.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItem.tsx @@ -30,6 +30,19 @@ export const MentionInputSuggestionsItem = ({ style, popoverContent, }: MentionInputSuggestionsItemProps) => { + const onSelectItem = () => { + onSelect({ + value, + inputValue, + label, + onClick, + addValueToInput, + closeOnSelect, + disabled, + loading, + }); + }; + return ( { + onSelectItem(); + }} onSelect={() => { - onSelect({ - value, - inputValue, - label, - onClick, - addValueToInput, - closeOnSelect, - disabled, - loading, - }); + onSelectItem(); }} > {icon && ( diff --git a/apps/web/src/context/Chats/useChat.ts b/apps/web/src/context/Chats/useChat.ts index b480bbdff..0207cef30 100644 --- a/apps/web/src/context/Chats/useChat.ts +++ b/apps/web/src/context/Chats/useChat.ts @@ -6,6 +6,7 @@ import { useGetChatMemoized, useGetChatMessageMemoized } from '@/api/buster_rest import { useStartNewChat, useStopChat } from '@/api/buster_rest/chats/queryRequestsV2'; import { useChatUpdate } from '@/api/buster_rest/chats/useChatUpdate'; import { useMemoizedFn } from '@/hooks/useMemoizedFn'; +import { timeout } from '@/lib/timeout'; type StartChatParams = { prompt: string | undefined; @@ -46,11 +47,13 @@ export const useChat = () => { const hasMultipleMessages = message_ids.length > 1; if (!hasMultipleMessages) { - navigate({ + await navigate({ to: '/app/chats/$chatId', params: { chatId: id }, }); } + + await timeout(500); }; const onStartNewChat = useMemoizedFn( From de07b2c64a445c80963050bc8435ec13a44719f3 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Wed, 1 Oct 2025 13:59:22 -0600 Subject: [PATCH 4/4] loading state should wait --- apps/web/src/context/Chats/useChat.ts | 57 ++++++++++++++------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/apps/web/src/context/Chats/useChat.ts b/apps/web/src/context/Chats/useChat.ts index 0207cef30..2103f1389 100644 --- a/apps/web/src/context/Chats/useChat.ts +++ b/apps/web/src/context/Chats/useChat.ts @@ -1,4 +1,5 @@ import type { MessageAnalysisMode } from '@buster/server-shared/chats'; +import { useMutation } from '@tanstack/react-query'; import { useNavigate } from '@tanstack/react-router'; import { create } from 'mutative'; import type { FileType } from '@/api/asset_interfaces/chat'; @@ -20,41 +21,43 @@ type StartChatParams = { export const useChat = () => { const navigate = useNavigate(); - const { mutateAsync: startNewChat, isPending: isSubmittingChat } = useStartNewChat(); + const { mutateAsync: startNewChatServerFn } = useStartNewChat(); const { mutateAsync: stopChatMutation } = useStopChat(); const getChatMemoized = useGetChatMemoized(); const getChatMessageMemoized = useGetChatMessageMemoized(); const { onUpdateChat, onUpdateChatMessage } = useChatUpdate(); - const startChat = async ({ - prompt, - chatId, - metricId, - dashboardId, - messageId, - mode, - }: StartChatParams) => { - const res = await startNewChat({ + const { mutateAsync: startChat, isPending: isSubmittingChat } = useMutation({ + mutationFn: async ({ prompt, - chat_id: chatId, - metric_id: metricId, - dashboard_id: dashboardId, - message_id: messageId, - message_analysis_mode: mode, - }); - - const { message_ids, id } = res; - - const hasMultipleMessages = message_ids.length > 1; - if (!hasMultipleMessages) { - await navigate({ - to: '/app/chats/$chatId', - params: { chatId: id }, + chatId, + metricId, + dashboardId, + messageId, + mode, + }: StartChatParams) => { + const res = await startNewChatServerFn({ + prompt, + chat_id: chatId, + metric_id: metricId, + dashboard_id: dashboardId, + message_id: messageId, + message_analysis_mode: mode, }); - } - await timeout(500); - }; + const { message_ids, id } = res; + + const hasMultipleMessages = message_ids.length > 1; + if (!hasMultipleMessages) { + await navigate({ + to: '/app/chats/$chatId', + params: { chatId: id }, + }); + } + + await timeout(150); + }, + }); const onStartNewChat = useMemoizedFn( async (d: { prompt: string; mode: StartChatParams['mode'] }) => {