Add button to remove user from List

This commit is contained in:
Alessio 2024-02-25 20:39:46 -08:00
parent 677eb0c8a4
commit 7330dfe05f
7 changed files with 79 additions and 12 deletions

View File

@ -100,7 +100,7 @@ func (app *Application) ListAddUser(w http.ResponseWriter, r *http.Request) {
} }
list := get_list_from_context(r.Context()) list := get_list_from_context(r.Context())
app.Profile.SaveListUser(list.ID, user.ID) app.Profile.SaveListUser(list.ID, user.ID)
http.Redirect(w, r, fmt.Sprintf("/lists/%d", list.ID), 302) http.Redirect(w, r, fmt.Sprintf("/lists/%d/users", list.ID), 302)
} }
func (app *Application) ListRemoveUser(w http.ResponseWriter, r *http.Request) { func (app *Application) ListRemoveUser(w http.ResponseWriter, r *http.Request) {
@ -115,7 +115,7 @@ func (app *Application) ListRemoveUser(w http.ResponseWriter, r *http.Request) {
} }
list := get_list_from_context(r.Context()) list := get_list_from_context(r.Context())
app.Profile.DeleteListUser(list.ID, user.ID) app.Profile.DeleteListUser(list.ID, user.ID)
http.Redirect(w, r, fmt.Sprintf("/lists/%d", list.ID), 302) http.Redirect(w, r, fmt.Sprintf("/lists/%d/users", list.ID), 302)
} }
func (app *Application) Lists(w http.ResponseWriter, r *http.Request) { func (app *Application) Lists(w http.ResponseWriter, r *http.Request) {

View File

@ -630,6 +630,42 @@ func TestListDetailInvalidId(t *testing.T) {
require.Equal(t, resp.StatusCode, 400) require.Equal(t, resp.StatusCode, 400)
} }
func TestListAddAndDeleteUser(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
// Initial
resp := do_request(httptest.NewRequest("GET", "/lists/2/users", nil))
require.Equal(resp.StatusCode, 200)
root, err := html.Parse(resp.Body)
require.NoError(err)
assert.Len(cascadia.QueryAll(root, selector(".users-list-container .author-info")), 2)
// Add a user
resp_add := do_request(httptest.NewRequest("GET", "/lists/2/add_user?user_handle=cernovich", nil))
require.Equal(resp_add.StatusCode, 302)
require.Equal("/lists/2/users", resp_add.Header.Get("Location"))
// Should be +1 user now
resp = do_request(httptest.NewRequest("GET", "/lists/2/users", nil))
require.Equal(resp.StatusCode, 200)
root, err = html.Parse(resp.Body)
require.NoError(err)
assert.Len(cascadia.QueryAll(root, selector(".users-list-container .author-info")), 3)
// Delete a user
resp_remove := do_request(httptest.NewRequest("GET", "/lists/2/remove_user?user_handle=cernovich", nil))
require.Equal(resp_remove.StatusCode, 302)
require.Equal("/lists/2/users", resp_remove.Header.Get("Location"))
// Should be +1 user now
resp = do_request(httptest.NewRequest("GET", "/lists/2/users", nil))
require.Equal(resp.StatusCode, 200)
root, err = html.Parse(resp.Body)
require.NoError(err)
assert.Len(cascadia.QueryAll(root, selector(".users-list-container .author-info")), 2)
}
// Messages // Messages
// -------- // --------

View File

@ -1,12 +1,16 @@
:root { :root {
--color-twitter-text-gray: #536171; --color-twitter-text-gray: #536171;
--color-twitter-blue: #1b95e0; /* hsv(203, 87.9, 87,8) */ --color-twitter-blue: #1b95e0; /* hsl(203, 78%, 49%) */
--color-twitter-blue-light: #7cc5f6; /* hsv(204, 49.6, 96.5) */ --color-twitter-blue-light: #7cc5f6; /* hsl(204, 87%, 73%) */
--color-twitter-off-white: #f7f9f9; /* hsv(180, 0.8, 97.6) */ --color-twitter-off-white: #f7f9f9; /* hsl(180, 14%, 97%) */
--color-twitter-off-white-dark: #dae5e5; /* hsv(180, 4.8, 89.8) */ --color-twitter-off-white-dark: #dae5e5; /* hsl(180, 17%, 88%) */
--color-outline-gray: #dcdcdc; --color-outline-gray: #dcdcdc;
--color-twitter-text-gray: #536471; --color-twitter-text-gray: #536471;
--color-twitter-danger-red: #f4212e; /* hsl(356, 91%, 54%) */
--color-twitter-danger-red2: #de1b28; /* hsl(356, 78%, 49%) */
--color-twitter-danger-red2-light: #f67e86; /* hsl(356, 87%, 73%) */
--color-twitter-danger-red2-hover: #f2a6aa; /* hsl(357, 75%, 80%);*/
--color-space-purple: #a49bfd; --color-space-purple: #a49bfd;
--color-space-purple-outline: #6452fc; --color-space-purple-outline: #6452fc;
/* /*
@ -310,6 +314,10 @@ h3 {
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
} }
.row.spread {
justify-content: space-between;
}
.vertical-reply-line-container { .vertical-reply-line-container {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;
@ -396,6 +404,16 @@ ul.quick-links {
transform: translate(0.1em, 0.1em); transform: translate(0.1em, 0.1em);
background-color: var(--color-twitter-blue); background-color: var(--color-twitter-blue);
} }
/* TODO: "quick-link" is really more of a button */
.quick-link.danger {
background-color: var(--color-twitter-danger-red2);
}
.quick-link.danger:hover {
background-color: var(--color-twitter-danger-red2-light);
}
.quick-link.danger:active {
background-color: var(--color-twitter-danger-red2);
}
.quick-link span { .quick-link span {
padding: 0 0.3em; padding: 0 0.3em;
@ -718,6 +736,12 @@ ul.space-participants-list li {
font-size: 0.9em; font-size: 0.9em;
color: var(--color-twitter-text-gray); color: var(--color-twitter-text-gray);
} }
.add-users-container {
padding: 1em;
text-align: center;
}
.sort-order-container { .sort-order-container {
padding: 1em 1em 1em 3em; padding: 1em 1em 1em 3em;
margin-bottom: -0.5em; margin-bottom: -0.5em;

View File

@ -7,5 +7,5 @@
{{.Title}} {{.Title}}
</h1> </h1>
{{template "list" .UserIDs}} {{template "list" (dict "UserIDs" .UserIDs)}}
{{end}} {{end}}

View File

@ -21,11 +21,11 @@
{{else}} {{else}}
<div class="add-users-container"> <div class="add-users-container">
<form action="/lists/{{.List.ID}}/add_user"> <form action="/lists/{{.List.ID}}/add_user">
<input type="text" name="user_handle" placeholder="@some_user_handle" /> <input type="text" name="user_handle" placeholder="@some_user_handle" style="width: 15em" />
<input type="submit" value="Add user" /> <input type="submit" value="Add user" />
</form> </form>
</div> </div>
{{template "list" .UserIDs}} {{template "list" (dict "UserIDs" .UserIDs "button_text" "Remove" "button_url" (printf "/lists/%d/remove_user" .List.ID))}}
{{end}} {{end}}
{{end}} {{end}}

View File

@ -20,7 +20,7 @@
</div> </div>
</div> </div>
{{if .IsUsersSearch}} {{if .IsUsersSearch}}
{{template "list" .UserIDs}} {{template "list" (dict "UserIDs" .UserIDs)}}
{{else}} {{else}}
<div class="sort-order-container"> <div class="sort-order-container">
<span class="sort-order-label">order:</span> <span class="sort-order-label">order:</span>

View File

@ -1,9 +1,16 @@
{{define "list"}} {{define "list"}}
<div class="users-list-container"> <div class="users-list-container">
{{range .}} {{range .UserIDs}}
{{$user := (user .)}} {{$user := (user .)}}
<div class="user"> <div class="user">
{{template "author-info" $user}} <div class="row spread">
{{template "author-info" $user}}
{{if $.button_text}}
<a class="unstyled-link quick-link danger" href="{{$.button_url}}?user_handle={{$user.Handle}}"onclick="return confirm('{{$.button_text}} this user? Are you sure?')">
{{$.button_text}}
</a>
{{end}}
</div>
<p class="bio">{{$user.Bio}}</p> <p class="bio">{{$user.Bio}}</p>
</div> </div>
{{end}} {{end}}