Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview/pages: add strings tab to profile

Signed-off-by: oppiliappan <me@oppi.li>

authored by

oppiliappan and committed by
Tangled
07b009bd 916560f8

+104 -70
+1 -1
appview/pages/templates/layouts/fragments/topbar.html
··· 61 61 > 62 62 <a href="/{{ $user }}">profile</a> 63 63 <a href="/{{ $user }}?tab=repos">repositories</a> 64 - <a href="/strings/{{ $user }}">strings</a> 64 + <a href="/{{ $user }}?tab=strings">strings</a> 65 65 <a href="/knots">knots</a> 66 66 <a href="/spindles">spindles</a> 67 67 <a href="/settings">settings</a>
+45
appview/pages/templates/user/strings.html
··· 1 + {{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · strings {{ end }} 2 + 3 + {{ define "profileContent" }} 4 + <div id="all-strings" class="md:col-span-8 order-2 md:order-2"> 5 + {{ block "allStrings" . }}{{ end }} 6 + </div> 7 + {{ end }} 8 + 9 + {{ define "allStrings" }} 10 + <div id="strings" class="grid grid-cols-1 gap-4 mb-6"> 11 + {{ range .Strings }} 12 + <div class="border border-gray-200 dark:border-gray-700 rounded-sm"> 13 + {{ template "singleString" (list $ .) }} 14 + </div> 15 + {{ else }} 16 + <p class="px-6 dark:text-white">This user does not have any strings yet.</p> 17 + {{ end }} 18 + </div> 19 + {{ end }} 20 + 21 + {{ define "singleString" }} 22 + {{ $root := index . 0 }} 23 + {{ $s := index . 1 }} 24 + <div class="py-4 px-6 rounded bg-white dark:bg-gray-800"> 25 + <div class="font-medium dark:text-white flex gap-2 items-center"> 26 + <a href="/strings/{{ or $root.Card.UserHandle $root.Card.UserDid }}/{{ $s.Rkey }}">{{ $s.Filename }}</a> 27 + </div> 28 + {{ with $s.Description }} 29 + <div class="text-gray-600 dark:text-gray-300 text-sm"> 30 + {{ . }} 31 + </div> 32 + {{ end }} 33 + 34 + {{ $stat := $s.Stats }} 35 + <div class="text-gray-400 pt-4 text-sm font-mono inline-flex gap-2 mt-auto"> 36 + <span>{{ $stat.LineCount }} line{{if ne $stat.LineCount 1}}s{{end}}</span> 37 + <span class="select-none [&:before]:content-['·']"></span> 38 + {{ with $s.Edited }} 39 + <span>edited {{ template "repo/fragments/shortTimeAgo" . }}</span> 40 + {{ else }} 41 + {{ template "repo/fragments/shortTimeAgo" $s.Created }} 42 + {{ end }} 43 + </div> 44 + </div> 45 + {{ end }}
+57 -10
appview/state/profile.go
··· 24 24 func (s *State) Profile(w http.ResponseWriter, r *http.Request) { 25 25 tabVal := r.URL.Query().Get("tab") 26 26 switch tabVal { 27 - case "", "overview": 28 - s.profileOverview(w, r) 29 27 case "repos": 30 28 s.reposPage(w, r) 31 29 case "followers": ··· 32 34 s.followingPage(w, r) 33 35 case "starred": 34 36 s.starredPage(w, r) 37 + case "strings": 38 + s.stringsPage(w, r) 39 + default: 40 + s.profileOverview(w, r) 35 41 } 36 42 } 37 43 ··· 54 52 profile, err := db.GetProfile(s.db, did) 55 53 if err != nil { 56 54 return nil, fmt.Errorf("failed to get profile: %w", err) 55 + } 56 + 57 + repoCount, err := db.CountRepos(s.db, db.FilterEq("did", did)) 58 + if err != nil { 59 + return nil, fmt.Errorf("failed to get repo count: %w", err) 60 + } 61 + 62 + stringCount, err := db.CountStrings(s.db, db.FilterEq("did", did)) 63 + if err != nil { 64 + return nil, fmt.Errorf("failed to get string count: %w", err) 65 + } 66 + 67 + starredCount, err := db.CountStars(s.db, db.FilterEq("starred_by_did", did)) 68 + if err != nil { 69 + return nil, fmt.Errorf("failed to get starred repo count: %w", err) 57 70 } 58 71 59 72 followStats, err := db.GetFollowerFollowingCount(s.db, did) ··· 95 78 } 96 79 97 80 return &pages.ProfileCard{ 98 - UserDid: did, 99 - UserHandle: ident.Handle.String(), 100 - Profile: profile, 101 - FollowStatus: followStatus, 102 - FollowersCount: followStats.Followers, 103 - FollowingCount: followStats.Following, 104 - Punchcard: punchcard, 81 + UserDid: did, 82 + UserHandle: ident.Handle.String(), 83 + Profile: profile, 84 + FollowStatus: followStatus, 85 + Stats: pages.ProfileStats{ 86 + RepoCount: repoCount, 87 + StringCount: stringCount, 88 + StarredCount: starredCount, 89 + FollowersCount: followStats.Followers, 90 + FollowingCount: followStats.Following, 91 + }, 92 + Punchcard: punchcard, 105 93 }, nil 106 94 } 107 95 ··· 240 218 }) 241 219 } 242 220 221 + func (s *State) stringsPage(w http.ResponseWriter, r *http.Request) { 222 + l := s.logger.With("handler", "stringsPage") 223 + 224 + profile, err := s.profile(r) 225 + if err != nil { 226 + l.Error("failed to build profile card", "err", err) 227 + s.pages.Error500(w) 228 + return 229 + } 230 + l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle) 231 + 232 + strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid)) 233 + if err != nil { 234 + l.Error("failed to get strings", "err", err) 235 + s.pages.Error500(w) 236 + return 237 + } 238 + 239 + err = s.pages.ProfileStrings(w, pages.ProfileStringsParams{ 240 + LoggedInUser: s.oauth.GetUser(r), 241 + Strings: strings, 242 + Card: profile, 243 + }) 244 + } 245 + 243 246 type FollowsPageParams struct { 244 247 Follows []pages.FollowCard 245 248 Card *pages.ProfileCard ··· 330 283 followStatus := db.IsNotFollowing 331 284 if _, exists := loggedInUserFollowing[did]; exists { 332 285 followStatus = db.IsFollowing 333 - } else if loggedInUser.Did == did { 286 + } else if loggedInUser != nil && loggedInUser.Did == did { 334 287 followStatus = db.IsSelf 335 288 } 336 289
+1 -59
appview/strings/strings.go
··· 5 5 "log/slog" 6 6 "net/http" 7 7 "path" 8 - "slices" 9 8 "strconv" 10 9 "time" 11 10 ··· 160 161 } 161 162 162 163 func (s *Strings) dashboard(w http.ResponseWriter, r *http.Request) { 163 - l := s.Logger.With("handler", "dashboard") 164 - 165 - id, ok := r.Context().Value("resolvedId").(identity.Identity) 166 - if !ok { 167 - l.Error("malformed middleware") 168 - w.WriteHeader(http.StatusInternalServerError) 169 - return 170 - } 171 - l = l.With("did", id.DID, "handle", id.Handle) 172 - 173 - all, err := db.GetStrings( 174 - s.Db, 175 - 0, 176 - db.FilterEq("did", id.DID), 177 - ) 178 - if err != nil { 179 - l.Error("failed to fetch strings", "err", err) 180 - w.WriteHeader(http.StatusInternalServerError) 181 - return 182 - } 183 - 184 - slices.SortFunc(all, func(a, b db.String) int { 185 - if a.Created.After(b.Created) { 186 - return -1 187 - } else { 188 - return 1 189 - } 190 - }) 191 - 192 - profile, err := db.GetProfile(s.Db, id.DID.String()) 193 - if err != nil { 194 - l.Error("failed to fetch user profile", "err", err) 195 - w.WriteHeader(http.StatusInternalServerError) 196 - return 197 - } 198 - loggedInUser := s.OAuth.GetUser(r) 199 - followStatus := db.IsNotFollowing 200 - if loggedInUser != nil { 201 - followStatus = db.GetFollowStatus(s.Db, loggedInUser.Did, id.DID.String()) 202 - } 203 - 204 - followStats, err := db.GetFollowerFollowingCount(s.Db, id.DID.String()) 205 - if err != nil { 206 - l.Error("failed to get follow stats", "err", err) 207 - } 208 - 209 - s.Pages.StringsDashboard(w, pages.StringsDashboardParams{ 210 - LoggedInUser: s.OAuth.GetUser(r), 211 - Card: pages.ProfileCard{ 212 - UserDid: id.DID.String(), 213 - UserHandle: id.Handle.String(), 214 - Profile: profile, 215 - FollowStatus: followStatus, 216 - FollowersCount: followStats.Followers, 217 - FollowingCount: followStats.Following, 218 - }, 219 - Strings: all, 220 - }) 164 + http.Redirect(w, r, fmt.Sprintf("/%s?tab=strings", chi.URLParam(r, "user")), http.StatusFound) 221 165 } 222 166 223 167 func (s *Strings) edit(w http.ResponseWriter, r *http.Request) {