Don't let user close browser window if they have unsaved changes (vibe-kanban) (#538)
* Perfect! The implementation is complete and passes all checks. ## Summary Added browser window close protection to prevent data loss when users have unsaved changes in the task dialog: - **Added `beforeunload` event listener** in [`TaskFormDialog.tsx`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-f59b-don-t-let/frontend/src/components/tasks/TaskFormDialog.tsx#L95-L111) - **Integrates with existing `hasUnsavedChanges()` logic** - no duplication - **Only active when dialog is open AND has unsaved content** - **Automatic cleanup** when dialog closes or changes are saved - **Browser-standard confirmation dialog** appears when user tries to close tab/window The feature now protects against data loss from both dialog close (existing) and browser window close (new) scenarios. * Cleanup script changes for task attempt f59bea00-6158-4cdd-ad19-1f30e40c1324 * Perfect! Now the browser window close protection works for both scenarios: ## Updated Implementation **Create mode:** Warns when user has entered title or description content **Edit mode:** Warns when user has modified title, description, or status from original values The `beforeunload` event will now trigger when: - **Creating a task** and typing content, then trying to close browser - **Editing a task** and changing any field, then trying to close browser Both the existing dialog close warning and new browser window close warning now protect against data loss in all editing scenarios. * Cleanup script changes for task attempt f59bea00-6158-4cdd-ad19-1f30e40c1324
This commit is contained in:
committed by
GitHub
parent
e99f9807fb
commit
6fb7b939d9
@@ -82,13 +82,38 @@ export function TaskFormDialog({
|
||||
|
||||
// Check if there's any content that would be lost
|
||||
const hasUnsavedChanges = useCallback(() => {
|
||||
// Only warn in create mode when there's content
|
||||
if (!isEditMode) {
|
||||
// Create mode - warn when there's content
|
||||
return title.trim() !== '' || description.trim() !== '';
|
||||
} else if (task) {
|
||||
// Edit mode - warn when current values differ from original task
|
||||
const titleChanged = title.trim() !== task.title.trim();
|
||||
const descriptionChanged =
|
||||
(description || '').trim() !== (task.description || '').trim();
|
||||
const statusChanged = status !== task.status;
|
||||
return titleChanged || descriptionChanged || statusChanged;
|
||||
}
|
||||
// No warning for edit mode - users can always reopen the task
|
||||
return false;
|
||||
}, [title, description, isEditMode]);
|
||||
}, [title, description, status, isEditMode, task]);
|
||||
|
||||
// Warn on browser/tab close if there are unsaved changes
|
||||
useEffect(() => {
|
||||
if (!isOpen) return; // dialog closed → nothing to do
|
||||
|
||||
// always re-evaluate latest fields via hasUnsavedChanges()
|
||||
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
||||
if (hasUnsavedChanges()) {
|
||||
e.preventDefault();
|
||||
// Chrome / Edge still require returnValue to be set
|
||||
e.returnValue = '';
|
||||
return '';
|
||||
}
|
||||
// nothing returned → no prompt
|
||||
};
|
||||
|
||||
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||
return () => window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||
}, [isOpen, hasUnsavedChanges]); // hasUnsavedChanges is memoised with title/descr deps
|
||||
|
||||
useEffect(() => {
|
||||
if (task) {
|
||||
|
||||
Reference in New Issue
Block a user