Match taskboard to Nexus dark board
This commit is contained in:
+33
-19
@@ -130,10 +130,13 @@ function boardView() {
|
||||
</div>
|
||||
<div class="actions">
|
||||
<span class="status-pill"><span class="dot ${connected ? "ok" : ""}"></span>OpenClaw ${connected ? "verbunden" : "pruefen"}</span>
|
||||
<button class="primary" id="new-task">+ Aufgabe</button>
|
||||
</div>
|
||||
</header>
|
||||
<section class="board">
|
||||
<form class="quick-create" id="quick-create">
|
||||
<input name="title" autocomplete="off" maxlength="180" placeholder="New task title">
|
||||
<button type="submit">Create task</button>
|
||||
</form>
|
||||
<section class="kanban">
|
||||
${states.map((name) => column(name)).join("")}
|
||||
</section>
|
||||
`;
|
||||
@@ -142,8 +145,8 @@ function boardView() {
|
||||
function column(name) {
|
||||
const tasks = state.tasks.filter((task) => task.state === name);
|
||||
return `
|
||||
<section class="column" data-state="${name}" aria-label="${name}">
|
||||
<h2><span>${name}</span><span class="count">${tasks.length}</span></h2>
|
||||
<section class="kanban-column" data-state="${name}" aria-label="${name}">
|
||||
<header><span>${name}</span><b>${tasks.length}</b></header>
|
||||
<div class="dropzone" data-state="${name}">
|
||||
${tasks.map(taskCard).join("") || `<p class="empty-state">Keine Aufgaben</p>`}
|
||||
</div>
|
||||
@@ -152,24 +155,22 @@ function column(name) {
|
||||
}
|
||||
|
||||
function taskCard(task) {
|
||||
const index = states.indexOf(task.state);
|
||||
return `
|
||||
<article class="task priority-${escapeHtml(task.priority).toLowerCase()}" draggable="true" data-task-id="${task.id}" tabindex="0" role="button" aria-label="Aufgabe ${escapeHtml(task.title)} oeffnen">
|
||||
<article class="task-card priority-${escapeHtml(task.priority).toLowerCase()}" draggable="true" data-task-id="${task.id}" tabindex="0" role="button" aria-label="Aufgabe ${escapeHtml(task.title)} oeffnen">
|
||||
<div class="task-card-head">
|
||||
<span class="badge">${escapeHtml(task.priority)}</span>
|
||||
<span class="meta">${escapeHtml(task.assignee || "luna")}</span>
|
||||
<span class="priority ${escapeHtml(task.priority).toLowerCase()}">${escapeHtml(task.priority)}</span>
|
||||
<button class="task-edit-btn" data-edit="${task.id}" title="Bearbeiten" aria-label="Aufgabe bearbeiten">✎</button>
|
||||
</div>
|
||||
<div>
|
||||
<h3>${escapeHtml(task.title)}</h3>
|
||||
${task.detail ? `<p>${escapeHtml(task.detail)}</p>` : ""}
|
||||
</div>
|
||||
<select class="task-status-select" data-status-task="${task.id}" aria-label="Status fuer ${escapeHtml(task.title)}">
|
||||
${states.map((x) => `<option value="${x}" ${x === task.state ? "selected" : ""}>${x}</option>`).join("")}
|
||||
</select>
|
||||
<div class="task-footer">
|
||||
<time class="meta" datetime="${escapeHtml(task.updatedAt)}">${formatDate(task.updatedAt)}</time>
|
||||
<div class="task-controls">
|
||||
<button class="icon-button" data-move="${task.id}" data-state="${states[Math.max(0, index - 1)]}" title="Zurueck">‹</button>
|
||||
<button class="icon-button" data-edit="${task.id}" title="Bearbeiten">✎</button>
|
||||
<button class="icon-button" data-move="${task.id}" data-state="${states[Math.min(states.length - 1, index + 1)]}" title="Weiter">›</button>
|
||||
</div>
|
||||
<span class="meta">${escapeHtml(task.assignee || "luna")}</span>
|
||||
</div>
|
||||
</article>
|
||||
`;
|
||||
@@ -232,18 +233,31 @@ function bindBoard() {
|
||||
dialogMeta.textContent = `Status ${task.state} · Aktualisiert ${formatDate(task.updatedAt)} · Erstellt ${formatDate(task.createdAt)}`;
|
||||
dialog.showModal();
|
||||
};
|
||||
document.querySelector("#new-task").addEventListener("click", () => {
|
||||
resetDialog();
|
||||
dialog.showModal();
|
||||
document.querySelector("#quick-create").addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(event.currentTarget);
|
||||
const title = String(formData.get("title") || "").trim();
|
||||
if (!title) return;
|
||||
await api("/api/tasks", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
title,
|
||||
state: "Backlog",
|
||||
priority: "Normal",
|
||||
assignee: state.settings?.defaultAssignee || "luna"
|
||||
})
|
||||
});
|
||||
await loadTasks();
|
||||
renderApp();
|
||||
});
|
||||
document.querySelector("#cancel-task").addEventListener("click", () => dialog.close());
|
||||
dialog.addEventListener("click", (event) => {
|
||||
if (event.target === dialog) dialog.close();
|
||||
});
|
||||
document.querySelectorAll("[data-move]").forEach((button) => {
|
||||
button.addEventListener("click", async (event) => {
|
||||
document.querySelectorAll("[data-status-task]").forEach((select) => {
|
||||
select.addEventListener("change", async (event) => {
|
||||
event.stopPropagation();
|
||||
await api(`/api/tasks/${button.dataset.move}`, { method: "PATCH", body: JSON.stringify({ state: button.dataset.state }) });
|
||||
await api(`/api/tasks/${select.dataset.statusTask}`, { method: "PATCH", body: JSON.stringify({ state: select.value }) });
|
||||
await loadTasks();
|
||||
renderApp();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user