Merge branch 'dev'
CI/CD / deploy (push) Failing after 2m19s
Details
CI/CD / deploy (push) Failing after 2m19s
Details
This commit is contained in:
commit
bdd6ab35ec
|
|
@ -20,7 +20,7 @@ class FolkTasksBoard extends HTMLElement {
|
|||
private isDemo = false;
|
||||
private dragTaskId: string | null = null;
|
||||
private editingTaskId: string | null = null;
|
||||
private showCreateForm = false;
|
||||
private showCreateForm: string | false = false;
|
||||
private boardView: "board" | "checklist" = "board";
|
||||
private dragOverStatus: string | null = null;
|
||||
private dragOverIndex = -1;
|
||||
|
|
@ -413,21 +413,28 @@ class FolkTasksBoard extends HTMLElement {
|
|||
return '';
|
||||
}
|
||||
|
||||
private async submitCreateTask(title: string, priority: string, description: string, dueDate?: string) {
|
||||
private async submitCreateTask(title: string, priority: string, description: string, dueDate?: string, status?: string) {
|
||||
if (!title.trim()) return;
|
||||
const taskStatus = status || this.statuses[0] || "TODO";
|
||||
if (this.isDemo) {
|
||||
this.tasks.push({ id: `d${Date.now()}`, title: title.trim(), status: this.statuses[0] || "TODO", priority, labels: [], description: description.trim() || undefined, due_date: dueDate || null, sort_order: 0 });
|
||||
this.tasks.push({ id: `d${Date.now()}`, title: title.trim(), status: taskStatus, priority, labels: [], description: description.trim() || undefined, due_date: dueDate || null, sort_order: 0 });
|
||||
this.showCreateForm = false;
|
||||
this.render();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const base = this.getApiBase();
|
||||
await fetch(`${base}/api/spaces/${this.workspaceSlug}/tasks`, {
|
||||
const res = await fetch(`${base}/api/spaces/${this.workspaceSlug}/tasks`, {
|
||||
method: "POST",
|
||||
headers: this.authHeaders({ "Content-Type": "application/json" }),
|
||||
body: JSON.stringify({ title: title.trim(), priority, description: description.trim() || undefined, due_date: dueDate || undefined }),
|
||||
body: JSON.stringify({ title: title.trim(), priority, status: taskStatus, description: description.trim() || undefined, due_date: dueDate || undefined }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
this.error = data.error || `Failed to create task (${res.status})`;
|
||||
this.render();
|
||||
return;
|
||||
}
|
||||
this.showCreateForm = false;
|
||||
this.loadTasks();
|
||||
} catch { this.error = "Failed to create task"; this.render(); }
|
||||
|
|
@ -647,6 +654,7 @@ class FolkTasksBoard extends HTMLElement {
|
|||
.column {
|
||||
min-width: 240px; max-width: 280px; flex-shrink: 0;
|
||||
background: var(--rs-bg-surface-sunken); border: 1px solid var(--rs-border); border-radius: 10px; padding: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.col-header { font-size: 13px; font-weight: 600; text-transform: uppercase; color: var(--rs-text-muted); margin-bottom: 10px; display: flex; justify-content: space-between; }
|
||||
.col-count { background: var(--rs-border); border-radius: 10px; padding: 0 8px; font-size: 11px; }
|
||||
|
|
@ -715,7 +723,8 @@ class FolkTasksBoard extends HTMLElement {
|
|||
@keyframes pulse-indicator { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; box-shadow: 0 0 8px var(--rs-primary); } }
|
||||
|
||||
/* Empty column drop zone */
|
||||
.empty-drop-zone { border: 2px dashed var(--rs-border); border-radius: 8px; padding: 24px 12px; text-align: center; color: var(--rs-text-muted); font-size: 12px; font-weight: 600; pointer-events: none; opacity: 0.4; transition: all 0.15s; }
|
||||
.empty-drop-zone { border: 2px dashed var(--rs-border); border-radius: 8px; padding: 24px 12px; text-align: center; color: var(--rs-text-muted); font-size: 12px; font-weight: 600; cursor: pointer; opacity: 0.4; transition: all 0.15s; }
|
||||
.empty-drop-zone:hover { opacity: 0.7; border-color: var(--rs-primary); color: var(--rs-primary); }
|
||||
.column.drag-over .empty-drop-zone { opacity: 1; border-color: #22c55e; color: #22c55e; background: rgba(34,197,94,0.05); }
|
||||
|
||||
/* Checklist view */
|
||||
|
|
@ -857,11 +866,12 @@ class FolkTasksBoard extends HTMLElement {
|
|||
this._tour.start();
|
||||
}
|
||||
|
||||
private renderCreateForm(): string {
|
||||
if (!this.showCreateForm) return "";
|
||||
private renderCreateForm(forStatus: string): string {
|
||||
if (this.showCreateForm !== forStatus) return "";
|
||||
return `
|
||||
<div class="create-form" id="create-form">
|
||||
<input type="text" id="cf-title" placeholder="Task title..." autofocus>
|
||||
<input type="hidden" id="cf-status" value="${this.esc(forStatus)}">
|
||||
<select id="cf-priority">
|
||||
<option value="LOW">Low</option>
|
||||
<option value="MEDIUM" selected>Medium</option>
|
||||
|
|
@ -922,14 +932,14 @@ class FolkTasksBoard extends HTMLElement {
|
|||
.sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0));
|
||||
const isDragSource = this.dragTaskId && this.dragSourceStatus === status;
|
||||
return `
|
||||
<div class="column${isDragSource ? ' drag-source' : ''}" data-status="${status}">
|
||||
<div class="column${isDragSource ? ' drag-source' : ''}" data-status="${status}" data-col-click="${status}">
|
||||
<div class="col-header">
|
||||
<span>${this.esc(status.replace(/_/g, " "))}</span>
|
||||
<span class="col-count">${columnTasks.length}</span>
|
||||
</div>
|
||||
${status === this.statuses[0] ? this.renderCreateForm() : ""}
|
||||
${this.renderCreateForm(status)}
|
||||
${columnTasks.map(t => this.renderTaskCard(t, status)).join("")}
|
||||
${columnTasks.length === 0 ? '<div class="empty-drop-zone">Drop here</div>' : ''}
|
||||
${columnTasks.length === 0 && this.showCreateForm !== status ? '<div class="empty-drop-zone" data-col-click="' + this.esc(status) + '">+ Add task</div>' : ''}
|
||||
</div>
|
||||
`;
|
||||
}).join("")}
|
||||
|
|
@ -1104,19 +1114,35 @@ class FolkTasksBoard extends HTMLElement {
|
|||
this.render();
|
||||
});
|
||||
this.shadow.getElementById("create-task")?.addEventListener("click", () => {
|
||||
this.showCreateForm = !this.showCreateForm;
|
||||
const firstStatus = this.statuses[0] || "TODO";
|
||||
this.showCreateForm = this.showCreateForm ? false : firstStatus;
|
||||
this.render();
|
||||
if (this.showCreateForm) {
|
||||
setTimeout(() => this.shadow.getElementById("cf-title")?.focus(), 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Column click to create task in that column
|
||||
this.shadow.querySelectorAll("[data-col-click]").forEach(el => {
|
||||
el.addEventListener("click", (e) => {
|
||||
// Don't trigger if clicking on a card, button, or input
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.closest('.task-card, button, input, select, textarea, .create-form')) return;
|
||||
const status = (el as HTMLElement).dataset.colClick!;
|
||||
if (this.showCreateForm === status) return;
|
||||
this.showCreateForm = status;
|
||||
this.render();
|
||||
setTimeout(() => this.shadow.getElementById("cf-title")?.focus(), 0);
|
||||
});
|
||||
});
|
||||
|
||||
// Create form handlers
|
||||
this.shadow.getElementById("cf-submit")?.addEventListener("click", () => {
|
||||
const title = (this.shadow.getElementById("cf-title") as HTMLInputElement)?.value || "";
|
||||
const priority = (this.shadow.getElementById("cf-priority") as HTMLSelectElement)?.value || "MEDIUM";
|
||||
const desc = (this.shadow.getElementById("cf-desc") as HTMLTextAreaElement)?.value || "";
|
||||
this.submitCreateTask(title, priority, desc);
|
||||
const status = (this.shadow.getElementById("cf-status") as HTMLInputElement)?.value || "";
|
||||
this.submitCreateTask(title, priority, desc, undefined, status);
|
||||
});
|
||||
this.shadow.getElementById("cf-cancel")?.addEventListener("click", () => {
|
||||
this.showCreateForm = false; this.render();
|
||||
|
|
@ -1126,7 +1152,8 @@ class FolkTasksBoard extends HTMLElement {
|
|||
const title = (this.shadow.getElementById("cf-title") as HTMLInputElement)?.value || "";
|
||||
const priority = (this.shadow.getElementById("cf-priority") as HTMLSelectElement)?.value || "MEDIUM";
|
||||
const desc = (this.shadow.getElementById("cf-desc") as HTMLTextAreaElement)?.value || "";
|
||||
this.submitCreateTask(title, priority, desc);
|
||||
const status = (this.shadow.getElementById("cf-status") as HTMLInputElement)?.value || "";
|
||||
this.submitCreateTask(title, priority, desc, undefined, status);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -854,6 +854,7 @@ export const tasksModule: RSpaceModule = {
|
|||
id: "rtasks",
|
||||
name: "rTasks",
|
||||
icon: "📋",
|
||||
publicWrite: true,
|
||||
description: "Kanban workspace boards for collaborative task management",
|
||||
scoping: { defaultScope: 'space', userConfigurable: false },
|
||||
docSchemas: [
|
||||
|
|
|
|||
Loading…
Reference in New Issue