From 38495e85919cc5e67ced3ce61da67f43eb8ae8a4 Mon Sep 17 00:00:00 2001 From: Alessio Date: Sun, 25 Feb 2024 21:58:56 -0800 Subject: [PATCH] Add button and query to delete a List --- internal/webserver/handler_lists.go | 16 +++++++- internal/webserver/static/styles.css | 20 +++++----- internal/webserver/tpl/list_of_lists.tpl | 48 +++++++++++++----------- pkg/persistence/list_queries.go | 7 ++++ pkg/persistence/list_queries_test.go | 20 ++++++++++ pkg/persistence/schema.sql | 2 +- sample_data/seed_data.sql | 2 +- 7 files changed, 81 insertions(+), 34 deletions(-) diff --git a/internal/webserver/handler_lists.go b/internal/webserver/handler_lists.go index 6176d45..3f664e0 100644 --- a/internal/webserver/handler_lists.go +++ b/internal/webserver/handler_lists.go @@ -69,13 +69,25 @@ func (app *Application) ListDetailUsers(w http.ResponseWriter, r *http.Request) 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) { app.traceLog.Printf("'ListDetail' handler (path: %q)", r.URL.Path) parts := strings.Split(strings.Trim(r.URL.Path, "/"), "/") if len(parts) == 1 && parts[0] == "" { - // No further path; just show the feed - app.ListDetailFeed(w, r) + switch r.Method { + case "DELETE": + app.ListDelete(w, r) + default: + // No further path; just show the feed + app.ListDetailFeed(w, r) + } + return } switch parts[0] { diff --git a/internal/webserver/static/styles.css b/internal/webserver/static/styles.css index cc7e102..8c5fdf7 100644 --- a/internal/webserver/static/styles.css +++ b/internal/webserver/static/styles.css @@ -693,30 +693,32 @@ ul.space-participants-list li { } .users-list-preview { - cursor: pointer; - display: flex; - font-size: 1.5em; + padding: 0.5em 1em; border-color: var(--color-twitter-off-white-dark); border-bottom-style: solid; 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; 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; align-items: flex-end; 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; 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; } diff --git a/internal/webserver/tpl/list_of_lists.tpl b/internal/webserver/tpl/list_of_lists.tpl index 0247458..37d5761 100644 --- a/internal/webserver/tpl/list_of_lists.tpl +++ b/internal/webserver/tpl/list_of_lists.tpl @@ -17,29 +17,35 @@
{{range .}} {{$max_display_users := 10}} -
- {{.Name}} - ({{(len .Users)}}) -
- {{range $i, $user := .Users}} - {{/* Only render the first 10-ish users */}} - {{if (lt $i $max_display_users)}} - - - +
+
+ {{.Name}} + ({{(len .Users)}}) +
+ {{range $i, $user := .Users}} + {{/* Only render the first 10-ish users */}} + {{if (lt $i $max_display_users)}} + + + + {{end}} {{end}} - {{end}} - {{if (gt (len .Users) $max_display_users)}} - ... - {{end}} + {{if (gt (len .Users) $max_display_users)}} + ... + {{end}} +
+ Delete
{{end}}
diff --git a/pkg/persistence/list_queries.go b/pkg/persistence/list_queries.go index 8c2cb5b..86246c3 100644 --- a/pkg/persistence/list_queries.go +++ b/pkg/persistence/list_queries.go @@ -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) { for user_id := range trove.Users { p.SaveListUser(list_id, user_id) diff --git a/pkg/persistence/list_queries_test.go b/pkg/persistence/list_queries_test.go index 4a076fe..5eb10e1 100644 --- a/pkg/persistence/list_queries_test.go +++ b/pkg/persistence/list_queries_test.go @@ -173,3 +173,23 @@ func TestGetAllLists(t *testing.T) { assert.True(len(lists) > 1) // Should be at least Offline Follows and `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) +} diff --git a/pkg/persistence/schema.sql b/pkg/persistence/schema.sql index b5abf42..b11be29 100644 --- a/pkg/persistence/schema.sql +++ b/pkg/persistence/schema.sql @@ -43,7 +43,7 @@ create table list_users(rowid integer primary key, list_id integer not null, user_id integer not null, 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) ); create index if not exists index_list_users_list_id on list_users (list_id); diff --git a/sample_data/seed_data.sql b/sample_data/seed_data.sql index 4842b1d..a2fa6ce 100644 --- a/sample_data/seed_data.sql +++ b/sample_data/seed_data.sql @@ -66,7 +66,7 @@ create table list_users(rowid integer primary key, list_id integer not null, user_id integer not null, 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) ); create index if not exists index_list_users_list_id on list_users (list_id);