From b9a591a178e3a8d2c3a00ca567ba7c2a415a2a99 Mon Sep 17 00:00:00 2001 From: uberswe Date: Sat, 29 Jan 2022 12:31:01 +0100 Subject: [PATCH] Adds search pagination --- database.go | 25 +++++++++++++++++++++++++ dist/templates/search.html | 8 ++++++++ main.go | 2 ++ routes/search.go | 37 +++++++++++++++++++++++++++++++++---- 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/database.go b/database.go index 01392b7..79676c5 100644 --- a/database.go +++ b/database.go @@ -71,6 +71,31 @@ func seed(db *gorm.DB) { Description: "Learn how to install Go on your machine and read the documentation on the Go website.", URL: "https://go.dev/learn/", }, + { + Title: "Uberswe on Github", + Description: "I am the creator of Golang Base Project. This is my Github profile.", + URL: "https://github.com/uberswe", + }, + { + Title: "Tournify", + Description: "A website to create tournaments or free which uses this project as a base.", + URL: "https://tournify.io", + }, + { + Title: "GORM", + Description: "The fantastic ORM library for Golang.", + URL: "https://gorm.io/", + }, + { + Title: "Bootstrap", + Description: "Quickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.", + URL: "https://getbootstrap.com/", + }, + { + Title: "Gin Web Framework", + Description: "Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.", + URL: "https://github.com/gin-gonic/gin", + }, } for _, w := range websites { diff --git a/dist/templates/search.html b/dist/templates/search.html index 573cdcc..99cf334 100644 --- a/dist/templates/search.html +++ b/dist/templates/search.html @@ -11,6 +11,14 @@

{{ $result.URL }}

{{ end }} + diff --git a/main.go b/main.go index 1172116..2b05297 100644 --- a/main.go +++ b/main.go @@ -107,6 +107,8 @@ func Run() { // We want to handle both POST and GET requests on the /search route. We define both but use the same function to handle the requests. r.GET("/search", controller.Search) r.POST("/search", controller.Search) + r.Any("/search/:page", controller.Search) + r.Any("/search/:page/:query", controller.Search) // We define our 404 handler for when a page can not be found r.NoRoute(controller.NoRoute) diff --git a/routes/search.go b/routes/search.go index 4898f08..146d584 100644 --- a/routes/search.go +++ b/routes/search.go @@ -6,30 +6,51 @@ import ( "github.com/uberswe/golang-base-project/models" "log" "net/http" + "net/url" + "strconv" ) // SearchData holds additional data needed to render the search HTML page type SearchData struct { PageData Results []models.Website + Prev bool + Next bool + PrevURL string + NextURL string } // Search renders the search HTML page and any search results func (controller Controller) Search(c *gin.Context) { + page := 1 + resultsPerPage := 5 pdS := controller.DefaultPageData(c) pdS.Title = pdS.Trans("Search") pd := SearchData{ PageData: pdS, } - search := c.PostForm("search") + search := "" + if c.Request.Method == "POST" && c.Request.RequestURI == "/search" { + search = c.PostForm("search") + c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("/search/1/%s", url.QueryEscape(search))) + return + } else { + search = c.Param("query") + if i, err := strconv.Atoi(c.Param("page")); err == nil { + page = i + } + } var results []models.Website log.Println(search) - search = fmt.Sprintf("%s%s%s", "%", search, "%") + searchFilter := fmt.Sprintf("%s%s%s", "%", search, "%") + search2 := fmt.Sprintf("%s%s", "%", search) + search4 := fmt.Sprintf("%s%s", search, "%") - log.Println(search) - res := controller.db.Where("title LIKE ? OR description LIKE ?", search, search).Find(&results) + res := controller.db. + Raw(fmt.Sprintf("SELECT * FROM websites WHERE title LIKE ? OR description LIKE ? ORDER BY CASE WHEN title LIKE ? OR description LIKE ? THEN 1 WHEN title LIKE ? OR description LIKE ? THEN 2 WHEN title LIKE ? OR description LIKE ? THEN 4 ELSE 3 END LIMIT %d OFFSET %d", resultsPerPage, resultsPerPage*(page-1)), searchFilter, searchFilter, search, search, search2, search2, search4, search4). + Find(&results) if res.Error != nil || len(results) == 0 { pd.Messages = append(pd.Messages, Message{ @@ -42,6 +63,14 @@ func (controller Controller) Search(c *gin.Context) { } pd.Results = results + if len(pd.Results) >= resultsPerPage { + pd.Next = true + pd.NextURL = fmt.Sprintf("/search/%d/%s", page+1, url.QueryEscape(search)) + } + if page > 1 { + pd.Prev = true + pd.PrevURL = fmt.Sprintf("/search/%d/%s", page-1, url.QueryEscape(search)) + } c.HTML(http.StatusOK, "search.html", pd) }