feat(portal-admin): user directory viewer screen #142
Reference in New Issue
Block a user
Delete Branch "feat/portal-admin-users-viewer"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Final PR of the portal-admin User-list chantier per ADR-0020 §"v1 scope — User list (read-only)". Ships the SPA viewer at
/usersthat consumesGET /api/admin/users(PR #141) and renders a filter form + paginated table mirroring the audit viewer's shape (PR #136). The full chantier is now closed: schema + sign-in upsert (#140) → read endpoint (#141) → this viewer.What lands
AdminUsersServiceThin
HttpClientwrapper aroundGET /api/admin/users. Drops empty-string filter values (Nest'sValidationPiperejects?foo=asfoo === '').providedIn: 'root'— the users page is the single v1 consumer.UsersPageSignal-driven page mirroring the
/auditviewer:username,displayName,audience,lastSeenAtFrom,lastSeenAtTolimit,offsetMAX_LIMIT.page,loading,errorhasNextPage,hasPreviousPage,resultRangeUI:
datetime-localinputs → ISO), page-size selector. Apply + Reset."No users match the current filters."), error. 403 surfaces "you do not have access"; everything else collapses to a generic retry message — same posture as the audit viewer.Routing + i18n + sidebar
/usersroute lazy-loaded inapp.routes.tswithroute.users.titlei18n marker.messages.fr.xlfupdated with the French translation (Utilisateurs — Administration APF Portal); the prod build'si18nMissingTranslation=errorpolicy would fail otherwise.AdminSidebar"User list" entry promoted fromaria-disabledplaceholder ("Soon" badge) to a liveRouterLinkat/users. The matching spec is updated.Notes for the reviewer
AuditPage(#136) intentionally — same signal layout, same flush dance in the spec, same 403/5xx error split, same datetime-local-to-ISO conversion. A future contributor coming from one viewer lands familiar code on the other.users= 3.76 KB gzip,audit= 4.35 KB gzip). No shared filter-form lib promoted yet — the duplication is mechanical and small (~120 LOC each), and ADR-0020's next admin modules (CMS, menu management) may diverge enough that premature factoring would be expensive to undo.firstSeenAt/lastSeenAt). Joining sign-in counts fromaudit.eventsviaHashUserIdServiceis deferred until admin demand justifies the extra query per row.Test plan
pnpm nx test portal-admin— 45 specs pass (was 30; +15: AdminUsersService 3, UsersPage 11, sidebar 1).pnpm exec nx affected -t format:check lint test build --base=origin/main— clean.userschunk at 14.59 KB raw / 3.76 KB gzip — comfortably under the per-chunk lazy budget.adminrole assignment + at least a couple of sign-in events to populate the directory. Once both exist: sign in via/api/admin/auth/login, navigate to/users, see the directory populate with each row's displayName + lastSeen, exercise the filters, observeadmin.users.queryrows inaudit.eventsper fetch.What's next — portal-admin v1 chantiers
This PR closes User list. Remaining ADR-0020 v1 modules:
cms.menu_items;GET /api/me/menuconsumed by portal-shell +/api/admin/menuadmin CRUD. Medium chantier.cms.pageswith slug + locale + body markdown), admin editor screen, portal-shell consumer for the rendering. Bigger chantier.Out of immediate scope: