Repository navigation
fix(system): fetch the Updates history grid from /api instead of server-rendering it (TIGER-383) - #366
Merged
Conversation
…er-rendering it (TIGER-383)
The updates history was the one admin grid that did not follow the client/server
contract: the controller handed the view `recent(15)` and the view looped it into
<tr> rows. WEBSERVICES.md §5 is explicit that list/table data is fetched from /api,
never server-rendered.
The consistency argument is the point, but there was a real gap behind it: dev had
24 history rows and the screen could only ever show 15. Nine runs existed that
nobody could reach, with no paging, no search and no way to ask "what happened
last month?".
Converted to the house DataTables pattern, following Cms_Service_Page::datatable
and the Access user grid rather than inventing a variant:
Tiger_Model_UpdateHistory::datatable() owns the query — search, sort, paging,
and both counts. A service never builds a predicate (AGENTS.md), so the
finder is named and lives on the model.
System_Service_Updates::datatable() _dtParams() -> finder -> _dtResponse().
Rows are STRUCTURED data only, never HTML; the step log rides along so the
expandable detail costs no second round trip.
The controller renders the shell and sets useDataTables.
The view is an empty <table>; the grid init lives in the module's JS ASSET
(this screen already loads one — no new inline <script>).
The per-run step log became a DataTables CHILD ROW, which is how DT expresses
"detail under this row"; the old sibling <tr class="collapse"> has no equivalent.
history() is KEPT, and now documents why: it is the plain read an API/MCP caller
wants without DataTables semantics, and `history` is a READ_VERB so a read-only
token can reach it. It was previously unwired from any UI.
Tests: 3 service tests (envelope + structured-rows-only + no markup; search
narrows recordsFiltered without moving the total; a plain admin is denied) and a
new controller test. The controller test asserts useDataTables — without that flag
the assets never load, the grid renders empty and the page's JS dies after the
failed init, silently, behind a 200. Mutation-checked: removing the flag fails it.
A second test guards against a `history` view-var reappearing.
Verified in a browser on tiger-dev as a superadmin: all 24 rows reachable and
sortable, the child-row log expands, 0 console errors. The paradigm scanner that
filed this ticket now reports rendered_rows = 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013vdyTeoDrGE4hKxt53TsE8
CI caught this and my local run did not: SystemControllerDispatchTest asserts the Updates screen's view-vars, including `history` as an array — the very var this change removes. I had filtered my local run to UpdatesService|UpdatesController, and this file's name mentions neither, so it never ran. The assertion is updated to the contract that now holds rather than the behaviour being replaced: useDataTables is set, and `history` is absent because the rows come from /api. Full integration suite run unfiltered this time: 1552 tests green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013vdyTeoDrGE4hKxt53TsE8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found by the paradigm scanner in PR #364. The updates history was the one admin grid not following the client/server contract — the controller handed the view
recent(15)and the view looped it into<tr>rows, where WEBSERVICES.md §5 says list/table data is fetched from/api.There was a real gap behind the consistency argument
Dev has 24 history rows. The screen could only ever show 15. Nine update runs existed that nobody could reach — no paging, no search, no way to ask "what happened last month?". The paradigm violation was the symptom; this was the damage.
Converted to the house pattern, not a variant
Followed
Cms_Service_Page::datatableand the Access user grid:Tiger_Model_UpdateHistory::datatable()System_Service_Updates::datatable()_dtParams()→ finder →_dtResponse()System_UpdatesControlleruseDataTables<table>; init lives in the module's JS assetA service never builds a predicate (AGENTS.md), so the finder is named and on the model. Rows are structured data only, never HTML — there's an assertion for that. This screen already loaded an external JS asset, so the grid init went there rather than adding an inline
<script>.The per-run step log became a DataTables child row, which is how DT expresses "detail under this row" — the old sibling
<tr class="collapse">has no equivalent. The log travels with the row payload, so expanding costs no second round trip.history()is kept, and now says whyIt was previously unwired from any UI. It survives because it's the plain read an API/MCP caller wants without DataTables semantics, and
historyis aREAD_VERB— so a read-only token can reach it. The admin grid usesdatatable().Tests
Three service tests — the DataTables envelope with structured-rows-only (asserting no markup is built server-side), search narrowing
recordsFilteredwithout moving the total, and a plain admin being denied — plus a new controller test.The controller test asserts
useDataTables, and that one earns its keep: without the flag the assets never load, the grid renders empty, and the page's JS dies after the failed init — silently, behind a 200, with nothing a casual look would catch. Mutation-checked: removing the flag fails it. A second test guards against ahistoryview-var reappearing.Verified in a browser
Signed in on tiger-dev as a superadmin: all 24 rows reachable and sortable, the child-row log expands with the full step list, 0 console errors.
And the scanner that filed this ticket now reports
rendered_rows= 0.Full unit suite green (1195 tests).
🤖 Generated with Claude Code
https://claude.ai/code/session_013vdyTeoDrGE4hKxt53TsE8