feat: choose project administrators on project creation#7580
Conversation
Adds a multi-user selector to the create project modal that lets the creator immediately grant project administrator permissions to other users. Selector is only rendered when there are organisation users who would actually benefit — organisation administrators already have full access to every project by default, and the creator is excluded. Reuses the existing UserSelect component. Refs #6838. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the user-only chip selector with a single SettingsButton-backed picker that searches across eligible users, groups, and roles in one list. Selected entries render as chips with the entity type as a sublabel, and submission fans the assignments out to the user, group, and role project-permission endpoints in parallel. Also add an optional 'description' prop to SettingsButton so help text can sit between the label/cog row and the content slot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Render selected administrators as "User: name" / "Group: name" / "Role: name" with the type label semibold on the left, dropping the muted email/type sublabel that previously sat to the right. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the inline-modal--sm size cap (355px max-width) and set the picker content to a fixed 480px width with a 320px scroll height so the combined list of users / groups / roles has more room. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
font-weight-bold (700) was too heavy; use semibold (600) for the User/Group/Role prefix in the project admin chip. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Render an optional dropdown node between the label/cog row and the description/content. Used by CreateProject to anchor the project administrator picker under the title rather than under the chip list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Restrict the project administrator picker to users and roles only; remove the group fetch, state, request fan-out, and UI strings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the unified Inline picker with a Project administrators heading plus two SettingsButtons (Users, Roles), each anchoring its own picker via the SettingsButton dropdown slot. UserSelect and MyRoleSelect handle search and selection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
OrganisationProvider registers its onSave listener once on mount, so the close function captures the initial empty adminIds/adminRoleIds and never sees the user's selections. Mirror both into refs and read from the refs when fanning out the user-permission / role-projects-permission POSTs after the project is created. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Docker builds report
|
There was a problem hiding this comment.
Code Review
This pull request refactors the CreateProject modal into a functional component and introduces the ability to assign project administrators and roles during the creation process. It also extends the SettingsButton component with new description and dropdown props. The review feedback identifies a potential stale closure issue with the onSave callback and recommends using a ref to ensure the latest version is called, while also suggesting safer handling of the data object in the close function to avoid destructuring errors.
Drop the raw _data.post calls in favour of two dedicated RTK Query
mutations:
- createProjectUserPermission (POST /projects/{id}/user-permissions/)
added to projectService.
- createProjectRolePermission (POST /organisations/{orgId}/roles/{roleId}/
projects-permissions/) added to rolePermissionService — separate from
the generic createRolePermissions endpoint so the body type can be
scoped to the project case without making project/environment
optional on the multi-level type.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-16)Details
Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)Details
|
Visual Regression19 screenshots compared. See report for details. |
…ermissions The mutation operates on the project user-permissions resource, so it belongs alongside the other user-permissions endpoint rather than in projectService. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Default-destructure data || {} so a null/undefined payload from
OrganisationProvider doesn't throw.
- Mirror onSave into onSaveRef so the latest parent callback is
invoked even if it changes between renders (the listener inside
OrganisationProvider is registered once on mount).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Type props (history, onSave), state, refs, and the OrganisationProvider save payload. Import OrganisationProvider and InputGroup explicitly rather than relying on JSX globals. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…name Use Promise.allSettled when assigning project administrators so all mutations attempt regardless of individual failures, and skip navigation/onSave when any fail so the user can retry from the modal. Trim project name on submit to reject whitespace-only inputs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| /> | ||
| } | ||
| content={ | ||
| <Row style={{ rowGap: '12px' }}> |
There was a problem hiding this comment.
can you please double check if this inline style is still needed ?
| setAssigningAdmins(true) | ||
| const failures = await assignProjectAdmins(projectId) | ||
| setAssigningAdmins(false) | ||
| if (failures) { |
There was a problem hiding this comment.
If assignProjectAdmins fails, we toast and return — but the project has already been created by OrganisationProvider, so the user ends up stuck on the modal with an invisible orphaned project. Dismissing the modal navigates nowhere; clicking Create again duplicates.
Could we close + navigate on partial failure too, with the toast saying something like "Project created — N admin assignment(s) failed. Retry in Project Settings → Members."? That way the failure becomes a notification rather than a dead end.
| const busy = isSaving || assigningAdmins | ||
| const showUserSelector = !!eligibleAdmins.length | ||
| const showRoleSelector = !!hasRbac && !!roles.length | ||
| const showAdminSelector = showUserSelector || showRoleSelector |
There was a problem hiding this comment.
When disableCreate is true the form fades, but the admin selectors and chip removals are still interactive behind it. Easiest fix is to unmount the whole block:
| const showAdminSelector = showUserSelector || showRoleSelector | |
| const showAdminSelector = (showUserSelector || showRoleSelector) && !disableCreate |
Do you mind double check that ?
Thanks for submitting a PR! Please check the boxes below:
Changes
Lets the creator assign other users and roles as project administrators directly from the Create Project modal, rather than having to open Project Settings → Members afterwards.
How did you test this code?