Merge pull request #1234 from buster-so/big-nate-bus-2019-fire-off-suggested-question-as-soon-as-its-clicked-instead

Big nate bus 2019 fire off suggested question as soon as its clicked instead
This commit is contained in:
Nate Kelley 2025-10-01 14:07:00 -06:00 committed by GitHub
commit f66837ebea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 69 additions and 44 deletions

View File

@ -104,6 +104,10 @@ export const BusterChatInputBase: React.FC<BusterChatInputProps> = React.memo(
onSubmit({ ...value, mode });
};
const onSuggestionItemClick = useMemoizedFn(() => {
onSubmitPreflight();
});
const onCloseCreateShortcutModal = useMemoizedFn(() => {
setOpenCreateShortcutModal(false);
});
@ -123,6 +127,7 @@ export const BusterChatInputBase: React.FC<BusterChatInputProps> = React.memo(
<MentionInputSuggestions
defaultValue={defaultValue}
onPressEnter={onSubmitPreflight}
onSuggestionItemClick={onSuggestionItemClick}
mentions={mentions}
suggestionItems={suggestionItems}
disabled={disabled}

View File

@ -166,6 +166,7 @@ const ModePopoverContent = ({
side="bottom"
sideOffset={10}
className="p-0"
onOpenAutoFocus={(e) => e.preventDefault()}
content={
<div className={cn('flex flex-col space-y-3 max-w-[210px] py-3')}>
<div className={cn('flex flex-col space-y-1', classes)}>

View File

@ -66,6 +66,12 @@ export const MentionInputSuggestions = forwardRef<
? !hasClickedSelect && suggestionItems.length > 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;
@ -113,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);
});
@ -193,6 +194,9 @@ export const MentionInputSuggestions = forwardRef<
)}
shouldFilter={shouldFilter}
filter={filter || customFilter}
onClick={() => {
setIsInteracting(true);
}}
>
<MentionInputSuggestionsContainer className={inputContainerClassName}>
<MentionInputSuggestionsMentionsInput

View File

@ -30,6 +30,19 @@ export const MentionInputSuggestionsItem = ({
style,
popoverContent,
}: MentionInputSuggestionsItemProps) => {
const onSelectItem = () => {
onSelect({
value,
inputValue,
label,
onClick,
addValueToInput,
closeOnSelect,
disabled,
loading,
});
};
return (
<PopoverContentWrapper popoverContent={popoverContent}>
<Command.Item
@ -42,17 +55,11 @@ export const MentionInputSuggestionsItem = ({
value={value}
data-testid={`type-${type}-value-${value}`}
style={style}
onMouseDown={() => {
onSelectItem();
}}
onSelect={() => {
onSelect({
value,
inputValue,
label,
onClick,
addValueToInput,
closeOnSelect,
disabled,
loading,
});
onSelectItem();
}}
>
{icon && (

View File

@ -9,7 +9,7 @@ import {
export interface PopoverProps
extends React.ComponentProps<typeof PopoverBase>,
Pick<React.ComponentProps<typeof PopoverContent>, 'align' | 'side'> {
Pick<React.ComponentProps<typeof PopoverContent>, 'align' | 'side' | 'onOpenAutoFocus'> {
children: React.ReactNode;
content: React.ReactNode;
className?: string;
@ -28,6 +28,7 @@ export const Popover = React.memo<PopoverProps>(
trigger = 'click',
size = 'default',
sideOffset,
onOpenAutoFocus,
...props
}) => {
return (
@ -41,6 +42,7 @@ export const Popover = React.memo<PopoverProps>(
className={className}
size={size}
sideOffset={sideOffset}
onOpenAutoFocus={onOpenAutoFocus}
>
{content}
</PopoverContent>

View File

@ -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';
@ -6,6 +7,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;
@ -19,39 +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) {
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,
});
}
};
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'] }) => {