From b88a998c9acdd8d383d6a7d7e8c7f55e9d0e06ab Mon Sep 17 00:00:00 2001 From: Kumi Date: Tue, 30 Jul 2024 14:09:38 +0200 Subject: [PATCH] feat: add state persistence and task change events Introduce state persistence to example to save and load Kanblendar state using localStorage, enhancing user experience by remembering their tasks and settings across sessions. Implement a new 'taskChanged' custom event to trigger state saving whenever tasks are created, moved, edited, or deleted. This ensures state consistency and reduces the risk of data loss. Refactor to attach Kanblendar instance to the window object for global access in example. --- example.js | 19 +++++++++++++++++-- kanblendar.js | 16 +++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/example.js b/example.js index ebb42f9..7f0d8cc 100644 --- a/example.js +++ b/example.js @@ -1,5 +1,20 @@ document.addEventListener('DOMContentLoaded', () => { - const kanblendar = new Kanblendar(); + window.kanblendar = new Kanblendar(); const createTaskBtn = document.getElementById('createTaskBtn'); - createTaskBtn.addEventListener('click', () => kanblendar.openModal()); + createTaskBtn.addEventListener('click', () => window.kanblendar.openModal()); + + function saveState() { + const serializedState = kanblendar.serialize(); + localStorage.setItem('kanblendarState', serializedState); + console.log('State saved!'); + } + + document.addEventListener('taskChanged', saveState); + + const serializedState = localStorage.getItem('kanblendarState'); + if (serializedState) { + kanblendar.deserialize(serializedState); + console.log('State loaded on page load!'); + } + }); \ No newline at end of file diff --git a/kanblendar.js b/kanblendar.js index e76021d..b5728d6 100644 --- a/kanblendar.js +++ b/kanblendar.js @@ -250,6 +250,7 @@ class Kanblendar { if (dropTarget.classList.contains('kanblendar-time-slot') || dropTarget.classList.contains('kanblendar-non-timed-tasks')) { dropTarget.appendChild(task); this.emitTaskMovedEvent(task, dropTarget); + this.emitTaskChangedEvent('move', task); } // Update the task's due time if dropped in a time slot and the current due time is not valid for that slot @@ -312,6 +313,7 @@ class Kanblendar { this.moveTaskToNonTimedSection(this.currentTask, column); } this.cancelNotification(this.currentTask.id); + this.emitTaskChangedEvent('edit', this.currentTask); } else { newTask = this.createTaskElement(title, description, dueTime, column, notifyBefore); this.moveTaskToColumn(newTask, column); @@ -320,6 +322,7 @@ class Kanblendar { } else { this.moveTaskToNonTimedSection(newTask, column); } + this.emitTaskChangedEvent('create', newTask); } if (dueTime && notifyBefore >= 0) { @@ -352,7 +355,7 @@ class Kanblendar { `; newTask.addEventListener('dragstart', (e) => this.dragStart(e)); newTask.addEventListener('click', (e) => this.openModal(newTask)); // Add click event to open modal for editing - this.tasks.set(id, { title, description, dueTime, notifyBefore }); + this.tasks.set(id, { title, description, dueTime, column, notifyBefore }); return newTask; } @@ -393,6 +396,7 @@ class Kanblendar { task.remove(); this.tasks.delete(task.id); this.adjustTimeSlotHeights(); // Adjust heights after deleting a task + this.emitTaskChangedEvent('delete', task); } scheduleNotification(title, description, dueTime, notifyBefore, taskId) { @@ -512,4 +516,14 @@ class Kanblendar { }); this.adjustTimeSlotHeights(); } + + emitTaskChangedEvent(action, task) { + const event = new CustomEvent('taskChanged', { + detail: { + action, + taskId: task.id + } + }); + document.dispatchEvent(event); + } } \ No newline at end of file