package main import ( "crowsnest/internal/data" "crowsnest/internal/model" "crowsnest/internal/viewmodel" "html/template" "net/http" "regexp" "strings" ) type articleDateOrder struct {} func (ord articleDateOrder) Weight(a *model.Article) int { return int(a.PublishDate.Unix()) } type articleTermFrequency struct { terms []string } func (ord articleTermFrequency) Weight(a *model.Article) int { score := 0 for _, term := range ord.terms { score += strings.Count(a.Content, term) } return score } func index(w http.ResponseWriter, req *http.Request) { // retrieve from repo fds, err := data.NewFileDatastore("./persistence/spiegel100.json") if err != nil { panic(err) } repo, err := data.NewDefaultRepository[*model.Article](fds, "article") if err != nil { panic(err) } articles, err := repo.GetByCriteria(articleDateOrder{}) if err != nil { panic(err) } // convert to viewmodel articleVMs := make([]*viewmodel.ArticleViewModel, 0, len(articles)) for _, a := range articles { articleVMs = append(articleVMs, viewmodel.NewArticleViewModel(a)) } // render template t := template.Must(template.ParseFiles("templates/article.html", "templates/layout.html")) err = t.ExecuteTemplate(w, "base", articleVMs[:10]) if err != nil { panic(err) } } func search(w http.ResponseWriter, req *http.Request) { // parse the form data err := req.ParseForm() if err != nil { http.Error(w, "Unable to parse form", http.StatusBadRequest) return } // collect search terms p := regexp.MustCompile("\\s+") searchTerms := make([]string, 0) for _, elem := range p.Split(req.FormValue("search"), -1) { elem = strings.TrimSpace(elem) if elem == "" { continue } searchTerms = append(searchTerms, elem) } // retrieve from repo fds, _ := data.NewFileDatastore("./persistence/spiegel100.json") repo, _ := data.NewDefaultRepository[*model.Article](fds, "article") var articles []*model.Article if len(searchTerms) != 0 { articles, _ = repo.GetByCriteria(articleTermFrequency{ terms: searchTerms }) } else { articles, _ = repo.GetAll() } // convert to viewmodel articleVMs := make([]*viewmodel.ArticleViewModel, 0, len(articles)) for _, a := range articles { articleVMs = append(articleVMs, viewmodel.NewArticleViewModel(a)) } t := template.Must(template.ParseFiles("templates/article.html", "templates/layout.html")) err = t.ExecuteTemplate(w, "base", articleVMs) if err != nil { panic(err) } } func main() { // routes http.HandleFunc("/", index) http.HandleFunc("/search", search) // serve files from the "static" directory fs := http.FileServer(http.Dir("./static")) http.Handle("/static", http.StripPrefix("/", fs)) // start server http.ListenAndServe(":8080", nil) }