From 843f899152caad6ee5b0f289b5ea966788e3c790 Mon Sep 17 00:00:00 2001 From: Cyrus Cheung Date: Fri, 25 Jul 2025 19:33:31 -0700 Subject: [PATCH 1/5] feat(web): ts mentions component --- webapp/src/components/sidebar_buttons/index.js | 1 + .../components/sidebar_buttons/sidebar_buttons.jsx | 13 +++++++++++++ webapp/src/components/sidebar_right/index.jsx | 3 ++- .../src/components/sidebar_right/sidebar_right.jsx | 10 +++++++++- webapp/src/constants/index.js | 1 + webapp/src/reducers/index.ts | 1 + webapp/src/selectors.ts | 1 + webapp/src/types/github_types.ts | 2 ++ 8 files changed, 30 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/sidebar_buttons/index.js b/webapp/src/components/sidebar_buttons/index.js index 6ecc4aebb..88dc774d6 100644 --- a/webapp/src/components/sidebar_buttons/index.js +++ b/webapp/src/components/sidebar_buttons/index.js @@ -15,6 +15,7 @@ function mapStateToProps(state) { return { connected: state[`plugins-${pluginId}`].connected, clientId: state[`plugins-${pluginId}`].clientId, + mentions: state[`plugins-${pluginId}`].sidebarContent.mentions, reviews: state[`plugins-${pluginId}`].sidebarContent.reviews, yourPrs: state[`plugins-${pluginId}`].sidebarContent.prs, yourAssignments: state[`plugins-${pluginId}`].sidebarContent.assignments, diff --git a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx index 63d1d5c8b..1df9a3cc4 100644 --- a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx +++ b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx @@ -14,6 +14,7 @@ export default class SidebarButtons extends React.PureComponent { connected: PropTypes.bool, clientId: PropTypes.string, enterpriseURL: PropTypes.string, + mentions: PropTypes.arrayOf(PropTypes.object), reviews: PropTypes.arrayOf(PropTypes.object), unreads: PropTypes.arrayOf(PropTypes.object), yourPrs: PropTypes.arrayOf(PropTypes.object), @@ -191,6 +192,18 @@ export default class SidebarButtons extends React.PureComponent { {' ' + unreads.length} + {'Mentions on Pull Requests'}} + > + this.openRHS(RHSStates.MENTIONS)} + style={button} + > + + + Date: Fri, 25 Jul 2025 19:50:12 -0700 Subject: [PATCH 2/5] feat(server): added query for mentions --- server/plugin/api.go | 12 ++++---- server/plugin/graphql/lhs_query.go | 9 ++++++ server/plugin/graphql/lhs_request.go | 41 ++++++++++++++++++++-------- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/server/plugin/api.go b/server/plugin/api.go index a3e68952c..7c8870f02 100644 --- a/server/plugin/api.go +++ b/server/plugin/api.go @@ -87,6 +87,7 @@ type SidebarContent struct { Reviews []*graphql.GithubPRDetails `json:"reviews"` Assignments []*github.Issue `json:"assignments"` Unreads []*FilteredNotification `json:"unreads"` + Mentions []*graphql.GithubPRDetails `json:"mentions"` } type Context struct { @@ -1037,19 +1038,19 @@ func (p *Plugin) createIssueComment(c *UserContext, w http.ResponseWriter, r *ht p.writeJSON(w, result) } -func (p *Plugin) getLHSData(c *UserContext) (reviewResp []*graphql.GithubPRDetails, assignmentResp []*github.Issue, openPRResp []*graphql.GithubPRDetails, err error) { +func (p *Plugin) getLHSData(c *UserContext) (reviewResp []*graphql.GithubPRDetails, assignmentResp []*github.Issue, openPRResp []*graphql.GithubPRDetails, mentionsResp []*graphql.GithubPRDetails, err error) { graphQLClient := p.graphQLConnect(c.GHInfo) - reviewResp, assignmentResp, openPRResp, err = graphQLClient.GetLHSData(c.Context.Ctx) + reviewResp, assignmentResp, openPRResp, mentionsResp, err = graphQLClient.GetLHSData(c.Context.Ctx) if err != nil { - return []*graphql.GithubPRDetails{}, []*github.Issue{}, []*graphql.GithubPRDetails{}, err + return []*graphql.GithubPRDetails{}, []*github.Issue{}, []*graphql.GithubPRDetails{}, []*graphql.GithubPRDetails{}, err } - return reviewResp, assignmentResp, openPRResp, nil + return reviewResp, assignmentResp, openPRResp, mentionsResp, nil } func (p *Plugin) getSidebarData(c *UserContext) (*SidebarContent, error) { - reviewResp, assignmentResp, openPRResp, err := p.getLHSData(c) + reviewResp, assignmentResp, openPRResp, mentionsResp, err := p.getLHSData(c) if err != nil { return nil, err } @@ -1058,6 +1059,7 @@ func (p *Plugin) getSidebarData(c *UserContext) (*SidebarContent, error) { PRs: openPRResp, Assignments: assignmentResp, Reviews: reviewResp, + Mentions: mentionsResp, Unreads: p.getUnreadsData(c), }, nil } diff --git a/server/plugin/graphql/lhs_query.go b/server/plugin/graphql/lhs_query.go index 8f6835253..6db7e77d2 100644 --- a/server/plugin/graphql/lhs_query.go +++ b/server/plugin/graphql/lhs_query.go @@ -120,4 +120,13 @@ var mainQuery struct { HasNextPage bool } } `graphql:"graphql: search(first:100, after:$openPrsCursor, query: $prOpenQueryArg, type: ISSUE)"` + + Mentions struct { + IssueCount int + Nodes []prSearchNodes + PageInfo struct { + EndCursor githubv4.String + HasNextPage bool + } + } `graphql:"mentions: search(first:100, after:$mentionsCursor, query: $prMentionsQueryArg, type: ISSUE)"` } diff --git a/server/plugin/graphql/lhs_request.go b/server/plugin/graphql/lhs_request.go index a3ebe9720..27c8abdd3 100644 --- a/server/plugin/graphql/lhs_request.go +++ b/server/plugin/graphql/lhs_request.go @@ -16,10 +16,12 @@ const ( queryParamReviewsCursor = "reviewsCursor" queryParamAssignmentsCursor = "assignmentsCursor" queryParamOpenPRsCursor = "openPrsCursor" + queryParamMentionsCursor = "mentionsCursor" queryParamOpenPRQueryArg = "prOpenQueryArg" queryParamReviewPRQueryArg = "prReviewQueryArg" queryParamAssigneeQueryArg = "assigneeQueryArg" + queryParamMentionsQueryArg = "prMentionsQueryArg" ) type GithubPRDetails struct { @@ -29,51 +31,54 @@ type GithubPRDetails struct { ChangedFiles *githubv4.Int `json:"changed_files,omitempty"` } -func (c *Client) GetLHSData(ctx context.Context) ([]*GithubPRDetails, []*github.Issue, []*GithubPRDetails, error) { +func (c *Client) GetLHSData(ctx context.Context) ([]*GithubPRDetails, []*github.Issue, []*GithubPRDetails, []*GithubPRDetails, error) { orgsList := c.getOrganizations() var resultAssignee []*github.Issue - var resultReview, resultOpenPR []*GithubPRDetails + var resultReview, resultOpenPR, resultMentions []*GithubPRDetails params := map[string]interface{}{ queryParamOpenPRQueryArg: githubv4.String(fmt.Sprintf("author:%s is:pr is:%s archived:false", c.username, githubv4.PullRequestStateOpen)), queryParamReviewPRQueryArg: githubv4.String(fmt.Sprintf("review-requested:%s is:pr is:%s archived:false", c.username, githubv4.PullRequestStateOpen)), queryParamAssigneeQueryArg: githubv4.String(fmt.Sprintf("assignee:%s is:%s archived:false", c.username, githubv4.PullRequestStateOpen)), + queryParamMentionsQueryArg: githubv4.String(fmt.Sprintf("mentions:%s is:%s is:pr archived:false", c.username, githubv4.PullRequestStateOpen)), queryParamReviewsCursor: (*githubv4.String)(nil), queryParamAssignmentsCursor: (*githubv4.String)(nil), queryParamOpenPRsCursor: (*githubv4.String)(nil), + queryParamMentionsCursor: (*githubv4.String)(nil), } var err error for _, org := range orgsList { - resultReview, resultAssignee, resultOpenPR, err = c.fetchLHSData(ctx, resultReview, resultAssignee, resultOpenPR, org, params) + resultReview, resultAssignee, resultOpenPR, resultMentions, err = c.fetchLHSData(ctx, resultReview, resultAssignee, resultOpenPR, resultMentions, org, params) if err != nil { - return nil, nil, nil, err + return nil, nil, nil, nil, err } } if len(orgsList) == 0 { - return c.fetchLHSData(ctx, resultReview, resultAssignee, resultOpenPR, "", params) + return c.fetchLHSData(ctx, resultReview, resultAssignee, resultOpenPR, resultMentions, "", params) } - return resultReview, resultAssignee, resultOpenPR, nil + return resultReview, resultAssignee, resultOpenPR, resultMentions, nil } -func (c *Client) fetchLHSData(ctx context.Context, resultReview []*GithubPRDetails, resultAssignee []*github.Issue, resultOpenPR []*GithubPRDetails, org string, params map[string]interface{}) ([]*GithubPRDetails, []*github.Issue, []*GithubPRDetails, error) { +func (c *Client) fetchLHSData(ctx context.Context, resultReview []*GithubPRDetails, resultAssignee []*github.Issue, resultOpenPR []*GithubPRDetails, resultMentions []*GithubPRDetails, org string, params map[string]interface{}) ([]*GithubPRDetails, []*github.Issue, []*GithubPRDetails, []*GithubPRDetails, error) { if org != "" { params[queryParamOpenPRQueryArg] = githubv4.String(fmt.Sprintf("org:%s %s", org, params[queryParamOpenPRQueryArg])) params[queryParamReviewPRQueryArg] = githubv4.String(fmt.Sprintf("org:%s %s", org, params[queryParamReviewPRQueryArg])) params[queryParamAssigneeQueryArg] = githubv4.String(fmt.Sprintf("org:%s %s", org, params[queryParamAssigneeQueryArg])) + params[queryParamMentionsQueryArg] = githubv4.String(fmt.Sprintf("org:%s %s", c.org, params[queryParamMentionsQueryArg])) } - allReviewRequestsFetched, allAssignmentsFetched, allOpenPRsFetched := false, false, false + allReviewRequestsFetched, allAssignmentsFetched, allOpenPRsFetched, allMentionsFetched := false, false, false, false for { - if allReviewRequestsFetched && allAssignmentsFetched && allOpenPRsFetched { + if allReviewRequestsFetched && allAssignmentsFetched && allOpenPRsFetched && allMentionsFetched { break } if err := c.executeQuery(ctx, &mainQuery, params); err != nil { - return nil, nil, nil, errors.Wrap(err, "Not able to excute the query") + return nil, nil, nil, nil, errors.Wrap(err, "Not able to excute the query") } if !allReviewRequestsFetched { @@ -117,9 +122,23 @@ func (c *Client) fetchLHSData(ctx context.Context, resultReview []*GithubPRDetai params[queryParamOpenPRsCursor] = githubv4.NewString(mainQuery.OpenPullRequests.PageInfo.EndCursor) } + + if !allMentionsFetched { + for i := range mainQuery.Mentions.Nodes { + resp := mainQuery.Mentions.Nodes[i] + pr := getPR(&resp) + resultMentions = append(resultMentions, pr) + } + + if !mainQuery.Mentions.PageInfo.HasNextPage { + allMentionsFetched = true + } + + params[queryParamMentionsCursor] = githubv4.NewString(mainQuery.Mentions.PageInfo.EndCursor) + } } - return resultReview, resultAssignee, resultOpenPR, nil + return resultReview, resultAssignee, resultOpenPR, resultMentions, nil } func getPR(prResp *prSearchNodes) *GithubPRDetails { From aa32b3db7ebf2e6de643bd883a29e12c42725321 Mon Sep 17 00:00:00 2001 From: Abbas Naqvi Date: Tue, 14 Oct 2025 17:14:44 +0530 Subject: [PATCH 3/5] fix lint --- server/plugin/graphql/lhs_request.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/plugin/graphql/lhs_request.go b/server/plugin/graphql/lhs_request.go index 7bd51bd4f..cd12bda27 100644 --- a/server/plugin/graphql/lhs_request.go +++ b/server/plugin/graphql/lhs_request.go @@ -73,10 +73,10 @@ func (c *Client) fetchLHSData( } params := map[string]interface{}{ - queryParamOpenPRQueryArg: githubv4.String(baseOpenPR), - queryParamReviewPRQueryArg: githubv4.String(baseReviewPR), - queryParamAssigneeQueryArg: githubv4.String(baseAssignee), - queryParamMentionsQueryArg: githubv4.String(baseMentions), + queryParamOpenPRQueryArg: githubv4.String(baseOpenPR), + queryParamReviewPRQueryArg: githubv4.String(baseReviewPR), + queryParamAssigneeQueryArg: githubv4.String(baseAssignee), + queryParamMentionsQueryArg: githubv4.String(baseMentions), queryParamReviewsCursor: (*githubv4.String)(nil), queryParamAssignmentsCursor: (*githubv4.String)(nil), From 7ca525336bb079cdec170e5b825cc66cd6e5d1df Mon Sep 17 00:00:00 2001 From: Cyrus Cheung Date: Thu, 25 Dec 2025 21:12:06 -0800 Subject: [PATCH 4/5] fix: add mentions cursor initialization in fetchLHSData function --- server/plugin/graphql/lhs_request.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/plugin/graphql/lhs_request.go b/server/plugin/graphql/lhs_request.go index cd12bda27..b9a8c4c21 100644 --- a/server/plugin/graphql/lhs_request.go +++ b/server/plugin/graphql/lhs_request.go @@ -81,6 +81,7 @@ func (c *Client) fetchLHSData( queryParamReviewsCursor: (*githubv4.String)(nil), queryParamAssignmentsCursor: (*githubv4.String)(nil), queryParamOpenPRsCursor: (*githubv4.String)(nil), + queryParamMentionsCursor: (*githubv4.String)(nil), } allReviewRequestsFetched, allAssignmentsFetched, allOpenPRsFetched, allMentionsFetched := false, false, false, false From e3faecf527c0e38ec21907007474fd17f14b2a7b Mon Sep 17 00:00:00 2001 From: Cyrus Cheung Date: Fri, 9 Jan 2026 20:52:29 -0800 Subject: [PATCH 5/5] fix: correct username reference in mentions query for fetching PRs --- server/plugin/graphql/lhs_request.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/plugin/graphql/lhs_request.go b/server/plugin/graphql/lhs_request.go index b9a8c4c21..2a4455519 100644 --- a/server/plugin/graphql/lhs_request.go +++ b/server/plugin/graphql/lhs_request.go @@ -63,7 +63,7 @@ func (c *Client) fetchLHSData( baseOpenPR := fmt.Sprintf("author:%s is:pr is:%s archived:false", username, githubv4.PullRequestStateOpen) baseReviewPR := fmt.Sprintf("review-requested:%s is:pr is:%s archived:false", username, githubv4.PullRequestStateOpen) baseAssignee := fmt.Sprintf("assignee:%s is:%s archived:false", username, githubv4.PullRequestStateOpen) - baseMentions := fmt.Sprintf("mentions:%s is:%s is:pr archived:false", c.username, githubv4.PullRequestStateOpen) + baseMentions := fmt.Sprintf("mentions:%s is:%s is:pr archived:false", username, githubv4.PullRequestStateOpen) if org != "" { baseOpenPR = fmt.Sprintf("org:%s %s", org, baseOpenPR)