From ede472a12896fdf35fea17f5c06c76209442de1a Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Fri, 4 Apr 2025 22:11:11 -0700 Subject: [PATCH] Blog search function --- pkg/controllers/search.go | 38 +++++++------ pkg/models/posts.go | 44 +++++++++++++++ pvt-www/_builtin/blog/search.gohtml | 84 +++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 pvt-www/_builtin/blog/search.gohtml diff --git a/pkg/controllers/search.go b/pkg/controllers/search.go index 761989c..6f1c19d 100644 --- a/pkg/controllers/search.go +++ b/pkg/controllers/search.go @@ -2,27 +2,35 @@ package controllers import ( "net/http" + "strconv" + + "git.kirsle.net/apps/gophertype/pkg/models" + "git.kirsle.net/apps/gophertype/pkg/responses" + "git.kirsle.net/apps/gophertype/pkg/session" ) // BlogSearch at "/blog/search" for searching blog entries. func BlogSearch(w http.ResponseWriter, r *http.Request) { - // var ( - // query = r.FormValue("q") - // pageStr = r.FormValue("page") - // page int - // ) + var ( + query = r.FormValue("q") + pageStr = r.FormValue("page") + page int + ) - // if a, err := strconv.Atoi(pageStr); err == nil { - // page = a - // } + if a, err := strconv.Atoi(pageStr); err == nil { + page = a + } - // pp, err := models.Posts.SearchPosts(query, page, 20) + pp, err := models.Posts.SearchPosts(query, page, 24) + if err != nil { + session.FlashError(w, r, "Error searching posts: %s", err) + responses.Redirect(w, r, "/") + return + } - // v := responses.NewTemplateVars(w, r) - // v.V["post"] = post + v := responses.NewTemplateVars(w, r) + v.V["posts"] = pp + v.V["search"] = query - // // Render the body. - // v.V["rendered"] = post.HTML() - - // responses.RenderTemplate(w, r, "_builtin/blog/view-post.gohtml", v) + responses.RenderTemplate(w, r, "_builtin/blog/search.gohtml", v) } diff --git a/pkg/models/posts.go b/pkg/models/posts.go index dcf9f30..f0c39b2 100644 --- a/pkg/models/posts.go +++ b/pkg/models/posts.go @@ -144,6 +144,50 @@ func (m postMan) GetIndexPosts(privacy string, page, perPage int) (PagedPosts, e return pp, r.Error } +// SearchPosts does a full text search over posts (public only). +func (m postMan) SearchPosts(search string, page, perPage int) (PagedPosts, error) { + var pp = PagedPosts{ + Page: page, + PerPage: perPage, + } + + if pp.Page < 1 { + pp.Page = 1 + } + if pp.PerPage <= 0 { + pp.PerPage = 20 + } + + var like = fmt.Sprintf("%%%s%%", search) + + query := DB.Preload("Author").Preload("Tags"). + Where("privacy = 'public' AND body ILIKE ?", like). + Order("sticky desc, created_at desc") + + // Count the total number of rows for paging purposes. + query.Model(&Post{}).Count(&pp.Total) + + // Query the paginated slice of results. + r := query. + Offset((pp.Page - 1) * pp.PerPage). + Limit(pp.PerPage). + Find(&pp.Posts) + + pp.Pages = int(math.Ceil(float64(pp.Total) / float64(pp.PerPage))) + if pp.Page < pp.Pages { + pp.NextPage = pp.Page + 1 + } + if pp.Page > 1 { + pp.PreviousPage = pp.Page - 1 + } + + if err := pp.CountComments(); err != nil { + console.Error("PagedPosts.CountComments: %s", err) + } + + return pp, r.Error +} + // GetPostsByTag gets posts by a certain tag. func (m postMan) GetPostsByTag(tag, privacy string, page, perPage int) (PagedPosts, error) { var pp = PagedPosts{ diff --git a/pvt-www/_builtin/blog/search.gohtml b/pvt-www/_builtin/blog/search.gohtml new file mode 100644 index 0000000..c1ac597 --- /dev/null +++ b/pvt-www/_builtin/blog/search.gohtml @@ -0,0 +1,84 @@ +{{ define "title" }}Search Results: {{.V.search}}{{ end }} +{{ define "content" }} + +
+
+

Search Results

+ + {{ $Pager := .V.posts }} + +

+ {{ $Pager.Total}} results found for: {{.V.search}} +

+ +
+
+ + Page {{ $Pager.Page }} of {{ $Pager.Pages }} + +
+ +
+ {{ if $Pager.PreviousPage }} + Previous + {{ end }} + {{ if $Pager.NextPage }} + Next page + {{ end }} +
+
+ +
+ {{ range .V.posts.Posts }} +
+
+
+
+ {{ if .Thumbnail }} + + + + {{ else }} +
+ +
+ {{ end }} +
+
+
+ {{ .Title }}
+ + {{ .CreatedAt.Format "Jan 02 2006" }} + {{ if ne .Privacy "public" }} + [{{ .Privacy }}] + {{ end }} + +
+
+
+ {{ end }} +
+ +
+
+ + Page {{ $Pager.Page }} of {{ $Pager.Pages }} + +
+ +
+ {{ if $Pager.PreviousPage }} + Previous + {{ end }} + {{ if $Pager.NextPage }} + Next page + {{ end }} +
+
+ +
+
+ +{{ end }}