feat(code): cartes liées au code — branches, PRs, commits (issue #1)
app/code_links.py: appariement pur (#n dans titres/corps/messages,
numéro en jeton de branche). Client: list_branches/list_pulls/
list_commits. Badge sur les cartes (board + fragments live),
section Code lié du panneau détail, /api/issues/{o}/{r}/{n}/code.
This commit is contained in:
@@ -1144,3 +1144,10 @@ footer {
|
||||
.sprint-render h1 { font-size: 1.5rem; }
|
||||
.sprint-render h2 { font-size: 1.15rem; margin-top: 22px; }
|
||||
.sprint-render a { color: var(--accent, #58a6ff); }
|
||||
|
||||
/* ── Code lié (0.13.0, #1) ── */
|
||||
.card-code { font-size: 0.78rem; color: var(--accent, #58a6ff); margin-top: 5px; }
|
||||
.detail-code { margin: 10px 0; }
|
||||
.code-line { padding: 3px 0; font-size: 0.9rem; color: var(--text-2, #b6c2d2); }
|
||||
.code-line a { color: var(--accent, #58a6ff); text-decoration: none; }
|
||||
.code-line code { background: var(--surface-3, #1d2942); border-radius: 4px; padding: 0 5px; }
|
||||
|
||||
@@ -369,12 +369,40 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const data = await r.json().catch(() => ({}));
|
||||
if (!r.ok || !data.ok) throw new Error(data.error || ('HTTP ' + r.status));
|
||||
fillDetail(data.issue, data.comments);
|
||||
loadCodeLinks(repoFull, number);
|
||||
} catch (err) {
|
||||
document.getElementById('detail-title').textContent = 'Erreur de chargement';
|
||||
showToast('❌ Détail indisponible : ' + err.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function loadCodeLinks(repoFull, number) {
|
||||
const box = document.getElementById('detail-code');
|
||||
if (!box) return;
|
||||
box.innerHTML = '';
|
||||
const [owner, repo] = repoFull.split('/', 2);
|
||||
try {
|
||||
const r = await fetch(`/api/issues/${owner}/${repo}/${number}/code`);
|
||||
const data = await r.json().catch(() => ({}));
|
||||
if (!r.ok || !data.ok) return;
|
||||
const parts = [];
|
||||
if ((data.branches || []).length) {
|
||||
parts.push('🌿 Branches : ' + data.branches.map(b => `<code>${b}</code>`).join(', '));
|
||||
}
|
||||
for (const pr of data.pulls || []) {
|
||||
const state = pr.merged ? 'fusionnée' : (pr.state === 'open' ? 'ouverte' : 'fermée');
|
||||
parts.push(`🔀 <a href="${pr.html_url}" target="_blank" rel="noopener">PR #${pr.number}</a> ${pr.title} — ${state}`);
|
||||
}
|
||||
for (const c of (data.commits || []).slice(0, 8)) {
|
||||
parts.push(`⑂ <a href="${c.html_url}" target="_blank" rel="noopener"><code>${c.sha}</code></a> ${c.message}${c.date ? ' · ' + c.date : ''}`);
|
||||
}
|
||||
box.innerHTML = parts.length
|
||||
? '<h3 class="detail-comments-title">🧬 Code lié</h3>' + parts.map(p => `<div class="code-line">${p}</div>`).join('')
|
||||
: '';
|
||||
} catch (err) { /* le code est un bonus, jamais bloquant */ }
|
||||
}
|
||||
|
||||
function fillDetail(issue, comments) {
|
||||
document.getElementById('detail-title').textContent = issue.title;
|
||||
const stateChip = document.getElementById('detail-state');
|
||||
|
||||
Reference in New Issue
Block a user