@damper/cli 0.6.10 → 0.6.11
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/dist/commands/status.js +7 -6
- package/dist/ui/task-picker.js +29 -22
- package/package.json +1 -1
package/dist/commands/status.js
CHANGED
|
@@ -49,24 +49,25 @@ export async function statusCommand() {
|
|
|
49
49
|
console.log();
|
|
50
50
|
for (const wt of projectWorktrees) {
|
|
51
51
|
const exists = fs.existsSync(wt.path);
|
|
52
|
-
const
|
|
53
|
-
// Try to get task status
|
|
52
|
+
const shortTaskId = wt.taskId.slice(0, 8);
|
|
53
|
+
// Try to get task status and title
|
|
54
54
|
let taskStatus = '';
|
|
55
|
+
let taskTitle = '';
|
|
55
56
|
if (api) {
|
|
56
57
|
try {
|
|
57
58
|
const task = await api.getTask(wt.taskId);
|
|
58
59
|
const statusColor = task.status === 'done' ? pc.green : task.status === 'in_progress' ? pc.yellow : pc.dim;
|
|
59
60
|
taskStatus = statusColor(`[${task.status}]`);
|
|
61
|
+
taskTitle = task.title;
|
|
60
62
|
}
|
|
61
63
|
catch {
|
|
62
64
|
taskStatus = pc.dim('[unknown]');
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
const statusIcon = exists ? pc.green('●') : pc.red('○');
|
|
66
|
-
|
|
67
|
-
console.log(`
|
|
68
|
-
console.log(` ${pc.dim('
|
|
69
|
-
console.log(` ${pc.dim('Created:')} ${new Date(wt.createdAt).toLocaleDateString()}`);
|
|
68
|
+
const titlePart = taskTitle ? ` ${taskTitle}` : '';
|
|
69
|
+
console.log(` ${statusIcon} ${pc.cyan(`#${shortTaskId}`)}${titlePart} ${taskStatus}`);
|
|
70
|
+
console.log(` ${wt.branch} ${pc.dim('·')} ${pc.dim(`created ${new Date(wt.createdAt).toLocaleDateString()}`)}`);
|
|
70
71
|
console.log();
|
|
71
72
|
}
|
|
72
73
|
}
|
package/dist/ui/task-picker.js
CHANGED
|
@@ -1,50 +1,57 @@
|
|
|
1
1
|
import { select, confirm, input, Separator } from '@inquirer/prompts';
|
|
2
2
|
import pc from 'picocolors';
|
|
3
|
+
function shortId(id) {
|
|
4
|
+
return id.slice(0, 8);
|
|
5
|
+
}
|
|
3
6
|
function getTypeIcon(type) {
|
|
4
7
|
switch (type) {
|
|
5
|
-
case 'bug': return
|
|
6
|
-
case 'feature': return
|
|
7
|
-
case 'improvement': return
|
|
8
|
-
default: return
|
|
8
|
+
case 'bug': return '🐛';
|
|
9
|
+
case 'feature': return '✨';
|
|
10
|
+
case 'improvement': return '💡';
|
|
11
|
+
default: return '📌';
|
|
9
12
|
}
|
|
10
13
|
}
|
|
11
14
|
function getPriorityIcon(priority) {
|
|
12
15
|
switch (priority) {
|
|
13
|
-
case 'high': return
|
|
14
|
-
case 'medium': return
|
|
15
|
-
default: return
|
|
16
|
+
case 'high': return '🔴 ';
|
|
17
|
+
case 'medium': return '🟡 ';
|
|
18
|
+
default: return '';
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
function formatTaskChoice(choice) {
|
|
19
22
|
const { task } = choice;
|
|
20
23
|
const typeIcon = getTypeIcon(task.type);
|
|
21
24
|
const priorityIcon = getPriorityIcon(task.priority);
|
|
25
|
+
const id = `${pc.dim('#')}${pc.cyan(shortId(task.id))}`;
|
|
22
26
|
if (choice.type === 'in_progress') {
|
|
23
27
|
const worktreeName = choice.worktree.path.split('/').pop() || choice.worktree.path;
|
|
24
|
-
let description = `${
|
|
25
|
-
description += `\n
|
|
28
|
+
let description = `${priorityIcon}${typeIcon} ${id} ${task.title}`;
|
|
29
|
+
description += `\n ${pc.dim(worktreeName)}`;
|
|
26
30
|
if (choice.lastNote) {
|
|
27
|
-
// Truncate long notes
|
|
28
31
|
const note = choice.lastNote.length > 60 ? choice.lastNote.slice(0, 60) + '...' : choice.lastNote;
|
|
29
|
-
description += `\n
|
|
32
|
+
description += `\n ${pc.dim(`Last: "${note}"`)}`;
|
|
30
33
|
}
|
|
31
34
|
return description;
|
|
32
35
|
}
|
|
33
36
|
if (choice.type === 'locked') {
|
|
34
|
-
let description = `${
|
|
35
|
-
description += pc.yellow(`
|
|
37
|
+
let description = `${priorityIcon}${typeIcon} ${id} ${task.title}`;
|
|
38
|
+
description += `\n ${pc.yellow(`locked by ${choice.lockedBy}`)}`;
|
|
36
39
|
return description;
|
|
37
40
|
}
|
|
38
41
|
// Available task
|
|
39
|
-
let description = `${
|
|
42
|
+
let description = `${priorityIcon}${typeIcon} ${id} ${task.title}`;
|
|
43
|
+
const meta = [];
|
|
40
44
|
if (task.quarter) {
|
|
41
|
-
|
|
45
|
+
meta.push(task.quarter);
|
|
42
46
|
}
|
|
43
47
|
if (task.hasImplementationPlan) {
|
|
44
|
-
|
|
48
|
+
meta.push('has plan');
|
|
45
49
|
}
|
|
46
50
|
if (task.subtaskProgress) {
|
|
47
|
-
|
|
51
|
+
meta.push(`${task.subtaskProgress.done}/${task.subtaskProgress.total} subtasks`);
|
|
52
|
+
}
|
|
53
|
+
if (meta.length > 0) {
|
|
54
|
+
description += `\n ${pc.dim(meta.join(' · '))}`;
|
|
48
55
|
}
|
|
49
56
|
return description;
|
|
50
57
|
}
|
|
@@ -97,7 +104,7 @@ export async function pickTask(options) {
|
|
|
97
104
|
}
|
|
98
105
|
const choices = [];
|
|
99
106
|
if (inProgressChoices.length > 0) {
|
|
100
|
-
choices.push(new Separator(pc.bold(
|
|
107
|
+
choices.push(new Separator(pc.bold(`\n--- In Progress (${inProgressChoices.length}) ---`)));
|
|
101
108
|
for (const choice of inProgressChoices) {
|
|
102
109
|
choices.push({
|
|
103
110
|
name: formatTaskChoice(choice),
|
|
@@ -106,7 +113,7 @@ export async function pickTask(options) {
|
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
if (availableChoices.length > 0) {
|
|
109
|
-
choices.push(new Separator(pc.bold(
|
|
116
|
+
choices.push(new Separator(pc.bold(`\n--- Available (${availableChoices.length}) ---`)));
|
|
110
117
|
for (const choice of availableChoices) {
|
|
111
118
|
choices.push({
|
|
112
119
|
name: formatTaskChoice(choice),
|
|
@@ -115,7 +122,7 @@ export async function pickTask(options) {
|
|
|
115
122
|
}
|
|
116
123
|
}
|
|
117
124
|
if (lockedChoices.length > 0) {
|
|
118
|
-
choices.push(new Separator(pc.bold(
|
|
125
|
+
choices.push(new Separator(pc.bold(`\n--- Locked (${lockedChoices.length}) ---`)));
|
|
119
126
|
for (const choice of lockedChoices) {
|
|
120
127
|
choices.push({
|
|
121
128
|
name: formatTaskChoice(choice),
|
|
@@ -139,7 +146,7 @@ export async function pickTask(options) {
|
|
|
139
146
|
const selected = await select({
|
|
140
147
|
message: 'Select a task to work on:',
|
|
141
148
|
choices: choices,
|
|
142
|
-
pageSize:
|
|
149
|
+
pageSize: 20,
|
|
143
150
|
});
|
|
144
151
|
if (selected.type === 'create_new') {
|
|
145
152
|
return handleCreateNewTask(api);
|
|
@@ -190,7 +197,7 @@ async function handleCreateNewTask(api) {
|
|
|
190
197
|
});
|
|
191
198
|
console.log(pc.dim('\nCreating task in Damper...'));
|
|
192
199
|
const task = await api.createTask(title.trim(), type);
|
|
193
|
-
console.log(pc.green(`✓ Created task #${task.id}: ${task.title}`));
|
|
200
|
+
console.log(pc.green(`✓ Created task #${shortId(task.id)}: ${task.title}`));
|
|
194
201
|
return {
|
|
195
202
|
task,
|
|
196
203
|
isResume: false,
|