Skip to content

refactor: scope-aware project and organisation integrations#7311

Open
kyle-ssg wants to merge 5 commits intomainfrom
refactor/integrations-page-scoping
Open

refactor: scope-aware project and organisation integrations#7311
kyle-ssg wants to merge 5 commits intomainfrom
refactor/integrations-page-scoping

Conversation

@kyle-ssg
Copy link
Copy Markdown
Member

@kyle-ssg kyle-ssg commented Apr 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

  • Project page now surfaces org-level integrations — org-only ones deep-link to the org page, or show "Manage Repositories" if already
    connected (fixes the GitHub dead-end).
  • Org page now surfaces project-level integrations — with a project picker in the modal that auto-loads existing config.
  • Org admins can create and edit integrations for all their projects from the organisation view
  • Permission-aware CTAs with tooltips for non-org-admins.
  • Cleaner cards: action menu replaces the button row; kebab on each active integration for Edit/Delete.
  • Dropped the InfoMessage blurbs — the UI now explains itself.
  • Migrate integrations to RTK

Project integrations page

image

Organistaion integrations page with the ability to create/edit at project level

image
abc.mov

How did you test this code?

  • Added and edited integrations

…ion pages

Clarify which integrations belong at which scope, tighten permission gating,
and let admins add project-level integrations from the org page.

- Project page: surface GitHub (org-only) with a permission-gated link to
  org settings; dual-level integrations (Jira, Grafana) expose both an
  "Add to project" primary CTA and a "Manage at organisation level" link.
- Org page: list all integrations, grouped into org-level (actionable) and
  project-level (now actionable via a project selector in the standard
  modal, gated by org admin via renderWithPermission).
- Integration modal: adds a project dropdown when required, seeds formData
  with field defaults so validation borders reflect actual state, suppresses
  autocomplete on all fields, and switches to edit mode when the selected
  project (and env, for per-env integrations) already has a configuration.
- Integration tiles: action area is now a single primary button or an
  ellipsis menu styled like the feature-row menu; each added config row
  gets its own Edit/Delete menu.
- Add to project / Add to organisation labelling, with Edit {scope}
  integration when an existing non-per-env config is present.

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 April 22, 2026 11:53
@kyle-ssg kyle-ssg requested review from Zaimwa9 and removed request for a team April 22, 2026 11:53
Copy link
Copy Markdown

@claude claude 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 skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, reopen this pull request to trigger a review.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 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 Apr 22, 2026 0:50am
flagsmith-frontend-staging Ready Ready Preview, Comment Apr 22, 2026 0:50am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Apr 22, 2026 0:50am

Request Review

@github-actions github-actions Bot added front-end Issue related to the React Front End Dashboard refactor labels Apr 22, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 22, 2026

Docker builds report

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

@kyle-ssg kyle-ssg marked this pull request as draft April 22, 2026 11:55
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 22, 2026

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

passed  11 passed

Details

stats  11 tests across 8 suites
duration  43.5 seconds
commit  6d1fec5
info  🔄 Run: #16250 (attempt 1)

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

passed  11 passed

Details

stats  11 tests across 8 suites
duration  55.5 seconds
commit  6d1fec5
info  🔄 Run: #16250 (attempt 1)

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

passed  17 passed

Details

stats  17 tests across 14 suites
duration  1 minute, 1 second
commit  6d1fec5
info  🔄 Run: #16250 (attempt 1)

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

passed  2 passed

Details

stats  2 tests across 2 suites
duration  45.7 seconds
commit  6d1fec5
info  🔄 Run: #16250 (attempt 1)

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

passed  11 passed

Details

stats  11 tests across 8 suites
duration  9.4 seconds
commit  b6a955d
info  🔄 Run: #16255 (attempt 1)

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

passed  11 passed

Details

stats  11 tests across 8 suites
duration  28.1 seconds
commit  b6a955d
info  🔄 Run: #16255 (attempt 1)

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

passed  2 passed

Details

stats  2 tests across 2 suites
duration  56 seconds
commit  b6a955d
info  🔄 Run: #16255 (attempt 1)

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

passed  1 passed

Details

stats  1 test across 1 suite
duration  1 minute, 2 seconds
commit  b6a955d
info  🔄 Run: #16255 (attempt 1)

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

passed  11 passed

Details

stats  11 tests across 8 suites
duration  10.5 seconds
commit  be18d49
info  🔄 Run: #16256 (attempt 1)

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

passed  11 passed

Details

