this repo has no description
1
fork

Configure Feed

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

feat: filter by language

+60 -5
+42
store/store.go
··· 10 10 "encoding/json" 11 11 "fmt" 12 12 "io" 13 + "sort" 13 14 "time" 14 15 15 16 "entgo.io/ent/dialect" ··· 393 394 out = append(out, r) 394 395 } 395 396 return out, rows.Err() 397 + } 398 + 399 + // PrimaryLanguages returns the sorted set of "primary" languages observed 400 + // across all enriched repos — i.e., the highest-bytes language per repo, 401 + // deduplicated. Used to populate the language filter dropdown. 402 + func (s *Store) PrimaryLanguages(ctx context.Context) ([]string, error) { 403 + rows, err := s.db.QueryContext(ctx, `SELECT languages FROM repos WHERE languages IS NOT NULL AND languages != '' AND languages != '{}'`) 404 + if err != nil { 405 + return nil, err 406 + } 407 + defer rows.Close() 408 + seen := make(map[string]struct{}) 409 + for rows.Next() { 410 + var raw string 411 + if err := rows.Scan(&raw); err != nil { 412 + return nil, err 413 + } 414 + var langs map[string]int64 415 + if err := json.Unmarshal([]byte(raw), &langs); err != nil { 416 + continue 417 + } 418 + var best string 419 + var bestN int64 420 + for k, v := range langs { 421 + if v > bestN { 422 + bestN, best = v, k 423 + } 424 + } 425 + if best != "" { 426 + seen[best] = struct{}{} 427 + } 428 + } 429 + if err := rows.Err(); err != nil { 430 + return nil, err 431 + } 432 + out := make([]string, 0, len(seen)) 433 + for k := range seen { 434 + out = append(out, k) 435 + } 436 + sort.Strings(out) 437 + return out, nil 396 438 } 397 439 398 440 // RecentRepos returns repos created since `since`, optionally filtered by
+10 -4
web/server.go
··· 66 66 http.Error(w, err.Error(), http.StatusInternalServerError) 67 67 return 68 68 } 69 + langs, err := s.PrimaryLanguages(r.Context()) 70 + if err != nil { 71 + http.Error(w, err.Error(), http.StatusInternalServerError) 72 + return 73 + } 69 74 render(w, "repos", struct { 70 - Active string 71 - Query query 72 - Repos []store.Repo 73 - }{"repos", q, repos}) 75 + Active string 76 + Query query 77 + Repos []store.Repo 78 + Languages []string 79 + }{"repos", q, repos, langs}) 74 80 } 75 81 } 76 82
+8 -1
web/templates/repos.html
··· 1 1 {{define "repos"}}{{template "head" .}} 2 2 <form method="get"> 3 - <label>language<input name="language" value="{{.Query.Language}}" placeholder="any"></label> 3 + <label>language 4 + <select name="language"> 5 + <option value=""{{if eq .Query.Language ""}} selected{{end}}>any</option> 6 + {{range .Languages}} 7 + <option value="{{.}}"{{if eq $.Query.Language .}} selected{{end}}>{{.}}</option> 8 + {{end}} 9 + </select> 10 + </label> 4 11 <label>since<input name="since" value="{{.Query.SinceRaw}}" placeholder="e.g. 24h"></label> 5 12 <button>filter</button> 6 13 </form>