feat(089): admin users view#2
Merged
hendrikebbers merged 9 commits intomainfrom Apr 26, 2026
Merged
Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes spec 089 step 1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- new server page /admin/users gated by IT-ADMIN role - client component with avatar/name/email columns, fallback icon for null avatarUrl, page-size selector (10/20/50/100/200) persisted in localStorage, prev/next pagination, total count display, skeleton loading and empty state - new getUsers API function and Users sidebar nav item - en/de translations for the new namespace and nav entry Closes spec 089 steps 2-5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- annotation-level check that listUsers carries @RequiresItAdmin - 401/403/200 role coverage in SecurityRoleIntegrationTest - pagination contract tests (default size 20, explicit size, page shape) - /api/users/me regression check that the existing endpoint stays open to authenticated users Closes spec 089 step 6. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 tests covering loading skeleton, empty state, avatar rendering with and without avatarUrl, default page size 20, localStorage hydration, total count (singular/plural), pagination button visibility, prev/next disabled boundaries, and prev/next navigation requests. Closes spec 089 step 8. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- replace bare <table> with shadcn Table primitives in users-client per the typescript convention (no raw HTML elements where a UI lib component exists) - handle getUsers rejection: log to console, surface a translated loadError message via a dedicated error UI; previously a network failure was silently rendered as the empty state, which is misleading - add users.loadError translation keys (de + en) and a test that verifies the error branch renders without falling through to empty - drop unused SessionProvider wrapper from the test - fix import order in PreAuthorizeAnnotationTest Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
Adds a read-only Users page to the admin area that lists every registered CRM user in a paginated table (avatar, name, email). Restricted to the
IT-ADMINrole at both the backend endpoint and the server-rendered Next.js page; the sidebar item is hidden for users without the role.Spec
specs/089-admin-users-view/specs/089-admin-users-view/design.mdspecs/089-admin-users-view/behaviors.mdspecs/089-admin-users-view/steps.mdChanges
Backend
UserController.listUsers(Pageable)returnsPage<UserDto>fromUserService.findAll, defaulting to size 20.@RequiresItAdmin;getMestays open to any authenticated user.UserControllerTest(pagination contract: default size, explicit size, response shape) and 6 newSecurityRoleIntegrationTestcases (401/403/200 across role combinations +/api/users/meregression).PreAuthorizeAnnotationTestpins@RequiresItAdminon the new method.Frontend
/admin/usersserver component gated byROLE_IT_ADMIN, falling back to<ForbiddenPage />.UsersClientpaginated table built on@open-elements/uiTable*primitives — avatar (32×32 circular<img>with<User>icon fallback fornullavatarUrl), page-size selector (10/20/50/100/200, persisted underpageSize.users, default 20), prev/next pagination with hidden/disabled states, total-count display (singular/plural), skeleton loading, dedicated empty and error states.getUsers(params)API helper following the existinggetContacts/getApiKeyspattern.Usersnav item under the existing adminCollapsibleGroup(visibility inherited fromcanSeeAdmin).nav.usersand a newusersnamespace.Test coverage
behaviors.mdmapped to tests insteps.md(Behavior Coverage table).main(44 pre-existing failures unchanged).95dfe69(bare<table>→Table*primitives, silent fetch error → catch + error UI, import order inPreAuthorizeAnnotationTest).Notes for the reviewer
PAGE_SIZE_OPTIONS/DEFAULT_PAGE_SIZE/PAGE_SIZE_STORAGE_KEYconstants. The behavior is implemented in theonValueChangehandler.Closes #1
🤖 Generated with Claude Code