feat(web): cascading record-type filter on the Audit page - #521
Conversation
A second "Record type" dropdown narrows the existing action dropdown to only actions actually recorded against that entity type, instead of one flat ~48-item list. The action->entity-type map is read off each audit.WriteAsync(...) call site (not derived from the action's own "Entity.Verb" prefix, which is wrong for the four Account.*Logo/Banner actions — recorded against FarmLogo, a shared row). Client-side narrowing only; the /api/v1/audit query still filters on `action` alone.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a34ab607cf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const availableActions = entityTypeFilter | ||
| ? AUDIT_ACTION_VALUES.filter((a) => AUDIT_ACTION_ENTITY_TYPE[a] === entityTypeFilter) | ||
| : AUDIT_ACTION_VALUES; |
There was a problem hiding this comment.
Normalize incompatible type/action URLs
When a shared or hand-edited URL contains a valid but incompatible pair such as ?entityType=Flock&action=User.Create, this list omits the selected action, so the Action control visually falls back to “All actions” while fetchPage continues querying User.Create. Validate actionFilter against availableActions and clear or ignore it when the pair is incompatible so a hidden filter cannot produce misleading results.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 983af91: actionFilter is now validated against availableActions for the current entityTypeFilter and ignored (not just reset on a dropdown click) when the URL's action isn't in scope for its type — closes it for both a manual click and a direct/shared URL load. Mutation-verified: reverting the validation makes the new test fail on its own action: undefined assertion.
| <div className="filters"> | ||
| <label>{t("entityTypeFilterLabel")} | ||
| <select value={entityTypeFilter} onChange={(e) => updateEntityTypeFilter(e.target.value)}> |
There was a problem hiding this comment.
Document the new cascading filter
This adds a user-visible control with non-obvious semantics—the record type narrows the Action choices but does not itself filter audit rows—without updating the SPA Help page or its in-app glossary. Add guidance to the Audit help section so users can understand the two-step filtering behavior, as required for every user-visible behavior change.
AGENTS.md reference: AGENTS.md:L251-L251
Useful? React with 👍 / 👎.
#520) codex review of #521: a URL like ?entityType=Flock&action=User.Create paired a valid but incompatible action with the record-type filter — the Action select fell back to no visible selection while fetchPage kept silently querying the hidden action. actionFilter is now validated against availableActions for the current entityTypeFilter (ignored, not just reset on a dropdown change), closing the gap for both a click and a direct URL load. Also documents the new filter in the SPA Help page + GLOSSARY.md (#520 was missing both, per AGENTS.md's per-PR doc-sync rule) and adds two tests: the incompatible-URL-pair case (mutation-verified — reverting the validation makes it fail on its own action:undefined assertion) and clearing entityType back to "All types".
|
Both findings are addressed in
Testing
|
Summary
AUDIT_ACTION_ENTITY_TYPE(web/src/i18n/enums.ts) is the action→entity-type map, read off everyaudit.WriteAsync(...)call site — not derived from the action's own"Entity.Verb"prefix, which is wrong forAccount.SetLogo/RemoveLogo/SetBanner/RemoveBanner(prefixedAccount, recorded againstFarmLogo, a shared row perFarmLogo.cs)./api/v1/auditstill filters onactionalone, same as before — no backend change, no new query param sent.actionso a hidden filter can never keep querying against a type no longer shown.entityTypeis a third URL search param, independent of the existingaction/entityIdparams from Audit: entity-scoped "View history" — who created/changed a specific record, and when #493.Closes #520.
Test plan
npm run typecheckcleanAuditPage.test.tsx(46 tests) +enums.test.ts— narrowing, action-reset-on-type-change, URL round-trip, garbage-query-value fallback