@@ -19,14 +19,15 @@ import {
1919} from '@/lib/credential-groups/providers'
2020import { SLACK_CUSTOM_BOT_PROVIDER_ID } from '@/lib/oauth/types'
2121import { RowActionsMenu } from '@/app/workspace/[workspaceId]/settings/components/row-actions-menu'
22+ import { SettingsEmptyState } from '@/app/workspace/[workspaceId]/settings/components/settings-empty-state'
2223import {
2324 RESOURCE_LIST_STACK ,
2425 SettingsResourceRow ,
2526} from '@/app/workspace/[workspaceId]/settings/components/settings-resource-row'
2627import { SettingsSection } from '@/app/workspace/[workspaceId]/settings/components/settings-section/settings-section'
2728import { SettingRow } from '@/ee/components/setting-row'
2829import { SlackManagedUsersModal } from '@/ee/credential-groups/components/slack-managed-users-modal'
29- import { useUpdateCredentialGroup } from '@/hooks/queries/credential-groups'
30+ import { useCredentialGroups , useUpdateCredentialGroup } from '@/hooks/queries/credential-groups'
3031import { useWorkspaceCredentials } from '@/hooks/queries/credentials'
3132
3233/** Stable identity so a pending/errored credentials query cannot churn the modal's `bots` prop. */
@@ -35,6 +36,8 @@ const EMPTY_SLACK_BOTS: WorkspaceCredential[] = []
3536interface CredentialGroupDetailsProps {
3637 credentialGroup : CredentialGroup
3738 workspaceId : string
39+ /** Filters the account types offered below; owned by the panel header's search field. */
40+ providerSearch : string
3841 /** Edited name; committed by the panel header's Save action, which owns the dirty state. */
3942 name : string
4043 onNameChange : ( name : string ) => void
@@ -61,12 +64,19 @@ function toOptionUpdateInput(
6164export function CredentialGroupDetails ( {
6265 credentialGroup,
6366 workspaceId,
67+ providerSearch,
6468 name,
6569 onNameChange,
6670 description,
6771 onDescriptionChange,
6872} : CredentialGroupDetailsProps ) {
6973 const updateGroup = useUpdateCredentialGroup ( )
74+ /**
75+ * Reads the same cache entry the list view already populated, so the deployment's configured
76+ * providers arrive without a second request.
77+ */
78+ const credentialGroups = useCredentialGroups ( workspaceId )
79+ const availableProviders = credentialGroups . data ?. availableProviders
7080 const slackBots = useWorkspaceCredentials ( {
7181 workspaceId,
7282 type : 'service_account' ,
@@ -132,6 +142,26 @@ export function CredentialGroupDetails({
132142 if ( await updateOptions ( options , `${ service . name } removed` ) ) setRemovingProvider ( null )
133143 }
134144
145+ /**
146+ * A provider whose OAuth client this deployment has not configured can never finish an
147+ * enrollment, so it is not offered — but one already on the group stays listed regardless, or
148+ * the row that removes it would disappear along with it.
149+ */
150+ const configuredProviders = new Set ( credentialGroup . options . map ( ( option ) => option . provider ) )
151+ const offerableProviders = availableProviders ? new Set ( availableProviders ) : null
152+ const providerQuery = providerSearch . trim ( ) . toLowerCase ( )
153+ const shownProviders = CREDENTIAL_GROUP_PROVIDER_IDS . filter ( ( provider ) => {
154+ if (
155+ ! configuredProviders . has ( provider ) &&
156+ offerableProviders &&
157+ ! offerableProviders . has ( provider )
158+ ) {
159+ return false
160+ }
161+ if ( ! providerQuery ) return true
162+ return getCredentialGroupProviderService ( provider ) . name . toLowerCase ( ) . includes ( providerQuery )
163+ } )
164+
135165 return (
136166 < >
137167 < SettingsSection label = 'Group details' >
@@ -161,8 +191,15 @@ export function CredentialGroupDetails({
161191 </ SettingsSection >
162192
163193 < SettingsSection label = 'Accounts people can connect' >
194+ { shownProviders . length === 0 ? (
195+ < SettingsEmptyState variant = 'inline' >
196+ { providerSearch . trim ( )
197+ ? `No account types found matching "${ providerSearch } "`
198+ : 'No account types are available. Configure an OAuth client to offer one.' }
199+ </ SettingsEmptyState >
200+ ) : null }
164201 < div className = { RESOURCE_LIST_STACK } >
165- { CREDENTIAL_GROUP_PROVIDER_IDS . map ( ( provider ) => {
202+ { shownProviders . map ( ( provider ) => {
166203 const service = getCredentialGroupProviderService ( provider )
167204 const support = getCredentialGroupProviderSupport ( provider )
168205 const option = credentialGroup . options . find (
0 commit comments