mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-23 11:50:14 +01:00
📂 refactor: Improve FileAttachment & File Form Deletion (#7471)
* refactor: optional attachment properties for `FileAttachment` * refactor: update ActionButton to use localized text * chore: localize text in DataTableFile, add missing translation, imports order, and linting * chore: linting in DataTable * fix: integrate Recoil state management for file deletion in DataTableFile * fix: integrate Recoil state management for file deletion in DataTable * fix: add temp_file_id to BatchFile type and update deleteFiles logic to properly remove files that are mapped to temp_file_id
This commit is contained in:
parent
e86842fd19
commit
eb1668ff22
7 changed files with 65 additions and 40 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { useState } from 'react';
|
||||
import { ListFilter } from 'lucide-react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import {
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
|
|
@ -36,6 +37,7 @@ import { TrashIcon, Spinner } from '~/components/svg';
|
|||
import useLocalize from '~/hooks/useLocalize';
|
||||
import { useMediaQuery } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
import store from '~/store';
|
||||
|
||||
interface DataTableProps<TData, TValue> {
|
||||
columns: ColumnDef<TData, TValue>[];
|
||||
|
|
@ -60,12 +62,14 @@ type Style = {
|
|||
export default function DataTable<TData, TValue>({ columns, data }: DataTableProps<TData, TValue>) {
|
||||
const localize = useLocalize();
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const setFiles = useSetRecoilState(store.filesByIndex(0));
|
||||
const { deleteFiles } = useDeleteFilesFromTable(() => setIsDeleting(false));
|
||||
|
||||
const [rowSelection, setRowSelection] = useState({});
|
||||
const [sorting, setSorting] = useState<SortingState>([]);
|
||||
const isSmallScreen = useMediaQuery('(max-width: 768px)');
|
||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||
const { deleteFiles } = useDeleteFilesFromTable(() => setIsDeleting(false));
|
||||
|
||||
const table = useReactTable({
|
||||
data,
|
||||
|
|
@ -96,7 +100,7 @@ export default function DataTable<TData, TValue>({ columns, data }: DataTablePro
|
|||
const filesToDelete = table
|
||||
.getFilteredSelectedRowModel()
|
||||
.rows.map((row) => row.original);
|
||||
deleteFiles({ files: filesToDelete as TFile[] });
|
||||
deleteFiles({ files: filesToDelete as TFile[], setFiles });
|
||||
setRowSelection({});
|
||||
}}
|
||||
disabled={!table.getFilteredSelectedRowModel().rows.length || isDeleting}
|
||||
|
|
@ -218,13 +222,10 @@ export default function DataTable<TData, TValue>({ columns, data }: DataTablePro
|
|||
<div className="flex items-center justify-end gap-2 py-4">
|
||||
<div className="ml-2 flex-1 truncate text-xs text-muted-foreground sm:ml-4 sm:text-sm">
|
||||
<span className="hidden sm:inline">
|
||||
{localize(
|
||||
'com_files_number_selected',
|
||||
{
|
||||
0: `${table.getFilteredSelectedRowModel().rows.length}`,
|
||||
1: `${table.getFilteredRowModel().rows.length}`,
|
||||
},
|
||||
)}
|
||||
{localize('com_files_number_selected', {
|
||||
0: `${table.getFilteredSelectedRowModel().rows.length}`,
|
||||
1: `${table.getFilteredRowModel().rows.length}`,
|
||||
})}
|
||||
</span>
|
||||
<span className="sm:hidden">
|
||||
{`${table.getFilteredSelectedRowModel().rows.length}/${
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import Image from '~/components/Chat/Messages/Content/Image';
|
|||
import { useAttachmentLink } from './LogLink';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
const FileAttachment = memo(({ attachment }: { attachment: TAttachment }) => {
|
||||
const FileAttachment = memo(({ attachment }: { attachment: Partial<TAttachment> }) => {
|
||||
const { handleDownload } = useAttachmentLink({
|
||||
href: attachment.filepath,
|
||||
filename: attachment.filename,
|
||||
href: attachment.filepath ?? '',
|
||||
filename: attachment.filename ?? '',
|
||||
});
|
||||
const extension = attachment.filename.split('.').pop();
|
||||
const extension = attachment.filename?.split('.').pop();
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -19,6 +19,9 @@ const FileAttachment = memo(({ attachment }: { attachment: TAttachment }) => {
|
|||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
if (!attachment.filepath) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
@ -88,6 +91,8 @@ export default function Attachment({ attachment }: { attachment?: TAttachment })
|
|||
|
||||
if (isImage) {
|
||||
return <ImageAttachment attachment={attachment} />;
|
||||
} else if (!attachment.filepath) {
|
||||
return null;
|
||||
}
|
||||
return <FileAttachment attachment={attachment} />;
|
||||
}
|
||||
|
|
@ -119,9 +124,11 @@ export function AttachmentGroup({ attachments }: { attachments?: TAttachment[] }
|
|||
<>
|
||||
{fileAttachments.length > 0 && (
|
||||
<div className="my-2 flex flex-wrap items-center gap-2.5">
|
||||
{fileAttachments.map((attachment, index) => (
|
||||
<FileAttachment attachment={attachment} key={`file-${index}`} />
|
||||
))}
|
||||
{fileAttachments.map((attachment, index) =>
|
||||
attachment.filepath ? (
|
||||
<FileAttachment attachment={attachment} key={`file-${index}`} />
|
||||
) : null,
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{imageAttachments.length > 0 && (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue