Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ The CLI uses Azure DevOps Personal Access Tokens (PAT) for authentication:
- `ado workitem close <id>` - Close a work item
- `ado workitem reopen <id>` - Reopen a work item
- `ado workitem comment <id>` - List or add comments on a work item
- `ado workitem status` - Show work items involving the current user

### Pull Requests
- `ado pr list --repository <repo>` - List pull requests
Expand Down Expand Up @@ -127,6 +128,18 @@ ado workitem edit 123 --title "New title" --state "In Progress"
ado workitem edit 123 --add-label "urgent,frontend" --area "MyTeam\\UI"
```

#### Work Item Status
```bash
# Show counts of items involving you
ado workitem status

# Show detailed table of related items
ado workitem status --table

# Limit results
ado workitem status --limit 50
```

## Global Options

- `-R, --repo <org/project>` - Target specific organization/project
Expand All @@ -139,6 +152,9 @@ ado workitem edit 123 --add-label "urgent,frontend" --area "MyTeam\\UI"
# List your assigned work items
ado workitem list --assignee @me

# Check work items that mention you or are assigned to you
ado workitem status

# Create a bug with high priority
ado workitem create --title "Critical login issue" --type Bug --priority 1 --assignee @me

Expand Down
71 changes: 71 additions & 0 deletions src/commands/workitem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ export function createWorkItemCommand(configManager: ConfigManager): Command {
}
});

command
.command('status')
.description('Show work items assigned to, created by, or mentioning the current user')
.option('-L, --limit <number>', 'Maximum number of items to fetch', '30')
.option('--table', 'Show results in a table instead of grouped counts')
.option('--full', 'Show full titles (no truncation)')
.option('--web', 'Open work items in browser when clicked')
.option('-R, --repo <org/project>', 'Target organization/project')
.action(async (options) => {
try {
if (options.repo) {
configManager.setRepository(options.repo);
}

await authManager.ensureAuthenticated();
await statusWorkItems(configManager, options);
} catch (error) {
console.error(chalk.red(`Error: ${error}`));
process.exit(1);
}
});

command
.command('create')
.description('Create a new work item')
Expand Down Expand Up @@ -217,6 +239,50 @@ async function listWorkItems(configManager: ConfigManager, options: ListWorkItem
}
}

async function statusWorkItems(configManager: ConfigManager, options: any): Promise<void> {
const spinner = ora('Fetching work items...').start();

try {
const client = new AdoApiClient(configManager);
const project = configManager.getProject();
if (!project) {
throw new Error('Project not configured. Use -R organization/project or set default repository.');
}

const wiql = buildStatusWiqlQuery(project);
const limit = parseInt(options.limit?.toString() || '30');

spinner.text = 'Executing query...';
const workItems = await client.getWorkItems(wiql, limit);

spinner.succeed(`Found ${workItems.length} work items`);

if (workItems.length === 0) {
console.log(chalk.yellow('No work items found matching the criteria.'));
return;
}

if (options.table) {
displayWorkItems(workItems, options);
} else {
const counts: Record<string, number> = {};
workItems.forEach(wi => {
const state = wi.fields['System.State'] || 'Unknown';
counts[state] = (counts[state] || 0) + 1;
});

console.log('');
console.log(chalk.cyan('Work Item Counts by State:'));
Object.entries(counts).forEach(([state, count]) => {
console.log(`${getStateWithColor(state.toUpperCase())}: ${count}`);
});
}
} catch (error) {
spinner.fail('Failed to fetch work items');
throw error;
}
}

function buildWiqlQuery(options: ListWorkItemsOptions, project: string): string {
let whereClause = `[System.TeamProject] = '${project}'`;

Expand Down Expand Up @@ -255,6 +321,11 @@ function buildWiqlQuery(options: ListWorkItemsOptions, project: string): string
return `SELECT [System.Id], [System.Title], [System.WorkItemType], [System.State], [System.AssignedTo], [System.CreatedDate] FROM WorkItems WHERE ${whereClause} ORDER BY ${orderBy}`;
}

function buildStatusWiqlQuery(project: string): string {
const whereClause = `[System.TeamProject] = '${project}' AND ([System.AssignedTo] = @Me OR [System.CreatedBy] = @Me OR [System.History] CONTAINS @Me)`;
return `SELECT [System.Id], [System.Title], [System.WorkItemType], [System.State], [System.AssignedTo], [System.CreatedDate] FROM WorkItems WHERE ${whereClause} ORDER BY [System.ChangedDate] DESC`;
}

function getOrderByClause(sort: string, order: string): string {
const fieldMap: Record<string, string> = {
created: '[System.CreatedDate]',
Expand Down