mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-24 09:49:32 +08:00
fix(frontend): blur upload button so "Upload File" tooltip doesn't persist after file picker closes (#13178)
fix(frontend): blur upload button so tooltip doesn't persist after file picker closes On the My Files page, clicking the "Upload Files" button kept the "Upload File" tooltip visible after the OS file picker closed. The button is wrapped in a Radix tooltip, which shows on focus; when the file dialog closed, focus was restored to the button and re-triggered the tooltip. Blur the button on click so focus doesn't return to it. Also tighten pre-existing `any` types in FilesTab to satisfy the no-explicit-any lint rule on the staged file.
This commit is contained in:
@ -1,30 +1,48 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import React from "react";
|
||||
import type { ReactNode } from "react";
|
||||
import { CategoryGroup } from "../categoryGroup";
|
||||
|
||||
type MockChildrenProps = {
|
||||
children?: ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
type MockCategoryDisclosureProps = {
|
||||
item: { name: string; display_name: string };
|
||||
openCategories: string[];
|
||||
};
|
||||
|
||||
type MockSearchConfigTriggerProps = {
|
||||
showConfig: boolean;
|
||||
setShowConfig: (value: boolean) => void;
|
||||
};
|
||||
|
||||
// Mock the UI components
|
||||
jest.mock("@/components/ui/sidebar", () => ({
|
||||
SidebarGroup: ({ children, className }: any) => (
|
||||
SidebarGroup: ({ children, className }: MockChildrenProps) => (
|
||||
<div data-testid="sidebar-group" className={className}>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
SidebarGroupContent: ({ children }: any) => (
|
||||
SidebarGroupContent: ({ children }: MockChildrenProps) => (
|
||||
<div data-testid="sidebar-group-content">{children}</div>
|
||||
),
|
||||
SidebarGroupLabel: ({ children, className }: any) => (
|
||||
SidebarGroupLabel: ({ children, className }: MockChildrenProps) => (
|
||||
<div data-testid="sidebar-group-label" className={className}>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
SidebarMenu: ({ children }: any) => (
|
||||
SidebarMenu: ({ children }: MockChildrenProps) => (
|
||||
<div data-testid="sidebar-menu">{children}</div>
|
||||
),
|
||||
}));
|
||||
|
||||
// Mock the CategoryDisclosure component
|
||||
jest.mock("../categoryDisclouse", () => ({
|
||||
CategoryDisclosure: ({ item, openCategories }: any) => (
|
||||
CategoryDisclosure: ({
|
||||
item,
|
||||
openCategories,
|
||||
}: MockCategoryDisclosureProps) => (
|
||||
<div data-testid={`category-disclosure-${item.name}`}>
|
||||
CategoryDisclosure for {item.display_name} - Open:{" "}
|
||||
{openCategories.includes(item.name).toString()}
|
||||
@ -42,7 +60,10 @@ jest.mock("@/utils/styleUtils", () => ({
|
||||
|
||||
// Mock the SearchConfigTrigger component
|
||||
jest.mock("../searchConfigTrigger", () => ({
|
||||
SearchConfigTrigger: ({ showConfig, setShowConfig }: any) => (
|
||||
SearchConfigTrigger: ({
|
||||
showConfig,
|
||||
setShowConfig,
|
||||
}: MockSearchConfigTriggerProps) => (
|
||||
<button
|
||||
data-testid="search-config-trigger"
|
||||
onClick={() => setShowConfig(!showConfig)}
|
||||
|
||||
@ -21,6 +21,7 @@ import useUploadFile from "@/hooks/files/use-upload-file";
|
||||
import DeleteConfirmationModal from "@/modals/deleteConfirmationModal";
|
||||
import FilesContextMenuComponent from "@/modals/fileManagerModal/components/filesContextMenuComponent";
|
||||
import useAlertStore from "@/stores/alertStore";
|
||||
import type { FileType } from "@/types/file_management";
|
||||
import { formatFileSize } from "@/utils/stringManipulation";
|
||||
import { FILE_ICONS } from "@/utils/styleUtils";
|
||||
import { cn } from "@/utils/utils";
|
||||
@ -30,8 +31,8 @@ import DragWrapComponent from "./dragWrapComponent";
|
||||
interface FilesTabProps {
|
||||
quickFilterText: string;
|
||||
setQuickFilterText: (text: string) => void;
|
||||
selectedFiles: any[];
|
||||
setSelectedFiles: (files: any[]) => void;
|
||||
selectedFiles: FileType[];
|
||||
setSelectedFiles: (files: FileType[]) => void;
|
||||
quantitySelected: number;
|
||||
setQuantitySelected: (quantity: number) => void;
|
||||
isShiftPressed: boolean;
|
||||
@ -47,14 +48,14 @@ const FilesTab = ({
|
||||
isShiftPressed,
|
||||
}: FilesTabProps) => {
|
||||
const { t } = useTranslation();
|
||||
const tableRef = useRef<AgGridReact<any>>(null);
|
||||
const tableRef = useRef<AgGridReact<FileType>>(null);
|
||||
const { data: files } = useGetFilesV2();
|
||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
|
||||
const { mutate: rename } = usePostRenameFileV2();
|
||||
const { mutate: deleteFiles, isPending: isDeleting } = useDeleteFilesV2();
|
||||
const handleRename = (params: NewValueParams<any, any>) => {
|
||||
const handleRename = (params: NewValueParams<FileType, string>) => {
|
||||
rename({
|
||||
id: params.data.id,
|
||||
name: params.newValue,
|
||||
@ -85,10 +86,14 @@ const FilesTab = ({
|
||||
: t("files.uploadedSuccessfully"),
|
||||
});
|
||||
}
|
||||
} catch (error: any) {
|
||||
} catch (error) {
|
||||
const message =
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: t("files.errorUploadingDetail");
|
||||
setErrorData({
|
||||
title: t("files.errorUploading"),
|
||||
list: [error.message || t("files.errorUploadingDetail")],
|
||||
list: [message],
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -276,7 +281,8 @@ const FilesTab = ({
|
||||
<ShadTooltip content={t("files.uploadFile")} side="bottom">
|
||||
<Button
|
||||
className="!px-3 md:!px-4 md:!pl-3.5"
|
||||
onClick={async () => {
|
||||
onClick={async (e) => {
|
||||
e.currentTarget.blur();
|
||||
await handleUpload();
|
||||
}}
|
||||
id="upload-file-btn"
|
||||
|
||||
Reference in New Issue
Block a user