forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
at ci-statuses 3.9 kB view raw
1package state 2 3import ( 4 "fmt" 5 "log" 6 "net/http" 7 "sort" 8 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 "tangled.org/core/api/tangled" 11 "tangled.org/core/appview/db" 12 "tangled.org/core/appview/models" 13 "tangled.org/core/appview/pages" 14 "tangled.org/core/appview/pagination" 15 "tangled.org/core/consts" 16) 17 18func (s *State) GoodFirstIssues(w http.ResponseWriter, r *http.Request) { 19 user := s.oauth.GetUser(r) 20 21 page := pagination.FromContext(r.Context()) 22 23 goodFirstIssueLabel := fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "good-first-issue") 24 25 repoLabels, err := db.GetRepoLabels(s.db, db.FilterEq("label_at", goodFirstIssueLabel)) 26 if err != nil { 27 log.Println("failed to get repo labels", err) 28 s.pages.Error503(w) 29 return 30 } 31 32 if len(repoLabels) == 0 { 33 s.pages.GoodFirstIssues(w, pages.GoodFirstIssuesParams{ 34 LoggedInUser: user, 35 RepoGroups: []*models.RepoGroup{}, 36 LabelDefs: make(map[string]*models.LabelDefinition), 37 Page: page, 38 }) 39 return 40 } 41 42 repoUris := make([]string, 0, len(repoLabels)) 43 for _, rl := range repoLabels { 44 repoUris = append(repoUris, rl.RepoAt.String()) 45 } 46 47 allIssues, err := db.GetIssuesPaginated( 48 s.db, 49 pagination.Page{ 50 Limit: 500, 51 }, 52 db.FilterIn("repo_at", repoUris), 53 db.FilterEq("open", 1), 54 ) 55 if err != nil { 56 log.Println("failed to get issues", err) 57 s.pages.Error503(w) 58 return 59 } 60 61 var goodFirstIssues []models.Issue 62 for _, issue := range allIssues { 63 if issue.Labels.ContainsLabel(goodFirstIssueLabel) { 64 goodFirstIssues = append(goodFirstIssues, issue) 65 } 66 } 67 68 repoGroups := make(map[syntax.ATURI]*models.RepoGroup) 69 for _, issue := range goodFirstIssues { 70 if group, exists := repoGroups[issue.Repo.RepoAt()]; exists { 71 group.Issues = append(group.Issues, issue) 72 } else { 73 repoGroups[issue.Repo.RepoAt()] = &models.RepoGroup{ 74 Repo: issue.Repo, 75 Issues: []models.Issue{issue}, 76 } 77 } 78 } 79 80 var sortedGroups []*models.RepoGroup 81 for _, group := range repoGroups { 82 sortedGroups = append(sortedGroups, group) 83 } 84 85 sort.Slice(sortedGroups, func(i, j int) bool { 86 iIsTangled := sortedGroups[i].Repo.Did == consts.TangledDid 87 jIsTangled := sortedGroups[j].Repo.Did == consts.TangledDid 88 89 // If one is tangled and the other isn't, non-tangled comes first 90 if iIsTangled != jIsTangled { 91 return jIsTangled // true if j is tangled (i should come first) 92 } 93 94 // Both tangled or both not tangled: sort by name 95 return sortedGroups[i].Repo.Name < sortedGroups[j].Repo.Name 96 }) 97 98 groupStart := page.Offset 99 groupEnd := page.Offset + page.Limit 100 if groupStart > len(sortedGroups) { 101 groupStart = len(sortedGroups) 102 } 103 if groupEnd > len(sortedGroups) { 104 groupEnd = len(sortedGroups) 105 } 106 107 paginatedGroups := sortedGroups[groupStart:groupEnd] 108 109 var allIssuesFromGroups []models.Issue 110 for _, group := range paginatedGroups { 111 allIssuesFromGroups = append(allIssuesFromGroups, group.Issues...) 112 } 113 114 var allLabelDefs []models.LabelDefinition 115 if len(allIssuesFromGroups) > 0 { 116 labelDefUris := make(map[string]bool) 117 for _, issue := range allIssuesFromGroups { 118 for labelDefUri := range issue.Labels.Inner() { 119 labelDefUris[labelDefUri] = true 120 } 121 } 122 123 uriList := make([]string, 0, len(labelDefUris)) 124 for uri := range labelDefUris { 125 uriList = append(uriList, uri) 126 } 127 128 if len(uriList) > 0 { 129 allLabelDefs, err = db.GetLabelDefinitions(s.db, db.FilterIn("at_uri", uriList)) 130 if err != nil { 131 log.Println("failed to fetch labels", err) 132 } 133 } 134 } 135 136 labelDefsMap := make(map[string]*models.LabelDefinition) 137 for i := range allLabelDefs { 138 labelDefsMap[allLabelDefs[i].AtUri().String()] = &allLabelDefs[i] 139 } 140 141 s.pages.GoodFirstIssues(w, pages.GoodFirstIssuesParams{ 142 LoggedInUser: user, 143 RepoGroups: paginatedGroups, 144 LabelDefs: labelDefsMap, 145 Page: page, 146 GfiLabel: labelDefsMap[goodFirstIssueLabel], 147 }) 148}