Merge pull request #1180 from buster-so/big-nate-bus-1967-closing-and-reopening-a-dashboard-in-chat-adds-a-large-blank

Big nate bus 1967 closing and reopening a dashboard in chat adds a large blank
This commit is contained in:
Nate Kelley 2025-09-26 11:55:44 -06:00 committed by GitHub
commit f4102880e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 39 additions and 19 deletions

View File

@ -80,8 +80,9 @@ export const usePrefetchGetDashboardClient = <TData = GetDashboardResponse>(
params?: Omit<UseQueryOptions<GetDashboardResponse, RustApiError, TData>, 'queryKey' | 'queryFn'> params?: Omit<UseQueryOptions<GetDashboardResponse, RustApiError, TData>, 'queryKey' | 'queryFn'>
) => { ) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const queryFn = useGetDashboardAndInitializeMetrics({ prefetchData: false });
return useMemoizedFn((id: string, versionNumber: number | 'LATEST') => { return useMemoizedFn((id: string, versionNumber: number | 'LATEST') => {
const queryFn = useGetDashboardAndInitializeMetrics({ prefetchData: false });
const getDashboardQueryKey = dashboardQueryKeys.dashboardGetDashboard(id, versionNumber); const getDashboardQueryKey = dashboardQueryKeys.dashboardGetDashboard(id, versionNumber);
const isStale = isQueryStale(getDashboardQueryKey, queryClient) || params?.staleTime === 0; const isStale = isQueryStale(getDashboardQueryKey, queryClient) || params?.staleTime === 0;
if (!isStale) return; if (!isStale) return;

View File

@ -1,9 +1,7 @@
import { ClientOnly } from '@tanstack/react-router';
import { cva, type VariantProps } from 'class-variance-authority'; import { cva, type VariantProps } from 'class-variance-authority';
import React, { useEffect, useRef } from 'react'; import React, { useImperativeHandle, useRef } from 'react';
import TextareaAutosize, { type TextareaAutosizeProps } from 'react-textarea-autosize'; import TextareaAutosize, { type TextareaAutosizeProps } from 'react-textarea-autosize';
import { cn } from '@/lib/classMerge'; import { cn } from '@/lib/classMerge';
import { useMounted } from '../../../hooks/useMount';
import { inputVariants } from './Input'; import { inputVariants } from './Input';
const inputTextAreaVariants = inputVariants; const inputTextAreaVariants = inputVariants;
@ -30,7 +28,11 @@ export interface InputTextAreaProps
onPressEnter?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void; onPressEnter?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
} }
export const InputTextArea = React.forwardRef<HTMLTextAreaElement, InputTextAreaProps>( export interface InputTextAreaRef {
forceRecalculateHeight: () => void;
}
export const InputTextArea = React.forwardRef<InputTextAreaRef, InputTextAreaProps>(
( (
{ {
className, className,
@ -46,14 +48,19 @@ export const InputTextArea = React.forwardRef<HTMLTextAreaElement, InputTextArea
) => { ) => {
const textareaRef = useRef<HTMLTextAreaElement | null>(null); const textareaRef = useRef<HTMLTextAreaElement | null>(null);
const combinedRef = (node: HTMLTextAreaElement) => { useImperativeHandle(
textareaRef.current = node; ref,
if (typeof ref === 'function') { () => ({
ref(node); forceRecalculateHeight: () => {
} else if (ref) { if (textareaRef.current) {
ref.current = node; // Force a recalculation by triggering an input event
} const event = new Event('input', { bubbles: true });
}; textareaRef.current.dispatchEvent(event);
}
},
}),
[]
);
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => { const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
@ -70,16 +77,16 @@ export const InputTextArea = React.forwardRef<HTMLTextAreaElement, InputTextArea
return ( return (
<TextareaAutosize <TextareaAutosize
ref={combinedRef} ref={textareaRef}
className={cn( className={cn(
inputTextAreaVariants({ variant }), inputTextAreaVariants({ variant }),
textAreaVariants({ rounding }), textAreaVariants({ rounding }),
'px-2.5 py-2.5 resize-none! box-border', 'px-2.5 py-2.5 resize-none! box-border',
className className
)} )}
value={props.value}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
style={style as Omit<React.CSSProperties, 'height'>} style={style as Omit<React.CSSProperties, 'height'>}
cacheMeasurements={false}
{...props} {...props}
/> />
); );

View File

@ -1,8 +1,10 @@
import React, { useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { useUpdateDashboard } from '@/api/buster_rest/dashboards'; import { useUpdateDashboard } from '@/api/buster_rest/dashboards';
import { InputTextArea } from '@/components/ui/inputs/InputTextArea'; import { InputTextArea, type InputTextAreaRef } from '@/components/ui/inputs/InputTextArea';
import { EditableTitle } from '@/components/ui/typography/EditableTitle'; import { EditableTitle } from '@/components/ui/typography/EditableTitle';
import { useDebounce } from '@/hooks/useDebounce';
import { useMount } from '@/hooks/useMount'; import { useMount } from '@/hooks/useMount';
import { useSize } from '@/hooks/useSize';
export const DASHBOARD_TITLE_INPUT_ID = (dashboardId: string) => `${dashboardId}-title-input`; export const DASHBOARD_TITLE_INPUT_ID = (dashboardId: string) => `${dashboardId}-title-input`;
@ -15,6 +17,9 @@ export const DashboardEditTitles: React.FC<{
dashboardId: string; dashboardId: string;
}> = React.memo(({ readOnly, title, description, dashboardId }) => { }> = React.memo(({ readOnly, title, description, dashboardId }) => {
const titleRef = useRef<HTMLInputElement>(null); const titleRef = useRef<HTMLInputElement>(null);
const inputTextAreaRef = useRef<InputTextAreaRef>(null);
const size = useSize(titleRef);
const debouncedWidth = useDebounce(size?.width, { wait: 50, maxWait: 85 });
const { mutateAsync: onUpdateDashboard } = useUpdateDashboard({ const { mutateAsync: onUpdateDashboard } = useUpdateDashboard({
saveToServer: false, saveToServer: false,
}); });
@ -37,6 +42,12 @@ export const DashboardEditTitles: React.FC<{
} }
}); });
useEffect(() => {
if (debouncedWidth) {
inputTextAreaRef.current?.forceRecalculateHeight();
}
}, [debouncedWidth]);
return ( return (
<div className="flex flex-col space-y-1.5"> <div className="flex flex-col space-y-1.5">
<EditableTitle <EditableTitle
@ -54,8 +65,9 @@ export const DashboardEditTitles: React.FC<{
{(description || !readOnly) && ( {(description || !readOnly) && (
<InputTextArea <InputTextArea
ref={inputTextAreaRef}
variant="ghost" variant="ghost"
readOnly={readOnly} readOnly={false}
onChange={onChangeDashboardDescription} onChange={onChangeDashboardDescription}
value={description} value={description}
minRows={1} minRows={1}

View File

@ -41,7 +41,7 @@ export const ChatInput: React.FC = React.memo(() => {
useEffect(() => { useEffect(() => {
if (hasChat) { if (hasChat) {
requestAnimationFrame(() => { requestAnimationFrame(() => {
textAreaRef.current?.focus(); textAreaRef.current?.focus?.();
}); });
} }
}, [hasChat, textAreaRef]); }, [hasChat, textAreaRef]);