feat(playlists): act on the selected rows from the toolbar, and undo either
While rows are selected the toolbar's second row is the band: the count, the last target as one click, Move to, Remove, Clear selection. Both write in one request and undo back to the places; a video the target held before stays there. Delete takes the selection when there is one. A failure puts the rows back ticked. A row's own move goes through the same write, so it undoes too, and the single-row move route and service function are gone. A playlist row drops its grip below a 24rem table: the row menu keeps the moves.
This commit is contained in:
@@ -51,7 +51,8 @@ def _ids(db, pl_id):
|
||||
|
||||
def _move(client, src, video_id, dst):
|
||||
return client.post(
|
||||
f"/api/playlists/{src}/items/{video_id}/move", json={"target_playlist_id": dst}
|
||||
f"/api/playlists/{src}/items/move-bulk",
|
||||
json={"video_ids": [video_id], "target_playlist_id": dst},
|
||||
)
|
||||
|
||||
|
||||
@@ -67,7 +68,8 @@ def test_move_leaves_the_video_in_exactly_one_list(db, make_user, as_user):
|
||||
"ok": True,
|
||||
"from_playlist_id": src.id,
|
||||
"to_playlist_id": dst.id,
|
||||
"video_id": "v1",
|
||||
"moved": ["v1"],
|
||||
"already_there": [],
|
||||
}
|
||||
db.expire_all()
|
||||
assert _ids(db, src.id) == ["v2"]
|
||||
@@ -116,8 +118,9 @@ def test_move_of_a_video_that_left_the_source_reports_it(db, make_user, as_user)
|
||||
dst = _playlist(db, user, "Target", [])
|
||||
|
||||
r = _move(as_user(user), src.id, "v1", dst.id)
|
||||
assert r.status_code == 404
|
||||
assert r.json()["detail"] == {"code": "playlist_move", "reason": "not_in_playlist"}
|
||||
assert r.status_code == 200
|
||||
assert (r.json()["moved"], r.json()["already_there"]) == ([], [])
|
||||
assert _ids(db, dst.id) == []
|
||||
|
||||
|
||||
def test_move_into_someone_elses_list_404s_and_changes_nothing(db, make_user, as_user):
|
||||
|
||||
@@ -107,7 +107,8 @@ PLEX = PlexPlaylist.__table__.name
|
||||
),
|
||||
lambda c, pid, other: c.post("/api/playlists/watch-later", json={"video_id": "v2"}),
|
||||
lambda c, pid, other: c.post(
|
||||
f"/api/playlists/{pid}/items/v1/move", json={"target_playlist_id": other}
|
||||
f"/api/playlists/{pid}/items/move-bulk",
|
||||
json={"video_ids": ["v1"], "target_playlist_id": other},
|
||||
),
|
||||
lambda c, pid, other: c.put(f"/api/playlists/{pid}/order", json={"video_ids": ["v1"]}),
|
||||
],
|
||||
@@ -173,7 +174,8 @@ PLEX_ITEMS = PlexPlaylistItem.__table__.name
|
||||
),
|
||||
lambda c, pid, other: c.delete(f"/api/playlists/{pid}/items/v1"),
|
||||
lambda c, pid, other: c.post(
|
||||
f"/api/playlists/{pid}/items/v1/move", json={"target_playlist_id": other}
|
||||
f"/api/playlists/{pid}/items/move-bulk",
|
||||
json={"video_ids": ["v1"], "target_playlist_id": other},
|
||||
),
|
||||
lambda c, pid, other: c.put(f"/api/playlists/{pid}/order", json={"video_ids": ["v1"]}),
|
||||
# the ORM cascade deletes the items before the list row
|
||||
@@ -199,7 +201,8 @@ def test_a_move_locks_both_lists_in_one_ordered_statement(db, make_user, as_user
|
||||
pid, other = _yt(db, user)
|
||||
statements.clear()
|
||||
r = as_user(user).post(
|
||||
f"/api/playlists/{pid}/items/v1/move", json={"target_playlist_id": other}
|
||||
f"/api/playlists/{pid}/items/move-bulk",
|
||||
json={"video_ids": ["v1"], "target_playlist_id": other},
|
||||
)
|
||||
assert r.status_code == 200, r.text
|
||||
lock = _locked_before_items(statements, YT, YT_ITEMS)
|
||||
|
||||
@@ -235,14 +235,13 @@ def test_a_move_never_leaves_a_video_in_two_lists(db, make_user):
|
||||
service.add_item(db, dst, "b", mark_dirty=False)
|
||||
db.commit()
|
||||
with pytest.raises(service.MoveRefused, match="same_playlist"):
|
||||
service.move_item(db, src, src, "a")
|
||||
service.move_item(db, src, dst, "a")
|
||||
service.move_item(db, src, dst, "b") # already in the target: dropped from the source
|
||||
service.move_items(db, src, src, ["a"])
|
||||
assert service.move_items(db, src, dst, ["a"]) == (["a"], [])
|
||||
# already in the target: dropped from the source
|
||||
assert service.move_items(db, src, dst, ["b"]) == ([], ["b"])
|
||||
db.commit()
|
||||
assert (_ids(db, src), _ids(db, dst)) == ([], ["b", "a"])
|
||||
with pytest.raises(service.MoveRefused, match="not_in_playlist"):
|
||||
service.move_item(db, src, dst, "a")
|
||||
db.rollback()
|
||||
assert service.move_items(db, src, dst, ["a"]) == ([], [])
|
||||
|
||||
|
||||
def test_a_reorder_keeps_what_it_left_out_after_the_listed(db, make_user):
|
||||
|
||||
Reference in New Issue
Block a user