Enable searching through the search bar

This commit is contained in:
Alessio 2023-08-20 15:02:47 -03:00
parent b8d0d6be7a
commit 72110e6558
6 changed files with 125 additions and 2 deletions

View File

@ -0,0 +1,58 @@
package webserver
import (
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"gitlab.com/offline-twitter/twitter_offline_engine/pkg/persistence"
)
func (app *Application) Search(w http.ResponseWriter, r *http.Request) {
app.traceLog.Printf("'Search' handler (path: %q)", r.URL.Path)
search_text := strings.Trim(r.URL.Path, "/")
if search_text == "" {
// Redirect GET param "q" to use a URL param instead
search_text = r.URL.Query().Get("q")
if search_text == "" {
app.error_400_with_message(w, "Empty search query")
return
// TODO: return an actual page
}
http.Redirect(w, r, fmt.Sprintf("/search/%s", url.PathEscape(search_text)), 302)
return
}
c, err := persistence.NewCursorFromSearchQuery(search_text)
if err != nil {
app.error_400_with_message(w, err.Error())
return
// TODO: return actual page
}
err = parse_cursor_value(&c, r)
if err != nil {
app.error_400_with_message(w, "invalid cursor (must be a number)")
return
}
feed, err := app.Profile.NextPage(c)
if err != nil {
if errors.Is(err, persistence.ErrEndOfFeed) {
// TODO
} else {
panic(err)
}
}
data := UserProfileData{Feed: feed} // TODO: wrong struct
if r.Header.Get("HX-Request") == "true" && c.CursorPosition == persistence.CURSOR_MIDDLE {
// It's a Show More request
app.buffered_render_tweet_htmx(w, "timeline", data)
} else {
app.buffered_render_tweet_page(w, "tpl/search.tpl", data)
}
}

View File

@ -118,6 +118,8 @@ func (app *Application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
app.UserFollow(w, r)
case "unfollow":
app.UserUnfollow(w, r)
case "search":
http.StripPrefix("/search", http.HandlerFunc(app.Search)).ServeHTTP(w, r)
default:
app.UserFeed(w, r)
}

View File

@ -1,10 +1,13 @@
package webserver_test
import (
"testing"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/andybalholm/cascadia"
"github.com/stretchr/testify/assert"
@ -158,6 +161,53 @@ func TestTimelineWithCursorBadNumber(t *testing.T) {
require.Equal(resp.StatusCode, 400)
}
// Search page
// -----------
func TestSearchQueryStringRedirect(t *testing.T) {
assert := assert.New(t)
// With a cursor but it sucks
resp := do_request(httptest.NewRequest("GET", "/search?q=asdf", nil))
assert.Equal(resp.StatusCode, 302)
assert.Equal(resp.Header.Get("Location"), "/search/asdf")
}
func TestSearch(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
resp := do_request(httptest.NewRequest("GET", fmt.Sprintf("/search/%s", url.PathEscape("to:spacex to:covfefeanon")), nil))
require.Equal(resp.StatusCode, 200)
root, err := html.Parse(resp.Body)
require.NoError(err)
title_node := cascadia.Query(root, selector("title"))
assert.Equal(title_node.FirstChild.Data, "Offline Twitter | Search")
tweet_nodes := cascadia.QueryAll(root, selector(".timeline > .tweet"))
assert.Len(tweet_nodes, 1)
}
func TestSearchWithCursor(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
// First, without the cursor
resp := do_request(httptest.NewRequest("GET", "/search/who%20are", nil))
require.Equal(resp.StatusCode, 200)
root, err := html.Parse(resp.Body)
require.NoError(err)
assert.Len(cascadia.QueryAll(root, selector(".timeline > .tweet")), 3)
// Add a cursor with the 1st tweet's posted_at time
resp = do_request(httptest.NewRequest("GET", "/search/who%20are?cursor=1628979529", nil))
require.Equal(resp.StatusCode, 200)
root, err = html.Parse(resp.Body)
require.NoError(err)
assert.Len(cascadia.QueryAll(root, selector(".timeline > .tweet")), 2)
}
// Tweet Detail page
// -----------------

View File

@ -381,6 +381,10 @@ svg {
left: 50%;
transform: translate(-50%, -50%);
}
.top-bar form {
flex-grow: 1;
display: flex;
}
.search-bar {
flex-grow: 1;
}

View File

@ -14,7 +14,9 @@
<a onclick="window.history.back()" class="back-button quick-link">
<img class="svg-icon" src="/static/icons/back.svg" />
</a>
<input class="search-bar" placeholder="Search" type="text" />
<form hx-get="/search" hx-push-url="true" hx-target="body">
<input name="q" class="search-bar" placeholder="Search" type="text" />
</form>
</div>
{{template "nav-sidebar"}}
<main>

View File

@ -0,0 +1,7 @@
{{define "title"}}Search{{end}}
{{define "main"}}
<div class="timeline">
{{template "timeline" .}}
</div>
{{end}}