Merge branch 'dev'
CI/CD / deploy (push) Successful in 2m20s Details

This commit is contained in:
Jeff Emmett 2026-04-06 14:50:10 -04:00
commit 4d15a352a6
1 changed files with 36 additions and 21 deletions

View File

@ -1276,30 +1276,45 @@ class FolkTasksBoard extends HTMLElement {
});
this.shadow.getElementById("detail-overlay")?.addEventListener("click", () => { this.detailTaskId = null; this.render(); });
this.shadow.getElementById("detail-close")?.addEventListener("click", () => { this.detailTaskId = null; this.render(); });
// Detail field auto-save on blur
const detailSave = () => {
// Detail field auto-save — save individual fields
const detailFieldSave = (field: string, value: any) => {
if (!this.detailTaskId) return;
const fields: Record<string, any> = {};
const titleEl = this.shadow.getElementById("detail-title") as HTMLInputElement;
const descEl = this.shadow.getElementById("detail-desc") as HTMLTextAreaElement;
const statusEl = this.shadow.getElementById("detail-status") as HTMLSelectElement;
const priorityEl = this.shadow.getElementById("detail-priority") as HTMLSelectElement;
const assigneeEl = this.shadow.getElementById("detail-assignee") as HTMLInputElement;
const dueEl = this.shadow.getElementById("detail-due") as HTMLInputElement;
if (titleEl) fields.title = titleEl.value.trim();
if (descEl) fields.description = descEl.value;
if (statusEl) fields.status = statusEl.value;
if (priorityEl) fields.priority = priorityEl.value || null;
if (assigneeEl) fields.assignee_id = assigneeEl.value.trim() || null;
if (dueEl) fields.due_date = dueEl.value ? new Date(dueEl.value).toISOString() : null;
this.updateTask(this.detailTaskId!, fields);
this.detailTaskId = this.detailTaskId; // keep panel open
// Update local task data immediately
const task = this.tasks.find(t => t.id === this.detailTaskId);
if (task) {
if (field === 'due_date') task.due_date = value;
else if (field === 'assignee_id') { task.assignee_id = value; task.assignee = value; }
else task[field] = value;
}
// Persist to server (non-blocking, don't re-render)
if (!this.isDemo) {
const base = this.getApiBase();
fetch(`${base}/api/tasks/${this.detailTaskId}`, {
method: "PATCH",
headers: this.authHeaders({ "Content-Type": "application/json" }),
body: JSON.stringify({ [field]: value }),
}).catch(() => { this.error = "Failed to save"; this.render(); });
}
};
['detail-title', 'detail-desc', 'detail-assignee', 'detail-due'].forEach(id => {
this.shadow.getElementById(id)?.addEventListener("blur", detailSave);
this.shadow.getElementById("detail-title")?.addEventListener("blur", (e) => {
const v = (e.target as HTMLInputElement).value.trim();
if (v) detailFieldSave('title', v);
});
['detail-status', 'detail-priority'].forEach(id => {
this.shadow.getElementById(id)?.addEventListener("change", detailSave);
this.shadow.getElementById("detail-desc")?.addEventListener("blur", (e) => {
detailFieldSave('description', (e.target as HTMLTextAreaElement).value);
});
this.shadow.getElementById("detail-status")?.addEventListener("change", (e) => {
detailFieldSave('status', (e.target as HTMLSelectElement).value);
});
this.shadow.getElementById("detail-priority")?.addEventListener("change", (e) => {
detailFieldSave('priority', (e.target as HTMLSelectElement).value || null);
});
this.shadow.getElementById("detail-assignee")?.addEventListener("blur", (e) => {
detailFieldSave('assignee_id', (e.target as HTMLInputElement).value.trim() || null);
});
this.shadow.getElementById("detail-due")?.addEventListener("change", (e) => {
const v = (e.target as HTMLInputElement).value;
detailFieldSave('due_date', v ? new Date(v).toISOString() : null);
});
// Detail label add
this.shadow.getElementById("detail-add-label")?.addEventListener("keydown", (e) => {