Skip to content

Add Project People + Activity Log quick links to admin header - #1429

Merged
jonfroehlich merged 3 commits into
masterfrom
1428-admin-header-quicklinks
Jul 27, 2026
Merged

Add Project People + Activity Log quick links to admin header#1429
jonfroehlich merged 3 commits into
masterfrom
1428-admin-header-quicklinks

Conversation

@jonfroehlich

Copy link
Copy Markdown
Member

Closes #1428. Supersedes #1423 (that PR was auto-closed when its branch was renamed to follow the <issue#>-slug convention; same work, rebased onto current master).

What & why

Two internal pages are easy to forget because neither is linked from the main site nav. This surfaces both in the admin top-nav (userlinks block of base_site.html):

  • Project People/view-project-people/ — the project-team roster (view_project_people view).
  • Activity Log → the superuser-only LogEntry changelist (Superuser: browse site-wide admin action log (all users, not just My actions) #1413), wrapped in {% if user.is_superuser %} so it only shows for superusers, matching the gate LogEntryAdmin already enforces. Editors/Contributors are never shown a link to a page they can't open.

The roster link is labeled Project People to match that page's own <h1>/<title> ("Project People Viewer") rather than inventing a second name for the same page.

Bug caught during review

The first draft used a bare {% url 'view_project_people' %}. website/urls.py sets app_name = "website", so the correct reverse is website:view_project_people — the bare name raises NoReverseMatch.

That's more than a broken link: base_site.html is the parent template of every admin page, so the exception fires on the index, every changelist, and every change form. Any logged-in staff user would have hit a 500 across the entire admin, and on -test (where DEBUG=True) that means a public traceback.

It slipped past the original manual testing because both checks stopped one step short of rendering the template — hitting /view-project-people/ exercises the URL path, not the reverse name, and an unauthenticated admin request 302s to login without ever rendering base_site.html.

Accessibility

Both new-tab links now carry a visually-hidden "(opens in a new tab)" cue (WCAG 3.2.5). .visually-hidden is Django admin's own screen-reader helper class from admin/css/base.css, so no new CSS ships.

Testing

New website/tests/test_admin_header_links.py renders the admin index as a real logged-in user and pins:

  • both {% url %} reverses resolve (a future rename fails a test instead of taking down the admin),
  • the Activity Log link appears for superusers and is absent for staff non-superusers,
  • the roster target is publicly reachable (200),
  • the new-tab cue is present on both links.

Verified locally against the dev stack — test_admin_header_links, test_logentry_admin, test_view_project_people, test_setup_admin_groups, test_admin_changelist, test_version_endpoint, test_template_comments all pass. CI on the pre-rebase commit was green on test, a11y, and e2e.

Release

Bumps ML_WEBSITE_VERSION to 2.28.1 with a release description.

🤖 Generated with Claude Code

jonfroehlich and others added 3 commits July 27, 2026 14:37
Surfaces two easy-to-forget internal pages in the admin top-nav (userlinks):

- Team Members -> /view-project-people/ (public project-team roster), which
  isn't linked from the main nav so it's easy to lose track of.
- Activity Log -> the superuser-only LogEntry changelist (#1413), wrapped in
  {% if user.is_superuser %} to match the page's own gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`website/urls.py` sets `app_name = "website"`, so the roster reverses as
`website:view_project_people`, not the bare `view_project_people`. The
un-namespaced `{% url %}` raised NoReverseMatch while rendering the
`userlinks` block of base_site.html -- which every admin page extends, so
the whole admin 500'd for any logged-in staff user, not just the linked
page. (It slipped through because the manual check only confirmed the URL
*path* served 200 and that the admin index 302'd to login; a 302 never
renders the template.)

Adds website/tests/test_admin_header_links.py to pin both reverses and
the superuser gate on the Activity Log link, so a future URL-name rename
fails a test instead of taking down the admin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Label the roster link "Project People" to match that page's own <h1>/
  <title> ("Project People Viewer") instead of introducing a second name
  for the same page.
- Give both new-tab links a visually-hidden "(opens in a new tab)" cue
  (WCAG 3.2.5). `.visually-hidden` is Django admin's own screen-reader
  helper class in admin/css/base.css, so no new CSS ships.
- Bump ML_WEBSITE_VERSION to 2.28.1 with a release description.

Test coverage extended to pin the new-tab cue on both links.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jonfroehlich
jonfroehlich merged commit 54c63b6 into master Jul 27, 2026
8 of 9 checks passed
@jonfroehlich
jonfroehlich deleted the 1428-admin-header-quicklinks branch July 27, 2026 21:54
jonfroehlich added a commit that referenced this pull request Jul 27, 2026
ML_WEBSITE_VERSION_DESCRIPTION renders verbatim in a callout at the top of
the admin index, so it should read as a release-note headline for lab
members adding content -- not as a changelog entry. The 2.28.1 text was a
~15-line paragraph that pushed the actual dashboard below the fold.

The full reasoning (the NoReverseMatch root cause, why manual testing
missed it, the regression-test strategy) is preserved in the 54c63b6
commit body and PR #1429.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Surface Project People + Activity Log in the admin header

1 participant