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