Skip to content

Commit 55677a0

Browse files
waleedlatif1claude
andcommitted
fix(settings): rename credentials to secrets, align role display
- Rename credentials/ folder to secrets/ to match the page name - Replace Badge with disabled Combobox for non-admin role display in secrets and integrations details views, full-width when no admin actions - Reorder integrations credential row buttons so Details is rightmost - Split credential-skeleton: page-level moves to secrets-skeleton, row-level moves to integrations/credential-skeleton - Cleanup: useMemo→const where deps were trivial, ROLE_OPTIONS const, --text-success token Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent d60747d commit 55677a0

9 files changed

Lines changed: 96 additions & 84 deletions

File tree

apps/sim/app/workspace/[workspaceId]/settings/[section]/settings.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ import { ApiKeysSkeleton } from '@/app/workspace/[workspaceId]/settings/componen
1313
import { BYOKSkeleton } from '@/app/workspace/[workspaceId]/settings/components/byok/byok-skeleton'
1414
import { CopilotSkeleton } from '@/app/workspace/[workspaceId]/settings/components/copilot/copilot-skeleton'
1515
import { CredentialSetsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/credential-sets/credential-sets-skeleton'
16-
import { CredentialsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/credentials/credential-skeleton'
1716
import { CustomToolsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/custom-tools/custom-tool-skeleton'
1817
import { GeneralSkeleton } from '@/app/workspace/[workspaceId]/settings/components/general/general-skeleton'
1918
import { InboxSkeleton } from '@/app/workspace/[workspaceId]/settings/components/inbox/inbox-skeleton'
2019
import { IntegrationsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/integrations/integrations-skeleton'
2120
import { McpSkeleton } from '@/app/workspace/[workspaceId]/settings/components/mcp/mcp-skeleton'
2221
import { RecentlyDeletedSkeleton } from '@/app/workspace/[workspaceId]/settings/components/recently-deleted/recently-deleted-skeleton'
22+
import { SecretsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/secrets/secrets-skeleton'
2323
import { SkillsSkeleton } from '@/app/workspace/[workspaceId]/settings/components/skills/skill-skeleton'
2424
import { WorkflowMcpServersSkeleton } from '@/app/workspace/[workspaceId]/settings/components/workflow-mcp-servers/workflow-mcp-servers-skeleton'
2525
import type { SettingsSection } from '@/app/workspace/[workspaceId]/settings/navigation'
@@ -59,12 +59,12 @@ const Integrations = dynamic(
5959
),
6060
{ loading: () => <IntegrationsSkeleton /> }
6161
)
62-
const Credentials = dynamic(
62+
const Secrets = dynamic(
6363
() =>
64-
import('@/app/workspace/[workspaceId]/settings/components/credentials/credentials').then(
65-
(m) => m.Credentials
64+
import('@/app/workspace/[workspaceId]/settings/components/secrets/secrets').then(
65+
(m) => m.Secrets
6666
),
67-
{ loading: () => <CredentialsSkeleton /> }
67+
{ loading: () => <SecretsSkeleton /> }
6868
)
6969
// const TemplateProfile = dynamic(
7070
// () =>
@@ -225,7 +225,7 @@ export function SettingsPage({ section }: SettingsPageProps) {
225225
<h2 className='mb-7 font-medium text-[22px] text-[var(--text-primary)]'>{label}</h2>
226226
{effectiveSection === 'general' && <General />}
227227
{effectiveSection === 'integrations' && <Integrations />}
228-
{effectiveSection === 'secrets' && <Credentials />}
228+
{effectiveSection === 'secrets' && <Secrets />}
229229
{/* {effectiveSection === 'template-profile' && <TemplateProfile />} */}
230230
{effectiveSection === 'credential-sets' && <CredentialSets />}
231231
{effectiveSection === 'access-control' && <AccessControl />}

apps/sim/app/workspace/[workspaceId]/settings/components/credentials/credentials.tsx

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Skeleton } from '@/components/emcn'
2+
3+
/**
4+
* Skeleton for a single integration credential row.
5+
*/
6+
export function CredentialSkeleton() {
7+
return (
8+
<div className='flex items-center justify-between gap-3'>
9+
<div className='flex min-w-0 items-center gap-2.5'>
10+
<Skeleton className='h-8 w-8 flex-shrink-0 rounded-md' />
11+
<div className='flex min-w-0 flex-col justify-center gap-[1px]'>
12+
<Skeleton className='h-4 w-[120px] rounded' />
13+
<Skeleton className='h-3.5 w-[160px] rounded' />
14+
</div>
15+
</div>
16+
<div className='flex flex-shrink-0 items-center gap-1'>
17+
<Skeleton className='h-9 w-[60px] rounded-md' />
18+
<Skeleton className='h-9 w-[88px] rounded-md' />
19+
</div>
20+
</div>
21+
)
22+
}

apps/sim/app/workspace/[workspaceId]/settings/components/integrations/integrations-manager.tsx

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import {
3535
import { getCanonicalScopesForProvider, getServiceConfigByProviderId } from '@/lib/oauth'
3636
import { getScopeDescription } from '@/lib/oauth/utils'
3737
import { getUserColor } from '@/lib/workspaces/colors'
38-
import { CredentialSkeleton } from '@/app/workspace/[workspaceId]/settings/components/credentials/credential-skeleton'
38+
import { CredentialSkeleton } from '@/app/workspace/[workspaceId]/settings/components/integrations/credential-skeleton'
3939
import {
4040
useCreateCredentialDraft,
4141
useCreateWorkspaceCredential,
@@ -59,12 +59,15 @@ import { useSettingsDirtyStore } from '@/stores/settings/dirty/store'
5959

6060
const logger = createLogger('IntegrationsManager')
6161

62-
const roleOptions = [
62+
const ROLE_OPTIONS = [
6363
{ value: 'member', label: 'Member' },
6464
{ value: 'admin', label: 'Admin' },
6565
] as const
6666

67-
const roleComboOptions = roleOptions.map((option) => ({ value: option.value, label: option.label }))
67+
const roleComboOptions = ROLE_OPTIONS.map((option) => ({
68+
value: option.value,
69+
label: option.label,
70+
}))
6871

6972
export function IntegrationsManager() {
7073
const params = useParams()
@@ -201,10 +204,7 @@ export function IntegrationsManager() {
201204
() => members.filter((member) => member.status === 'active'),
202205
[members]
203206
)
204-
const adminMemberCount = useMemo(
205-
() => activeMembers.filter((member) => member.role === 'admin').length,
206-
[activeMembers]
207-
)
207+
const adminMemberCount = activeMembers.filter((member) => member.role === 'admin').length
208208

209209
const workspaceUserOptions = useMemo(() => {
210210
const activeMemberUserIds = new Set(activeMembers.map((member) => member.userId))
@@ -246,15 +246,12 @@ export function IntegrationsManager() {
246246
)
247247
}, [credentials, createDisplayName])
248248

249-
const isDescriptionDirty = useMemo(() => {
250-
if (!selectedCredential) return false
251-
return selectedDescriptionDraft !== (selectedCredential.description || '')
252-
}, [selectedCredential, selectedDescriptionDraft])
253-
254-
const isDisplayNameDirty = useMemo(() => {
255-
if (!selectedCredential) return false
256-
return selectedDisplayNameDraft !== selectedCredential.displayName
257-
}, [selectedCredential, selectedDisplayNameDraft])
249+
const isDescriptionDirty = selectedCredential
250+
? selectedDescriptionDraft !== (selectedCredential.description || '')
251+
: false
252+
const isDisplayNameDirty = selectedCredential
253+
? selectedDisplayNameDraft !== selectedCredential.displayName
254+
: false
258255

259256
const isDetailsDirty = isDescriptionDirty || isDisplayNameDirty
260257

@@ -1310,7 +1307,10 @@ export function IntegrationsManager() {
13101307
{activeMembers.map((member) => (
13111308
<div
13121309
key={member.id}
1313-
className='grid grid-cols-[1fr_120px_72px] items-center gap-2'
1310+
className={cn(
1311+
'grid items-center gap-2',
1312+
isSelectedAdmin ? 'grid-cols-[1fr_120px_72px]' : 'grid-cols-[1fr_200px]'
1313+
)}
13141314
>
13151315
<div className='flex min-w-0 items-center gap-2.5'>
13161316
<Avatar className='h-8 w-8 flex-shrink-0'>
@@ -1324,7 +1324,7 @@ export function IntegrationsManager() {
13241324
</AvatarFallback>
13251325
</Avatar>
13261326
<div className='min-w-0'>
1327-
<p className='truncate font-medium text-[var(--text-primary)] text-sm'>
1327+
<p className='truncate font-medium text-[var(--text-primary)] text-small'>
13281328
{member.userName || member.userEmail || member.userId}
13291329
</p>
13301330
<p className='truncate text-[var(--text-tertiary)] text-caption'>
@@ -1336,7 +1336,7 @@ export function IntegrationsManager() {
13361336
<Combobox
13371337
options={roleComboOptions}
13381338
value={
1339-
roleOptions.find((option) => option.value === member.role)?.label || ''
1339+
ROLE_OPTIONS.find((option) => option.value === member.role)?.label || ''
13401340
}
13411341
selectedValue={member.role}
13421342
onChange={(value) =>
@@ -1348,7 +1348,7 @@ export function IntegrationsManager() {
13481348
}
13491349
size='sm'
13501350
/>
1351-
{isSelectedAdmin ? (
1351+
{isSelectedAdmin && (
13521352
<Button
13531353
variant='ghost'
13541354
onClick={() => handleRemoveMember(member.userId)}
@@ -1357,8 +1357,6 @@ export function IntegrationsManager() {
13571357
>
13581358
Remove
13591359
</Button>
1360-
) : (
1361-
<div />
13621360
)}
13631361
</div>
13641362
))}
@@ -1380,7 +1378,7 @@ export function IntegrationsManager() {
13801378
<Combobox
13811379
options={roleComboOptions}
13821380
value={
1383-
roleOptions.find((option) => option.value === memberRole)?.label || ''
1381+
ROLE_OPTIONS.find((option) => option.value === memberRole)?.label || ''
13841382
}
13851383
selectedValue={memberRole}
13861384
onChange={(value) => setMemberRole(value as WorkspaceCredentialRole)}
@@ -1520,9 +1518,6 @@ export function IntegrationsManager() {
15201518
</div>
15211519
</div>
15221520
<div className='flex flex-shrink-0 items-center gap-1'>
1523-
<Button variant='default' onClick={() => handleSelectCredential(credential)}>
1524-
Details
1525-
</Button>
15261521
{credential.role === 'admin' && (
15271522
<Button
15281523
variant='ghost'
@@ -1536,6 +1531,9 @@ export function IntegrationsManager() {
15361531
Disconnect
15371532
</Button>
15381533
)}
1534+
<Button variant='default' onClick={() => handleSelectCredential(credential)}>
1535+
Details
1536+
</Button>
15391537
</div>
15401538
</div>
15411539
)
@@ -1549,7 +1547,10 @@ export function IntegrationsManager() {
15491547

15501548
{filteredAvailableIntegrations.length > 0 && (
15511549
<div
1552-
className={`flex flex-col gap-2${hasCredentials || showNoResults ? ' mt-2 border-[var(--border)] border-t pt-4' : ''}`}
1550+
className={cn(
1551+
'flex flex-col gap-2',
1552+
(hasCredentials || showNoResults) && 'mt-2 border-[var(--border)] border-t pt-4'
1553+
)}
15531554
>
15541555
<p className='mb-1 font-medium text-[12px] text-[var(--text-muted)]'>
15551556
Available integrations

apps/sim/app/workspace/[workspaceId]/settings/components/integrations/integrations-skeleton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Skeleton } from '@/components/emcn'
2-
import { CredentialSkeleton } from '@/app/workspace/[workspaceId]/settings/components/credentials/credential-skeleton'
2+
import { CredentialSkeleton } from '@/app/workspace/[workspaceId]/settings/components/integrations/credential-skeleton'
33

44
/**
55
* Skeleton for the Integrations section shown during dynamic import loading.

apps/sim/app/workspace/[workspaceId]/settings/components/credentials/credentials-manager.tsx renamed to apps/sim/app/workspace/[workspaceId]/settings/components/secrets/secrets-manager.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ function NewWorkspaceVariableRow({
355355
)
356356
}
357357

358-
export function CredentialsManager() {
358+
export function SecretsManager() {
359359
const params = useParams()
360360
const router = useRouter()
361361
const workspaceId = (params?.workspaceId as string) || ''
@@ -474,10 +474,7 @@ export function CredentialsManager() {
474474
[members]
475475
)
476476

477-
const adminMemberCount = useMemo(
478-
() => activeMembers.filter((member) => member.role === 'admin').length,
479-
[activeMembers]
480-
)
477+
const adminMemberCount = activeMembers.filter((member) => member.role === 'admin').length
481478

482479
const isSelectedAdmin = selectedCredential?.role === 'admin'
483480

@@ -1232,7 +1229,7 @@ export function CredentialsManager() {
12321229
aria-label='Copy value'
12331230
>
12341231
{copyIdSuccess ? (
1235-
<Check className='h-3 w-3 text-[var(--success)]' />
1232+
<Check className='h-3 w-3 text-[var(--text-success)]' />
12361233
) : (
12371234
<Clipboard className='h-3 w-3 text-[var(--text-icon)]' />
12381235
)}
@@ -1287,7 +1284,10 @@ export function CredentialsManager() {
12871284
{activeMembers.map((member) => (
12881285
<div
12891286
key={member.id}
1290-
className='grid grid-cols-[1fr_120px_72px] items-center gap-2'
1287+
className={cn(
1288+
'grid items-center gap-2',
1289+
isSelectedAdmin ? 'grid-cols-[1fr_120px_72px]' : 'grid-cols-[1fr_200px]'
1290+
)}
12911291
>
12921292
<div className='flex min-w-0 items-center gap-2.5'>
12931293
<Avatar className='h-8 w-8 flex-shrink-0'>
@@ -1342,10 +1342,20 @@ export function CredentialsManager() {
13421342
</Button>
13431343
</>
13441344
) : (
1345-
<>
1346-
<Badge variant='gray-secondary'>{member.role}</Badge>
1347-
<div />
1348-
</>
1345+
<Combobox
1346+
options={ROLE_OPTIONS.map((option) => ({
1347+
value: option.value,
1348+
label: option.label,
1349+
}))}
1350+
value={
1351+
ROLE_OPTIONS.find((option) => option.value === member.role)?.label ||
1352+
''
1353+
}
1354+
selectedValue={member.role}
1355+
placeholder='Role'
1356+
disabled
1357+
size='sm'
1358+
/>
13491359
)}
13501360
</div>
13511361
))}

apps/sim/app/workspace/[workspaceId]/settings/components/credentials/credential-skeleton.tsx renamed to apps/sim/app/workspace/[workspaceId]/settings/components/secrets/secrets-skeleton.tsx

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,9 @@ const GRID_COLS = 'grid grid-cols-[minmax(0,1fr)_8px_minmax(0,1fr)_auto_auto] it
44
const COL_SPAN_ALL = 'col-span-5'
55

66
/**
7-
* Skeleton for a single integration credential row.
7+
* Skeleton for a single secret row matching the secrets grid layout.
88
*/
9-
export function CredentialSkeleton() {
10-
return (
11-
<div className='flex items-center justify-between gap-3'>
12-
<div className='flex min-w-0 items-center gap-2.5'>
13-
<Skeleton className='h-8 w-8 flex-shrink-0 rounded-md' />
14-
<div className='flex min-w-0 flex-col justify-center gap-[1px]'>
15-
<Skeleton className='h-4 w-[120px] rounded' />
16-
<Skeleton className='h-3.5 w-[160px] rounded' />
17-
</div>
18-
</div>
19-
<div className='flex flex-shrink-0 items-center gap-1'>
20-
<Skeleton className='h-9 w-[60px] rounded-md' />
21-
<Skeleton className='h-9 w-[88px] rounded-md' />
22-
</div>
23-
</div>
24-
)
25-
}
26-
27-
/**
28-
* Skeleton for a single secret row matching the credentials grid layout.
29-
*/
30-
function CredentialRowSkeleton() {
9+
function SecretRowSkeleton() {
3110
return (
3211
<div className='contents'>
3312
<Skeleton className='h-9 rounded-md' />
@@ -40,9 +19,9 @@ function CredentialRowSkeleton() {
4019
}
4120

4221
/**
43-
* Skeleton for the Credentials (Secrets) page shown during dynamic import loading.
22+
* Skeleton for the Secrets page shown during dynamic import loading.
4423
*/
45-
export function CredentialsSkeleton() {
24+
export function SecretsSkeleton() {
4625
return (
4726
<div className='flex h-full flex-col gap-4'>
4827
<div className='flex items-center gap-2'>
@@ -54,14 +33,14 @@ export function CredentialsSkeleton() {
5433
<div className='flex flex-col gap-4'>
5534
<div className={`${GRID_COLS} gap-y-2`}>
5635
<Skeleton className={`${COL_SPAN_ALL} h-5 w-[70px]`} />
57-
<CredentialRowSkeleton />
58-
<CredentialRowSkeleton />
36+
<SecretRowSkeleton />
37+
<SecretRowSkeleton />
5938

6039
<div className={`${COL_SPAN_ALL} h-[8px]`} />
6140

6241
<Skeleton className={`${COL_SPAN_ALL} h-5 w-[55px]`} />
63-
<CredentialRowSkeleton />
64-
<CredentialRowSkeleton />
42+
<SecretRowSkeleton />
43+
<SecretRowSkeleton />
6544
</div>
6645
</div>
6746
</div>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { SecretsManager } from '@/app/workspace/[workspaceId]/settings/components/secrets/secrets-manager'
2+
3+
export function Secrets() {
4+
return (
5+
<div className='h-full min-h-0'>
6+
<SecretsManager />
7+
</div>
8+
)
9+
}

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-sidebar/settings-sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ export function SettingsSidebar({
214214
break
215215
case 'secrets':
216216
prefetchWorkspaceCredentials(queryClient, workspaceId)
217-
void import('@/app/workspace/[workspaceId]/settings/components/credentials/credentials')
217+
void import('@/app/workspace/[workspaceId]/settings/components/secrets/secrets')
218218
break
219219
case 'subscription':
220220
prefetchSubscriptionData(queryClient)

0 commit comments

Comments
 (0)