@yemi33/minions 0.1.85 → 0.1.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/dashboard/js/render-prd.js +50 -29
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -13,37 +13,54 @@ function renderPrd(prd, prog) {
|
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
// Derive status from work items
|
|
17
|
-
const allWi = window._lastWorkItems || [];
|
|
18
|
-
const prdItems = (prog?.items || []).filter(i => !i._archived);
|
|
19
|
-
const implementItems = allWi.filter(w => prdItems.some(pi => pi.id === w.id));
|
|
20
|
-
const allDone = implementItems.length > 0 && implementItems.every(w => w.status === 'done' || w.status === 'in-pr' || w.status === 'implemented' || w.status === 'complete');
|
|
21
|
-
const hasActive = implementItems.some(w => w.status === 'pending' || w.status === 'dispatched');
|
|
22
|
-
|
|
23
|
-
// Find the active PRD file for action buttons
|
|
24
|
-
const prdFile = prd.existing?.[0]?.file || '';
|
|
25
|
-
const prdStatus = prd.existing?.[0]?.status || '';
|
|
26
|
-
const effectiveStatus = allDone && !hasActive ? 'completed' : hasActive ? 'in-progress' : prdStatus || 'active';
|
|
27
|
-
|
|
28
16
|
const statusColors = { 'completed': 'var(--green)', 'in-progress': 'var(--blue)', 'awaiting-approval': 'var(--yellow)', 'paused': 'var(--muted)', 'approved': 'var(--green)' };
|
|
29
17
|
const statusLabels = { 'completed': 'Completed', 'in-progress': 'In Progress', 'awaiting-approval': 'Awaiting Approval', 'paused': 'Paused', 'approved': 'Approved' };
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
19
|
+
// Show per-PRD status summary in header when multiple PRDs exist
|
|
20
|
+
const existing = prd.existing || [];
|
|
21
|
+
const allWi = window._lastWorkItems || [];
|
|
22
|
+
const prdItems = (prog?.items || []).filter(i => !i._archived);
|
|
23
|
+
|
|
24
|
+
if (existing.length <= 1) {
|
|
25
|
+
// Single PRD — show status + actions in header
|
|
26
|
+
const implementItems = allWi.filter(w => prdItems.some(pi => pi.id === w.id));
|
|
27
|
+
const allDone = implementItems.length > 0 && implementItems.every(w => w.status === 'done' || w.status === 'in-pr' || w.status === 'implemented' || w.status === 'complete');
|
|
28
|
+
const hasActive = implementItems.some(w => w.status === 'pending' || w.status === 'dispatched');
|
|
29
|
+
const prdFile = existing[0]?.file || '';
|
|
30
|
+
const prdStatus = existing[0]?.status || '';
|
|
31
|
+
const effectiveStatus = allDone && !hasActive ? 'completed' : hasActive ? 'in-progress' : prdStatus || 'active';
|
|
32
|
+
|
|
33
|
+
let actions = '';
|
|
34
|
+
if (prdFile) {
|
|
35
|
+
if (effectiveStatus === 'awaiting-approval') {
|
|
36
|
+
actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Approve</button>';
|
|
37
|
+
} else if (effectiveStatus === 'completed') {
|
|
38
|
+
actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="triggerVerify(\'' + escHtml(prdFile) + '\',this)">Verify</button>' +
|
|
39
|
+
' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--muted);border-color:var(--border);margin-left:4px" onclick="planDelete(\'' + escHtml(prdFile) + '\')">Archive</button>';
|
|
40
|
+
} else if (effectiveStatus === 'in-progress') {
|
|
41
|
+
actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--yellow);border-color:var(--yellow);margin-left:4px" onclick="planPause(\'' + escHtml(prdFile) + '\',this)">Pause</button>';
|
|
42
|
+
} else if (effectiveStatus === 'paused') {
|
|
43
|
+
actions = ' <button class="pr-pager-btn" style="font-size:9px;padding:1px 6px;color:var(--green);border-color:var(--green);margin-left:4px" onclick="planApprove(\'' + escHtml(prdFile) + '\',this)">Resume</button>';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
badge.innerHTML = '<span style="font-weight:600;font-size:11px;color:' + (statusColors[effectiveStatus] || 'var(--muted)') + '">' + (statusLabels[effectiveStatus] || effectiveStatus) + '</span>' +
|
|
47
|
+
' <span style="color:var(--muted);font-size:10px">' + (prd.age || '') + '</span>' + actions;
|
|
48
|
+
} else {
|
|
49
|
+
// Multiple PRDs — show count summary, per-PRD details are in renderPrdProgress groups
|
|
50
|
+
const counts = { completed: 0, 'in-progress': 0, 'awaiting-approval': 0, paused: 0 };
|
|
51
|
+
for (const p of existing) {
|
|
52
|
+
const items = prdItems.filter(i => i.source === p.file);
|
|
53
|
+
const wiForPrd = allWi.filter(w => items.some(pi => pi.id === w.id));
|
|
54
|
+
const allDone = wiForPrd.length > 0 && wiForPrd.every(w => w.status === 'done' || w.status === 'in-pr' || w.status === 'implemented' || w.status === 'complete');
|
|
55
|
+
const hasActive = wiForPrd.some(w => w.status === 'pending' || w.status === 'dispatched');
|
|
56
|
+
const s = allDone && !hasActive ? 'completed' : hasActive ? 'in-progress' : p.status || 'active';
|
|
57
|
+
counts[s] = (counts[s] || 0) + 1;
|
|
42
58
|
}
|
|
59
|
+
const parts = Object.entries(counts).filter(([, n]) => n > 0).map(([s, n]) =>
|
|
60
|
+
'<span style="font-size:10px;color:' + (statusColors[s] || 'var(--muted)') + '">' + n + ' ' + (statusLabels[s] || s).toLowerCase() + '</span>'
|
|
61
|
+
);
|
|
62
|
+
badge.innerHTML = '<span style="font-weight:600;font-size:11px;color:var(--text)">' + existing.length + ' PRDs</span> ' + parts.join(' · ');
|
|
43
63
|
}
|
|
44
|
-
|
|
45
|
-
badge.innerHTML = '<span style="font-weight:600;font-size:11px;color:' + (statusColors[effectiveStatus] || 'var(--muted)') + '">' + (statusLabels[effectiveStatus] || effectiveStatus) + '</span>' +
|
|
46
|
-
' <span style="color:var(--muted);font-size:10px">' + (prd.age || '') + '</span>' + actions;
|
|
47
64
|
section.innerHTML = '';
|
|
48
65
|
}
|
|
49
66
|
|
|
@@ -52,10 +69,10 @@ function renderPrdProgress(prog) {
|
|
|
52
69
|
const countEl = document.getElementById('prd-progress-count');
|
|
53
70
|
if (!prog) { el.innerHTML = ''; countEl.textContent = '—'; return; }
|
|
54
71
|
|
|
55
|
-
// Compute progress from active (non-archived) items
|
|
72
|
+
// Compute overall progress from active (non-archived) items
|
|
56
73
|
const activeItems = (prog.items || []).filter(i => !i._archived);
|
|
57
74
|
if (activeItems.length > 0) {
|
|
58
|
-
const activeDone = activeItems.filter(i => i.status === 'done' || i.status === 'implemented' || i.status === 'in-pr').length;
|
|
75
|
+
const activeDone = activeItems.filter(i => i.status === 'done' || i.status === 'implemented' || i.status === 'in-pr').length;
|
|
59
76
|
countEl.textContent = Math.round((activeDone / activeItems.length) * 100) + '%';
|
|
60
77
|
} else {
|
|
61
78
|
countEl.textContent = '—';
|
|
@@ -159,7 +176,7 @@ function renderPrdProgress(prog) {
|
|
|
159
176
|
(prLinks ? '<span>' + prLinks + '</span>' : '') +
|
|
160
177
|
'<span class="prd-item-priority ' + (i.priority || '') + '">' + escHtml(i.priority || '') + '</span>' +
|
|
161
178
|
'<span onclick="event.stopPropagation();prdItemRemove(\'' + src + '\',\'' + iid + '\')" style="color:var(--red);cursor:pointer;font-size:10px;padding:0 4px" title="Remove item">x</span>' +
|
|
162
|
-
(i.description ? '<div style="width:100%;font-size:11px;color:var(--muted);padding:2px 0 2px 42px;line-height:1.4">' +
|
|
179
|
+
(i.description ? '<div style="width:100%;font-size:11px;color:var(--muted);padding:2px 0 2px 42px;line-height:1.4">' + renderMd(i.description) + '</div>' : '') +
|
|
163
180
|
'</div>';
|
|
164
181
|
};
|
|
165
182
|
|
|
@@ -220,6 +237,9 @@ function renderPrdProgress(prog) {
|
|
|
220
237
|
: isCompleted
|
|
221
238
|
? '<span onclick="event.stopPropagation();triggerVerify(\'' + escHtml(g.file) + '\',this)" style="color:var(--green);cursor:pointer;font-size:9px;padding:1px 6px;background:rgba(63,185,80,0.1);border:1px solid rgba(63,185,80,0.3);border-radius:3px">Verify</span>'
|
|
222
239
|
: '<span onclick="event.stopPropagation();planPause(\'' + escHtml(g.file) + '\',this)" style="color:var(--yellow);cursor:pointer;font-size:9px;padding:1px 6px;background:rgba(210,153,34,0.1);border:1px solid rgba(210,153,34,0.3);border-radius:3px">Pause</span>';
|
|
240
|
+
const archiveBtn = isCompleted
|
|
241
|
+
? '<span onclick="event.stopPropagation();planDelete(\'' + escHtml(g.file) + '\')" style="color:var(--muted);cursor:pointer;font-size:9px;padding:1px 6px;background:var(--surface);border:1px solid var(--border);border-radius:3px">Archive</span>'
|
|
242
|
+
: '';
|
|
223
243
|
const deleteBtn = '<span onclick="event.stopPropagation();planDelete(\'' + escHtml(g.file) + '\')" style="color:var(--red);cursor:pointer;font-size:9px;padding:1px 6px;background:rgba(248,81,73,0.1);border:1px solid rgba(248,81,73,0.3);border-radius:3px">Delete</span>';
|
|
224
244
|
const sourcePlanLink = g.sourcePlan
|
|
225
245
|
? '<span onclick="event.stopPropagation();planView(\'' + escHtml(g.sourcePlan) + '\')" style="color:var(--blue);cursor:pointer;font-size:9px;padding:1px 6px;background:rgba(56,139,253,0.1);border:1px solid rgba(56,139,253,0.3);border-radius:3px" title="View source plan">📄 Plan</span>'
|
|
@@ -244,6 +264,7 @@ function renderPrdProgress(prog) {
|
|
|
244
264
|
: '<span style="color:var(--muted);font-weight:400;font-size:10px;margin-left:auto;display:flex;align-items:center;gap:6px">' +
|
|
245
265
|
sourcePlanLink +
|
|
246
266
|
pauseResumeBtn +
|
|
267
|
+
archiveBtn +
|
|
247
268
|
deleteBtn +
|
|
248
269
|
'</span>') +
|
|
249
270
|
staleRecovery +
|
package/package.json
CHANGED