diff --git a/server/plugin/api.go b/server/plugin/api.go index bcf2cc822..88ed27c17 100644 --- a/server/plugin/api.go +++ b/server/plugin/api.go @@ -88,6 +88,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 { @@ -1035,19 +1036,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 } @@ -1056,6 +1057,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 6dbf93ab1..2a4455519 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,24 +31,24 @@ 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 var err error for _, org := range orgsList { - resultReview, resultAssignee, resultOpenPR, err = c.fetchLHSData(ctx, resultReview, resultAssignee, resultOpenPR, org, c.username) + resultReview, resultAssignee, resultOpenPR, resultMentions, err = c.fetchLHSData(ctx, resultReview, resultAssignee, resultOpenPR, resultMentions, org, c.username) if err != nil { c.logger.Error("Error fetching LHS data for org", "org", org, "error", err.Error()) } } if len(orgsList) == 0 { - return c.fetchLHSData(ctx, resultReview, resultAssignee, resultOpenPR, "", c.username) + return c.fetchLHSData(ctx, resultReview, resultAssignee, resultOpenPR, resultMentions, "", c.username) } - return resultReview, resultAssignee, resultOpenPR, nil + return resultReview, resultAssignee, resultOpenPR, resultMentions, nil } func (c *Client) fetchLHSData( @@ -54,37 +56,43 @@ func (c *Client) fetchLHSData( resultReview []*GithubPRDetails, resultAssignee []*github.Issue, resultOpenPR []*GithubPRDetails, + resultMentions []*GithubPRDetails, org string, username string, -) ([]*GithubPRDetails, []*github.Issue, []*GithubPRDetails, error) { +) ([]*GithubPRDetails, []*github.Issue, []*GithubPRDetails, []*GithubPRDetails, error) { 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", username, githubv4.PullRequestStateOpen) if org != "" { baseOpenPR = fmt.Sprintf("org:%s %s", org, baseOpenPR) baseReviewPR = fmt.Sprintf("org:%s %s", org, baseReviewPR) baseAssignee = fmt.Sprintf("org:%s %s", org, baseAssignee) + baseMentions = fmt.Sprintf("org:%s %s", org, baseMentions) } params := map[string]interface{}{ - queryParamOpenPRQueryArg: githubv4.String(baseOpenPR), - queryParamReviewPRQueryArg: githubv4.String(baseReviewPR), - queryParamAssigneeQueryArg: githubv4.String(baseAssignee), + queryParamOpenPRQueryArg: githubv4.String(baseOpenPR), + queryParamReviewPRQueryArg: githubv4.String(baseReviewPR), + queryParamAssigneeQueryArg: githubv4.String(baseAssignee), + queryParamMentionsQueryArg: githubv4.String(baseMentions), + queryParamReviewsCursor: (*githubv4.String)(nil), queryParamAssignmentsCursor: (*githubv4.String)(nil), queryParamOpenPRsCursor: (*githubv4.String)(nil), + queryParamMentionsCursor: (*githubv4.String)(nil), } - 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 execute the query") + return nil, nil, nil, nil, errors.Wrap(err, "Not able to execute the query") } if !allReviewRequestsFetched { @@ -128,9 +136,23 @@ func (c *Client) fetchLHSData( 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 { 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} + > + + +