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 search bar to profile-repos tab

this search bar has `language` and `topic` as keyword filters.

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

authored by

oppiliappan and committed by tangled.org fa04d2f6 c3dcdbba

+129 -10
+3
appview/pages/pages.go
··· 649 649 Repos []models.Repo 650 650 Card *ProfileCard 651 651 Active string 652 + Page pagination.Page 653 + RepoCount int 654 + FilterQuery string 652 655 } 653 656 654 657 func (p *Pages) ProfileRepos(w io.Writer, params ProfileReposParams) error {
+39 -1
appview/pages/templates/user/repos.html
··· 2 2 3 3 {{ define "profileContent" }} 4 4 <div id="all-repos" class="md:col-span-8 order-2 md:order-2"> 5 - {{ block "ownRepos" . }}{{ end }} 5 + <div class="mb-4"> 6 + <form id="search-form" class="flex relative" method="GET"> 7 + <input type="hidden" name="tab" value="repos"> 8 + <div class="flex-1 flex relative"> 9 + <input 10 + id="search-q" 11 + class="flex-1 py-1 pl-2 pr-10 mr-[-1px] rounded-r-none peer" 12 + type="text" 13 + name="q" 14 + value="{{ .FilterQuery }}" 15 + placeholder="search repos..." 16 + > 17 + <a 18 + {{ if .FilterQuery }}href="?tab=repos"{{ else }}href="#"{{ end }} 19 + class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 {{ if not .FilterQuery }}hidden{{ end }} peer-[:not(:placeholder-shown)]:block" 20 + > 21 + {{ i "x" "w-4 h-4" }} 22 + </a> 23 + </div> 24 + <button 25 + type="submit" 26 + class="p-2 text-gray-400 border rounded-r border-gray-300 dark:border-gray-600" 27 + > 28 + {{ i "search" "w-4 h-4" }} 29 + </button> 30 + </form> 31 + </div> 32 + 33 + {{ block "ownRepos" . }}{{ end }} 34 + 35 + {{if gt .RepoCount .Page.Limit }} 36 + {{ $handle := resolve .Card.UserDid }} 37 + {{ template "fragments/pagination" (dict 38 + "Page" .Page 39 + "TotalCount" .RepoCount 40 + "BasePath" (printf "/%s" $handle) 41 + "QueryParams" (queryParams "tab" "repos" "q" .FilterQuery) 42 + ) }} 43 + {{ end }} 6 44 </div> 7 45 {{ end }} 8 46
+87 -9
appview/state/profile.go
··· 17 17 "github.com/gorilla/feeds" 18 18 "tangled.org/core/api/tangled" 19 19 "tangled.org/core/appview/db" 20 + "tangled.org/core/appview/middleware" 20 21 "tangled.org/core/appview/models" 21 22 "tangled.org/core/appview/pages" 23 + "tangled.org/core/appview/pagination" 24 + "tangled.org/core/appview/searchquery" 22 25 "tangled.org/core/orm" 23 26 "tangled.org/core/xrpc" 24 27 ) ··· 30 27 tabVal := r.URL.Query().Get("tab") 31 28 switch tabVal { 32 29 case "repos": 33 - s.reposPage(w, r) 30 + middleware. 31 + Paginate(http.HandlerFunc(s.reposPage)). 32 + ServeHTTP(w, r) 34 33 case "followers": 35 34 s.followersPage(w, r) 36 35 case "following": ··· 233 228 } 234 229 l = l.With("profileDid", profile.UserDid) 235 230 236 - repos, err := db.GetRepos( 237 - s.db, 238 - orm.FilterEq("did", profile.UserDid), 239 - ) 240 - if err != nil { 241 - l.Error("failed to get repos", "err", err) 242 - s.pages.Error500(w) 243 - return 231 + params := r.URL.Query() 232 + page := pagination.FromContext(r.Context()) 233 + 234 + query := searchquery.Parse(params.Get("q")) 235 + 236 + var language string 237 + if lang := query.Get("language"); lang != nil { 238 + language = *lang 239 + } 240 + 241 + tf := searchquery.ExtractTextFilters(query) 242 + 243 + searchOpts := models.RepoSearchOptions{ 244 + Keywords: tf.Keywords, 245 + Phrases: tf.Phrases, 246 + NegatedKeywords: tf.NegatedKeywords, 247 + NegatedPhrases: tf.NegatedPhrases, 248 + Did: profile.UserDid, 249 + Language: language, 250 + Page: page, 251 + } 252 + 253 + var repos []models.Repo 254 + var totalRepos int64 255 + 256 + if searchOpts.HasSearchFilters() { 257 + res, err := s.indexer.Repos.Search(r.Context(), searchOpts) 258 + if err != nil { 259 + l.Error("failed to search repos", "err", err) 260 + s.pages.Error500(w) 261 + return 262 + } 263 + 264 + if len(res.Hits) > 0 { 265 + repos, err = db.GetRepos(s.db, orm.FilterIn("id", res.Hits)) 266 + if err != nil { 267 + l.Error("failed to get repos by IDs", "err", err) 268 + s.pages.Error500(w) 269 + return 270 + } 271 + 272 + // sort repos to match search result order (by relevance) 273 + repoMap := make(map[int64]models.Repo, len(repos)) 274 + for _, repo := range repos { 275 + repoMap[repo.Id] = repo 276 + } 277 + repos = make([]models.Repo, 0, len(res.Hits)) 278 + for _, id := range res.Hits { 279 + if repo, ok := repoMap[id]; ok { 280 + repos = append(repos, repo) 281 + } 282 + } 283 + } 284 + totalRepos = int64(res.Total) 285 + } else { 286 + repos, err = db.GetReposPaginated( 287 + s.db, 288 + page, 289 + orm.FilterEq("did", profile.UserDid), 290 + ) 291 + if err != nil { 292 + l.Error("failed to get repos", "err", err) 293 + s.pages.Error500(w) 294 + return 295 + } 296 + 297 + totalRepos, err = db.CountRepos( 298 + s.db, 299 + orm.FilterEq("did", profile.UserDid), 300 + ) 301 + if err != nil { 302 + l.Error("failed to count repos", "err", err) 303 + s.pages.Error500(w) 304 + return 305 + } 244 306 } 245 307 246 308 err = s.pages.ProfileRepos(w, pages.ProfileReposParams{ 247 309 LoggedInUser: s.oauth.GetMultiAccountUser(r), 248 310 Repos: repos, 249 311 Card: profile, 312 + Page: page, 313 + RepoCount: int(totalRepos), 314 + FilterQuery: query.String(), 250 315 }) 316 + if err != nil { 317 + l.Error("failed to render page", "err", err) 318 + } 251 319 } 252 320 253 321 func (s *State) starredPage(w http.ResponseWriter, r *http.Request) {