fix(kanban): synchronize real Gitea issues & PRs with Whiteboard Kanban columns

This commit is contained in:
2026-10-03 21:18:02 +02:00
parent b545fa8920
commit f011461229
2 changed files with 109 additions and 36 deletions
+61 -30
View File
@@ -402,7 +402,9 @@
<div class="infra-card">
<div class="infra-title">🐙 GITEA KANBAN & PRS</div>
<div>
<span class="infra-val" id="giteaPrs">2</span> <span style="font-size:14px; color:#94a3b8">open PRs</span> |
<span class="infra-val" id="giteaPrs">0</span> <span style="font-size:13px; color:#94a3b8">PRs</span> |
<span class="infra-val" id="giteaReview" style="color:#ec4899">0</span> <span style="font-size:13px; color:#94a3b8">rev</span> |
<span class="infra-val" id="giteaWip" style="color:#38bdf8">0</span> <span style="font-size:13px; color:#94a3b8">wip</span> |
<span class="badge-ok" id="giteaStatus">CONNECTED</span>
</div>
</div>
@@ -692,11 +694,17 @@
}
// 3. Update Gitea HUD & Kanban
document.getElementById('giteaPrs').innerText = data.gitea.open_prs_count;
document.getElementById('giteaPrs').innerText = data.gitea.open_prs_count || 0;
const gStatus = document.getElementById('giteaStatus');
gStatus.innerText = data.gitea.connected ? 'CONNECTED' : 'DISCONNECTED';
gStatus.className = data.gitea.connected ? 'badge-ok' : 'badge-busy';
if (data.gitea.kanban_columns) kanbanState = data.gitea.kanban_columns;
if (data.gitea.kanban_columns) {
kanbanState = data.gitea.kanban_columns;
const revElem = document.getElementById('giteaReview');
if (revElem) revElem.innerText = kanbanState.review || 0;
const wipElem = document.getElementById('giteaWip');
if (wipElem) wipElem.innerText = kanbanState.in_progress || 0;
}
// 4. Update Agents
if (data.agents) {
@@ -984,40 +992,63 @@
ctx.fillText(f.label, f.x + 12, f.y + h + 24);
} else if (f.type === 'WHITEBOARD') {
// Gitea Kanban Board on the Wall!
const w = 110, h = 50;
// Realtime Gitea Kanban Board on the Wall!
const w = 120, h = 54;
ctx.fillStyle = "#ffffff";
ctx.fillRect(f.x, f.y, w, h);
ctx.strokeStyle = "#94a3b8";
ctx.strokeStyle = "#64748b";
ctx.lineWidth = 2;
ctx.strokeRect(f.x, f.y, w, h);
// Kanban Columns: Ready | WIP | Review
ctx.strokeStyle = "#cbd5e1";
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(f.x + 36, f.y); ctx.lineTo(f.x + 36, f.y + h);
ctx.moveTo(f.x + 72, f.y); ctx.lineTo(f.x + 72, f.y + h);
ctx.stroke();
// Header Bar
ctx.fillStyle = "#1e293b";
ctx.fillRect(f.x, f.y, w, 12);
ctx.font = "8px 'Press Start 2P'";
ctx.fillStyle = "#0f172a";
ctx.fillText("RDY", f.x + 6, f.y + 10);
ctx.fillText("WIP", f.x + 42, f.y + 10);
ctx.fillText("REV", f.x + 78, f.y + 10);
ctx.fillStyle = "#facc15";
ctx.fillText("KANBAN BOARD", f.x + 8, f.y + 9);
// Colored Sticky notes based on actual kanban counts
for (let i = 0; i < Math.min(kanbanState.ready, 3); i++) {
ctx.fillStyle = "#facc15"; // Yellow ready sticky
ctx.fillRect(f.x + 8, f.y + 14 + i * 11, 20, 8);
}
for (let i = 0; i < Math.min(kanbanState.in_progress, 2); i++) {
ctx.fillStyle = "#38bdf8"; // Blue wip sticky
ctx.fillRect(f.x + 44, f.y + 14 + i * 11, 20, 8);
}
for (let i = 0; i < Math.min(kanbanState.review, 3); i++) {
ctx.fillStyle = "#f43f5e"; // Pink review sticky
ctx.fillRect(f.x + 80, f.y + 14 + i * 11, 20, 8);
// 4 Columns: Plan | WIP | Review | Done
const colW = w / 4;
const colColors = ["#94a3b8", "#38bdf8", "#ec4899", "#22c55e"];
const colHeaders = ["PLN", "WIP", "REV", "OK"];
const colCounts = [
kanbanState.planned || 0,
kanbanState.in_progress || 0,
kanbanState.review || 0,
kanbanState.done || 0
];
for (let c = 0; c < 4; c++) {
const cx = f.x + c * colW;
if (c > 0) {
ctx.strokeStyle = "#e2e8f0";
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(cx, f.y + 12); ctx.lineTo(cx, f.y + h);
ctx.stroke();
}
// Column Header Label
ctx.font = "7px 'Press Start 2P'";
ctx.fillStyle = "#475569";
ctx.fillText(colHeaders[c], cx + 4, f.y + 21);
// Draw Mini Sticky Notes
const count = colCounts[c];
const stickiesToShow = Math.min(count, 3);
for (let s = 0; s < stickiesToShow; s++) {
ctx.fillStyle = colColors[c];
ctx.fillRect(cx + 4, f.y + 24 + s * 9, colW - 8, 7);
ctx.strokeStyle = "rgba(0,0,0,0.3)";
ctx.strokeRect(cx + 4, f.y + 24 + s * 9, colW - 8, 7);
}
// Counter Badge if count > 0
if (count > 0) {
ctx.font = "10px 'VT323'";
ctx.fillStyle = "#0f172a";
ctx.fillText(count.toString(), cx + colW - 10, f.y + 21);
}
}
} else if (f.type === 'BULLMQ_STATION') {