@@ -3,10 +3,65 @@ import { getWebApi } from '../../api/client.js';
33import { listWorkItems } from '../../api/workItems.js' ;
44import { getConfig } from '../../config/index.js' ;
55import { outputTable , outputJson , relativeDate , colorState , truncate } from '../../output/index.js' ;
6+ import { getTeamIterations , getTeams } from '../../api/teamSettings.js' ;
7+ import { WebApi } from 'azure-devops-node-api' ;
8+
9+
10+ async function getIterationPathByOptions ( connection : WebApi , project : string , iteration : string | undefined ) : Promise < string | undefined > {
11+ if ( ! iteration ) {
12+ return undefined ;
13+ }
14+
15+ iteration = iteration . toLowerCase ( ) ;
16+
17+ if ( iteration === 'all' ) {
18+ return undefined ;
19+ }
20+
21+ if ( iteration !== 'current' && iteration !== 'next' ) {
22+ return iteration ;
23+ }
24+
25+
26+ const myTeams = await getTeams ( connection , project , { mine : true } ) ;
27+
28+ if ( myTeams . length === 0 ) {
29+ process . stdout . write ( 'No teams found for the current user.\n' ) ;
30+ return undefined ;
31+ }
32+
33+ const team = myTeams [ 0 ] . name ! ;
34+ const iterations = await getTeamIterations ( connection , project , team , { current : true } ) ;
35+
36+ if ( iterations . length === 0 ) {
37+ process . stdout . write ( `No current iteration found for team ${ team } .\n` ) ;
38+ return undefined ;
39+ }
40+
41+ const currentIteration = iterations [ 0 ] ;
42+ if ( iteration === 'current' ) {
43+ return currentIteration . path ;
44+ }
45+
46+ if ( iteration === 'next' ) {
47+ const allIterations = await getTeamIterations ( connection , project , team , { } ) ;
48+ const currentIndex = allIterations . findIndex ( i => i . id === currentIteration . id ) ;
49+
50+ if ( currentIndex === - 1 || currentIndex === allIterations . length - 1 ) {
51+ process . stdout . write ( `No next iteration found for team ${ team } .\n` ) ;
52+ return undefined ;
53+ }
54+
55+ return allIterations [ currentIndex + 1 ] . path ;
56+ }
57+
58+ return undefined ;
59+ }
660
761async function issueListHandler ( options : {
862 state ?: string ;
963 assignee ?: string ;
64+ iteration ?: string ;
1065 label ?: string ;
1166 limit ?: string ;
1267 project ?: string ;
@@ -26,12 +81,15 @@ async function issueListHandler(options: {
2681
2782 const connection = await getWebApi ( config . orgUrl ) ;
2883
84+ let iterationPath = await getIterationPathByOptions ( connection , config . project , options . iteration ) ;
85+
2986 const items = await listWorkItems ( connection , config . project , {
3087 state : options . state ,
3188 assignee : options . assignee ,
3289 tag : options . label ,
3390 limit : options . limit ? parseInt ( options . limit , 10 ) : 30 ,
3491 type : options . type ,
92+ iterationPath,
3593 } ) ;
3694
3795 if ( options . json !== undefined ) {
@@ -71,9 +129,10 @@ export function registerIssueList(issueCmd: Command): void {
71129 issueCmd
72130 . command ( 'list' )
73131 . description ( 'List work items in a project' )
74- . option ( '-s, --state <state>' , 'Filter by state: open| closed|all ' , 'open ' )
132+ . option ( '-s, --state <state>' , 'Filter by states (comma-separated, e.g. open, closed) ' , '!removed & !deleted & !closed ' )
75133 . option ( '-a, --assignee <assignee>' , 'Filter by assignee (use @me for yourself)' )
76134 . option ( '-l, --label <label>' , 'Filter by tag/label' )
135+ . option ( '-i, --iteration <path>' , 'Filter by iteration path (or current, next, all)' , 'current' )
77136 . option ( '-t, --type <type>' , 'Filter by work item type (e.g. Bug, Task, User Story)' )
78137 . option ( '--limit <number>' , 'Max items to return' , '30' )
79138 . option ( '-p, --project <project>' , 'Azure DevOps project (overrides config)' )
0 commit comments