Add create task modal

This commit is contained in:
2026-06-26 18:07:11 +02:00
parent 1de4169303
commit 13cec807a2
4 changed files with 73 additions and 51 deletions
+56 -30
View File
@@ -1,5 +1,11 @@
const states = ["Backlog", "In Progress", "Review", "Done"];
const priorities = ["Low", "Normal", "High", "Urgent"];
const priorities = ["Low", "Normal", "Medium", "High", "Urgent"];
const assignees = [
{ value: "bao", label: "Bao" },
{ value: "maxi", label: "Maxi" },
{ value: "luna", label: "Luna" },
{ value: "iris", label: "Iris" }
];
const app = document.querySelector("#app");
const state = {
@@ -132,10 +138,9 @@ function boardView() {
<span class="status-pill"><span class="dot ${connected ? "ok" : ""}"></span>OpenClaw ${connected ? "verbunden" : "pruefen"}</span>
</div>
</header>
<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>
<div class="quick-create">
<button class="primary" type="button" id="open-create-task">Create task</button>
</div>
<section class="kanban">
${states.map((name) => column(name)).join("")}
</section>
@@ -186,23 +191,23 @@ function taskDialog() {
<label class="field">Titel
<input name="title" required>
</label>
<label class="field">Details
<label class="field">Beschreibung
<textarea name="detail"></textarea>
</label>
<div class="grid">
<label class="field">Status
<label class="field status-field">Status
<select name="state">${states.map((x) => `<option>${x}</option>`).join("")}</select>
</label>
<label class="field">Prioritaet
<label class="field">Priorität
<select name="priority">${priorities.map((x) => `<option>${x}</option>`).join("")}</select>
</label>
</div>
<label class="field">Assignee
<input name="assignee" value="${escapeHtml(state.settings?.defaultAssignee || "luna")}">
<label class="field">Zuweisen an
<select name="assignee">${assigneeOptions(state.settings?.defaultAssignee || "luna")}</select>
</label>
<div class="dialog-actions">
<button class="ghost" type="button" id="cancel-task">Abbrechen</button>
<button class="primary" type="submit">Speichern</button>
<button class="primary" type="submit" id="save-task">Speichern</button>
</div>
</form>
</dialog>
@@ -214,41 +219,36 @@ function bindBoard() {
const form = document.querySelector("#task-form");
const dialogTitle = document.querySelector("#dialog-title");
const dialogMeta = document.querySelector("#dialog-meta");
const saveTaskButton = document.querySelector("#save-task");
let draggedTaskId = null;
const resetDialog = () => {
form.reset();
form.elements.id.value = "";
form.elements.assignee.value = state.settings?.defaultAssignee || "luna";
form.elements.state.value = "Backlog";
form.elements.priority.value = "Medium";
form.elements.assignee.value = normalizeAssignee(state.settings?.defaultAssignee || "luna");
form.classList.add("task-form-create");
dialogTitle.textContent = "Neue Aufgabe";
dialogMeta.textContent = "";
dialogMeta.textContent = "Erstelle eine neue Aufgabe fuer das Mission-Control-Board.";
saveTaskButton.textContent = "Aufgabe erstellen";
};
const openTaskDialog = (task) => {
form.classList.remove("task-form-create");
form.elements.id.value = task.id;
form.elements.title.value = task.title;
form.elements.detail.value = task.detail || "";
form.elements.state.value = task.state;
form.elements.priority.value = task.priority;
form.elements.assignee.value = task.assignee || "";
ensureAssigneeOption(form.elements.assignee, task.assignee || state.settings?.defaultAssignee || "luna");
form.elements.assignee.value = normalizeAssignee(task.assignee || state.settings?.defaultAssignee || "luna");
dialogTitle.textContent = task.title;
dialogMeta.textContent = `Status ${task.state} · Aktualisiert ${formatDate(task.updatedAt)} · Erstellt ${formatDate(task.createdAt)}`;
saveTaskButton.textContent = "Speichern";
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("#open-create-task").addEventListener("click", () => {
resetDialog();
dialog.showModal();
});
document.querySelector("#cancel-task").addEventListener("click", () => dialog.close());
dialog.addEventListener("click", (event) => {
@@ -388,4 +388,30 @@ function formatDate(value) {
return new Date(value).toLocaleString("de-DE", { dateStyle: "short", timeStyle: "short" });
}
function normalizeAssignee(value) {
return String(value || "").trim().toLowerCase();
}
function assigneeLabel(value) {
const normalized = normalizeAssignee(value);
const known = assignees.find((x) => x.value === normalized);
if (known) return known.label;
return normalized ? normalized.charAt(0).toUpperCase() + normalized.slice(1) : "Luna";
}
function assigneeOptions(selected) {
const normalized = normalizeAssignee(selected);
const options = [...assignees];
if (normalized && !options.some((x) => x.value === normalized)) {
options.push({ value: normalized, label: assigneeLabel(normalized) });
}
return options.map((x) => `<option value="${escapeHtml(x.value)}" ${x.value === normalized ? "selected" : ""}>${escapeHtml(x.label)}</option>`).join("");
}
function ensureAssigneeOption(select, value) {
const normalized = normalizeAssignee(value);
if (!normalized || Array.from(select.options).some((option) => option.value === normalized)) return;
select.add(new Option(assigneeLabel(normalized), normalized));
}
init();