Skip to content

feat: choose project administrators on project creation#7580

Open
kyle-ssg wants to merge 18 commits into
mainfrom
feat/project-admin-selector
Open

feat: choose project administrators on project creation#7580
kyle-ssg wants to merge 18 commits into
mainfrom
feat/project-admin-selector

Conversation

@kyle-ssg
Copy link
Copy Markdown
Member

@kyle-ssg kyle-ssg commented May 22, 2026

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to `docs/` if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section 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.

image

How did you test this code?

  • Created a project with a non-admin user and a custom role selected; confirmed both appear with admin permission under Project Settings.

kyle-ssg and others added 11 commits May 22, 2026 13:10
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>
@kyle-ssg kyle-ssg requested a review from a team as a code owner May 22, 2026 13:56
@kyle-ssg kyle-ssg requested review from talissoncosta and removed request for a team May 22, 2026 13:56
@vercel
Copy link
Copy Markdown

vercel Bot commented May 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview, Comment May 22, 2026 2:36pm
flagsmith-frontend-staging Ready Ready Preview, Comment May 22, 2026 2:36pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview May 22, 2026 2:36pm

Request Review

@kyle-ssg kyle-ssg marked this pull request as draft May 22, 2026 13:56
@github-actions github-actions Bot added front-end Issue related to the React Front End Dashboard feature New feature or request labels May 22, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-api:pr-7580 Finished ✅ Results
ghcr.io/flagsmith/flagsmith:pr-7580 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-7580 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-api-test:pr-7580 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-e2e:pr-7580 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-frontend:pr-7580 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-api:pr-7580 Finished ✅ Results
ghcr.io/flagsmith/flagsmith:pr-7580 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-7580 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-frontend:pr-7580 Finished ✅ Results

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread frontend/web/components/modals/CreateProject.js Outdated
Comment thread frontend/web/components/modals/CreateProject.js Outdated
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>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  41.7 seconds
commit  c8da1dd
info  🔄 Run: #16930 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  31.9 seconds
commit  c8da1dd
info  🔄 Run: #16930 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  51 seconds
commit  c8da1dd
info  🔄 Run: #16930 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  1 minute, 2 seconds
commit  c8da1dd
info  🔄 Run: #16930 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  39.1 seconds
commit  e7975de
info  🔄 Run: #16940 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  39.4 seconds
commit  e7975de
info  🔄 Run: #16940 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  32.5 seconds
commit  e7975de
info  🔄 Run: #16940 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  37.9 seconds
commit  1863489
info  🔄 Run: #16942 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  3 passed

Details

stats  3 tests across 3 suites
duration  55.7 seconds
commit  e7975de
info  🔄 Run: #16940 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  42.4 seconds
commit  1863489
info  🔄 Run: #16942 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  32.7 seconds
commit  1863489
info  🔄 Run: #16942 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  37.2 seconds
commit  1863489
info  🔄 Run: #16942 (attempt 1)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

Visual Regression

19 screenshots compared. See report for details.
View full report

…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>
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels May 22, 2026
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels May 22, 2026
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>
kyle-ssg and others added 2 commits May 22, 2026 15:33
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>
Copy link
Copy Markdown
Contributor

@talissoncosta talissoncosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just some minor suggestions. No blockers.

/>
}
content={
<Row style={{ rowGap: '12px' }}>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please double check if this inline style is still needed ?

setAssigningAdmins(true)
const failures = await assignProjectAdmins(projectId)
setAssigningAdmins(false)
if (failures) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

Suggested change
const showAdminSelector = showUserSelector || showRoleSelector
const showAdminSelector = (showUserSelector || showRoleSelector) && !disableCreate

Do you mind double check that ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add option to choose a project admin when creating a project

2 participants