134134 . gap-dep-head , . gap-line { padding-left : 16px ; }
135135 . gap-line . nested { padding-left : 32px ; }
136136 . gap-line button { padding : 0 8px ; font-size : 12px ; }
137+ . gap-summary { flex : 1 1 0 ; min-width : 8em ; }
138+ . gap-dep-head > . status { margin-left : auto; }
137139 . row-key . via-jira > a { text-decoration : underline dashed; text-underline-offset : 3px ; }
138140 . link-icon { width : 13px ; height : 13px ; margin-right : 2px ; vertical-align : -2px ; fill : none; stroke : currentColor; stroke-width : 2 ; stroke-linecap : round; stroke-linejoin : round; }
139141 . issue-row . summary { overflow : hidden; text-overflow : ellipsis; white-space : nowrap; }
@@ -334,7 +336,7 @@ <h2 x-text="t('services')"></h2>
334336 </ template >
335337 < template x-for ="entry in unlisted " :key ="entry.project ">
336338 < div class ="service unlisted ">
337- < b :title ="entry.project " x-text ="shortName(entry.project) "> </ b >
339+ < b :title ="entry.project "> < a :href =" entry.url " x-text ="shortName(entry.project) "> </ a > </ b >
338340 < span class ="cell cell-outside " x-text ="t('notInReport') "> </ span >
339341 < span class ="muted " x-text ="t('linkedTo') "> </ span >
340342 < template x-for ="key in entry.keys " :key ="key "> < span class ="key " x-text ="key "> </ span > </ template >
@@ -394,7 +396,7 @@ <h2 x-text="t('release')"></h2>
394396 < div class ="gap-head ">
395397 < span class ="dot " :class ="'dot-' + (task.issue ? task.issue.status_category : 'new') " :title ="task.issue && task.issue.status "> </ span >
396398 < a :href ="task.url " x-text ="task.key "> </ a >
397- < span x-text ="task.issue ? task.issue.summary : '' "> </ span >
399+ < span class =" gap-summary " x-text ="task.issue ? task.issue.summary : '' "> </ span >
398400 </ div >
399401 < template x-for ="(item, index) in gapRows(task) " :key ="index ">
400402 < div >
@@ -403,15 +405,20 @@ <h2 x-text="t('release')"></h2>
403405 < span class ="muted " x-text ="relationLabel(item.dep.relation) "> </ span >
404406 < span class ="dot " :class ="'dot-' + (item.dep.issue.status_category || 'new') " :title ="item.dep.issue.status "> </ span >
405407 < a :href ="item.dep.issue.url " x-text ="item.dep.key "> </ a >
406- < span class ="muted " x-text ="item.dep.issue.summary "> </ span >
408+ < span class ="muted gap-summary " x-text ="item.dep.issue.summary "> </ span >
407409 < template x-if ="!item.dep.lines.length ">
408410 < span :class ="statusClass(item.dep.issue) " x-text ="item.dep.issue.status "> </ span >
409411 </ template >
410412 </ div >
411413 </ template >
412414 < template x-if ="item.line ">
413415 < div class ="gap-line " :class ="{ nested: item.nested } ">
414- < span :title ="item.line.project " x-text ="shortName(item.line.project) "> </ span >
416+ < template x-if ="item.line.url ">
417+ < a :href ="item.line.url " :title ="item.line.project " x-text ="shortName(item.line.project) "> </ a >
418+ </ template >
419+ < template x-if ="!item.line.url ">
420+ < span :title ="item.line.project " x-text ="shortName(item.line.project) "> </ span >
421+ </ template >
415422 < span class ="cell " :class ="'cell-' + (item.line.state === 'tag' ? 'untagged' : item.line.state) " x-text ="item.line.reason "> </ span >
416423 < template x-if ="item.line.state === 'tag' ">
417424 < button type ="button " @click ="pickGap(item.line) " x-text ="t('gapPick', { tag: item.line.tag }) "> </ button >
@@ -864,8 +871,8 @@ <h2 x-text="t('release')"></h2>
864871 }
865872 }
866873 for ( const [ key , issue ] of Object . entries ( issues ) ) {
867- const outside = new Set ( issue . links . map ( ( link ) => link . project ) . filter ( ( project ) => ! projects . has ( project ) ) ) ;
868- for ( const project of outside ) reach [ key ] . push ( { project, state : "outside" } ) ;
874+ const outside = new Map ( issue . links . filter ( ( link ) => ! projects . has ( link . project ) ) . map ( ( link ) => [ link . project , link . project_url ] ) ) ;
875+ for ( const [ project , url ] of outside ) reach [ key ] . push ( { project, state : "outside" , url } ) ;
869876 }
870877 return reach ;
871878 } ;
@@ -899,7 +906,7 @@ <h2 x-text="t('release')"></h2>
899906 const report = await response . json ( ) ;
900907 for ( const service of report . services ) {
901908 const tag = service . release && service . release . tag ? service . release . tag . name : "" ;
902- this . picks [ service . project ] = service . candidates . some ( ( item ) => item . tag . name === tag ) ? tag : "" ;
909+ this . picks [ service . project ] = this . candidateOf ( service , tag ) ? tag : "" ;
903910 }
904911 this . reach = reachOf ( report ) ;
905912 this . names = namesOf ( report ) ;
@@ -973,7 +980,7 @@ <h2 x-text="t('release')"></h2>
973980 return this . pickable
974981 . map ( ( service ) => ( {
975982 service,
976- candidate : service . candidates . find ( ( item ) => item . tag . name === picks [ service . project ] ) ,
983+ candidate : this . candidateOf ( service , picks [ service . project ] ) ,
977984 } ) )
978985 . filter ( ( item ) => item . candidate ) ;
979986 } ,
@@ -1114,7 +1121,7 @@ <h2 x-text="t('release')"></h2>
11141121 } ,
11151122 postGap ( task ) {
11161123 const line = ( item , indent ) =>
1117- `${ indent } - ${ item . project } : ${ [ item . reason , ...this . gapChanges ( item ) . map ( ( change ) => `[${ change . label } ](${ change . url } )` ) ] . join ( " " ) } ` ;
1124+ `${ indent } - ${ item . url ? `[ ${ item . project } ]( ${ item . url } )` : item . project } : ${ [ item . reason , ...this . gapChanges ( item ) . map ( ( change ) => `[${ change . label } ](${ change . url } )` ) ] . join ( " " ) } ` ;
11181125 return [
11191126 `- [${ task . key } ](${ task . url } )${ task . issue ? " " + task . issue . summary : "" } ` ,
11201127 ...task . lines . map ( ( item ) => line ( item , " " ) ) ,
@@ -1153,7 +1160,7 @@ <h2 x-text="t('release')"></h2>
11531160 for ( const key of this . chosen ) {
11541161 for ( const item of this . reach [ key ] ) {
11551162 if ( ! plan . has ( item . project ) ) {
1156- plan . set ( item . project , { project : item . project , state : item . state , keys : [ ] , best : null , untagged : [ ] , elsewhere : [ ] } ) ;
1163+ plan . set ( item . project , { project : item . project , state : item . state , url : item . url , keys : [ ] , best : null , untagged : [ ] , elsewhere : [ ] } ) ;
11571164 }
11581165 const entry = plan . get ( item . project ) ;
11591166 entry . keys . push ( key ) ;
@@ -1259,7 +1266,7 @@ <h2 x-text="t('release')"></h2>
12591266 if ( wanted . size ) {
12601267 for ( const service of this . pickable ) {
12611268 const tag = wanted . get ( service . project ) || "" ;
1262- const known = ! tag || service . candidates . some ( ( item ) => item . tag . name === tag ) ;
1269+ const known = ! tag || this . candidateOf ( service , tag ) ;
12631270 this . picks [ service . project ] = known ? tag : "" ;
12641271 if ( known ) wanted . delete ( service . project ) ;
12651272 }
@@ -1278,7 +1285,10 @@ <h2 x-text="t('release')"></h2>
12781285 history . replaceState ( null , "" , hash ? `#${ hash } ` : location . pathname + location . search ) ;
12791286 } ,
12801287 pickOf ( service ) {
1281- return service . candidates . find ( ( item ) => item . tag . name === this . picks [ service . project ] ) ;
1288+ return this . candidateOf ( service , this . picks [ service . project ] ) ;
1289+ } ,
1290+ candidateOf ( service , tag ) {
1291+ return service . candidates . find ( ( item ) => item . tag . name === tag ) ;
12821292 } ,
12831293 pickHint ( service ) {
12841294 return service . candidates . length ? this . t ( "pickTag" ) : "" ;
0 commit comments