@@ -807,44 +807,46 @@ export const User = (() => {
807807 return filtered ;
808808 } ;
809809
810+ const isBlockedOnUser = ( pr , user ) => {
811+ if ( ! pr . turnData ?. pr_state ?. unblock_action || ! user ) return false ;
812+ return Object . keys ( pr . turnData . pr_state . unblock_action ) . includes ( user . login ) ;
813+ } ;
814+
810815 const renderPRList = ( container , prs , isDraft = false , section = "" , state ) => {
811816 if ( ! container ) return ;
812817
813818 const filteredPRs = applyFilters ( prs , section ) ;
819+ const currentUser = window . App ?. state ?. currentUser || null ;
820+ const viewingUser = window . App ?. state ?. viewingUser || currentUser ;
814821
815822 const sortedPRs = [ ...filteredPRs ] . sort ( ( a , b ) => {
816- if ( a . draft && ! b . draft ) return 1 ;
817- if ( ! a . draft && b . draft ) return - 1 ;
818-
819- if ( a . draft === b . draft ) {
820- if ( ! a . draft && ! b . draft ) {
821- if (
822- a . status_tags ?. includes ( "blocked on you" ) &&
823- ! b . status_tags ?. includes ( "blocked on you" )
824- )
825- return - 1 ;
826- if (
827- ! a . status_tags ?. includes ( "blocked on you" ) &&
828- b . status_tags ?. includes ( "blocked on you" )
829- )
830- return 1 ;
831-
832- if (
833- a . status_tags ?. includes ( "ready-to-merge" ) &&
834- ! b . status_tags ?. includes ( "ready-to-merge" )
835- )
836- return - 1 ;
837- if (
838- ! a . status_tags ?. includes ( "ready-to-merge" ) &&
839- b . status_tags ?. includes ( "ready-to-merge" )
840- )
841- return 1 ;
842- }
843-
844- return new Date ( b . updated_at ) - new Date ( a . updated_at ) ;
823+ // Categorize PRs
824+ const aBlockedOnViewing = isBlockedOnUser ( a , viewingUser ) ;
825+ const bBlockedOnViewing = isBlockedOnUser ( b , viewingUser ) ;
826+ const aDraft = a . draft || false ;
827+ const bDraft = b . draft || false ;
828+
829+ // Priority 1: Blocked on viewing user
830+ // Priority 2: Normal (not blocked, not draft)
831+ // Priority 3: Draft
832+
833+ // Determine categories
834+ const getCategory = ( pr ) => {
835+ if ( isBlockedOnUser ( pr , viewingUser ) ) return 1 ; // Highest priority
836+ if ( pr . draft ) return 3 ; // Lowest priority
837+ return 2 ; // Normal
838+ } ;
839+
840+ const aCategory = getCategory ( a ) ;
841+ const bCategory = getCategory ( b ) ;
842+
843+ // Sort by category first
844+ if ( aCategory !== bCategory ) {
845+ return aCategory - bCategory ;
845846 }
846-
847- return 0 ;
847+
848+ // Within same category, sort by last modification time (most recent first - descending order)
849+ return new Date ( b . updated_at ) - new Date ( a . updated_at ) ;
848850 } ) ;
849851
850852 container . innerHTML = sortedPRs . map ( ( pr ) => createPRCard ( pr ) ) . join ( "" ) ;
@@ -854,12 +856,60 @@ export const User = (() => {
854856 }
855857 } ;
856858
859+ const buildWaitingOn = ( pr , viewingUser , currentUser , isIncomingPR = false ) => {
860+ if ( ! pr . turnData ?. pr_state ?. unblock_action ) {
861+ return '' ;
862+ }
863+
864+ // unblock_action is a dictionary where keys are usernames and values have critical/reason
865+ const unblockAction = pr . turnData . pr_state . unblock_action ;
866+ const usernames = Object . keys ( unblockAction ) ;
867+
868+ if ( usernames . length === 0 ) {
869+ return '' ;
870+ }
871+
872+ const waitingList = usernames . map ( username => {
873+ const action = unblockAction [ username ] ;
874+ const isViewingUser = viewingUser && username === viewingUser . login ;
875+ const isCurrentUser = currentUser && username === currentUser . login ;
876+
877+ let displayName = username ;
878+ let className = 'pr-waiting-on-user' ;
879+
880+ // If viewing someone else's dashboard, highlight their name
881+ if ( viewingUser && currentUser && viewingUser . login !== currentUser . login ) {
882+ if ( isViewingUser ) {
883+ displayName = viewingUser . login ;
884+ // Use red for incoming PRs, green for outgoing
885+ className = isIncomingPR ? 'pr-waiting-on-you' : 'pr-waiting-on-you-green' ;
886+ }
887+ } else {
888+ // Normal behavior when viewing your own dashboard
889+ if ( isCurrentUser ) {
890+ displayName = 'YOU' ;
891+ className = 'pr-waiting-on-you' ;
892+ }
893+ }
894+
895+ const title = action . reason || 'Waiting for action' ;
896+
897+ return `<span class="${ className } " title="${ escapeHtml ( title ) } ">${ escapeHtml ( displayName ) } </span>` ;
898+ } ) . join ( ', ' ) ;
899+
900+ return ` <span class="pr-waiting-on"><span class="pr-waiting-on-label">(waiting on</span> ${ waitingList } <span class="pr-waiting-on-label">)</span></span>` ;
901+ } ;
902+
857903 const createPRCard = ( pr ) => {
858904 const state = getPRState ( pr ) ;
859- const badges = buildBadges ( pr ) ;
905+ const currentUser = window . App ?. state ?. currentUser || null ;
906+ const viewingUser = window . App ?. state ?. viewingUser || currentUser ;
907+ const badges = buildBadges ( pr , viewingUser , currentUser ) ;
860908 const ageText = getAgeText ( pr ) ;
861909 const reviewers = buildReviewers ( pr . requested_reviewers || [ ] ) ;
862910 const needsAction = pr . status_tags ?. includes ( "blocked on you" ) ;
911+ // Determine if this is an incoming PR (PR author is not the viewing user)
912+ const isIncomingPR = pr . user . login !== ( viewingUser ?. login || currentUser ?. login ) ;
863913
864914 const getActivityIcon = ( type ) => {
865915 const icons = {
@@ -936,8 +986,10 @@ export const User = (() => {
936986 </div>
937987 ` ;
938988
989+ const blockedOnViewing = isBlockedOnUser ( pr , viewingUser ) ;
990+
939991 return `
940- <div class="pr-card" data-state="${ state } " data-pr-id="${ pr . id } " ${ needsAction ? 'data-needs-action="true"' : "" } ${ pr . draft ? 'data-draft="true"' : "" } >
992+ <div class="pr-card" data-state="${ state } " data-pr-id="${ pr . id } " ${ needsAction ? 'data-needs-action="true"' : "" } ${ pr . draft ? 'data-draft="true"' : "" } ${ blockedOnViewing ? 'data-blocked-on-viewing="true"' : "" } >
941993 <div class="pr-header">
942994 <a href="${ pr . html_url } " class="pr-title" target="_blank" rel="noopener">
943995 ${ escapeHtml ( pr . title ) }
@@ -950,6 +1002,7 @@ export const User = (() => {
9501002 <span class="pr-repo">${ pr . repository . full_name } </span>
9511003 <span class="pr-number">#${ pr . number } </span>
9521004 <span class="pr-author">by ${ pr . user . login } </span>
1005+ ${ buildWaitingOn ( pr , viewingUser , currentUser , isIncomingPR ) }
9531006 </div>
9541007 <div class="pr-meta-right">
9551008 <span class="pr-age">${ ageText } </span>
@@ -968,6 +1021,17 @@ export const User = (() => {
9681021 const section = existingCard . closest ( "#incomingPRs" )
9691022 ? "incoming"
9701023 : "outgoing" ;
1024+
1025+ // Check if this PR's blocking status affects sorting
1026+ const viewingUser = state . viewingUser || state . currentUser ;
1027+ const wasBlockedOnViewing = existingCard . hasAttribute ( 'data-blocked-on-viewing' ) ;
1028+ const isNowBlockedOnViewing = isBlockedOnUser ( pr , viewingUser ) ;
1029+
1030+ // If blocking status changed, re-render the entire section to maintain sort order
1031+ if ( wasBlockedOnViewing !== isNowBlockedOnViewing ) {
1032+ updatePRSections ( state ) ;
1033+ return ;
1034+ }
9711035
9721036 const hideStale = getCookie ( `${ section } FilterStale` ) === "true" ;
9731037 const shouldHide = ( hideStale && isStale ( pr ) ) ;
@@ -1029,7 +1093,7 @@ export const User = (() => {
10291093 return "xlarge" ;
10301094 } ;
10311095
1032- const buildBadges = ( pr ) => {
1096+ const buildBadges = ( pr , viewingUser , currentUser ) => {
10331097 const badges = [ ] ;
10341098
10351099 // Add prominent badges first based on turnData
@@ -1050,15 +1114,21 @@ export const User = (() => {
10501114 badges . push ( '<span class="badge badge-draft">draft</span>' ) ;
10511115 }
10521116
1117+ // Check if PR is blocked on viewing user
1118+ if ( isBlockedOnUser ( pr , viewingUser ) ) {
1119+ if ( viewingUser && currentUser && viewingUser . login === currentUser . login ) {
1120+ badges . push ( '<span class="badge badge-blocked-on-you">blocked on you</span>' ) ;
1121+ } else if ( viewingUser ) {
1122+ badges . push ( `<span class="badge badge-blocked-on-you">blocked on ${ viewingUser . login } </span>` ) ;
1123+ }
1124+ }
1125+
10531126 if ( pr . status_tags ?. includes ( "loading" ) ) {
10541127 badges . push ( '<span class="badge badge-loading">Loading</span>' ) ;
10551128 } else if ( pr . status_tags && pr . status_tags . length > 0 ) {
10561129 const needsBadges = pr . status_tags
1057- . filter ( ( tag ) => tag . startsWith ( "needs-" ) || tag === "blocked on you" )
1130+ . filter ( ( tag ) => tag . startsWith ( "needs-" ) )
10581131 . map ( ( tag ) => {
1059- if ( tag === "blocked on you" ) {
1060- return '<span class="badge badge-blocked">blocked on you</span>' ;
1061- }
10621132 const displayText = tag . replace ( "needs-" , "" ) . replace ( / _ / g, " " ) ;
10631133 return `<span class="badge badge-needs">${ displayText } </span>` ;
10641134 } ) ;
0 commit comments