105105 . cell { padding : 0 6px ; border-radius : 4px ; font-size : 12px ; white-space : nowrap; }
106106 . cell-tag { background : color-mix ( in srgb, var ( --accent ) 14% , transparent) ; color : var ( --accent ) ; }
107107 . cell-untagged { background : color-mix ( in srgb, var ( --warn ) 16% , transparent) ; color : var ( --warn ) ; }
108- . cell-elsewhere { background : color-mix ( in srgb, var ( --good ) 14% , transparent) ; color : var ( --good ) ; }
108+ . cell-production , . cell-older { background : color-mix ( in srgb, var ( --good ) 14% , transparent) ; color : var ( --good ) ; }
109+ . cell-open , . cell-branch { background : color-mix ( in srgb, var ( --warn ) 16% , transparent) ; color : var ( --warn ) ; }
110+ . cell-closed , . cell-elsewhere { background : var ( --panel ) ; color : var ( --muted ) ; }
109111 . cell-outside , . cell-failed { background : color-mix ( in srgb, var ( --bad ) 12% , transparent) ; color : var ( --bad ) ; }
110112 . issue-tools { display : flex; flex-wrap : wrap; gap : 8px ; margin : 6px 0 ; }
111113 . issue-tools input { flex : 1 ; min-width : 140px ; font : inherit; padding : 2px 8px ; border : 1px solid var ( --border ) ; border-radius : 6px ;
@@ -205,8 +207,8 @@ <h2 x-text="t('services')"></h2>
205207 x-text ="service.untagged && service.untagged.next_tag ? t('createTag', { name: service.untagged.next_tag }) : t('createAnyTag') "> </ a >
206208 </ span >
207209 </ template >
208- < template x-if ="planOf(service).elsewhere.length && !planOf(service).best && !planOf(service).untagged.length ">
209- < span class ="muted " x-text ="t('planElsewhere', { keys: planOf(service).elsewhere.join(', ') } ) "> </ span >
210+ < template x-if ="planOf(service).elsewhere.length ">
211+ < span class ="muted " x-text ="outOfRangeText( planOf(service)) "> </ span >
210212 </ template >
211213 < template x-if ="missedBy(service).length ">
212214 < span class ="warn " x-text ="t('planMissed', { tag: picks[service.project], keys: missedBy(service).join(', ') }) "> </ span >
@@ -535,12 +537,17 @@ <h2 x-text="t('release')"></h2>
535537 shipsAnywayTitle : "Not chosen, but a picked tag ships it" ,
536538 reachUntagged : "no tag yet" ,
537539 reachElsewhere : "in prod or not merged" ,
540+ reachProduction : "in prod" ,
541+ reachOlder : "older than the range" ,
542+ reachOpen : "not merged" ,
543+ reachClosed : "closed" ,
544+ reachBranch : "merged into {branch}" ,
538545 notInReport : "not in this report" ,
539546 linkedTo : "linked to" ,
540547 planFor : "for" ,
541548 planAlso : "also ships" ,
542549 planNoTag : "{keys}: no tag yet." ,
543- planElsewhere : "{keys}: in production or not merged , nothing to pick" ,
550+ planElsewhere : "{items} , nothing to pick" ,
544551 planMissed : "{tag} does not ship {keys}" ,
545552 } ,
546553 ru : {
@@ -631,12 +638,17 @@ <h2 x-text="t('release')"></h2>
631638 shipsAnywayTitle : "Задача не выбрана, но выбранный тег её содержит" ,
632639 reachUntagged : "нет тега" ,
633640 reachElsewhere : "на проде или не влита" ,
641+ reachProduction : "на проде" ,
642+ reachOlder : "старше диапазона" ,
643+ reachOpen : "не влита" ,
644+ reachClosed : "закрыта" ,
645+ reachBranch : "влита в {branch}" ,
634646 notInReport : "нет в этом отчёте" ,
635647 linkedTo : "связан с" ,
636648 planFor : "для" ,
637649 planAlso : "также войдут" ,
638650 planNoTag : "{keys}: тега ещё нет." ,
639- planElsewhere : "{keys}: уже на проде или не влиты , выбирать нечего" ,
651+ planElsewhere : "{items} , выбирать нечего" ,
640652 planMissed : "{tag} не содержит {keys}" ,
641653 } ,
642654 } ;
@@ -703,6 +715,19 @@ <h2 x-text="t('release')"></h2>
703715
704716 const byKey = ( a , b ) => a . localeCompare ( b , undefined , { numeric : true } ) ;
705717
718+ const OUT_OF_RANGE = new Set ( [ "production" , "older" , "open" , "branch" , "closed" , "elsewhere" ] ) ;
719+
720+ const outOfRange = ( service , links ) => {
721+ if ( links . some ( ( link ) => link . state === "opened" || link . state === "locked" ) ) return { state : "open" } ;
722+ if ( links . some ( ( link ) => link . state === "merged" && link . target_branch === service . default_branch ) ) {
723+ return { state : service . truncated ? "older" : "production" } ;
724+ }
725+ const merged = links . find ( ( link ) => link . state === "merged" ) ;
726+ if ( merged ) return { state : "branch" , branch : merged . target_branch } ;
727+ if ( links . some ( ( link ) => link . state === "closed" ) ) return { state : "closed" } ;
728+ return { state : "elsewhere" } ;
729+ } ;
730+
706731 const reachOf = ( report ) => {
707732 const issues = report . jira ? report . jira . issues : { } ;
708733 const reach = Object . fromEntries ( Object . keys ( issues ) . map ( ( key ) => [ key , [ ] ] ) ) ;
@@ -726,7 +751,7 @@ <h2 x-text="t('release')"></h2>
726751 continue ;
727752 }
728753 if ( ! indexes . length ) {
729- if ( links . length ) reach [ key ] . push ( { project, state : "elsewhere" } ) ;
754+ if ( links . length ) reach [ key ] . push ( { project, ... outOfRange ( service , links ) } ) ;
730755 continue ;
731756 }
732757 const index = Math . min ( ...indexes ) ;
@@ -916,7 +941,7 @@ <h2 x-text="t('release')"></h2>
916941 entry . keys . push ( key ) ;
917942 if ( item . state === "tag" && ( ! entry . best || item . tagIndex < entry . best . tagIndex ) ) entry . best = item ;
918943 if ( item . state === "untagged" ) entry . untagged . push ( key ) ;
919- if ( item . state === "elsewhere" ) entry . elsewhere . push ( key ) ;
944+ if ( OUT_OF_RANGE . has ( item . state ) ) entry . elsewhere . push ( { key, ... item } ) ;
920945 }
921946 }
922947 return plan ;
@@ -941,10 +966,27 @@ <h2 x-text="t('release')"></h2>
941966 shipsAnyway ( key ) {
942967 return ! this . chosen . includes ( key ) && this . picked . some ( ( { candidate } ) => candidate . jira_keys . some ( ( item ) => item . key === key ) ) ;
943968 } ,
969+ reachLabel ( item ) {
970+ if ( item . state === "tag" ) return item . tag ;
971+ if ( item . state === "branch" ) return this . t ( "reachBranch" , { branch : item . branch } ) ;
972+ const states = {
973+ untagged : "reachUntagged" ,
974+ production : "reachProduction" ,
975+ older : "reachOlder" ,
976+ open : "reachOpen" ,
977+ closed : "reachClosed" ,
978+ elsewhere : "reachElsewhere" ,
979+ outside : "notInReport" ,
980+ failed : "failedToCollect" ,
981+ } ;
982+ return this . t ( states [ item . state ] ) ;
983+ } ,
984+ outOfRangeText ( entry ) {
985+ const items = entry . elsewhere . map ( ( item ) => `${ item . key } ${ this . reachLabel ( item ) } ` ) . join ( ", " ) ;
986+ return entry . best || entry . untagged . length ? items : this . t ( "planElsewhere" , { items } ) ;
987+ } ,
944988 reachText ( item ) {
945- const name = item . project . split ( "/" ) . pop ( ) ;
946- const states = { untagged : "reachUntagged" , elsewhere : "reachElsewhere" , outside : "notInReport" , failed : "failedToCollect" } ;
947- return `${ name } ${ item . state === "tag" ? item . tag : this . t ( states [ item . state ] ) } ` ;
989+ return `${ item . project . split ( "/" ) . pop ( ) } ${ this . reachLabel ( item ) } ` ;
948990 } ,
949991 showIssues ( view ) {
950992 this . issueView = view ;
0 commit comments