125 lines
4.1 KiB
Go
125 lines
4.1 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/robertjanetzko/LegendsBrowser2/backend/model"
|
|
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
|
)
|
|
|
|
type searchHandler struct {
|
|
server *DfServer
|
|
}
|
|
|
|
type SearchResult struct {
|
|
Label string `json:"label"`
|
|
Value string `json:"value"`
|
|
}
|
|
|
|
func (h searchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
if h.server.context.world == nil {
|
|
h.server.renderLoading(w, r)
|
|
return
|
|
}
|
|
|
|
term := r.URL.Query().Get("term")
|
|
|
|
world := h.server.context.world
|
|
if term != "" {
|
|
var results []SearchResult
|
|
results = searchMap(term, world.HistoricalFigures, results, "/hf")
|
|
results = searchMap(term, world.Entities, results, "/entity")
|
|
results = searchMap(term, world.Sites, results, "/site")
|
|
for _, site := range world.Sites {
|
|
results = searchMap(term, site.Structures, results, fmt.Sprintf("/site/%d/structure", site.Id_))
|
|
}
|
|
results = searchMap(term, world.Regions, results, "/region")
|
|
results = searchMap(term, world.Artifacts, results, "/artifavt")
|
|
results = searchMap(term, world.WorldConstructions, results, "/worldconstruction")
|
|
results = searchMap(term, world.DanceForms, results, "/danceForm")
|
|
results = searchMap(term, world.MusicalForms, results, "/musicalForm")
|
|
results = searchMap(term, world.PoeticForms, results, "/poeticForm")
|
|
results = searchMap(term, world.WrittenContents, results, "/writtencontent")
|
|
results = searchMap(term, world.Landmasses, results, "/landmass")
|
|
results = searchMap(term, world.MountainPeaks, results, "/mountain")
|
|
|
|
sort.Slice(results, func(i, j int) bool { return results[i].Label < results[j].Label })
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(results)
|
|
} else {
|
|
term = r.URL.Query().Get("search")
|
|
|
|
var structures []*model.Structure
|
|
for _, site := range world.Sites {
|
|
structures = search(term, site.Structures, structures)
|
|
}
|
|
|
|
results := struct {
|
|
Term string
|
|
HistoricalFigures []*model.HistoricalFigure
|
|
Entities []*model.Entity
|
|
Sites []*model.Site
|
|
Structures []*model.Structure
|
|
Regions []*model.Region
|
|
Artifacts []*model.Artifact
|
|
WorldConstructions []*model.WorldConstruction
|
|
DanceForms []*model.DanceForm
|
|
MusicalForms []*model.MusicalForm
|
|
PoeticForms []*model.PoeticForm
|
|
WrittenContents []*model.WrittenContent
|
|
Landmasses []*model.Landmass
|
|
MountainPeaks []*model.MountainPeak
|
|
}{
|
|
Term: term,
|
|
HistoricalFigures: search(term, world.HistoricalFigures, nil),
|
|
Entities: search(term, world.Entities, nil),
|
|
Sites: search(term, world.Sites, nil),
|
|
Structures: structures,
|
|
Regions: search(term, world.Regions, nil),
|
|
Artifacts: search(term, world.Artifacts, nil),
|
|
WorldConstructions: search(term, world.WorldConstructions, nil),
|
|
DanceForms: search(term, world.DanceForms, nil),
|
|
MusicalForms: search(term, world.MusicalForms, nil),
|
|
PoeticForms: search(term, world.PoeticForms, nil),
|
|
WrittenContents: search(term, world.WrittenContents, nil),
|
|
Landmasses: search(term, world.Landmasses, nil),
|
|
MountainPeaks: search(term, world.MountainPeaks, nil),
|
|
}
|
|
|
|
err := h.server.templates.Render(w, "search.html", results)
|
|
if err != nil {
|
|
httpError(w, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func searchMap[T model.Named](s string, input map[int]T, output []SearchResult, baseUrl string) []SearchResult {
|
|
s = strings.ToLower(s)
|
|
for id, v := range input {
|
|
if strings.Contains(strings.ToLower(v.Name()), s) {
|
|
output = append(output, SearchResult{
|
|
Label: util.Title(v.Name()),
|
|
Value: fmt.Sprintf("%s/%d", baseUrl, id),
|
|
})
|
|
}
|
|
}
|
|
return output
|
|
}
|
|
|
|
func search[T model.Named](s string, input map[int]T, output []T) []T {
|
|
s = strings.ToLower(s)
|
|
for _, v := range input {
|
|
if strings.Contains(strings.ToLower(v.Name()), s) {
|
|
output = append(output, v)
|
|
}
|
|
}
|
|
sort.Slice(output, func(i, j int) bool { return output[i].Name() < output[j].Name() })
|
|
return output
|
|
}
|