bdtui 0.3.1 → 0.3.2
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 +6 -0
- package/package.json +1 -1
- package/src/state.js +6 -1
- package/src/views/detail.js +38 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.3.2] - 2026-05-24
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Detail-pane dependency rows redesigned: status-colored icons (○ open, ◐ in_progress, ● blocked, ✓ closed, ❄ deferred) with the whole row tinted by effective status. Open beads whose blockers aren't all closed now render as blocked, mirroring how `bd blocked` derives the Blocked tab.
|
|
10
|
+
|
|
5
11
|
## [0.3.1] - 2026-05-16
|
|
6
12
|
|
|
7
13
|
### Added
|
package/package.json
CHANGED
package/src/state.js
CHANGED
|
@@ -9,6 +9,7 @@ export const state = {
|
|
|
9
9
|
filter: 'ready',
|
|
10
10
|
typeFilter: 'all', // 'all' | 'epic' | 'task'
|
|
11
11
|
epicFilter: null, // null or epic bead id — when set, list is scoped to that epic + its children
|
|
12
|
+
blockedIds: new Set(), // ids that appear in `bd blocked` — derived state, not raw status
|
|
12
13
|
cwd: process.cwd(),
|
|
13
14
|
};
|
|
14
15
|
|
|
@@ -76,7 +77,11 @@ function buildTreeOrder(beads, parentOf) {
|
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export async function loadList() {
|
|
79
|
-
const beads = await
|
|
80
|
+
const [beads, blocked] = await Promise.all([
|
|
81
|
+
bdList(state.filter, state.cwd),
|
|
82
|
+
bdList('blocked', state.cwd).catch(() => []),
|
|
83
|
+
]);
|
|
84
|
+
state.blockedIds = new Set((blocked || []).map((b) => b.id));
|
|
80
85
|
const byId = new Map(beads.map((b) => [b.id, b]));
|
|
81
86
|
|
|
82
87
|
// Build parent-child map from real bd deps (dependency_type === 'parent-child').
|
package/src/views/detail.js
CHANGED
|
@@ -5,6 +5,22 @@ const STATUS_COLOR = {
|
|
|
5
5
|
open: 'white', in_progress: 'cyan', blocked: 'red',
|
|
6
6
|
deferred: 'yellow', closed: 'gray',
|
|
7
7
|
};
|
|
8
|
+
|
|
9
|
+
// Dep-row palette: tuned for at-a-glance scanning in the dependency list.
|
|
10
|
+
// open / ready → green (go)
|
|
11
|
+
// in_progress → yellow (active)
|
|
12
|
+
// blocked → red (stop)
|
|
13
|
+
// deferred → gray (parked)
|
|
14
|
+
// closed → gray (done, recede)
|
|
15
|
+
const DEP_STATUS_COLOR = {
|
|
16
|
+
open: 'green', in_progress: 'yellow', blocked: 'red',
|
|
17
|
+
deferred: 'gray', closed: 'gray',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const STATUS_ICON = {
|
|
21
|
+
open: '○', in_progress: '◐', blocked: '●',
|
|
22
|
+
closed: '✓', deferred: '❄',
|
|
23
|
+
};
|
|
8
24
|
const PRIORITY_COLOR = ['red', 'yellow', 'green', 'cyan', 'gray'];
|
|
9
25
|
const PRIORITY_LABEL = ['Critical', 'High', 'Normal', 'Low', 'Trivial'];
|
|
10
26
|
|
|
@@ -30,11 +46,26 @@ function sectionHeader(title) {
|
|
|
30
46
|
return `\n${bold(t('cyan', title))}\n${t('gray', '─'.repeat(44))}`;
|
|
31
47
|
}
|
|
32
48
|
|
|
33
|
-
function depLine(dep
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
49
|
+
function depLine(dep) {
|
|
50
|
+
const rawId = esc(dep.id || String(dep));
|
|
51
|
+
const rawTitle = dep.title ? esc(dep.title) : '';
|
|
52
|
+
const issueType = dep.issue_type ? esc(dep.issue_type) : null;
|
|
53
|
+
|
|
54
|
+
// Effective status mirrors how `bd blocked` derives the Blocked tab:
|
|
55
|
+
// an open bead whose blockers aren't all closed reads as "blocked",
|
|
56
|
+
// not "open". `bd dep list` only returns the raw stored status.
|
|
57
|
+
const effectiveStatus = (dep.status === 'open' && state.blockedIds.has(dep.id))
|
|
58
|
+
? 'blocked'
|
|
59
|
+
: dep.status;
|
|
60
|
+
|
|
61
|
+
const statusColor = DEP_STATUS_COLOR[effectiveStatus] || 'white';
|
|
62
|
+
const icon = STATUS_ICON[effectiveStatus] || ' ';
|
|
63
|
+
const idText = `{bold}${rawId}{/bold}`;
|
|
64
|
+
const typeTag = issueType ? ` [${issueType}]` : '';
|
|
65
|
+
const titleText = rawTitle ? ` — ${rawTitle}` : '';
|
|
66
|
+
|
|
67
|
+
const row = `${icon} ${idText}${typeTag}${titleText}`;
|
|
68
|
+
return ` {${statusColor}-fg}${row}{/${statusColor}-fg}`;
|
|
38
69
|
}
|
|
39
70
|
|
|
40
71
|
// Apply inline markdown styling to already-escaped text. Order matters:
|
|
@@ -153,11 +184,11 @@ export function renderDetail(box) {
|
|
|
153
184
|
// ── Dependencies ───────────────────────────────────────────────────────────
|
|
154
185
|
if (b.depsDown?.length > 0) {
|
|
155
186
|
lines.push(sectionHeader(`Depends on (${b.depsDown.length})`));
|
|
156
|
-
for (const d of b.depsDown) lines.push(depLine(d
|
|
187
|
+
for (const d of b.depsDown) lines.push(depLine(d));
|
|
157
188
|
}
|
|
158
189
|
if (b.depsUp?.length > 0) {
|
|
159
190
|
lines.push(sectionHeader(`Needed by (${b.depsUp.length})`));
|
|
160
|
-
for (const d of b.depsUp) lines.push(depLine(d
|
|
191
|
+
for (const d of b.depsUp) lines.push(depLine(d));
|
|
161
192
|
}
|
|
162
193
|
|
|
163
194
|
// ── Description ────────────────────────────────────────────────────────────
|