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.
This commit is contained in:
Kumi 2024-07-30 14:09:38 +02:00
parent 0f530dc401
commit b88a998c9a
Signed by: kumi
GPG key ID: ECBCC9082395383F
2 changed files with 32 additions and 3 deletions

View file

@ -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!');
}
});

View file

@ -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);
}
}