diff --git a/appview/pages/templates/layouts/fragments/topbar.html b/appview/pages/templates/layouts/fragments/topbar.html
index 20da4098..d581fbae 100644
--- a/appview/pages/templates/layouts/fragments/topbar.html
+++ b/appview/pages/templates/layouts/fragments/topbar.html
@@ -61,7 +61,7 @@
>
profile
repositories
- strings
+ strings
knots
spindles
settings
diff --git a/appview/pages/templates/user/strings.html b/appview/pages/templates/user/strings.html
new file mode 100644
index 00000000..6501485b
--- /dev/null
+++ b/appview/pages/templates/user/strings.html
@@ -0,0 +1,45 @@
+{{ define "title" }}{{ or .Card.UserHandle .Card.UserDid }} · strings {{ end }}
+
+{{ define "profileContent" }}
+
+ {{ block "allStrings" . }}{{ end }}
+
+{{ end }}
+
+{{ define "allStrings" }}
+
+ {{ range .Strings }}
+
+ {{ template "singleString" (list $ .) }}
+
+ {{ else }}
+
This user does not have any strings yet.
+ {{ end }}
+
+{{ end }}
+
+{{ define "singleString" }}
+ {{ $root := index . 0 }}
+ {{ $s := index . 1 }}
+
+
+ {{ with $s.Description }}
+
+ {{ . }}
+
+ {{ end }}
+
+ {{ $stat := $s.Stats }}
+
+ {{ $stat.LineCount }} line{{if ne $stat.LineCount 1}}s{{end}}
+
+ {{ with $s.Edited }}
+ edited {{ template "repo/fragments/shortTimeAgo" . }}
+ {{ else }}
+ {{ template "repo/fragments/shortTimeAgo" $s.Created }}
+ {{ end }}
+
+
+{{ end }}
diff --git a/appview/state/profile.go b/appview/state/profile.go
index 857f1bf6..71173c2c 100644
--- a/appview/state/profile.go
+++ b/appview/state/profile.go
@@ -24,8 +24,6 @@ import (
func (s *State) Profile(w http.ResponseWriter, r *http.Request) {
tabVal := r.URL.Query().Get("tab")
switch tabVal {
- case "", "overview":
- s.profileOverview(w, r)
case "repos":
s.reposPage(w, r)
case "followers":
@@ -34,6 +32,10 @@ func (s *State) Profile(w http.ResponseWriter, r *http.Request) {
s.followingPage(w, r)
case "starred":
s.starredPage(w, r)
+ case "strings":
+ s.stringsPage(w, r)
+ default:
+ s.profileOverview(w, r)
}
}
@@ -54,6 +56,21 @@ func (s *State) profile(r *http.Request) (*pages.ProfileCard, error) {
return nil, fmt.Errorf("failed to get profile: %w", err)
}
+ repoCount, err := db.CountRepos(s.db, db.FilterEq("did", did))
+ if err != nil {
+ return nil, fmt.Errorf("failed to get repo count: %w", err)
+ }
+
+ stringCount, err := db.CountStrings(s.db, db.FilterEq("did", did))
+ if err != nil {
+ return nil, fmt.Errorf("failed to get string count: %w", err)
+ }
+
+ starredCount, err := db.CountStars(s.db, db.FilterEq("starred_by_did", did))
+ if err != nil {
+ return nil, fmt.Errorf("failed to get starred repo count: %w", err)
+ }
+
followStats, err := db.GetFollowerFollowingCount(s.db, did)
if err != nil {
return nil, fmt.Errorf("failed to get follower stats: %w", err)
@@ -78,13 +95,18 @@ func (s *State) profile(r *http.Request) (*pages.ProfileCard, error) {
}
return &pages.ProfileCard{
- UserDid: did,
- UserHandle: ident.Handle.String(),
- Profile: profile,
- FollowStatus: followStatus,
- FollowersCount: followStats.Followers,
- FollowingCount: followStats.Following,
- Punchcard: punchcard,
+ UserDid: did,
+ UserHandle: ident.Handle.String(),
+ Profile: profile,
+ FollowStatus: followStatus,
+ Stats: pages.ProfileStats{
+ RepoCount: repoCount,
+ StringCount: stringCount,
+ StarredCount: starredCount,
+ FollowersCount: followStats.Followers,
+ FollowingCount: followStats.Following,
+ },
+ Punchcard: punchcard,
}, nil
}
@@ -218,6 +240,31 @@ func (s *State) starredPage(w http.ResponseWriter, r *http.Request) {
})
}
+func (s *State) stringsPage(w http.ResponseWriter, r *http.Request) {
+ l := s.logger.With("handler", "stringsPage")
+
+ profile, err := s.profile(r)
+ if err != nil {
+ l.Error("failed to build profile card", "err", err)
+ s.pages.Error500(w)
+ return
+ }
+ l = l.With("profileDid", profile.UserDid, "profileHandle", profile.UserHandle)
+
+ strings, err := db.GetStrings(s.db, 0, db.FilterEq("did", profile.UserDid))
+ if err != nil {
+ l.Error("failed to get strings", "err", err)
+ s.pages.Error500(w)
+ return
+ }
+
+ err = s.pages.ProfileStrings(w, pages.ProfileStringsParams{
+ LoggedInUser: s.oauth.GetUser(r),
+ Strings: strings,
+ Card: profile,
+ })
+}
+
type FollowsPageParams struct {
Follows []pages.FollowCard
Card *pages.ProfileCard
@@ -283,7 +330,7 @@ func (s *State) followPage(
followStatus := db.IsNotFollowing
if _, exists := loggedInUserFollowing[did]; exists {
followStatus = db.IsFollowing
- } else if loggedInUser.Did == did {
+ } else if loggedInUser != nil && loggedInUser.Did == did {
followStatus = db.IsSelf
}
diff --git a/appview/strings/strings.go b/appview/strings/strings.go
index 4af0b363..cb9328ab 100644
--- a/appview/strings/strings.go
+++ b/appview/strings/strings.go
@@ -5,7 +5,6 @@ import (
"log/slog"
"net/http"
"path"
- "slices"
"strconv"
"time"
@@ -161,64 +160,7 @@ func (s *Strings) contents(w http.ResponseWriter, r *http.Request) {
}
func (s *Strings) dashboard(w http.ResponseWriter, r *http.Request) {
- l := s.Logger.With("handler", "dashboard")
-
- id, ok := r.Context().Value("resolvedId").(identity.Identity)
- if !ok {
- l.Error("malformed middleware")
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- l = l.With("did", id.DID, "handle", id.Handle)
-
- all, err := db.GetStrings(
- s.Db,
- 0,
- db.FilterEq("did", id.DID),
- )
- if err != nil {
- l.Error("failed to fetch strings", "err", err)
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
-
- slices.SortFunc(all, func(a, b db.String) int {
- if a.Created.After(b.Created) {
- return -1
- } else {
- return 1
- }
- })
-
- profile, err := db.GetProfile(s.Db, id.DID.String())
- if err != nil {
- l.Error("failed to fetch user profile", "err", err)
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- loggedInUser := s.OAuth.GetUser(r)
- followStatus := db.IsNotFollowing
- if loggedInUser != nil {
- followStatus = db.GetFollowStatus(s.Db, loggedInUser.Did, id.DID.String())
- }
-
- followStats, err := db.GetFollowerFollowingCount(s.Db, id.DID.String())
- if err != nil {
- l.Error("failed to get follow stats", "err", err)
- }
-
- s.Pages.StringsDashboard(w, pages.StringsDashboardParams{
- LoggedInUser: s.OAuth.GetUser(r),
- Card: pages.ProfileCard{
- UserDid: id.DID.String(),
- UserHandle: id.Handle.String(),
- Profile: profile,
- FollowStatus: followStatus,
- FollowersCount: followStats.Followers,
- FollowingCount: followStats.Following,
- },
- Strings: all,
- })
+ http.Redirect(w, r, fmt.Sprintf("/%s?tab=strings", chi.URLParam(r, "user")), http.StatusFound)
}
func (s *Strings) edit(w http.ResponseWriter, r *http.Request) {