From 3e78d4343c003c0b8e2f9c16679b40ef72ce2585 Mon Sep 17 00:00:00 2001 From: bruno Date: Wed, 8 Jul 2026 10:18:28 -0400 Subject: [PATCH] feat: full inline issue editing (title + body + assignee) Replaced bare prompt() with proper edit form in card modal: - showEditForm: renders title input + body textarea + assignee field - saveIssueEdit: PATCH /api/issues/... with title, body, assignee - 'Annuler' button returns to card detail view - Old editIssueInline (prompt only) removed - Added .form-label CSS style --- app/templates/board.html | 45 ++++++++++++++++++++++++++++++++++------ static/css/app.css | 1 + 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/app/templates/board.html b/app/templates/board.html index 9369150..5956fd0 100644 --- a/app/templates/board.html +++ b/app/templates/board.html @@ -211,6 +211,10 @@ function renderCardDetail(owner, repo, data) { const issue = data.issue || {}, comments = data.comments || [], checklists = data.checklists || [], card = data.card || {}; let h = ''; + + // Edit mode toggle: store data for later + window._issueData = {owner, repo, issue, comments, checklists, card}; + h += `
${issue.state} ${escHtml(issue.title||'')}
`; h += `
`; (issue.labels||[]).forEach(l => h += `${escHtml(l.name)}`); @@ -238,11 +242,45 @@ comments.forEach(c => h += `
${escHtml(c.user?.login||'')}${(c.created_at||'').substr(0,10)}
${escHtml(c.body||'')}
`); h += `
`; h += `
🔗 Ouvrir dans Gitea`; - h += ``; + h += ``; h += `
`; return h; } + function showEditForm(owner, repo, issueId) { + const content = document.getElementById('card-modal-content'); + const data = window._issueData || {}; + const issue = data.issue || {}; + fetch(`/api/collaborators/${owner}/${repo}`).then(r=>r.json()).then(cdata => { + let h = '
'; + h += ''; + h += ''; + h += ''; + h += ''; + h += '
'; + h += ''; + h += '
'; + h += '
'; + h += ''; + h += ''; + h += '
'; + content.innerHTML = h; + }); + } + + async function saveIssueEdit(evt, owner, repo, issueId) { + evt.preventDefault(); + const title = document.getElementById('edit-title').value.trim(); + const body = document.getElementById('edit-body').value.trim(); + const assignee = document.getElementById('edit-assignee').value.trim(); + if (!title) return; + const params = new URLSearchParams({title, body, assignee}); + await fetch(`/api/issues/${owner}/${repo}/${issueId}?${params}`, { + method: 'PATCH', headers: {'X-CSRF-Token': getCSRFToken()} + }); + openCardDetail(owner, repo, issueId); + } + function escHtml(s) { return (s||'').replace(/&/g,'&').replace(//g,'>'); } async function updateCardMeta(o,r,i,priority,dueDate) { await fetch(`/api/card/${o}/${r}/${i}?priority=${priority}&due_date=${dueDate}`,{method:'POST',headers:{'X-CSRF-Token':getCSRFToken()}}); } async function toggleCheckItem(id,checked) { await fetch(`/api/checklist-items/${id}?checked=${checked}`,{method:'PATCH',headers:{'X-CSRF-Token':getCSRFToken()}}); } @@ -259,11 +297,6 @@ openCardDetail(o,r,issueId); } async function createChecklist(o,r,issueId) { await fetch(`/api/checklists/${o}/${r}/${issueId}`,{method:'POST',headers:{'X-CSRF-Token':getCSRFToken()}}); openCardDetail(o,r,issueId); } - async function editIssueInline(o,r,issueId) { - const t=prompt('Nouveau titre:',''); if(!t)return; - await fetch(`/api/issues/${o}/${r}/${issueId}?title=${encodeURIComponent(t)}`,{method:'PATCH',headers:{'X-CSRF-Token':getCSRFToken()}}); - closeModal(); window.location.reload(); - } async function registerWebhook(o,r) { try { const resp=await fetch(`/api/webhook/register/${o}/${r}`,{method:'POST',headers:{'X-CSRF-Token':getCSRFToken()}}); diff --git a/static/css/app.css b/static/css/app.css index 3eebd37..056a8e8 100644 --- a/static/css/app.css +++ b/static/css/app.css @@ -199,6 +199,7 @@ body { min-height: 100vh; } margin-bottom: 8px; } .form-input:focus, .form-select:focus { outline: none; border-color: var(--accent); } +.form-label { font-size: 12px; color: var(--text-dim); display: block; margin: 8px 0 4px 0; } .form-input-sm { background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 4px 6px; color: var(--text); font-size: 12px; } .form-select-sm { background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 2px 4px; color: var(--text); font-size: 12px; } .form-row { display: flex; gap: 8px; }