Enable searching through the search bar
This commit is contained in:
parent
b8d0d6be7a
commit
72110e6558
58
internal/webserver/handler_search.go
Normal file
58
internal/webserver/handler_search.go
Normal 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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
// -----------------
|
||||
|
||||
|
@ -381,6 +381,10 @@ svg {
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.top-bar form {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
}
|
||||
.search-bar {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
@ -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>
|
||||
|
7
internal/webserver/tpl/search.tpl
Normal file
7
internal/webserver/tpl/search.tpl
Normal file
@ -0,0 +1,7 @@
|
||||
{{define "title"}}Search{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<div class="timeline">
|
||||
{{template "timeline" .}}
|
||||
</div>
|
||||
{{end}}
|
Loading…
x
Reference in New Issue
Block a user