this repo has no description
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, ok := r.Context().Value("page").(pagination.Page)
22 if !ok {
23 page = pagination.FirstPage()
24 }
25
26 goodFirstIssueLabel := fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, "good-first-issue")
27
28 repoLabels, err := db.GetRepoLabels(s.db, db.FilterEq("label_at", goodFirstIssueLabel))
29 if err != nil {
30 log.Println("failed to get repo labels", err)
31 s.pages.Error503(w)
32 return
33 }
34
35 if len(repoLabels) == 0 {
36 s.pages.GoodFirstIssues(w, pages.GoodFirstIssuesParams{
37 LoggedInUser: user,
38 RepoGroups: []*models.RepoGroup{},
39 LabelDefs: make(map[string]*models.LabelDefinition),
40 Page: page,
41 })
42 return
43 }
44
45 repoUris := make([]string, 0, len(repoLabels))
46 for _, rl := range repoLabels {
47 repoUris = append(repoUris, rl.RepoAt.String())
48 }
49
50 allIssues, err := db.GetIssues(
51 s.db,
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 return sortedGroups[i].Repo.Name < sortedGroups[j].Repo.Name
87 })
88
89 groupStart := page.Offset
90 groupEnd := page.Offset + page.Limit
91 if groupStart > len(sortedGroups) {
92 groupStart = len(sortedGroups)
93 }
94 if groupEnd > len(sortedGroups) {
95 groupEnd = len(sortedGroups)
96 }
97
98 paginatedGroups := sortedGroups[groupStart:groupEnd]
99
100 var allIssuesFromGroups []models.Issue
101 for _, group := range paginatedGroups {
102 allIssuesFromGroups = append(allIssuesFromGroups, group.Issues...)
103 }
104
105 var allLabelDefs []models.LabelDefinition
106 if len(allIssuesFromGroups) > 0 {
107 labelDefUris := make(map[string]bool)
108 for _, issue := range allIssuesFromGroups {
109 for labelDefUri := range issue.Labels.Inner() {
110 labelDefUris[labelDefUri] = true
111 }
112 }
113
114 uriList := make([]string, 0, len(labelDefUris))
115 for uri := range labelDefUris {
116 uriList = append(uriList, uri)
117 }
118
119 if len(uriList) > 0 {
120 allLabelDefs, err = db.GetLabelDefinitions(s.db, db.FilterIn("at_uri", uriList))
121 if err != nil {
122 log.Println("failed to fetch labels", err)
123 }
124 }
125 }
126
127 labelDefsMap := make(map[string]*models.LabelDefinition)
128 for i := range allLabelDefs {
129 labelDefsMap[allLabelDefs[i].AtUri().String()] = &allLabelDefs[i]
130 }
131
132 s.pages.GoodFirstIssues(w, pages.GoodFirstIssuesParams{
133 LoggedInUser: user,
134 RepoGroups: paginatedGroups,
135 LabelDefs: labelDefsMap,
136 Page: page,
137 GfiLabel: labelDefsMap[goodFirstIssueLabel],
138 })
139}