From 2f5770566c0f40cfbc24212cadb02f29cda07427 Mon Sep 17 00:00:00 2001 From: Gokul TP Date: Sun, 13 Aug 2023 10:10:25 +0100 Subject: [PATCH] Added relevant issues for stories --- assets/schema.graphql | 4 +- internal/graphql/schema/issueresolver.go | 6 +++ .../storyissues_from_reposqueryresolver.go | 54 +++++++++++++++++++ .../storyrelevant_issuesqueryresolver.go | 54 +++++++++++++++++++ .../models/issuesstore/githubstore/issues.go | 32 +++++++++-- internal/models/issuesstore/issue.go | 5 ++ internal/models/usersstore/badge.go | 14 ++--- matro.json | 18 +++++++ 8 files changed, 174 insertions(+), 13 deletions(-) create mode 100644 internal/graphql/schema/storyissues_from_reposqueryresolver.go create mode 100644 internal/graphql/schema/storyrelevant_issuesqueryresolver.go diff --git a/assets/schema.graphql b/assets/schema.graphql index 0e92d96..0231051 100644 --- a/assets/schema.graphql +++ b/assets/schema.graphql @@ -56,8 +56,8 @@ type BadgeEdge { } enum BadgeSortBy { - points, time_created, + points, } type Comment implements Node { @@ -176,8 +176,10 @@ type Story implements Node { contentJson: String! createdBy: User! id: ID! + issuesFromRepos(first: Int, last: Int, after: String, before: String, sortOrder: SortOrder, sortBy: IssueSortBy): IssuesConnection! languages: [String]! reactions(first: Int, last: Int, after: String, before: String, sortOrder: SortOrder, sortBy: ReactionSortBy): ReactionsConnection! + relevantIssues(first: Int, last: Int, after: String, before: String, sortOrder: SortOrder, sortBy: IssueSortBy): IssuesConnection! repos: [String]! thumbnail: String! timeCreated: Time! diff --git a/internal/graphql/schema/issueresolver.go b/internal/graphql/schema/issueresolver.go index 57bdf41..cd7a22a 100644 --- a/internal/graphql/schema/issueresolver.go +++ b/internal/graphql/schema/issueresolver.go @@ -51,6 +51,7 @@ type CreateIssueInput struct { RepositoryUpdatedAt graphql.Time Title string Url string + StoryID graphql.ID UserID graphql.ID } @@ -58,6 +59,10 @@ func (n *CreateIssueInput) ToModel() (*issuesstore.Issue, error) { if n == nil { return nil, nil } + storyID, err := ParseGraphqlID(n.StoryID) + if err != nil { + return nil, err + } return &issuesstore.Issue{ Body: n.Body, @@ -69,6 +74,7 @@ func (n *CreateIssueInput) ToModel() (*issuesstore.Issue, error) { RepositoryUpdatedAt: n.RepositoryUpdatedAt.Time, Title: n.Title, Url: n.Url, + StoryID: storyID.ID, }, nil } func (n *Issue) ID(ctx context.Context) graphql.ID { diff --git a/internal/graphql/schema/storyissues_from_reposqueryresolver.go b/internal/graphql/schema/storyissues_from_reposqueryresolver.go new file mode 100644 index 0000000..ae438c4 --- /dev/null +++ b/internal/graphql/schema/storyissues_from_reposqueryresolver.go @@ -0,0 +1,54 @@ +package schema + +import ( + "context" + + "github.com/firstcontributions/backend/internal/models/issuesstore" + "github.com/firstcontributions/backend/internal/storemanager" +) + +type StoryIssuesFromReposInput struct { + First *int32 + Last *int32 + After *string + Before *string + SortOrder *string + SortBy *string +} + +func (n *Story) IssuesFromRepos(ctx context.Context, in *StoryIssuesFromReposInput) (*IssuesConnection, error) { + var first, last *int64 + if in.First != nil { + tmp := int64(*in.First) + first = &tmp + } + if in.Last != nil { + tmp := int64(*in.Last) + last = &tmp + } + store := storemanager.FromContext(ctx) + issueType := "issues_from_repo_story" + + filters := &issuesstore.IssueFilters{ + IssueType: &issueType, + Story: n.ref, + } + sortByStr := "" + if in.SortBy != nil { + sortByStr = *in.SortBy + } + data, hasNextPage, hasPreviousPage, cursors, err := store.IssuesStore.GetIssues( + ctx, + filters, + in.After, + in.Before, + first, + last, + issuesstore.GetIssueSortByFromString(sortByStr), + in.SortOrder, + ) + if err != nil { + return nil, err + } + return NewIssuesConnection(filters, data, hasNextPage, hasPreviousPage, cursors), nil +} diff --git a/internal/graphql/schema/storyrelevant_issuesqueryresolver.go b/internal/graphql/schema/storyrelevant_issuesqueryresolver.go new file mode 100644 index 0000000..e45652d --- /dev/null +++ b/internal/graphql/schema/storyrelevant_issuesqueryresolver.go @@ -0,0 +1,54 @@ +package schema + +import ( + "context" + + "github.com/firstcontributions/backend/internal/models/issuesstore" + "github.com/firstcontributions/backend/internal/storemanager" +) + +type StoryRelevantIssuesInput struct { + First *int32 + Last *int32 + After *string + Before *string + SortOrder *string + SortBy *string +} + +func (n *Story) RelevantIssues(ctx context.Context, in *StoryRelevantIssuesInput) (*IssuesConnection, error) { + var first, last *int64 + if in.First != nil { + tmp := int64(*in.First) + first = &tmp + } + if in.Last != nil { + tmp := int64(*in.Last) + last = &tmp + } + store := storemanager.FromContext(ctx) + issueType := "relevant_issues_story" + + filters := &issuesstore.IssueFilters{ + IssueType: &issueType, + Story: n.ref, + } + sortByStr := "" + if in.SortBy != nil { + sortByStr = *in.SortBy + } + data, hasNextPage, hasPreviousPage, cursors, err := store.IssuesStore.GetIssues( + ctx, + filters, + in.After, + in.Before, + first, + last, + issuesstore.GetIssueSortByFromString(sortByStr), + in.SortOrder, + ) + if err != nil { + return nil, err + } + return NewIssuesConnection(filters, data, hasNextPage, hasPreviousPage, cursors), nil +} diff --git a/internal/models/issuesstore/githubstore/issues.go b/internal/models/issuesstore/githubstore/issues.go index a392277..a4da898 100644 --- a/internal/models/issuesstore/githubstore/issues.go +++ b/internal/models/issuesstore/githubstore/issues.go @@ -5,17 +5,20 @@ import ( "fmt" "github.com/firstcontributions/backend/internal/models/issuesstore" + "github.com/firstcontributions/backend/internal/models/storiesstore" "github.com/firstcontributions/backend/internal/models/usersstore" "github.com/shurcooL/githubv4" ) const ( - IssueTypeLastRepo = "last_repo_issues" - IssueTypeRecentRepo = "issues_from_other_recent_repos" - IssueTypeRelevant = "relevant_issues" + IssueTypeLastRepo = "last_repo_issues" + IssueTypeRecentRepo = "issues_from_other_recent_repos" + IssueTypeRelevant = "relevant_issues" + IssueTypeReposInStory = "issues_from_repo_story" + IssueTypeRelevantForStory = "relevant_issues_story" ) -func getQuery(user *usersstore.User, issueType string) (string, error) { +func getQuery(user *usersstore.User, story *storiesstore.Story, issueType string) (string, error) { query := "is:issue is:open no:assignee" switch issueType { @@ -35,6 +38,25 @@ func getQuery(user *usersstore.User, issueType string) (string, error) { query += fmt.Sprintf(" repo:%s", *repo) } return query + " label:\"help wanted\",\"good first issue\",\"goodfirstissue\"", nil + case IssueTypeReposInStory: + ln := len(story.Repos) + if len(user.Tags.RecentRepos) < 1 { + return "", fmt.Errorf("no recent repos") + } + count := min(7, ln) + + for _, repo := range story.Repos[:count] { + query += fmt.Sprintf(" repo:%s", *repo) + } + return query + " label:\"help wanted\",\"good first issue\",\"goodfirstissue\"", nil + case IssueTypeRelevantForStory: + languageCount := min(3, len(story.Languages)) + languages := story.Languages[:languageCount] + + for _, lng := range languages { + query += fmt.Sprintf(" language:%s", *lng) + } + return query + " label:\"good first issue\",\"goodfirstissue\"", nil default: languageCount := min(3, len(user.Tags.Languages)) languages := user.Tags.Languages[:languageCount] @@ -149,7 +171,7 @@ func (g *GitHubStore) GetIssues( tmp := githubv4.String(*before) beforeGql = &tmp } - query, err := getQuery(filters.User, *filters.IssueType) + query, err := getQuery(filters.User, filters.Story, *filters.IssueType) if err != nil { return nil, false, false, nil, nil } diff --git a/internal/models/issuesstore/issue.go b/internal/models/issuesstore/issue.go index 1233f6d..44bd676 100644 --- a/internal/models/issuesstore/issue.go +++ b/internal/models/issuesstore/issue.go @@ -3,6 +3,7 @@ package issuesstore import ( "time" + "github.com/firstcontributions/backend/internal/models/storiesstore" "github.com/firstcontributions/backend/internal/models/usersstore" "github.com/firstcontributions/backend/pkg/authorizer" "github.com/firstcontributions/backend/pkg/cursor" @@ -16,6 +17,7 @@ const ( ) type Issue struct { + StoryID string `bson:"story_id"` UserID string `bson:"user_id"` Body string `bson:"body,omitempty"` CommentCount int64 `bson:"comment_count,omitempty"` @@ -35,6 +37,8 @@ func NewIssue() *Issue { } func (issue *Issue) Get(field string) interface{} { switch field { + case "story_id": + return issue.StoryID case "user_id": return issue.UserID case "body": @@ -65,6 +69,7 @@ func (issue *Issue) Get(field string) interface{} { type IssueFilters struct { Ids []string IssueType *string + Story *storiesstore.Story User *usersstore.User } diff --git a/internal/models/usersstore/badge.go b/internal/models/usersstore/badge.go index 1418209..efbac36 100644 --- a/internal/models/usersstore/badge.go +++ b/internal/models/usersstore/badge.go @@ -11,8 +11,8 @@ type BadgeSortBy uint8 const ( BadgeSortByDefault BadgeSortBy = iota - BadgeSortByPoints BadgeSortByTimeCreated + BadgeSortByPoints ) type Badge struct { @@ -72,10 +72,10 @@ type BadgeFilters struct { func (s BadgeSortBy) String() string { switch s { - case BadgeSortByPoints: - return "points" case BadgeSortByTimeCreated: return "time_created" + case BadgeSortByPoints: + return "points" default: return "time_created" } @@ -83,10 +83,10 @@ func (s BadgeSortBy) String() string { func GetBadgeSortByFromString(s string) BadgeSortBy { switch s { - case "points": - return BadgeSortByPoints case "time_created": return BadgeSortByTimeCreated + case "points": + return BadgeSortByPoints default: return BadgeSortByDefault } @@ -94,10 +94,10 @@ func GetBadgeSortByFromString(s string) BadgeSortBy { func (s BadgeSortBy) CursorType() cursor.ValueType { switch s { - case BadgeSortByPoints: - return cursor.ValueTypeInt case BadgeSortByTimeCreated: return cursor.ValueTypeTime + case BadgeSortByPoints: + return cursor.ValueTypeInt default: return cursor.ValueTypeTime } diff --git a/matro.json b/matro.json index e79cbbe..c394d3c 100644 --- a/matro.json +++ b/matro.json @@ -242,6 +242,24 @@ "joined_data": true, "paginated": true }, + "issues_from_repos" : { + "type": "list", + "schema": "issue", + "joined_data": true, + "paginated": true, + "hardcoded_filters" : { + "issue_type": "issues_from_repo_story" + } + }, + "relevant_issues" : { + "type": "list", + "schema": "issue", + "joined_data": true, + "paginated": true, + "hardcoded_filters" : { + "issue_type": "relevant_issues_story" + } + }, "created_by" : { "type": "object", "schema": "user",