Skip to content

Commit 33ac828

Browse files
authored
fix(settings): settings components and behavior consolidation (#2100)
* fix(settings): settings components and behavior consolidation * ack PR comments
1 parent 29156e3 commit 33ac828

File tree

17 files changed

+406
-439
lines changed

17 files changed

+406
-439
lines changed

apps/sim/app/api/organizations/[id]/invitations/route.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,40 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
244244
const emailsToInvite = newEmails.filter((email: string) => !pendingEmails.includes(email))
245245

246246
if (emailsToInvite.length === 0) {
247+
const isSingleEmail = processedEmails.length === 1
248+
const existingMembersEmails = processedEmails.filter((email: string) =>
249+
existingEmails.includes(email)
250+
)
251+
const pendingInvitationEmails = processedEmails.filter((email: string) =>
252+
pendingEmails.includes(email)
253+
)
254+
255+
if (isSingleEmail) {
256+
if (existingMembersEmails.length > 0) {
257+
return NextResponse.json(
258+
{
259+
error: 'Failed to send invitation. User is already a part of the organization.',
260+
},
261+
{ status: 400 }
262+
)
263+
}
264+
if (pendingInvitationEmails.length > 0) {
265+
return NextResponse.json(
266+
{
267+
error:
268+
'Failed to send invitation. A pending invitation already exists for this email.',
269+
},
270+
{ status: 400 }
271+
)
272+
}
273+
}
274+
247275
return NextResponse.json(
248276
{
249-
error: 'All emails are already members or have pending invitations',
277+
error: 'All emails are already members or have pending invitations.',
250278
details: {
251-
existingMembers: processedEmails.filter((email: string) =>
252-
existingEmails.includes(email)
253-
),
254-
pendingInvitations: processedEmails.filter((email: string) =>
255-
pendingEmails.includes(email)
256-
),
279+
existingMembers: existingMembersEmails,
280+
pendingInvitations: pendingInvitationEmails,
257281
},
258282
},
259283
{ status: 400 }

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,11 @@ export function Account(_props: AccountProps) {
232232
<div className='flex flex-1 flex-col justify-center'>
233233
<h3 className='font-medium text-base'>{profile?.name || ''}</h3>
234234
<p className='font-normal text-muted-foreground text-sm'>{profile?.email || ''}</p>
235-
{uploadError && <p className='mt-1 text-destructive text-xs'>{uploadError}</p>}
235+
{uploadError && (
236+
<p className='mt-1 text-[#DC2626] text-[11px] leading-tight dark:text-[#F87171]'>
237+
{uploadError}
238+
</p>
239+
)}
236240
</div>
237241
</div>
238242

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/api-keys/api-keys.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,9 @@ export function ApiKeys({ onOpenChange, registerCloseHandler }: ApiKeysProps) {
512512
autoFocus
513513
/>
514514
{createError && (
515-
<div className='text-[#DC2626] text-[12px] leading-tight dark:text-[#F87171]'>
515+
<p className='text-[#DC2626] text-[11px] leading-tight dark:text-[#F87171]'>
516516
{createError}
517-
</div>
517+
</p>
518518
)}
519519
</div>
520520
</div>

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/creator-profile/creator-profile.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,11 @@ export function CreatorProfile() {
291291
/>
292292
</div>
293293
<div className='flex flex-col gap-1'>
294-
{uploadError && <p className='text-destructive text-sm'>{uploadError}</p>}
294+
{uploadError && (
295+
<p className='text-[#DC2626] text-[11px] leading-tight dark:text-[#F87171]'>
296+
{uploadError}
297+
</p>
298+
)}
295299
<p className='text-muted-foreground text-xs'>PNG or JPEG (max 5MB)</p>
296300
</div>
297301
</div>
@@ -411,9 +415,9 @@ export function CreatorProfile() {
411415
{/* Error Message */}
412416
{saveError && (
413417
<div className='px-6 pb-2'>
414-
<div className='text-[#DC2626] text-[12px] leading-tight dark:text-[#F87171]'>
418+
<p className='text-[#DC2626] text-[11px] leading-tight dark:text-[#F87171]'>
415419
{saveError}
416-
</div>
420+
</p>
417421
</div>
418422
)}
419423

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/custom-tools/custom-tools.tsx

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

33
import { useState } from 'react'
4-
import { AlertCircle, Plus, Search } from 'lucide-react'
4+
import { Plus, Search } from 'lucide-react'
55
import { useParams } from 'next/navigation'
66
import {
77
Button,
@@ -13,7 +13,7 @@ import {
1313
ModalHeader,
1414
ModalTitle,
1515
} from '@/components/emcn'
16-
import { Alert, AlertDescription, Input, Skeleton } from '@/components/ui'
16+
import { Input, Skeleton } from '@/components/ui'
1717
import { createLogger } from '@/lib/logs/console/logger'
1818
import { CustomToolModal } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tool-input/components/custom-tool-modal/custom-tool-modal'
1919
import { useCustomTools, useDeleteCustomTool } from '@/hooks/queries/custom-tools'
@@ -84,7 +84,6 @@ export function CustomTools() {
8484
setShowDeleteDialog(false)
8585

8686
try {
87-
// Pass null workspaceId for user-scoped tools (legacy tools without workspaceId)
8887
await deleteToolMutation.mutateAsync({
8988
workspaceId: tool.workspaceId ?? null,
9089
toolId: toolToDelete.id,
@@ -105,24 +104,13 @@ export function CustomTools() {
105104
const handleToolSaved = () => {
106105
setShowAddForm(false)
107106
setEditingTool(null)
108-
// React Query will automatically refetch via cache invalidation
109107
refetchTools()
110108
}
111109

112110
return (
113111
<div className='relative flex h-full flex-col'>
114112
{/* Fixed Header with Search */}
115113
<div className='px-6 pt-4 pb-2'>
116-
{/* Error Alert - only show when modal is not open */}
117-
{error && !showAddForm && !editingTool && (
118-
<Alert variant='destructive' className='mb-4'>
119-
<AlertCircle className='h-4 w-4' />
120-
<AlertDescription>
121-
{error instanceof Error ? error.message : 'An error occurred'}
122-
</AlertDescription>
123-
</Alert>
124-
)}
125-
126114
{/* Search Input */}
127115
{isLoading ? (
128116
<Skeleton className='h-9 w-56 rounded-[8px]' />
@@ -148,6 +136,12 @@ export function CustomTools() {
148136
<CustomToolSkeleton />
149137
<CustomToolSkeleton />
150138
</div>
139+
) : error ? (
140+
<div className='flex h-full flex-col items-center justify-center gap-2'>
141+
<p className='text-[#DC2626] text-[11px] leading-tight dark:text-[#F87171]'>
142+
{error instanceof Error ? error.message : 'Failed to load tools'}
143+
</p>
144+
</div>
151145
) : tools.length === 0 && !showAddForm && !editingTool ? (
152146
<div className='flex h-full items-center justify-center text-muted-foreground text-sm'>
153147
Click "Create Tool" below to get started

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,9 @@ export function Files() {
273273
{/* Error message */}
274274
{uploadError && (
275275
<div className='px-6 pb-2'>
276-
<div className='text-[#DC2626] text-[12px] leading-tight dark:text-[#F87171]'>
276+
<p className='text-[#DC2626] text-[11px] leading-tight dark:text-[#F87171]'>
277277
{uploadError}
278-
</div>
278+
</p>
279279
</div>
280280
)}
281281

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components-new/settings-modal/components/mcp/components/add-server-form.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,9 @@ export function AddServerForm({
253253
<div className='space-y-1.5'>
254254
{/* Error message above buttons */}
255255
{testResult && !testResult.success && (
256-
<div className='text-[#DC2626] text-[12px] leading-tight dark:text-[#F87171]'>
256+
<p className='text-[#DC2626] text-[11px] leading-tight dark:text-[#F87171]'>
257257
{testResult.error || testResult.message}
258-
</div>
258+
</p>
259259
)}
260260

261261
{/* Buttons row */}

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

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
'use client'
22

33
import { useCallback, useRef, useState } from 'react'
4-
import { AlertCircle, Plus, Search } from 'lucide-react'
4+
import { Plus, Search } from 'lucide-react'
55
import { useParams } from 'next/navigation'
66
import { Button } from '@/components/emcn'
7-
import { Alert, AlertDescription, Input, Skeleton } from '@/components/ui'
7+
import { Input, Skeleton } from '@/components/ui'
88
import { createLogger } from '@/lib/logs/console/logger'
99
import { createMcpToolId } from '@/lib/mcp/utils'
1010
import { checkEnvVarTrigger } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/env-var-dropdown'
@@ -24,7 +24,6 @@ export function MCP() {
2424
const params = useParams()
2525
const workspaceId = params.workspaceId as string
2626

27-
// React Query hooks
2827
const {
2928
data: servers = [],
3029
isLoading: serversLoading,
@@ -42,7 +41,7 @@ export function MCP() {
4241
transport: 'streamable-http',
4342
url: '',
4443
timeout: 30000,
45-
headers: {}, // Start with no headers
44+
headers: {},
4645
})
4746

4847
const [showEnvVars, setShowEnvVars] = useState(false)
@@ -207,7 +206,6 @@ export function MCP() {
207206

208207
try {
209208
await deleteServerMutation.mutateAsync({ workspaceId, serverId })
210-
// TanStack Query mutations automatically invalidate and refetch tools
211209

212210
logger.info(`Removed MCP server: ${serverId}`)
213211
} catch (error) {
@@ -264,27 +262,23 @@ export function MCP() {
264262
/>
265263
</div>
266264
)}
267-
268-
{/* Error Alert */}
269-
{(toolsError || serversError) && (
270-
<Alert variant='destructive' className='mt-4'>
271-
<AlertCircle className='h-4 w-4' />
272-
<AlertDescription>
273-
{toolsError instanceof Error
274-
? toolsError.message
275-
: serversError instanceof Error
276-
? serversError.message
277-
: 'An error occurred'}
278-
</AlertDescription>
279-
</Alert>
280-
)}
281265
</div>
282266

283267
{/* Scrollable Content */}
284268
<div className='min-h-0 flex-1 overflow-y-auto px-6'>
285269
<div className='space-y-2 pt-2 pb-6'>
286270
{/* Server List */}
287-
{serversLoading ? (
271+
{toolsError || serversError ? (
272+
<div className='flex h-full flex-col items-center justify-center gap-2'>
273+
<p className='text-[#DC2626] text-[11px] leading-tight dark:text-[#F87171]'>
274+
{toolsError instanceof Error
275+
? toolsError.message
276+
: serversError instanceof Error
277+
? serversError.message
278+
: 'Failed to load MCP servers'}
279+
</p>
280+
</div>
281+
) : serversLoading ? (
288282
<div className='space-y-2'>
289283
<McpServerSkeleton />
290284
<McpServerSkeleton />
@@ -342,7 +336,6 @@ export function MCP() {
342336
) : (
343337
<div className='space-y-2'>
344338
{filteredServers.map((server: any) => {
345-
// Add defensive checks for server properties
346339
if (!server || !server.id) {
347340
return null
348341
}

0 commit comments

Comments
 (0)