feat(feed): filter by year — per-year count facet + year control (E8·S2)
Add a Year filter to the feed rail: quick chips for recent years plus a 'More…' popover listing all years with per-year video counts, sortable by year or count. Selecting a year narrows the feed to that whole calendar year (a published_after/before range applied in the api layer) and is mutually exclusive with the Upload-date control. Backend: new /api/feed/years endpoint + feed_years() — one grouped query that honours every filter EXCEPT the publish-date narrowing (dropped), so the year list stays a live drill-down and switching years never zeroes the others. FE keys the list on the date-stripped filters, so picking a year re-queries the feed but not the list. Wires year through FeedFilters, the filterParams/URL (?year) round-trip, the active-filter chip row, and the panel layout. i18n HU+EN. Tests: feed_years count query (date narrowing ignored, other filters honoured); dateFilter year-clearing; urlState year round-trip.
This commit is contained in:
@@ -201,6 +201,58 @@ def test_untagged_filter_keeps_only_channels_the_user_has_not_tagged(db, as_user
|
||||
assert _feed_ids(client, "show=all&untagged=true") == {"chSysv", "chNonev"}
|
||||
|
||||
|
||||
def test_feed_years_counts_ignore_the_date_narrowing_but_honour_other_filters(
|
||||
db, as_user, make_user
|
||||
):
|
||||
"""The year facet (item 8 / E8·S2): `/api/feed/years` returns a per-year video count, newest first,
|
||||
with the publish-date narrowing DROPPED (so switching years stays a drill-down) but every other
|
||||
filter still applied (here: a channel pick)."""
|
||||
user = make_user(email="years@example.com")
|
||||
chans = {c: Channel(id=c, title=c, subscriber_count=10) for c in ("chX", "chY")}
|
||||
db.add_all(chans.values())
|
||||
db.flush()
|
||||
# chX: 2 videos in 2024, 1 in 2022; chY: 1 in 2023 (should drop once we scope to chX).
|
||||
spread = {
|
||||
"chX": [(2024, 1), (2024, 2), (2022, 5)],
|
||||
"chY": [(2023, 3)],
|
||||
}
|
||||
for cid, dates in spread.items():
|
||||
db.add(Subscription(user_id=user.id, channel_id=cid, priority=0, hidden=False))
|
||||
for i, (yr, day) in enumerate(dates):
|
||||
db.add(
|
||||
Video(
|
||||
id=f"{cid}v{i}",
|
||||
channel_id=cid,
|
||||
published_at=datetime(yr, 1, day, tzinfo=timezone.utc),
|
||||
title=f"{cid} clip {i}",
|
||||
is_short=False,
|
||||
live_status="none",
|
||||
via_search=False,
|
||||
via_explore=False,
|
||||
)
|
||||
)
|
||||
db.commit()
|
||||
client = as_user(user)
|
||||
|
||||
# All channels: every year present, counted, newest first.
|
||||
resp = client.get("/api/feed/years?show=all")
|
||||
assert resp.status_code == 200, resp.text
|
||||
assert resp.json()["years"] == [
|
||||
{"year": 2024, "count": 2},
|
||||
{"year": 2023, "count": 1},
|
||||
{"year": 2022, "count": 1},
|
||||
]
|
||||
|
||||
# A channel filter narrows the year list; a date narrowing is ignored (the point of the facet — so
|
||||
# a selected year never zeroes out the others). Scoping to chX drops 2023, keeps 2024 (×2) + 2022.
|
||||
resp = client.get("/api/feed/years?show=all&channel_ids=chX&published_after=2024-01-01")
|
||||
assert resp.status_code == 200, resp.text
|
||||
assert resp.json()["years"] == [
|
||||
{"year": 2024, "count": 2},
|
||||
{"year": 2022, "count": 1},
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("case", _SUMMARY_CASES)
|
||||
def test_feed_summary_matches_count_plus_facets(db, as_user, make_user, case):
|
||||
# /feed/summary must return byte-identical numbers to the old /feed/count + /facets it replaces,
|
||||
|
||||
Reference in New Issue
Block a user