stats  11 tests across 8 suites
duration  52.6 seconds
commit  be18d49
info  🔄 Run: #16256 (attempt 1)

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

passed  1 passed

Details

stats  1 test across 1 suite
duration  44.8 seconds
commit  be18d49
info  🔄 Run: #16256 (attempt 1)

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

passed  3 passed

Details

stats  3 tests across 3 suites
duration  20.5 seconds
commit  be18d49
info  🔄 Run: #16256 (attempt 1)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 22, 2026

Visual Regression

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

…, reset form on project switch

- Add useGetIntegrationQuery to replace ad-hoc _data fetches for existing integration config
- Extract ProjectSelect component mirroring EnvironmentSelect
- Reset form state when the selected project changes so stale values (notably flagsmithEnvironment, used to key per-environment queries) don't leak between projects
- Initialise every field key in default form data so controlled inputs actually clear instead of going uncontrolled
- Collapse the external-integration CTA ladder into a single getPrimaryCta helper
- Simplify renderActions to honour action.requiresOrgAdmin/disabled directly

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ration summary

Render each read-only entry as a col-md-3 cell with label above value inside a shared row, so multiple entries flow side-by-side instead of stacking. Edit mode rendering is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ct renderField

- Add create/update RTK mutations for integration config; modal submit goes through them with tag-based invalidation
- Alphabetise integrations by display title on both project and organisation pages
- Extract renderField helpers to remove nested ternary in the fields loop
- Tighten Res['integration'] to (ActiveIntegration & Record<string, any>)[]
- Shorten a couple of stale comments

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.

Thanks for handling that @kyle-ssg.

I've added some comments, mostly clarifications..

Comment on lines +41 to +48
const ReadOnlyEnvironmentName: FC<{ environmentId?: string }> = ({
environmentId,
}) => {
const { data: environment } = useGetEnvironmentQuery(
{ id: environmentId as any },
{ skip: !environmentId },
)
return <>{environment?.name || ''}</>
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.

Is environmentId here the api_key or the numeric id? Req['getEnvironment'] is { id: number }, so the as any looks like it's papering over a mismatch. If it's the api_key, could we rename to environmentApiKey: string to match the standardisation ?

getIntegration: {
integrationId: string
projectId?: string
environmentId?: string
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.

Could you confirm the value is the api_key? If so, can we name the field environmentApiKey: string to align?

Comment on lines +366 to +367
<IntegrationActionsMenu
actions={[
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 check if this component can be replaced by DropdownMenu ?

Suggested change
<IntegrationActionsMenu
actions={[
<DropdownMenu
items={[

}
return button
}
return <IntegrationActionsMenu actions={actions} />
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 check if this component can be replaced by DropdownMenu ?

Suggested change
return <IntegrationActionsMenu actions={actions} />
return <DropdownMenu items={actions} />

Comment on lines +288 to 301
const onError = (err: any) => {
const defaultError =
'There was an error adding your integration. Please check the details and try again.'
res.text().then((errorText) => {
try {
const err = JSON.parse(errorText)
setError(err[0] || defaultError)
} catch {
setError(defaultError)
} finally {
setIsLoading(false)
}
})
try {
const payload = err?.data ?? err
setError(
(Array.isArray(payload) ? payload[0] : undefined) || defaultError,
)
} catch {
setError(defaultError)
} finally {
setIsLoading(false)
}
}
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.

The try/catch/finally here isn't doing anything — nothing inside the try can throw now that we're not parsing JSON. Could flatten to its body.

integrationData[b]?.title || b,
),
)
const organisationId = AccountStore.getOrganisation()?.id
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 we get orgId from another source to avoid getting this data from flux ?

Comment on lines +57 to +66
{!!projectIntegrations.length && (
<>
<h5 className='mt-5 mb-3'>Project-level integrations</h5>
<IntegrationList
organisationId={organisationId}
integrations={projectIntegrations}
isOrgAdmin={isOrgAdmin}
/>
</>
)}
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.

I tried this end-to-end and the UX confused me. Steps:

  1. Opened the org integrations page.
  2. In the "Project-level integrations" section, clicked Add on a project-level integration, picked a project, filled in the fields, hit save.
  3. Nothing appeared on the org page after closing the modal — I thought the save had failed.
  4. Navigated to that project's integrations page, and the integration was there.

Is this the intended behaviour?

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

Labels

front-end Issue related to the React Front End Dashboard refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GitHub integration is org-wide but managed at project level in the UI

2 participants