phase: 175_history_pagination
All criteria verified. This pass found no defects — the phase was fully implemented by prior task runs, and every gate is green. **Phase 175 final verification pass — report** - Verified tasks 01–03 implementation in-tree: `list_chats` `?limit=` (25, 1–100) / `?offset=` + `func.count` `total`; `SavedChatList.total` required; `#history-pager` below `#history-table-wrap` (hidden default, aria-labels, aria-hidden SVGs); `history.js` `PAGE_SIZE=25`/offset state, parameterized fetch, `updatePager`, refresh-keeps-current-page; CSS pill union + ≤640px block. No code changes were needed. - Full suite: `uv run pytest --cov=app --cov-report=term-missing` → **exit 0, TOTAL 99%** (>90% gate). - `uv run ruff check .` → all checks passed; `uv run pyright` → 0 errors, 0 warnings. - Phase E2E in isolation: `uv run pytest tests/e2e/test_history_pagination.py -v --no-cov` → **9 passed** (page 1-of-2 / 2-of-2 walk, replace-not-append, refresh-on-page-2, delete-to-empty + single-page hide, anonymous no-fetch, 375px mobile, a11y/no-CDN). - Regression set, each in isolation: test_chat_history 5✓, test_history_page_width 5✓, test_share_chat 4✓, test_stale_saved_chats 3✓, test_history_copy 1✓; integration `test_chats_api.py` green (incl. updated `test_list_empty` two-key pin and all five new pagination pins). - Completion criteria: all nine boxes satisfied (API slice/422/honest-total pins ✓; E2E walk + status lines ✓; refresh/delete/hide ✓; anonymous gate ✓; mobile ✓; gates ✓; E2E + regression ✓; docs ✓; commit/phase-move is the harness's). - Documentation: README.md reviewed in full — the saved-chats section already carries the `?limit=`/`?offset=`/`total` contract from this phase; all 31 `.env.example` vars documented; AGENTS.md verified accurate. **Consistent — no changes needed.** - Deviations: none. No defects found in previously completed work. - Next pending phase: none — 175 is the only entry in `todo/`.
This commit is contained in:
@@ -4010,7 +4010,7 @@ a.answer-image:hover { text-decoration: underline; } /* flat — the caption und
|
||||
gap: 0.75rem 1.5rem;
|
||||
}
|
||||
#view-history .page-head .page-head-title { min-width: 0; }
|
||||
.history-refresh {
|
||||
.history-refresh, .history-pager-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -4028,12 +4028,38 @@ a.answer-image:hover { text-decoration: underline; } /* flat — the caption und
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.history-refresh:hover { background: var(--brand-hover); color: var(--bg); }
|
||||
.history-refresh:disabled { opacity: 0.6; cursor: wait; }
|
||||
.history-refresh:hover, .history-pager-btn:hover { background: var(--brand-hover); color: var(--bg); }
|
||||
.history-refresh:disabled, .history-pager-btn:disabled { opacity: 0.6; cursor: wait; }
|
||||
/* The refresh glyph is hidden on desktop (the label carries the
|
||||
pill); below 640px it joins the visible label in the full-width
|
||||
pill (the <=640 block — the icon-only squeeze is gone). */
|
||||
.history-refresh svg { width: 16px; height: 16px; display: none; }
|
||||
pill (the <=640 block — the icon-only squeeze is gone). The
|
||||
phase-175 pager buttons join the rule (the selector union — the
|
||||
same glyph language: visible label at every width, the glyph is
|
||||
the mobile companion). */
|
||||
.history-refresh svg, .history-pager-btn svg { width: 16px; height: 16px; display: none; }
|
||||
|
||||
/* ---------- History pager (phase 175, task 02 — TODO.md L3) ----------
|
||||
"Need pagination on the history page - it gets long fast" (owner
|
||||
2026-10-10). Root cause: the saved-chat list used to fetch and
|
||||
render EVERY row; the server now ships a 25-row page + the full
|
||||
count, and this row is the walk control — Prev / "Page N of M" /
|
||||
Next, sitting UNDER the table card (index.html, phase 175).
|
||||
Token reuse (B3): the buttons join the .history-refresh pill
|
||||
through the selector unions above (the solid brand pill, the
|
||||
:disabled opacity, the svg sizing — NO new palette variable), and
|
||||
the row's gap is the page's OWN 0.75rem (the #view-history
|
||||
.page-head row gap — no new spacing token). Hidden by default
|
||||
(the markup ships `hidden`): history.js's updatePager() reveals
|
||||
the row only while `total > PAGE_SIZE` (A4 — no dead "Page 1 of
|
||||
1" control; it disappears with the empty state). The status span
|
||||
needs no rule beyond the inherited text. Below 640px the row
|
||||
stacks (the .settings-actions idiom) and the pills go full width
|
||||
(the .history-refresh mobile idiom — the ≤640px block below). */
|
||||
.history-pager {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
/* ---------- History page (phase 50) ----------
|
||||
/history.html: the admin-only saved-chats list (task 04). The
|
||||
@@ -6486,8 +6512,14 @@ a.answer-image:hover { text-decoration: underline; } /* flat — the caption und
|
||||
.sync-btn { width: 100%; }
|
||||
.sync-cancel-btn { width: 100%; } /* phase 134: the Cancel pill stacks full-width under the Sync pill (the row already wraps) */
|
||||
.sync-label { max-width: none; flex: 1 1 auto; min-width: 0; }
|
||||
.history-refresh { width: 100%; }
|
||||
.history-refresh svg { display: block; }
|
||||
.history-refresh, .history-pager-btn { width: 100%; }
|
||||
.history-refresh svg, .history-pager-btn svg { display: block; }
|
||||
/* Phase 175 (task 02, D6): the pager row STACKS (the
|
||||
.settings-actions idiom) so the full-width Prev / Next pills
|
||||
don't side-by-side overflow the phone width (the pill rule's
|
||||
flex-shrink: 0 would keep each at 100%); the "Page N of M"
|
||||
status sits between them (the 0.75rem gap goes vertical). */
|
||||
.history-pager { flex-direction: column; align-items: center; }
|
||||
}
|
||||
|
||||
/* Phase 46: prefers-reduced-motion stills the mobile menu — no
|
||||
|
||||
Reference in New Issue
Block a user