Add following and unfollowing

This commit is contained in:
Alessio 2023-08-17 18:09:01 -03:00
parent d10445813c
commit 901e4dce0e
5 changed files with 131 additions and 2 deletions

View File

@ -121,6 +121,10 @@ func (app *Application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
app.ChangeSession(w, r) app.ChangeSession(w, r)
case "timeline": case "timeline":
app.Timeline(w, r) app.Timeline(w, r)
case "follow":
app.UserFollow(w, r)
case "unfollow":
app.UserUnfollow(w, r)
default: default:
app.UserFeed(w, r) app.UserFeed(w, r)
} }
@ -431,3 +435,50 @@ func parse_form(req *http.Request, result interface{}) error {
} }
return nil return nil
} }
func (app *Application) UserFollow(w http.ResponseWriter, r *http.Request) {
app.traceLog.Printf("'UserFollow' handler (path: %q)", r.URL.Path)
if r.Method != "POST" {
http.Error(w, "Method not allowed", 405)
return
}
parts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
if len(parts) != 2 {
app.error_400_with_message(w, "Bad URL: "+r.URL.Path)
return
}
user, err := app.Profile.GetUserByHandle(scraper.UserHandle(parts[1]))
if err != nil {
app.error_404(w)
return
}
app.Profile.SetUserFollowed(&user, true)
app.buffered_render_basic_htmx(w, "following-button", user)
}
func (app *Application) UserUnfollow(w http.ResponseWriter, r *http.Request) {
app.traceLog.Printf("'UserUnfollow' handler (path: %q)", r.URL.Path)
if r.Method != "POST" {
http.Error(w, "Method not allowed", 405)
return
}
parts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
if len(parts) != 2 {
app.error_400_with_message(w, "Bad URL: "+r.URL.Path)
return
}
user, err := app.Profile.GetUserByHandle(scraper.UserHandle(parts[1]))
if err != nil {
app.error_404(w)
return
}
app.Profile.SetUserFollowed(&user, false)
app.buffered_render_basic_htmx(w, "following-button", user)
}

View File

@ -4,6 +4,7 @@ import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"strings"
"github.com/andybalholm/cascadia" "github.com/andybalholm/cascadia"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -189,6 +190,55 @@ func TestTweetDetailInvalidNumber(t *testing.T) {
require.Equal(resp.StatusCode, 400) require.Equal(resp.StatusCode, 400)
} }
// Follow and unfollow
// -------------------
func TestFollowUnfollow(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
user, err := profile.GetUserByHandle("kwamurai")
require.NoError(err)
require.False(user.IsFollowed)
// Follow the user
resp := do_request(httptest.NewRequest("POST", "/follow/kwamurai", nil))
require.Equal(resp.StatusCode, 200)
root, err := html.Parse(resp.Body)
require.NoError(err)
button := cascadia.Query(root, selector("button"))
assert.Contains(button.Attr, html.Attribute{Key: "hx-post", Val: "/unfollow/kwamurai"})
assert.Equal(strings.TrimSpace(button.FirstChild.Data), "Unfollow")
user, err = profile.GetUserByHandle("kwamurai")
require.NoError(err)
require.True(user.IsFollowed)
// Unfollow the user
resp = do_request(httptest.NewRequest("POST", "/unfollow/kwamurai", nil))
require.Equal(resp.StatusCode, 200)
root, err = html.Parse(resp.Body)
require.NoError(err)
button = cascadia.Query(root, selector("button"))
assert.Contains(button.Attr, html.Attribute{Key: "hx-post", Val: "/follow/kwamurai"})
assert.Equal(strings.TrimSpace(button.FirstChild.Data), "Follow")
user, err = profile.GetUserByHandle("kwamurai")
require.NoError(err)
require.False(user.IsFollowed)
}
func TestFollowUnfollowPostOnly(t *testing.T) {
require := require.New(t)
resp := do_request(httptest.NewRequest("GET", "/follow/kwamurai", nil))
require.Equal(resp.StatusCode, 405)
resp = do_request(httptest.NewRequest("GET", "/unfollow/kwamurai", nil))
require.Equal(resp.StatusCode, 405)
}
// Static content // Static content
// -------------- // --------------

View File

@ -400,3 +400,12 @@ input[type="submit"] {
.retweeted-by-label { .retweeted-by-label {
margin: 0 0.2em; margin: 0 0.2em;
} }
.user-bio {
margin: 1.5em 0;
}
.followers-followees-container {
margin-top: 1em;
gap: 4em;
}

View File

@ -0,0 +1,17 @@
{{define "following-button"}}
{{if .IsFollowed}}
<button class="following-button"
hx-post="/unfollow/{{.Handle}}"
hx-swap="outerHTML"
>
Unfollow
</button>
{{else}}
<button class="following-button"
hx-post="/follow/{{.Handle}}"
hx-swap="outerHTML"
>
Follow
</button>
{{end}}
{{end}}

View File

@ -8,8 +8,10 @@
{{end}} {{end}}
<div class="user-feed-header-info-container"> <div class="user-feed-header-info-container">
<div class="row">
{{template "author-info" $user}} {{template "author-info" $user}}
<button>{{if $user.IsFollowed}}Unfollow{{else}}Follow{{end}}</button> {{template "following-button" $user}}
</div>
<div class="user-bio"> <div class="user-bio">
<span>{{$user.Bio}}</span> <span>{{$user.Bio}}</span>
</div> </div>