feat(audit): every row keeps its date; dividers for Today, Yesterday, Last 7 days, Older (#5214)

The operator found "Today 08:03" in place of a date odd on the audit log,
and asked for the recency groups as dividers instead. |when now always
writes the date ("Thu 8 Oct 08:03"); mark_day_groups gives each entry its
group in the reader's zone, and a divider row opens each group. A scrolled
page carries the group the last one ended in, so it is not opened twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 08:22:03 -04:00
co-authored by Claude Opus 5.5
parent 31e93e96cf
commit 7a444da871
7 changed files with 100 additions and 26 deletions
+29 -2
View File
@@ -49,11 +49,11 @@ async def test_the_page_names_and_links_the_entity(app):
async def test_the_log_continues_itself_instead_of_a_load_more_link(app):
events = [{"event": _ev("host", "h1", "host.renamed"), "detail": {}, "entity": None}]
async with app.test_request_context("/audit/"):
more = await render_template("audit/list.html", events=events,
more = await render_template("audit/list.html", events=events, last_group="Today",
after="2026-10-07T03:00:00+00:00|0190abc", action_filter="host.")
last = await render_template("audit/_rows.html", events=events, after=None, action_filter="")
assert ('data-scroll-more hx-get="/audit/?before=2026-10-07T03%3A00%3A00%2B00%3A00%7C0190abc'
'&amp;action=host."') in more
'&amp;action=host.&amp;group=Today"') in more
assert "Load more" not in more
assert "data-scroll-more" not in last and "End of the list." in last
@@ -107,3 +107,30 @@ async def test_each_entry_shows_its_exact_moment_in_the_readers_zone(app):
assert '<div><span class="tone-dim">was</span> web-0</div>' in page
table = page[page.index('<table class="table">'):]
assert "style=" not in table
def test_dividers_open_each_day_group_once_even_across_pages():
"""#5214: the operator wants Today, Yesterday, the last week and older as
dividers, with every row's own date beside it."""
from steward.audit.service import mark_day_groups
now = datetime(2026, 10, 8, 18, 0, tzinfo=timezone.utc)
at = lambda d, h=12: NS(timestamp=datetime(2026, 10, d, h, 0, tzinfo=timezone.utc))
page1 = [{"event": at(8)}, {"event": at(8, 9)}, {"event": at(7)}, {"event": at(5)}]
assert mark_day_groups(page1, timezone.utc, "", now) == "Last 7 days"
assert [(i["group"], i["opens_group"]) for i in page1] == [
("Today", True), ("Today", False), ("Yesterday", True), ("Last 7 days", True)]
# The next page carries the group the last ended in, so it doesn't reopen it.
page2 = [{"event": at(3)}, {"event": at(1)}]
assert mark_day_groups(page2, timezone.utc, "Last 7 days", now) == "Older"
assert [(i["group"], i["opens_group"]) for i in page2] == [("Last 7 days", False), ("Older", True)]
async def test_a_divider_row_heads_each_group(app):
events = [{"event": _ev("host", "h1", "host.renamed"), "detail": {}, "entity": None, "facts": [],
"group": "Today", "opens_group": True},
{"event": _ev("host", "h1", "host.renamed"), "detail": {}, "entity": None, "facts": [],
"group": "Today", "opens_group": False}]
async with app.test_request_context("/audit/"):
page = await render_template("audit/_rows.html", events=events, after=None, action_filter="")
assert page.count('<tr class="table-divider"><th colspan="5" scope="rowgroup">Today</th></tr>') == 1
assert "Today 1" not in page and ">Tue 6 Oct " in page # the row keeps its date