refactor: optimize bulk delete handler and UI feedback

- Refactored the bulk delete handler to utilize Promise.all for concurrent deletion of features, improving performance and error handling.
- Updated the BoardView component to handle deletion results more effectively, providing user feedback for both successful and failed deletions.
- Enhanced local state management to avoid redundant API calls during feature deletion.
This commit is contained in:
Shirone
2026-01-11 11:17:28 +01:00
parent 7522e58fee
commit 6e4b611662
2 changed files with 32 additions and 22 deletions

View File

@@ -30,23 +30,22 @@ export function createBulkDeleteHandler(featureLoader: FeatureLoader) {
return; return;
} }
const results: BulkDeleteResult[] = []; const results = await Promise.all(
featureIds.map(async (featureId) => {
for (const featureId of featureIds) {
try {
const success = await featureLoader.delete(projectPath, featureId); const success = await featureLoader.delete(projectPath, featureId);
results.push({ featureId, success }); if (success) {
} catch (error) { return { featureId, success: true };
results.push({ }
return {
featureId, featureId,
success: false, success: false,
error: getErrorMessage(error), error: 'Deletion failed. Check server logs for details.',
}); };
} })
} );
const successCount = results.filter((r) => r.success).length; const successCount = results.reduce((count, r) => count + (r.success ? 1 : 0), 0);
const failureCount = results.filter((r) => !r.success).length; const failureCount = results.length - successCount;
res.json({ res.json({
success: failureCount === 0, success: failureCount === 0,

View File

@@ -514,24 +514,35 @@ export function BoardView() {
const featureIds = Array.from(selectedFeatureIds); const featureIds = Array.from(selectedFeatureIds);
const result = await api.features.bulkDelete(currentProject.path, featureIds); const result = await api.features.bulkDelete(currentProject.path, featureIds);
if (result.success) { const successfullyDeletedIds =
// Delete from local state result.results?.filter((r) => r.success).map((r) => r.featureId) ?? [];
featureIds.forEach((featureId) => {
persistFeatureDelete(featureId); if (successfullyDeletedIds.length > 0) {
// Delete from local state without calling the API again
successfullyDeletedIds.forEach((featureId) => {
useAppStore.getState().removeFeature(featureId);
}); });
toast.success(`Deleted ${result.deletedCount} features`); toast.success(`Deleted ${successfullyDeletedIds.length} features`);
exitSelectionMode(); }
loadFeatures();
} else { if (result.failedCount && result.failedCount > 0) {
toast.error('Failed to delete some features', { toast.error('Failed to delete some features', {
description: `${result.failedCount} features failed to delete`, description: `${result.failedCount} features failed to delete`,
}); });
} }
// Exit selection mode and reload if the operation was at least partially processed.
if (result.results) {
exitSelectionMode();
loadFeatures();
} else if (!result.success) {
toast.error('Failed to delete features', { description: result.error });
}
} catch (error) { } catch (error) {
logger.error('Bulk delete failed:', error); logger.error('Bulk delete failed:', error);
toast.error('Failed to delete features'); toast.error('Failed to delete features');
} }
}, [currentProject, selectedFeatureIds, persistFeatureDelete, exitSelectionMode, loadFeatures]); }, [currentProject, selectedFeatureIds, exitSelectionMode, loadFeatures]);
// Get selected features for mass edit dialog // Get selected features for mass edit dialog
const selectedFeatures = useMemo(() => { const selectedFeatures = useMemo(() => {