package main
import (
"bytes"
"html/template"
"net/http"
"sort"
"strings"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/i18n"
"git.neuromancer.ovh/bastien-mrq/gitfed/internal/store"
)
var exploreTpl = newTpl("explore", `
{{.Flash}}
<div class="gf-page-head"><h1>{{t .Lang "explore.title"}}</h1><span class="count">{{len .Repos}} {{t .Lang "explore.repo_count"}}</span></div>
<p class="gf-page-sub">{{t .Lang "explore.subtitle"}}</p>
<form class="gf-search" method="get" action="/explore">
{{if .Topic}}<input type="hidden" name="topic" value="{{.Topic}}">{{end}}
{{icon "search"}}
<input type="search" name="q" value="{{.Query}}" placeholder="{{t .Lang "explore.search_placeholder"}}">
</form>
{{if .AllTopics}}
<div class="gf-topics-row">
<span class="label">{{t .Lang "explore.topics_label"}}</span>
{{range .AllTopics}}
{{if eq . $.Topic}}
<a class="chip active" href="/explore{{if $.Query}}?q={{$.Query}}{{end}}">{{.}} {{icon "close"}}</a>
{{else}}
<a class="chip" href="/explore?topic={{.}}{{if $.Query}}&q={{$.Query}}{{end}}">{{.}}</a>
{{end}}
{{end}}
</div>
{{end}}
<div class="gf-card">
{{if .Repos}}
<div class="gf-repo-list">
{{range .Repos}}
<div class="gf-repo-row">
<div class="gf-repo-icon">{{icon "folder"}}</div>
<div class="gf-repo-main">
<div class="name"><a href="/r/{{.Name}}">{{.Name}}</a> <span class="owner">— {{if localUser .Owner $.Domain}}<a href="/u/{{localUser .Owner $.Domain}}">{{.Owner}}</a>{{else}}{{.Owner}}{{end}}</span></div>
{{if .Topics}}<div class="topics">{{range .Topics}}<a href="/explore?topic={{.}}">{{.}}</a>{{end}}</div>{{end}}
</div>
<span class="badge trusted">{{t $.Lang "common.public"}}</span>
</div>
{{end}}
</div>
{{else}}
<div class="gf-empty">
{{icon "search"}}
<p><strong>{{t .Lang "explore.empty_title"}}</strong></p>
<p class="muted">{{t .Lang "explore.empty_hint"}}</p>
<a class="clear" href="/explore">{{t .Lang "explore.clear"}} →</a>
</div>
{{end}}
</div>
`)
func (s *server) handleExplore(w http.ResponseWriter, r *http.Request) {
topic := r.URL.Query().Get("topic")
query := strings.TrimSpace(r.URL.Query().Get("q"))
lang := s.lang(r)
repos, err := s.ops.ListRepos()
if err != nil {
s.serverError(w, r, err)
return
}
topicSet := map[string]bool{}
var visible []store.Repo
needle := strings.ToLower(query)
for _, repo := range repos {
if !repo.Public {
continue
}
for _, t := range repo.Topics {
topicSet[t] = true
}
if topic != "" && !containsTopic(repo.Topics, topic) {
continue
}
if needle != "" && !strings.Contains(strings.ToLower(repo.Name), needle) {
continue
}
visible = append(visible, repo)
}
allTopics := make([]string, 0, len(topicSet))
for t := range topicSet {
allTopics = append(allTopics, t)
}
sort.Strings(allTopics)
var buf bytes.Buffer
_ = exploreTpl.Execute(&buf, struct {
Repos []store.Repo
AllTopics []string
Topic, Query, Lang, Domain string
Flash template.HTML
}{visible, allTopics, topic, query, string(lang), s.domain, flash(r)})
s.render(w, r, i18n.T(lang, "explore.title"), "explore", template.HTML(buf.String()))
}
func containsTopic(topics []string, topic string) bool {
for _, t := range topics {
if t == topic {
return true
}
}
return false
}