From 6037c158f4443942aa3f46c2e95efa475d4098b3 Mon Sep 17 00:00:00 2001 From: SergeantPanda Date: Fri, 7 Nov 2025 15:25:09 -0600 Subject: [PATCH] Fix header checkbox not clearing on bulk delete in logo tables. --- frontend/src/components/tables/LogosTable.jsx | 34 +++++++++++++------ .../src/components/tables/VODLogosTable.jsx | 29 ++++++++++++---- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/tables/LogosTable.jsx b/frontend/src/components/tables/LogosTable.jsx index 9ebeed43..3e278ebd 100644 --- a/frontend/src/components/tables/LogosTable.jsx +++ b/frontend/src/components/tables/LogosTable.jsx @@ -115,6 +115,7 @@ const LogosTable = () => { pageSize: pageSize, }); const [paginationString, setPaginationString] = useState(''); + const tableRef = React.useRef(null); // Debounce the name filter useEffect(() => { @@ -162,6 +163,14 @@ const LogosTable = () => { /** * Functions */ + const clearSelections = useCallback(() => { + setSelectedRows(new Set()); + // Clear table's internal selection state if table is initialized + if (tableRef.current?.setSelectedTableIds) { + tableRef.current.setSelectedTableIds([]); + } + }, []); + const executeDeleteLogo = useCallback( async (id, deleteFile = false) => { setIsLoading(true); @@ -185,10 +194,10 @@ const LogosTable = () => { setDeleteTarget(null); setLogoToDelete(null); setIsBulkDelete(false); - setSelectedRows(new Set()); // Clear selections + clearSelections(); // Clear selections } }, - [fetchAllLogos] + [fetchAllLogos, clearSelections] ); const executeBulkDelete = useCallback( @@ -215,10 +224,10 @@ const LogosTable = () => { setIsLoading(false); setConfirmDeleteOpen(false); setIsBulkDelete(false); - setSelectedRows(new Set()); // Clear selections + clearSelections(); // Clear selections } }, - [selectedRows, fetchAllLogos] + [selectedRows, fetchAllLogos, clearSelections] ); const executeCleanupUnused = useCallback( @@ -249,10 +258,10 @@ const LogosTable = () => { } finally { setIsCleaningUp(false); setConfirmCleanupOpen(false); - setSelectedRows(new Set()); // Clear selections after cleanup + clearSelections(); // Clear selections after cleanup } }, - [fetchAllLogos] + [fetchAllLogos, clearSelections] ); const editLogo = useCallback(async (logo = null) => { @@ -289,10 +298,10 @@ const LogosTable = () => { if (checked) { setSelectedRows(new Set(data.map((logo) => logo.id))); } else { - setSelectedRows(new Set()); + clearSelections(); } }, - [data] + [data, clearSelections] ); const deleteBulkLogos = useCallback(() => { @@ -310,8 +319,8 @@ const LogosTable = () => { // Clear selections when logos data changes (e.g., after filtering) useEffect(() => { - setSelectedRows(new Set()); - }, [data.length]); + clearSelections(); + }, [data.length, clearSelections]); // Update pagination when pageSize changes useEffect(() => { @@ -616,6 +625,11 @@ const LogosTable = () => { }, }); + // Store table reference for clearing selections + React.useEffect(() => { + tableRef.current = table; + }, [table]); + return ( <> { @@ -129,6 +130,14 @@ export default function VODLogosTable() { setSelectedRows(new Set(newSelection)); }, []); + const clearSelections = useCallback(() => { + setSelectedRows(new Set()); + // Clear table's internal selection state if table is initialized + if (tableRef.current?.setSelectedTableIds) { + tableRef.current.setSelectedTableIds([]); + } + }, []); + const handleConfirmDelete = async () => { try { if (deleteTarget.length === 1) { @@ -146,15 +155,17 @@ export default function VODLogosTable() { color: 'green', }); } - setSelectedRows(new Set()); - setConfirmDeleteOpen(false); - setDeleteTarget(null); } catch (error) { notifications.show({ title: 'Error', message: error.message || 'Failed to delete VOD logos', color: 'red', }); + } finally { + // Always clear selections and close dialog, even on error + clearSelections(); + setConfirmDeleteOpen(false); + setDeleteTarget(null); } }; @@ -171,7 +182,6 @@ export default function VODLogosTable() { message: `Cleaned up ${result.deleted_count} unused VOD logos`, color: 'green', }); - setConfirmCleanupOpen(false); } catch (error) { notifications.show({ title: 'Error', @@ -180,13 +190,15 @@ export default function VODLogosTable() { }); } finally { setIsCleaningUp(false); + setConfirmCleanupOpen(false); + clearSelections(); // Clear selections after cleanup } }; // Clear selections only when filters change (not on every data fetch) useEffect(() => { - setSelectedRows(new Set()); - }, [nameFilter, usageFilter]); + clearSelections(); + }, [nameFilter, usageFilter, clearSelections]); useEffect(() => { const startItem = (currentPage - 1) * pageSize + 1; @@ -395,6 +407,11 @@ export default function VODLogosTable() { }, }); + // Store table reference for clearing selections + React.useEffect(() => { + tableRef.current = table; + }, [table]); + return (