From fa04d2f6d95c595650c5c60a0dd01ed476034e48 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Mon, 23 Mar 2026 08:12:19 +0000 Subject: [PATCH] appview/pages: add search bar to profile-repos tab this search bar has `language` and `topic` as keyword filters. Signed-off-by: oppiliappan --- appview/pages/pages.go | 3 +++ appview/state/profile.go | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- appview/pages/templates/user/repos.html | 40 +++++++++++++++++++++++++++++++++++++++- 3 file(s) changed, 129 insertion(s)(+), 10 deletion(s)(-) diff --git a/appview/pages/pages.go b/appview/pages/pages.go --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -649,6 +649,9 @@ Repos []models.Repo Card *ProfileCard Active string + Page pagination.Page + RepoCount int + FilterQuery string } func (p *Pages) ProfileRepos(w io.Writer, params ProfileReposParams) error { diff --git a/appview/state/profile.go b/appview/state/profile.go --- a/appview/state/profile.go +++ b/appview/state/profile.go @@ -17,8 +17,11 @@ "github.com/gorilla/feeds" "tangled.org/core/api/tangled" "tangled.org/core/appview/db" + "tangled.org/core/appview/middleware" "tangled.org/core/appview/models" "tangled.org/core/appview/pages" + "tangled.org/core/appview/pagination" + "tangled.org/core/appview/searchquery" "tangled.org/core/orm" "tangled.org/core/xrpc" ) @@ -27,7 +30,9 @@ tabVal := r.URL.Query().Get("tab") switch tabVal { case "repos": - s.reposPage(w, r) + middleware. + Paginate(http.HandlerFunc(s.reposPage)). + ServeHTTP(w, r) case "followers": s.followersPage(w, r) case "following": @@ -228,21 +233,94 @@ } l = l.With("profileDid", profile.UserDid) - repos, err := db.GetRepos( - s.db, - orm.FilterEq("did", profile.UserDid), - ) - if err != nil { - l.Error("failed to get repos", "err", err) - s.pages.Error500(w) - return + params := r.URL.Query() + page := pagination.FromContext(r.Context()) + + query := searchquery.Parse(params.Get("q")) + + var language string + if lang := query.Get("language"); lang != nil { + language = *lang + } + + tf := searchquery.ExtractTextFilters(query) + + searchOpts := models.RepoSearchOptions{ + Keywords: tf.Keywords, + Phrases: tf.Phrases, + NegatedKeywords: tf.NegatedKeywords, + NegatedPhrases: tf.NegatedPhrases, + Did: profile.UserDid, + Language: language, + Page: page, + } + + var repos []models.Repo + var totalRepos int64 + + if searchOpts.HasSearchFilters() { + res, err := s.indexer.Repos.Search(r.Context(), searchOpts) + if err != nil { + l.Error("failed to search repos", "err", err) + s.pages.Error500(w) + return + } + + if len(res.Hits) > 0 { + repos, err = db.GetRepos(s.db, orm.FilterIn("id", res.Hits)) + if err != nil { + l.Error("failed to get repos by IDs", "err", err) + s.pages.Error500(w) + return + } + + // sort repos to match search result order (by relevance) + repoMap := make(map[int64]models.Repo, len(repos)) + for _, repo := range repos { + repoMap[repo.Id] = repo + } + repos = make([]models.Repo, 0, len(res.Hits)) + for _, id := range res.Hits { + if repo, ok := repoMap[id]; ok { + repos = append(repos, repo) + } + } + } + totalRepos = int64(res.Total) + } else { + repos, err = db.GetReposPaginated( + s.db, + page, + orm.FilterEq("did", profile.UserDid), + ) + if err != nil { + l.Error("failed to get repos", "err", err) + s.pages.Error500(w) + return + } + + totalRepos, err = db.CountRepos( + s.db, + orm.FilterEq("did", profile.UserDid), + ) + if err != nil { + l.Error("failed to count repos", "err", err) + s.pages.Error500(w) + return + } } err = s.pages.ProfileRepos(w, pages.ProfileReposParams{ LoggedInUser: s.oauth.GetMultiAccountUser(r), Repos: repos, Card: profile, + Page: page, + RepoCount: int(totalRepos), + FilterQuery: query.String(), }) + if err != nil { + l.Error("failed to render page", "err", err) + } } func (s *State) starredPage(w http.ResponseWriter, r *http.Request) { diff --git a/appview/pages/templates/user/repos.html b/appview/pages/templates/user/repos.html --- a/appview/pages/templates/user/repos.html +++ b/appview/pages/templates/user/repos.html @@ -2,7 +2,45 @@ {{ define "profileContent" }}
- {{ block "ownRepos" . }}{{ end }} +
+
+ + + +
+
+ + {{ block "ownRepos" . }}{{ end }} + + {{if gt .RepoCount .Page.Limit }} + {{ $handle := resolve .Card.UserDid }} + {{ template "fragments/pagination" (dict + "Page" .Page + "TotalCount" .RepoCount + "BasePath" (printf "/%s" $handle) + "QueryParams" (queryParams "tab" "repos" "q" .FilterQuery) + ) }} + {{ end }}
{{ end }} -- tangled.sh