Add button and query to delete a List
This commit is contained in:
parent
66b32e4c6f
commit
38495e8591
@ -69,14 +69,26 @@ func (app *Application) ListDetailUsers(w http.ResponseWriter, r *http.Request)
|
|||||||
app.buffered_render_page(w, "tpl/list.tpl", PageGlobalData{TweetTrove: trove}, data)
|
app.buffered_render_page(w, "tpl/list.tpl", PageGlobalData{TweetTrove: trove}, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *Application) ListDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
|
list := get_list_from_context(r.Context())
|
||||||
|
app.Profile.DeleteList(list.ID)
|
||||||
|
http.Redirect(w, r, "/lists", 302)
|
||||||
|
}
|
||||||
|
|
||||||
func (app *Application) ListDetail(w http.ResponseWriter, r *http.Request) {
|
func (app *Application) ListDetail(w http.ResponseWriter, r *http.Request) {
|
||||||
app.traceLog.Printf("'ListDetail' handler (path: %q)", r.URL.Path)
|
app.traceLog.Printf("'ListDetail' handler (path: %q)", r.URL.Path)
|
||||||
parts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
|
parts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
|
||||||
|
|
||||||
if len(parts) == 1 && parts[0] == "" {
|
if len(parts) == 1 && parts[0] == "" {
|
||||||
|
switch r.Method {
|
||||||
|
case "DELETE":
|
||||||
|
app.ListDelete(w, r)
|
||||||
|
default:
|
||||||
// No further path; just show the feed
|
// No further path; just show the feed
|
||||||
app.ListDetailFeed(w, r)
|
app.ListDetailFeed(w, r)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
case "users":
|
case "users":
|
||||||
|
@ -693,30 +693,32 @@ ul.space-participants-list li {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.users-list-preview {
|
.users-list-preview {
|
||||||
cursor: pointer;
|
padding: 0.5em 1em;
|
||||||
display: flex;
|
|
||||||
font-size: 1.5em;
|
|
||||||
border-color: var(--color-twitter-off-white-dark);
|
border-color: var(--color-twitter-off-white-dark);
|
||||||
border-bottom-style: solid;
|
border-bottom-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
padding: 0.5em 1em;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
.users-list-preview span.num-users {
|
.users-list-preview .list-info-container{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.users-list-preview .list-info-container span.num-users {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
color: var(--color-twitter-text-gray);
|
color: var(--color-twitter-text-gray);
|
||||||
}
|
}
|
||||||
.users-list-preview .first-N-profile-images {
|
.users-list-preview .list-info-container .first-N-profile-images {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
margin-left: 1.5em;
|
margin-left: 1.5em;
|
||||||
}
|
}
|
||||||
.users-list-preview .first-N-profile-images a {
|
.users-list-preview .list-info-container .first-N-profile-images a {
|
||||||
margin-right: -1.2em;
|
margin-right: -1.2em;
|
||||||
line-height: 0; /* TODO: This is duplicated from `.author-info a` and possibly others */
|
line-height: 0; /* TODO: This is duplicated from `.author-info a` and possibly others */
|
||||||
}
|
}
|
||||||
|
|
||||||
.users-list-preview .first-N-profile-images .ellipsis {
|
.users-list-preview .list-info-container .first-N-profile-images .ellipsis {
|
||||||
margin-left: 1.5em;
|
margin-left: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
<div class="users-list-previews">
|
<div class="users-list-previews">
|
||||||
{{range .}}
|
{{range .}}
|
||||||
{{$max_display_users := 10}}
|
{{$max_display_users := 10}}
|
||||||
<div class="users-list-preview" hx-get="/lists/{{.ID}}" hx-trigger="click" hx-target="body" hx-push-url="true">
|
<div class="users-list-preview row spread">
|
||||||
|
<div class="list-info-container" hx-get="/lists/{{.ID}}" hx-trigger="click" hx-target="body" hx-push-url="true">
|
||||||
<span class="list-name">{{.Name}}</span>
|
<span class="list-name">{{.Name}}</span>
|
||||||
<span class="num-users">({{(len .Users)}})</span>
|
<span class="num-users">({{(len .Users)}})</span>
|
||||||
<div class="first-N-profile-images" hx-trigger="click consume">
|
<div class="first-N-profile-images" hx-trigger="click consume">
|
||||||
@ -41,6 +42,11 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<a class="unstyled-link quick-link danger"
|
||||||
|
hx-delete="/lists/{{.ID}}" hx-target="body"
|
||||||
|
onclick="return confirm('Delete this list? Are you sure?')"
|
||||||
|
>Delete</a>
|
||||||
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -53,6 +53,13 @@ func (p Profile) SaveList(l *List) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Profile) DeleteList(list_id ListID) {
|
||||||
|
_, err := p.DB.Exec(`delete from lists where rowid = ?`, list_id)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("Error executing DeleteList(%d):\n %w", list_id, err).Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p Profile) SaveListUsers(list_id ListID, trove TweetTrove) {
|
func (p Profile) SaveListUsers(list_id ListID, trove TweetTrove) {
|
||||||
for user_id := range trove.Users {
|
for user_id := range trove.Users {
|
||||||
p.SaveListUser(list_id, user_id)
|
p.SaveListUser(list_id, user_id)
|
||||||
|
@ -173,3 +173,23 @@ func TestGetAllLists(t *testing.T) {
|
|||||||
assert.True(len(lists) > 1) // Should be at least Offline Follows and `l`
|
assert.True(len(lists) > 1) // Should be at least Offline Follows and `l`
|
||||||
assert.Contains(lists, l)
|
assert.Contains(lists, l)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteList(t *testing.T) {
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
profile, err := persistence.LoadProfile("../../sample_data/profile")
|
||||||
|
require.NoError(err)
|
||||||
|
|
||||||
|
// Create an offline list
|
||||||
|
l := List{IsOnline: false, Name: fmt.Sprintf("Test List %d", rand.Int())}
|
||||||
|
require.Equal(l.ID, ListID(0))
|
||||||
|
profile.SaveList(&l)
|
||||||
|
require.NotEqual(l.ID, ListID(0)) // ID should be assigned when it's saved
|
||||||
|
|
||||||
|
// Delete it
|
||||||
|
profile.DeleteList(l.ID)
|
||||||
|
|
||||||
|
// Check it's gone
|
||||||
|
_, err = profile.GetListById(l.ID)
|
||||||
|
require.Error(err)
|
||||||
|
}
|
||||||
|
@ -43,7 +43,7 @@ create table list_users(rowid integer primary key,
|
|||||||
list_id integer not null,
|
list_id integer not null,
|
||||||
user_id integer not null,
|
user_id integer not null,
|
||||||
unique(list_id, user_id)
|
unique(list_id, user_id)
|
||||||
foreign key(list_id) references lists(rowid)
|
foreign key(list_id) references lists(rowid) on delete cascade
|
||||||
foreign key(user_id) references users(id)
|
foreign key(user_id) references users(id)
|
||||||
);
|
);
|
||||||
create index if not exists index_list_users_list_id on list_users (list_id);
|
create index if not exists index_list_users_list_id on list_users (list_id);
|
||||||
|
@ -66,7 +66,7 @@ create table list_users(rowid integer primary key,
|
|||||||
list_id integer not null,
|
list_id integer not null,
|
||||||
user_id integer not null,
|
user_id integer not null,
|
||||||
unique(list_id, user_id)
|
unique(list_id, user_id)
|
||||||
foreign key(list_id) references lists(rowid)
|
foreign key(list_id) references lists(rowid) on delete cascade
|
||||||
foreign key(user_id) references users(id)
|
foreign key(user_id) references users(id)
|
||||||
);
|
);
|
||||||
create index if not exists index_list_users_list_id on list_users (list_id);
|
create index if not exists index_list_users_list_id on list_users (list_id);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user