Skip to content

Recent Activity feed - #75

Draft
a-effort wants to merge 3 commits into
mainfrom
feat/activity-view
Draft

Recent Activity feed#75
a-effort wants to merge 3 commits into
mainfrom
feat/activity-view

Conversation

@a-effort

@a-effort a-effort commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Builds ActivityView, the Recent Activity feed. ?view=activity previously fell through to the "coming soon" placeholder: the earlier spike shipped the plumbing (types, api client, hook, fixture, MSW handler) but never the list itself.

Blocked by #74

This view cannot load real data until #74 merges. The BFF strips its own /api before forwarding, so /api/logs/activity reaches the gateway as /logs/activity and 404s. Every request from this view fails with "Recent activity could not be loaded." until that fix lands. #74 is small and independent, and was split out so it can be reviewed on its own.

Verified locally with #74's branch checked out.

Depends on #69

The first commit here (d967052) is Altamimi-Dev's from #69, which adds the enabled option this hook needs. #69's head is on a fork, so GitHub will not let this PR base on it and that commit shows up in the diff. Once #69 merges I will git rebase --onto origin/main d967052.

Review this PR's own two commits, not d967052.

What's here

  • activityStatus.ts holds the single status to {icon, tone} map, using the set ui/sonner.tsx already ships. Keeping it in one record is what makes the app-wide token rollout ([Bug] Standardize status icons and colors app-wide  #62) a one-file change here.
  • Filter tabs count error/warning the same way the mini cards do, so the two cannot disagree.
  • The feed is requested at limit: 100 rather than the hook's default of 10, because search filters the fetched window client-side.
  • No self-gating. HOME_STATES.activity already declares requiredPermission: "audit:read", so the page renders the skeleton while permissions load and PermissionDenied when the caller lacks it.
  • useRecentActivity now keeps the original error instead of flattening it to { message }. ApiError carries the status and isPermissionDenied needs the instance, so a 403 that slips past the page gate (stale or coarser client permissions, team-switch race) renders as denied rather than as a generic failure.
  • Second commit aligns text styles, spacing and the panel to Figma frame 4979-39243, and adds a text-xxs theme token (10px/16) for the step below Tailwind's built-in scale.

Open question: info vs success

Server-side,info is a successful read/execute audit row, or a low-severity security event, and any security event with a missing or unrecognized severity falls back to it.

Tests

10 new tests in ActivityView.test.tsx covering rows, relative timestamps, the screen-reader status label, tab counts, severity filtering, search, empty-feed versus empty-filter, the 403 path, the non-403 path and the loading skeleton.

Full suite: 3096 passed, 1 skipped, 184 files. tsc, eslint and prettier clean.

Altamimi-Dev and others added 3 commits August 21, 2026 17:44
/api/logs/activity requires audit:read, which no default non-admin role
holds, so every non-admin home load fired a guaranteed 403. Add an
`enabled` option to useRecentActivity, mirroring useSystemHealth's flag
for the admin-only /version probe, and gate the home call on it.

Signed-off-by: Ahmad Al Tamimi <altamimi.dev@gmail.com>
?view=activity fell through to the "coming soon" placeholder; the spike
had shipped the plumbing (types, api client, hook, fixture, MSW handler)
but never the list itself. Adds ActivityView and wires it into the
Dashboard main-content switch.

- activityStatus.ts holds the one status -> {icon, tone} map, using the
  set ui/sonner.tsx already ships. Keeping it in a single record is what
  makes the app-wide token rollout (#62) a one-file change here. `info`
  is unaccented, matching sonner, so high-volume read/execute rows
  recede while errors and warnings carry.
- Filter tabs count `error`/`warning` the same way the mini cards do, so
  the two can't disagree. `info` gets no tab of its own.
- The feed is requested at limit 100, not the hook's default of 10:
  search filters the fetched window client-side, so a 10-row window
  would make it near-useless.
- No self-gating. HOME_STATES.activity already declares
  requiredPermission: "audit:read", so the page renders the skeleton
  while permissions load and PermissionDenied when the caller lacks it.

useRecentActivity now keeps the original error instead of flattening it
to { message }. ApiError carries the status, and isPermissionDenied
needs the instance, so a 403 that slips past the page gate (stale or
coarser client permissions, team-switch race) can render as denied
rather than as a generic failure.

Signed-off-by: Anna Effort <anna.effort@ibm.com>
Measured against frame 4979-39243.

- Text style updates.
- Adds a `text-xxs` theme token (10px/16) for the step below Tailwind's
  built-in scale, matching Figma's own `text-xxs`.
- Wraps the feed in the single bordered panel the design shows, with a
  divider under the tab row, replacing the loose filters + ringed list.
- Drops the count from "All activity" and lets the remaining counts
  inherit their label colour rather than rendering muted.
- TabsTrigger has no display utility, so the `gap-*` between label and
  count was inert; set inline-flex here.

Signed-off-by: Anna Effort <anna.effort@ibm.com>
@a-effort a-effort changed the title feat: build the Recent Activity feed view Recent Activity feed Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants