Monorepo for Tangled tangled.org

group profile timeline by month

Changed files
+401 -90
appview
+48 -18
appview/db/issues.go
··· 12 OwnerDid string 13 IssueId int 14 IssueAt string 15 - Created *time.Time 16 Title string 17 Body string 18 Open bool 19 Metadata *IssueMetadata 20 } 21 22 type IssueMetadata struct { 23 CommentCount int 24 // labels, assignee etc. 25 } 26 ··· 143 if err != nil { 144 return nil, err 145 } 146 - issue.Created = &createdTime 147 issue.Metadata = &metadata 148 149 issues = append(issues, issue) ··· 156 return issues, nil 157 } 158 159 - func GetIssuesByOwnerDid(e Execer, ownerDid string) ([]Issue, error) { 160 var issues []Issue 161 162 rows, err := e.Query( ··· 168 i.title, 169 i.body, 170 i.open, 171 - count(c.id) 172 from 173 issues i 174 - left join 175 - comments c on i.repo_at = c.repo_at and i.issue_id = c.issue_id 176 where 177 - i.owner_did = ? 178 - group by 179 - i.id, i.owner_did, i.repo_at, i.issue_id, i.created, i.title, i.body, i.open 180 order by 181 i.created desc`, 182 - ownerDid) 183 if err != nil { 184 return nil, err 185 } ··· 187 188 for rows.Next() { 189 var issue Issue 190 - var createdAt string 191 - var metadata IssueMetadata 192 - err := rows.Scan(&issue.OwnerDid, &issue.RepoAt, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open, &metadata.CommentCount) 193 if err != nil { 194 return nil, err 195 } 196 197 - createdTime, err := time.Parse(time.RFC3339, createdAt) 198 if err != nil { 199 return nil, err 200 } 201 - issue.Created = &createdTime 202 - issue.Metadata = &metadata 203 204 issues = append(issues, issue) 205 } ··· 226 if err != nil { 227 return nil, err 228 } 229 - issue.Created = &createdTime 230 231 return &issue, nil 232 } ··· 246 if err != nil { 247 return nil, nil, err 248 } 249 - issue.Created = &createdTime 250 251 comments, err := GetComments(e, repoAt, issueId) 252 if err != nil {
··· 12 OwnerDid string 13 IssueId int 14 IssueAt string 15 + Created time.Time 16 Title string 17 Body string 18 Open bool 19 + 20 + // optionally, populate this when querying for reverse mappings 21 + // like comment counts, parent repo etc. 22 Metadata *IssueMetadata 23 } 24 25 type IssueMetadata struct { 26 CommentCount int 27 + Repo *Repo 28 // labels, assignee etc. 29 } 30 ··· 147 if err != nil { 148 return nil, err 149 } 150 + issue.Created = createdTime 151 issue.Metadata = &metadata 152 153 issues = append(issues, issue) ··· 160 return issues, nil 161 } 162 163 + // timeframe here is directly passed into the sql query filter, and any 164 + // timeframe in the past should be negative; e.g.: "-3 months" 165 + func GetIssuesByOwnerDid(e Execer, ownerDid string, timeframe string) ([]Issue, error) { 166 var issues []Issue 167 168 rows, err := e.Query( ··· 174 i.title, 175 i.body, 176 i.open, 177 + r.did, 178 + r.name, 179 + r.knot, 180 + r.rkey, 181 + r.created 182 from 183 issues i 184 + join 185 + repos r on i.repo_at = r.at_uri 186 where 187 + i.owner_did = ? and i.created >= date ('now', ?) 188 order by 189 i.created desc`, 190 + ownerDid, timeframe) 191 if err != nil { 192 return nil, err 193 } ··· 195 196 for rows.Next() { 197 var issue Issue 198 + var issueCreatedAt, repoCreatedAt string 199 + var repo Repo 200 + err := rows.Scan( 201 + &issue.OwnerDid, 202 + &issue.RepoAt, 203 + &issue.IssueId, 204 + &issueCreatedAt, 205 + &issue.Title, 206 + &issue.Body, 207 + &issue.Open, 208 + &repo.Did, 209 + &repo.Name, 210 + &repo.Knot, 211 + &repo.Rkey, 212 + &repoCreatedAt, 213 + ) 214 if err != nil { 215 return nil, err 216 } 217 218 + issueCreatedTime, err := time.Parse(time.RFC3339, issueCreatedAt) 219 + if err != nil { 220 + return nil, err 221 + } 222 + issue.Created = issueCreatedTime 223 + 224 + repoCreatedTime, err := time.Parse(time.RFC3339, repoCreatedAt) 225 if err != nil { 226 return nil, err 227 } 228 + repo.Created = repoCreatedTime 229 + 230 + issue.Metadata = &IssueMetadata{ 231 + Repo: &repo, 232 + } 233 234 issues = append(issues, issue) 235 } ··· 256 if err != nil { 257 return nil, err 258 } 259 + issue.Created = createdTime 260 261 return &issue, nil 262 } ··· 276 if err != nil { 277 return nil, nil, err 278 } 279 + issue.Created = createdTime 280 281 comments, err := GetComments(e, repoAt, issueId) 282 if err != nil {
+117 -48
appview/db/profile.go
··· 1 package db 2 3 import ( 4 "fmt" 5 - "sort" 6 "time" 7 ) 8 9 - type ProfileTimelineEvent struct { 10 - EventAt time.Time 11 - Type string 12 - *Issue 13 - *Pull 14 - *Repo 15 16 - // optional: populate only if Repo is a fork 17 - Source *Repo 18 } 19 20 - func MakeProfileTimeline(e Execer, forDid string) ([]ProfileTimelineEvent, error) { 21 - timeline := []ProfileTimelineEvent{} 22 - limit := 30 23 24 - pulls, err := GetPullsByOwnerDid(e, forDid) 25 if err != nil { 26 - return timeline, fmt.Errorf("error getting pulls by owner did: %w", err) 27 } 28 29 for _, pull := range pulls { 30 - repo, err := GetRepoByAtUri(e, string(pull.RepoAt)) 31 - if err != nil { 32 - return timeline, fmt.Errorf("error getting repo by at uri: %w", err) 33 } 34 35 - timeline = append(timeline, ProfileTimelineEvent{ 36 - EventAt: pull.Created, 37 - Type: "pull", 38 - Pull: &pull, 39 - Repo: repo, 40 - }) 41 } 42 43 - issues, err := GetIssuesByOwnerDid(e, forDid) 44 if err != nil { 45 - return timeline, fmt.Errorf("error getting issues by owner did: %w", err) 46 } 47 48 for _, issue := range issues { 49 - repo, err := GetRepoByAtUri(e, string(issue.RepoAt)) 50 - if err != nil { 51 - return timeline, fmt.Errorf("error getting repo by at uri: %w", err) 52 } 53 54 - timeline = append(timeline, ProfileTimelineEvent{ 55 - EventAt: *issue.Created, 56 - Type: "issue", 57 - Issue: &issue, 58 - Repo: repo, 59 - }) 60 } 61 62 repos, err := GetAllReposByDid(e, forDid) 63 if err != nil { 64 - return timeline, fmt.Errorf("error getting all repos by did: %w", err) 65 } 66 67 for _, repo := range repos { 68 var sourceRepo *Repo 69 if repo.Source != "" { 70 sourceRepo, err = GetRepoByAtUri(e, repo.Source) ··· 73 } 74 } 75 76 - timeline = append(timeline, ProfileTimelineEvent{ 77 - EventAt: repo.Created, 78 - Type: "repo", 79 - Repo: &repo, 80 - Source: sourceRepo, 81 }) 82 } 83 84 - sort.Slice(timeline, func(i, j int) bool { 85 - return timeline[i].EventAt.After(timeline[j].EventAt) 86 - }) 87 - 88 - if len(timeline) > limit { 89 - timeline = timeline[:limit] 90 - } 91 92 - return timeline, nil 93 }
··· 1 package db 2 3 import ( 4 + "encoding/json" 5 "fmt" 6 "time" 7 ) 8 9 + type RepoEvent struct { 10 + Repo *Repo 11 + Source *Repo 12 + } 13 + 14 + type ProfileTimeline struct { 15 + ByMonth []ByMonth 16 + } 17 + 18 + type ByMonth struct { 19 + RepoEvents []RepoEvent 20 + IssueEvents IssueEvents 21 + PullEvents PullEvents 22 + } 23 + 24 + type IssueEvents struct { 25 + Items []*Issue 26 + } 27 + 28 + type IssueEventStats struct { 29 + Open int 30 + Closed int 31 + } 32 + 33 + func (i IssueEvents) Stats() IssueEventStats { 34 + var open, closed int 35 + for _, issue := range i.Items { 36 + if issue.Open { 37 + open += 1 38 + } else { 39 + closed += 1 40 + } 41 + } 42 + 43 + return IssueEventStats{ 44 + Open: open, 45 + Closed: closed, 46 + } 47 + } 48 + 49 + type PullEvents struct { 50 + Items []*Pull 51 + } 52 + 53 + func (p PullEvents) Stats() PullEventStats { 54 + var open, merged, closed int 55 + for _, pull := range p.Items { 56 + switch pull.State { 57 + case PullOpen: 58 + open += 1 59 + case PullMerged: 60 + merged += 1 61 + case PullClosed: 62 + closed += 1 63 + } 64 + } 65 + 66 + return PullEventStats{ 67 + Open: open, 68 + Merged: merged, 69 + Closed: closed, 70 + } 71 + } 72 73 + type PullEventStats struct { 74 + Closed int 75 + Open int 76 + Merged int 77 } 78 79 + const TimeframeMonths = 3 80 + 81 + func MakeProfileTimeline(e Execer, forDid string) (*ProfileTimeline, error) { 82 + timeline := ProfileTimeline{ 83 + ByMonth: make([]ByMonth, TimeframeMonths), 84 + } 85 + currentMonth := time.Now().Month() 86 + timeframe := fmt.Sprintf("-%d months", TimeframeMonths) 87 88 + pulls, err := GetPullsByOwnerDid(e, forDid, timeframe) 89 if err != nil { 90 + return nil, fmt.Errorf("error getting pulls by owner did: %w", err) 91 } 92 93 + // group pulls by month 94 for _, pull := range pulls { 95 + pullMonth := pull.Created.Month() 96 + 97 + if currentMonth-pullMonth > TimeframeMonths { 98 + // shouldn't happen; but times are weird 99 + continue 100 } 101 102 + idx := currentMonth - pullMonth 103 + items := &timeline.ByMonth[idx].PullEvents.Items 104 + 105 + *items = append(*items, &pull) 106 } 107 108 + issues, err := GetIssuesByOwnerDid(e, forDid, timeframe) 109 if err != nil { 110 + return nil, fmt.Errorf("error getting issues by owner did: %w", err) 111 } 112 113 for _, issue := range issues { 114 + issueMonth := issue.Created.Month() 115 + 116 + if currentMonth-issueMonth > TimeframeMonths { 117 + // shouldn't happen; but times are weird 118 + continue 119 } 120 121 + idx := currentMonth - issueMonth 122 + items := &timeline.ByMonth[idx].IssueEvents.Items 123 + 124 + *items = append(*items, &issue) 125 } 126 127 repos, err := GetAllReposByDid(e, forDid) 128 if err != nil { 129 + return nil, fmt.Errorf("error getting all repos by did: %w", err) 130 } 131 132 for _, repo := range repos { 133 + // TODO: get this in the original query; requires COALESCE because nullable 134 var sourceRepo *Repo 135 if repo.Source != "" { 136 sourceRepo, err = GetRepoByAtUri(e, repo.Source) ··· 139 } 140 } 141 142 + repoMonth := repo.Created.Month() 143 + 144 + if currentMonth-repoMonth > TimeframeMonths { 145 + // shouldn't happen; but times are weird 146 + continue 147 + } 148 + 149 + idx := currentMonth - repoMonth 150 + 151 + items := &timeline.ByMonth[idx].RepoEvents 152 + *items = append(*items, RepoEvent{ 153 + Repo: &repo, 154 + Source: sourceRepo, 155 }) 156 } 157 158 + x, _ := json.MarshalIndent(timeline, "", "\t") 159 + fmt.Println(string(x)) 160 161 + return &timeline, nil 162 }
+40 -14
appview/db/pulls.go
··· 64 // meta 65 Created time.Time 66 PullSource *PullSource 67 } 68 69 type PullSource struct { ··· 522 return &pull, nil 523 } 524 525 - func GetPullsByOwnerDid(e Execer, did string) ([]Pull, error) { 526 var pulls []Pull 527 528 rows, err := e.Query(` 529 select 530 - owner_did, 531 - repo_at, 532 - pull_id, 533 - created, 534 - title, 535 - state 536 from 537 - pulls 538 where 539 - owner_did = ? 540 order by 541 - created desc`, did) 542 if err != nil { 543 return nil, err 544 } ··· 546 547 for rows.Next() { 548 var pull Pull 549 - var createdAt string 550 err := rows.Scan( 551 &pull.OwnerDid, 552 &pull.RepoAt, 553 &pull.PullId, 554 - &createdAt, 555 &pull.Title, 556 &pull.State, 557 ) 558 if err != nil { 559 return nil, err 560 } 561 562 - createdTime, err := time.Parse(time.RFC3339, createdAt) 563 if err != nil { 564 return nil, err 565 } 566 - pull.Created = createdTime 567 568 pulls = append(pulls, pull) 569 }
··· 64 // meta 65 Created time.Time 66 PullSource *PullSource 67 + 68 + // optionally, populate this when querying for reverse mappings 69 + Repo *Repo 70 } 71 72 type PullSource struct { ··· 525 return &pull, nil 526 } 527 528 + // timeframe here is directly passed into the sql query filter, and any 529 + // timeframe in the past should be negative; e.g.: "-3 months" 530 + func GetPullsByOwnerDid(e Execer, did, timeframe string) ([]Pull, error) { 531 var pulls []Pull 532 533 rows, err := e.Query(` 534 select 535 + p.owner_did, 536 + p.repo_at, 537 + p.pull_id, 538 + p.created, 539 + p.title, 540 + p.state, 541 + r.did, 542 + r.name, 543 + r.knot, 544 + r.rkey, 545 + r.created 546 from 547 + pulls p 548 + join 549 + repos r on p.repo_at = r.at_uri 550 where 551 + p.owner_did = ? and p.created >= date ('now', ?) 552 order by 553 + p.created desc`, did, timeframe) 554 if err != nil { 555 return nil, err 556 } ··· 558 559 for rows.Next() { 560 var pull Pull 561 + var repo Repo 562 + var pullCreatedAt, repoCreatedAt string 563 err := rows.Scan( 564 &pull.OwnerDid, 565 &pull.RepoAt, 566 &pull.PullId, 567 + &pullCreatedAt, 568 &pull.Title, 569 &pull.State, 570 + &repo.Did, 571 + &repo.Name, 572 + &repo.Knot, 573 + &repo.Rkey, 574 + &repoCreatedAt, 575 ) 576 if err != nil { 577 return nil, err 578 } 579 580 + pullCreatedTime, err := time.Parse(time.RFC3339, pullCreatedAt) 581 if err != nil { 582 return nil, err 583 } 584 + pull.Created = pullCreatedTime 585 + 586 + repoCreatedTime, err := time.Parse(time.RFC3339, repoCreatedAt) 587 + if err != nil { 588 + return nil, err 589 + } 590 + repo.Created = repoCreatedTime 591 + 592 + pull.Repo = &repo 593 594 pulls = append(pulls, pull) 595 }
+3 -1
appview/db/repos.go
··· 77 where 78 r.did = ? 79 group by 80 - r.at_uri`, did) 81 if err != nil { 82 return nil, err 83 }
··· 77 where 78 r.did = ? 79 group by 80 + r.at_uri 81 + order by r.created desc`, 82 + did) 83 if err != nil { 84 return nil, err 85 }
+3 -2
appview/pages/pages.go
··· 178 CollaboratingRepos []db.Repo 179 ProfileStats ProfileStats 180 FollowStatus db.FollowStatus 181 - DidHandleMap map[string]string 182 AvatarUri string 183 - ProfileTimeline []db.ProfileTimelineEvent 184 } 185 186 type ProfileStats struct {
··· 178 CollaboratingRepos []db.Repo 179 ProfileStats ProfileStats 180 FollowStatus db.FollowStatus 181 AvatarUri string 182 + ProfileTimeline *db.ProfileTimeline 183 + 184 + DidHandleMap map[string]string 185 } 186 187 type ProfileStats struct {
+179 -2
appview/pages/templates/user/profile.html
··· 9 {{ block "ownRepos" . }}{{ end }} 10 {{ block "collaboratingRepos" . }}{{ end }} 11 </div> 12 - 13 <div class="md:col-span-2 order-3 md:order-3"> 14 - {{ block "profileTimeline" . }}{{ end }} 15 </div> 16 </div> 17 {{ end }} 18 19 20 {{ define "profileTimeline" }} 21 <div class="flex flex-col gap-3 relative">
··· 9 {{ block "ownRepos" . }}{{ end }} 10 {{ block "collaboratingRepos" . }}{{ end }} 11 </div> 12 <div class="md:col-span-2 order-3 md:order-3"> 13 + {{ block "profileTimeline2" . }}{{ end }} 14 </div> 15 </div> 16 {{ end }} 17 18 + {{ define "profileTimeline2" }} 19 + <p class="text-sm font-bold py-2 dark:text-white">ACTIVITY</p> 20 + <div class="flex flex-col gap-6 relative"> 21 + {{ with .ProfileTimeline }} 22 + {{ range $idx, $byMonth := .ByMonth }} 23 + {{ with $byMonth }} 24 + <div> 25 + {{ if eq $idx 0 }} 26 + <p class="text-sm font-bold py-2 dark:text-white">This month</p> 27 + {{ else }} 28 + {{ $s := "s" }} 29 + {{ if eq $idx 1 }} 30 + {{ $s = "" }} 31 + {{ end }} 32 + <p class="text-sm font-bold py-2 dark:text-white">{{$idx}} month{{$s}} ago</p> 33 + {{ end }} 34 + 35 + <div class="flex flex-col gap-4"> 36 + {{ block "repoEvents" (list .RepoEvents $.DidHandleMap) }} {{ end }} 37 + {{ block "issueEvents" (list .IssueEvents $.DidHandleMap) }} {{ end }} 38 + {{ block "pullEvents" (list .PullEvents $.DidHandleMap) }} {{ end }} 39 + </div> 40 + </div> 41 + 42 + {{ end }} 43 + {{ else }} 44 + <p class="dark:text-white">This user does not have any activity yet.</p> 45 + {{ end }} 46 + {{ end }} 47 + </div> 48 + {{ end }} 49 + 50 + {{ define "repoEvents" }} 51 + {{ $items := index . 0 }} 52 + {{ $handleMap := index . 1 }} 53 + 54 + {{ if gt (len $items) 0 }} 55 + <details open> 56 + <summary class="list-none cursor-pointer"> 57 + <div class="flex items-center gap-2"> 58 + {{ i "unfold-vertical" "w-4 h-4" }} 59 + created {{ len $items }} repositories 60 + </div> 61 + </summary> 62 + <div class="p-2 pl-8 text-sm flex flex-col gap-3"> 63 + {{ range $items }} 64 + <div class="flex flex-wrap items-center gap-2"> 65 + <span class="text-gray-500 dark:text-gray-400"> 66 + {{ if .Source }} 67 + {{ i "git-fork" "w-4 h-4" }} 68 + {{ else }} 69 + {{ i "book-plus" "w-4 h-4" }} 70 + {{ end }} 71 + </span> 72 + <a href="/{{ index $handleMap .Repo.Did }}/{{ .Repo.Name }}" class="no-underline hover:underline"> 73 + {{- .Repo.Name -}} 74 + </a> 75 + <time class="text-gray-700 dark:text-gray-400 text-xs ml-2">{{ .Repo.Created | shortTimeFmt }}</time> 76 + </div> 77 + {{ end }} 78 + </div> 79 + </details> 80 + {{ end }} 81 + {{ end }} 82 + 83 + {{ define "issueEvents" }} 84 + {{ $i := index . 0 }} 85 + {{ $items := $i.Items }} 86 + {{ $stats := $i.Stats }} 87 + {{ $handleMap := index . 1 }} 88 + 89 + {{ if gt (len $items) 0 }} 90 + <details open> 91 + <summary class="list-none cursor-pointer"> 92 + <div class="flex items-center gap-2"> 93 + {{ i "unfold-vertical" "w-4 h-4" }} 94 + <span> 95 + created {{ len $items }} issues 96 + </span> 97 + <span class="px-2 py-1/2 text-sm rounded-sm text-white bg-green-600 dark:bg-green-700"> 98 + {{$stats.Open}} open 99 + </span> 100 + <span class="px-2 py-1/2 text-sm rounded-sm text-white bg-gray-800 dark:bg-gray-700"> 101 + {{$stats.Closed}} closed 102 + </span> 103 + </div> 104 + </summary> 105 + <div class="p-2 pl-8 text-sm flex flex-col gap-3"> 106 + {{ range $items }} 107 + {{ $repoOwner := index $handleMap .Metadata.Repo.Did }} 108 + {{ $repoName := .Metadata.Repo.Name }} 109 + {{ $repoUrl := printf "%s/%s" $repoOwner $repoName }} 110 + 111 + <div class="flex flex-wrap items-center gap-2 text-gray-600 dark:text-gray-300"> 112 + {{ if .Open }} 113 + <span class="text-green-600 dark:text-green-500"> 114 + {{ i "circle-dot" "w-4 h-4" }} 115 + </span> 116 + {{ else }} 117 + <span class="text-gray-500 dark:text-gray-400"> 118 + {{ i "ban" "w-4 h-4" }} 119 + </span> 120 + {{ end }} 121 + <a href="/{{$repoUrl}}/issues/{{ .IssueId }}" class="no-underline hover:underline"> 122 + <span class="text-gray-500 dark:text-gray-400">#{{ .IssueId }}</span> 123 + {{ .Title -}} 124 + </a> 125 + on 126 + <a href="/{{$repoUrl}}" class="no-underline hover:underline"> 127 + {{$repoUrl}} 128 + </a> 129 + <time class="text-gray-700 dark:text-gray-400 text-xs ml-2">{{ .Created | shortTimeFmt }}</time> 130 + </p> 131 + {{ end }} 132 + </div> 133 + </details> 134 + {{ end }} 135 + {{ end }} 136 + 137 + {{ define "pullEvents" }} 138 + {{ $i := index . 0 }} 139 + {{ $items := $i.Items }} 140 + {{ $stats := $i.Stats }} 141 + {{ $handleMap := index . 1 }} 142 + {{ if gt (len $items) 0 }} 143 + <details open> 144 + <summary class="list-none cursor-pointer"> 145 + <div class="flex items-center gap-2"> 146 + {{ i "unfold-vertical" "w-4 h-4" }} 147 + <span> 148 + created {{ len $items }} pull requests 149 + </span> 150 + <span class="px-2 py-1/2 text-sm rounded-sm text-white bg-green-600 dark:bg-green-700"> 151 + {{$stats.Open}} open 152 + </span> 153 + <span class="px-2 py-1/2 text-sm rounded-sm text-white bg-purple-600 dark:bg-purple-700"> 154 + {{$stats.Merged}} merged 155 + </span> 156 + <span class="px-2 py-1/2 text-sm rounded-sm text-black dark:text-white bg-gray-50 dark:bg-gray-700 "> 157 + {{$stats.Closed}} closed 158 + </span> 159 + </div> 160 + </summary> 161 + <div class="p-2 pl-8 text-sm flex flex-col gap-3"> 162 + {{ range $items }} 163 + {{ $repoOwner := index $handleMap .Repo.Did }} 164 + {{ $repoName := .Repo.Name }} 165 + {{ $repoUrl := printf "%s/%s" $repoOwner $repoName }} 166 + 167 + <div class="flex flex-wrap items-center gap-2 text-gray-600 dark:text-gray-300"> 168 + {{ if .State.IsOpen }} 169 + <span class="text-green-600 dark:text-green-500"> 170 + {{ i "git-pull-request" "w-4 h-4" }} 171 + </span> 172 + {{ else if .State.IsMerged }} 173 + <span class="text-purple-600 dark:text-purple-500"> 174 + {{ i "git-merge" "w-4 h-4" }} 175 + </span> 176 + {{ else }} 177 + <span class="text-gray-600 dark:text-gray-300"> 178 + {{ i "git-pull-request-closed" "w-4 h-4" }} 179 + </span> 180 + {{ end }} 181 + <a href="/{{$repoUrl}}/pulls/{{ .PullId }}" class="no-underline hover:underline"> 182 + <span class="text-gray-500 dark:text-gray-400">#{{ .PullId }}</span> 183 + {{ .Title -}} 184 + </a> 185 + on 186 + <a href="/{{$repoUrl}}" class="no-underline hover:underline"> 187 + {{$repoUrl}} 188 + </a> 189 + <time class="text-gray-700 dark:text-gray-400 text-xs ml-2">{{ .Created | shortTimeFmt }}</time> 190 + </p> 191 + {{ end }} 192 + </div> 193 + </details> 194 + {{ end }} 195 + {{ end }} 196 197 {{ define "profileTimeline" }} 198 <div class="flex flex-col gap-3 relative">
+11 -5
appview/state/profile.go
··· 43 for _, r := range collaboratingRepos { 44 didsToResolve = append(didsToResolve, r.Did) 45 } 46 - for _, evt := range timeline { 47 - if evt.Repo != nil { 48 - if evt.Repo.Source != "" { 49 - didsToResolve = append(didsToResolve, evt.Source.Did) 50 } 51 } 52 - didsToResolve = append(didsToResolve, evt.Repo.Did) 53 } 54 55 resolvedIds := s.resolver.ResolveIdents(r.Context(), didsToResolve)
··· 43 for _, r := range collaboratingRepos { 44 didsToResolve = append(didsToResolve, r.Did) 45 } 46 + for _, byMonth := range timeline.ByMonth { 47 + for _, pe := range byMonth.PullEvents.Items { 48 + didsToResolve = append(didsToResolve, pe.Repo.Did) 49 + } 50 + for _, ie := range byMonth.IssueEvents.Items { 51 + didsToResolve = append(didsToResolve, ie.Metadata.Repo.Did) 52 + } 53 + for _, re := range byMonth.RepoEvents { 54 + didsToResolve = append(didsToResolve, re.Repo.Did) 55 + if re.Source != nil { 56 + didsToResolve = append(didsToResolve, re.Source.Did) 57 } 58 } 59 } 60 61 resolvedIds := s.resolver.ResolveIdents(r.Context(), didsToResolve)