M6: browse notes by creation date (Timeline lens)
A temporal recall path — find a note by WHEN it was captured, not just what it contains (task 1903, first of the M6 recall items). Backend: list_notes gains an optional created_at range (created_after / created_before, half-open interval) + sort=created; also lays groundwork for the richer-search facets (task 1902). New _parse_iso_dt helper with a DB-free unit test. Frontend: a Timeline view (sidebar nav + 'g t' + command palette) grouping active notes newest-first into local-time buckets (Today / Yesterday / Earlier this week / this month / Month YYYY), plus an optional From/To date filter. Built as a lens on the same NoteCard masonry, consistent with the existing Reminders/Search views. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FRgehjoz7Yv8LkUfADxACm
This commit is contained in:
@@ -4,6 +4,7 @@ from thoughtsync.app import create_app
|
||||
from thoughtsync.models.note import NOTE_COLORS, Note
|
||||
from thoughtsync.notes import (
|
||||
_escape_like,
|
||||
_parse_iso_dt,
|
||||
derive_display_title,
|
||||
is_empty_note,
|
||||
normalize_color,
|
||||
@@ -157,6 +158,20 @@ def test_escape_like():
|
||||
assert _escape_like("plain") == "plain"
|
||||
|
||||
|
||||
def test_parse_iso_dt():
|
||||
# A full ISO instant round-trips (used to validate the Timeline date range).
|
||||
d = _parse_iso_dt("2026-07-19T12:30:00+00:00")
|
||||
assert (d.year, d.month, d.day, d.hour, d.minute) == (2026, 7, 19, 12, 30)
|
||||
assert d.tzinfo is not None
|
||||
# a trailing Z is accepted as UTC
|
||||
assert _parse_iso_dt("2026-07-19T00:00:00Z").tzinfo is not None
|
||||
# a plain calendar date parses to midnight
|
||||
assert _parse_iso_dt("2026-07-19").hour == 0
|
||||
# garbage raises (the endpoint turns this into a 400)
|
||||
with pytest.raises(ValueError):
|
||||
_parse_iso_dt("not-a-date")
|
||||
|
||||
|
||||
async def test_titles_requires_auth(app):
|
||||
client = app.test_client()
|
||||
resp = await client.get("/api/notes/titles")
|
||||
|
||||
Reference in New Issue
Block a user