feat: implement document deletion functionality and streamline column visibility management in DocumentsTable

This commit is contained in:
Anish Sarkar 2026-02-05 01:29:15 +05:30
parent d5fd4c2863
commit e615a6478c
3 changed files with 50 additions and 68 deletions

View file

@ -4,7 +4,6 @@ import { useSetAtom } from "jotai";
import {
CircleAlert,
CircleX,
Columns3,
FilePlus2,
FileType,
ListFilter,
@ -31,11 +30,9 @@ import {
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import type { DocumentTypeEnum } from "@/contracts/types/document.types";
import { getDocumentTypeIcon, getDocumentTypeLabel } from "./DocumentTypeIcon";
import type { ColumnVisibility } from "./types";
export function DocumentsFilters({
typeCounts: typeCountsRecord,
@ -45,8 +42,6 @@ export function DocumentsFilters({
onBulkDelete,
onToggleType,
activeTypes,
columnVisibility,
onToggleColumn,
}: {
typeCounts: Partial<Record<DocumentTypeEnum, number>>;
selectedIds: Set<number>;
@ -55,8 +50,6 @@ export function DocumentsFilters({
onBulkDelete: () => Promise<void>;
onToggleType: (type: DocumentTypeEnum, checked: boolean) => void;
activeTypes: DocumentTypeEnum[];
columnVisibility: ColumnVisibility;
onToggleColumn: (id: keyof ColumnVisibility, checked: boolean) => void;
}) {
const t = useTranslations("documents");
const id = React.useId();
@ -252,57 +245,7 @@ export function DocumentsFilters({
</PopoverContent>
</Popover>
{/* View/Columns Popover */}
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
size="sm"
className="h-9 gap-2 border-dashed border-border/60 text-muted-foreground hover:text-foreground hover:border-border"
>
<Columns3 size={14} className="text-muted-foreground" />
<span className="hidden sm:inline">View</span>
</Button>
</PopoverTrigger>
<PopoverContent className="w-36 !p-0 overflow-hidden" align="end">
<div className="px-2.5 pt-3 pb-2">
<div className="mb-1.5 px-1 text-[11px] font-medium text-muted-foreground">
Toggle columns
</div>
<div className="space-y-0.5">
{(
[
["document_type", "Source"],
["created_by", "User"],
["created_at", "Created"],
] as Array<[keyof ColumnVisibility, string]>
).map(([key, label], i) => (
<button
key={key}
type="button"
className="flex w-full items-center gap-2 py-1 px-2.5 rounded-md hover:bg-muted/50 transition-colors cursor-pointer text-left"
onClick={() => onToggleColumn(key, !columnVisibility[key])}
>
<Checkbox
id={`${id}-col-${i}`}
checked={columnVisibility[key]}
onCheckedChange={(checked: boolean) => onToggleColumn(key, !!checked)}
className="h-3.5 w-3.5 flex-shrink-0 data-[state=checked]:bg-primary data-[state=checked]:border-primary"
/>
<Label
htmlFor={`${id}-col-${i}`}
className="flex flex-1 items-center gap-2 font-normal text-xs cursor-pointer min-w-0"
>
<span className="truncate min-w-0">{label}</span>
</Label>
</button>
))}
</div>
</div>
</PopoverContent>
</Popover>
{/* Bulk Delete Button - positioned next to View on mobile */}
{/* Bulk Delete Button */}
{selectedIds.size > 0 && (
<AlertDialog>
<AlertDialogTrigger asChild>

View file

@ -28,6 +28,7 @@ import {
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { documentsApiService } from "@/lib/apis/documents-api.service";
import { DocumentTypeChip } from "./DocumentTypeIcon";
import { RowActions } from "./RowActions";
import type { ColumnVisibility, Document } from "./types";
export type SortKey = keyof Pick<Document, "title" | "document_type" | "created_at">;
@ -142,6 +143,8 @@ export function DocumentsTableShell({
sortKey,
sortDesc,
onSortChange,
deleteDocument,
searchSpaceId,
}: {
documents: Document[];
loading: boolean;
@ -153,6 +156,8 @@ export function DocumentsTableShell({
sortKey: SortKey;
sortDesc: boolean;
onSortChange: (key: SortKey) => void;
deleteDocument: (id: number) => Promise<boolean>;
searchSpaceId: string;
}) {
const t = useTranslations("documents");
const { openDialog } = useDocumentUploadDialog();
@ -273,7 +278,7 @@ export function DocumentsTableShell({
<Table className="table-fixed w-full">
<TableHeader>
<TableRow className="hover:bg-transparent border-b border-border/40">
<TableHead className="w-8 px-0 text-center border-r border-border/40">
<TableHead className="w-8 px-0 text-center">
<div className="flex items-center justify-center h-full">
<Skeleton className="h-4 w-4 rounded" />
</div>
@ -296,6 +301,9 @@ export function DocumentsTableShell({
<Skeleton className="h-3 w-16" />
</TableHead>
)}
<TableHead className="w-10">
<span className="sr-only">Actions</span>
</TableHead>
</TableRow>
</TableHeader>
</Table>
@ -307,7 +315,7 @@ export function DocumentsTableShell({
key={`skeleton-${index}`}
className="border-b border-border/40 hover:bg-transparent"
>
<TableCell className="w-8 px-0 py-2.5 text-center border-r border-border/40">
<TableCell className="w-8 px-0 py-2.5 text-center">
<div className="flex items-center justify-center h-full">
<Skeleton className="h-4 w-4 rounded" />
</div>
@ -333,6 +341,9 @@ export function DocumentsTableShell({
<Skeleton className="h-4 w-20" />
</TableCell>
)}
<TableCell className="w-10 py-2.5 text-center">
<Skeleton className="h-6 w-6 mx-auto rounded" />
</TableCell>
</TableRow>
))}
</TableBody>
@ -406,7 +417,7 @@ export function DocumentsTableShell({
<Table className="table-fixed w-full">
<TableHeader>
<TableRow className="hover:bg-transparent border-b border-border/40">
<TableHead className="w-8 px-0 text-center border-r border-border/40">
<TableHead className="w-8 px-0 text-center">
<div className="flex items-center justify-center h-full">
<Checkbox
checked={allSelectedOnPage || (someSelectedOnPage && "indeterminate")}
@ -461,6 +472,9 @@ export function DocumentsTableShell({
</SortableHeader>
</TableHead>
)}
<TableHead className="w-10">
<span className="sr-only">Actions</span>
</TableHead>
</TableRow>
</TableHeader>
</Table>
@ -488,7 +502,7 @@ export function DocumentsTableShell({
: "hover:bg-muted/30"
}`}
>
<TableCell className="w-8 px-0 py-2.5 text-center border-r border-border/40">
<TableCell className="w-8 px-0 py-2.5 text-center">
<div className="flex items-center justify-center h-full">
<Checkbox
checked={isSelected}
@ -549,6 +563,13 @@ export function DocumentsTableShell({
</Tooltip>
</TableCell>
)}
<TableCell className="w-10 py-2.5 text-center">
<RowActions
document={doc}
deleteDocument={deleteDocument}
searchSpaceId={searchSpaceId}
/>
</TableCell>
</motion.tr>
);
})}
@ -626,6 +647,11 @@ export function DocumentsTableShell({
)}
</div>
</div>
<RowActions
document={doc}
deleteDocument={deleteDocument}
searchSpaceId={searchSpaceId}
/>
</div>
</motion.div>
);

View file

@ -138,10 +138,6 @@ export default function DocumentsTable() {
setPageIndex(0);
};
const onToggleColumn = (id: keyof ColumnVisibility, checked: boolean) => {
setColumnVisibility((prev) => ({ ...prev, [id]: checked }));
};
const [isRefreshing, setIsRefreshing] = useState(false);
const refreshCurrentView = useCallback(async () => {
@ -193,6 +189,23 @@ export default function DocumentsTable() {
}
};
// Single document delete handler for RowActions
const handleDeleteDocument = useCallback(async (id: number): Promise<boolean> => {
try {
await deleteDocumentMutation({ id });
toast.success(t("delete_success") || "Document deleted");
// If in search mode, refetch search results to reflect deletion
if (isSearchMode) {
await refetchSearch();
}
// Real-time mode: Electric will sync the deletion automatically
return true;
} catch (e) {
console.error("Error deleting document:", e);
return false;
}
}, [deleteDocumentMutation, isSearchMode, refetchSearch, t]);
const handleSortChange = useCallback((key: SortKey) => {
setSortKey((currentKey) => {
if (currentKey === key) {
@ -237,8 +250,6 @@ export default function DocumentsTable() {
onBulkDelete={onBulkDelete}
onToggleType={onToggleType}
activeTypes={activeTypes}
columnVisibility={columnVisibility}
onToggleColumn={onToggleColumn}
/>
{/* Table */}
@ -253,6 +264,8 @@ export default function DocumentsTable() {
sortKey={sortKey}
sortDesc={sortDesc}
onSortChange={handleSortChange}
deleteDocument={handleDeleteDocument}
searchSpaceId={String(searchSpaceId)}
/>
{/* Pagination */}