Skip to content

Commit a217dac

Browse files
authored
fix(envvars): use getEnv on the client-side when we need to inject vars for docker runtime, fix folder container & removed folder/subfolder creation modals (#751)
* use getEnv on the client-side when we need to inject vars for docker runtime, fix folder container & removed folder/subfolder creation modals * consolidated naming utils * additional type safety
1 parent d8a7aaa commit a217dac

File tree

22 files changed

+382
-338
lines changed

22 files changed

+382
-338
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/deploy-modal.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { Button } from '@/components/ui/button'
1717
import { Card, CardContent } from '@/components/ui/card'
1818
import { CopyButton } from '@/components/ui/copy-button'
1919
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
20-
import { env } from '@/lib/env'
20+
import { getEnv } from '@/lib/env'
2121
import { createLogger } from '@/lib/logs/console-logger'
2222
import { cn } from '@/lib/utils'
2323
import { ChatDeploy } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/deploy-modal/components/chat-deploy/chat-deploy'
@@ -225,7 +225,7 @@ export function DeployModal({
225225
}
226226

227227
const data = await response.json()
228-
const endpoint = `${env.NEXT_PUBLIC_APP_URL}/api/workflows/${workflowId}/execute`
228+
const endpoint = `${getEnv('NEXT_PUBLIC_APP_URL')}/api/workflows/${workflowId}/execute`
229229
const inputFormatExample = getInputFormatExample()
230230

231231
setDeploymentInfo({
@@ -288,7 +288,7 @@ export function DeployModal({
288288
}
289289

290290
// Update the local deployment info
291-
const endpoint = `${env.NEXT_PUBLIC_APP_URL}/api/workflows/${workflowId}/execute`
291+
const endpoint = `${getEnv('NEXT_PUBLIC_APP_URL')}/api/workflows/${workflowId}/execute`
292292
const inputFormatExample = getInputFormatExample()
293293

294294
const newDeploymentInfo = {
@@ -597,7 +597,7 @@ export function DeployModal({
597597
<DeployForm
598598
apiKeys={apiKeys}
599599
keysLoaded={keysLoaded}
600-
endpointUrl={`${env.NEXT_PUBLIC_APP_URL}/api/workflows/${workflowId}/execute`}
600+
endpointUrl={`${getEnv('NEXT_PUBLIC_APP_URL')}/api/workflows/${workflowId}/execute`}
601601
workflowId={workflowId || ''}
602602
onSubmit={onDeploy}
603603
getInputFormatExample={getInputFormatExample}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/components/google-drive-picker.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
CommandList,
1414
} from '@/components/ui/command'
1515
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
16-
import { env } from '@/lib/env'
16+
import { getEnv } from '@/lib/env'
1717
import { createLogger } from '@/lib/logs/console-logger'
1818
import {
1919
type Credential,
@@ -301,7 +301,7 @@ export function GoogleDrivePicker({
301301
showUploadFolders: true,
302302
supportDrives: true,
303303
multiselect: false,
304-
appId: env.NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER,
304+
appId: getEnv('NEXT_PUBLIC_GOOGLE_PROJECT_NUMBER'),
305305
// Enable folder selection when mimeType is folder
306306
setSelectFolderEnabled: !!mimeTypeFilter?.includes('folder'),
307307
callbackFunction: (data) => {

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/file-selector/file-selector-input.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useEffect, useState } from 'react'
44
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
5-
import { env } from '@/lib/env'
5+
import { getEnv } from '@/lib/env'
66
import type { SubBlockConfig } from '@/blocks/types'
77
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
88
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
@@ -169,8 +169,8 @@ export function FileSelectorInput({
169169
}
170170

171171
// For Google Drive
172-
const clientId = env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || ''
173-
const apiKey = env.NEXT_PUBLIC_GOOGLE_API_KEY || ''
172+
const clientId = getEnv('NEXT_PUBLIC_GOOGLE_CLIENT_ID') || ''
173+
const apiKey = getEnv('NEXT_PUBLIC_GOOGLE_API_KEY') || ''
174174

175175
// Render Google Calendar selector
176176
if (isGoogleCalendar) {

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

Lines changed: 37 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ import { logger } from '@sentry/nextjs'
55
import { File, Folder, Plus, Upload } from 'lucide-react'
66
import { useParams, useRouter } from 'next/navigation'
77
import { Button } from '@/components/ui/button'
8-
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
9-
import { Input } from '@/components/ui/input'
10-
import { Label } from '@/components/ui/label'
118
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
9+
import { generateFolderName } from '@/lib/naming'
1210
import { cn } from '@/lib/utils'
1311
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider'
1412
import { useFolderStore } from '@/stores/folders/store'
@@ -25,8 +23,6 @@ export function CreateMenu({
2523
isCollapsed,
2624
isCreatingWorkflow = false,
2725
}: CreateMenuProps) {
28-
const [showFolderDialog, setShowFolderDialog] = useState(false)
29-
const [folderName, setFolderName] = useState('')
3026
const [isCreating, setIsCreating] = useState(false)
3127
const [isOpen, setIsOpen] = useState(false)
3228
const [pressTimer, setPressTimer] = useState<NodeJS.Timeout | null>(null)
@@ -61,10 +57,37 @@ export function CreateMenu({
6157
}
6258
}, [onCreateWorkflow, isCreatingWorkflow, router, workspaceId])
6359

64-
const handleCreateFolder = useCallback(() => {
60+
const handleCreateFolder = useCallback(async () => {
6561
setIsOpen(false)
66-
setShowFolderDialog(true)
67-
}, [])
62+
63+
if (isCreating) {
64+
logger.info('Folder creation already in progress, ignoring request')
65+
return
66+
}
67+
68+
if (!workspaceId) {
69+
logger.error('No workspaceId available for folder creation')
70+
return
71+
}
72+
73+
try {
74+
setIsCreating(true)
75+
76+
// Generate folder name using fresh data from API
77+
const folderName = await generateFolderName(workspaceId)
78+
79+
await createFolder({
80+
name: folderName,
81+
workspaceId: workspaceId,
82+
})
83+
84+
logger.info(`Created folder: ${folderName}`)
85+
} catch (error) {
86+
logger.error('Failed to create folder:', { error })
87+
} finally {
88+
setIsCreating(false)
89+
}
90+
}, [createFolder, workspaceId])
6891

6992
const handleImportWorkflow = useCallback(() => {
7093
setIsOpen(false)
@@ -146,30 +169,6 @@ export function CreateMenu({
146169
}
147170
}, [pressTimer])
148171

149-
const handleFolderSubmit = async (e: React.FormEvent) => {
150-
e.preventDefault()
151-
if (!folderName.trim() || !workspaceId) return
152-
153-
setIsCreating(true)
154-
try {
155-
await createFolder({
156-
name: folderName.trim(),
157-
workspaceId: workspaceId,
158-
})
159-
setFolderName('')
160-
setShowFolderDialog(false)
161-
} catch (error) {
162-
logger.error('Failed to create folder:', { error })
163-
} finally {
164-
setIsCreating(false)
165-
}
166-
}
167-
168-
const handleCancel = () => {
169-
setFolderName('')
170-
setShowFolderDialog(false)
171-
}
172-
173172
return (
174173
<>
175174
<Popover open={isOpen} onOpenChange={setIsOpen}>
@@ -221,11 +220,15 @@ export function CreateMenu({
221220
</button>
222221

223222
<button
224-
className='flex w-full cursor-pointer items-center gap-2 rounded-md px-3 py-2 font-[380] text-card-foreground text-sm outline-none hover:bg-secondary/50 focus:bg-secondary/50'
223+
className={cn(
224+
'flex w-full cursor-pointer items-center gap-2 rounded-md px-3 py-2 font-[380] text-card-foreground text-sm outline-none hover:bg-secondary/50 focus:bg-secondary/50',
225+
isCreating && 'cursor-not-allowed opacity-50'
226+
)}
225227
onClick={handleCreateFolder}
228+
disabled={isCreating}
226229
>
227230
<Folder className='h-4 w-4' />
228-
New folder
231+
{isCreating ? 'Creating...' : 'New folder'}
229232
</button>
230233

231234
{userPermissions.canEdit && (
@@ -246,36 +249,6 @@ export function CreateMenu({
246249
disabled={!userPermissions.canEdit}
247250
onClose={() => setIsOpen(false)}
248251
/>
249-
250-
{/* Folder creation dialog */}
251-
<Dialog open={showFolderDialog} onOpenChange={setShowFolderDialog}>
252-
<DialogContent className='sm:max-w-[425px]'>
253-
<DialogHeader>
254-
<DialogTitle>Create New Folder</DialogTitle>
255-
</DialogHeader>
256-
<form onSubmit={handleFolderSubmit} className='space-y-4'>
257-
<div className='space-y-2'>
258-
<Label htmlFor='folder-name'>Folder Name</Label>
259-
<Input
260-
id='folder-name'
261-
value={folderName}
262-
onChange={(e) => setFolderName(e.target.value)}
263-
placeholder='Enter folder name...'
264-
autoFocus
265-
required
266-
/>
267-
</div>
268-
<div className='flex justify-end space-x-2'>
269-
<Button type='button' variant='outline' onClick={handleCancel}>
270-
Cancel
271-
</Button>
272-
<Button type='submit' disabled={!folderName.trim() || isCreating}>
273-
{isCreating ? 'Creating...' : 'Create Folder'}
274-
</Button>
275-
</div>
276-
</form>
277-
</DialogContent>
278-
</Dialog>
279252
</>
280253
)
281254
}

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-context-menu/folder-context-menu.tsx

Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,15 @@ import { useState } from 'react'
44
import { File, Folder, MoreHorizontal, Pencil, Trash2 } from 'lucide-react'
55
import { useParams } from 'next/navigation'
66
import { Button } from '@/components/ui/button'
7-
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
87
import {
98
DropdownMenu,
109
DropdownMenuContent,
1110
DropdownMenuItem,
1211
DropdownMenuTrigger,
1312
} from '@/components/ui/dropdown-menu'
14-
import { Input } from '@/components/ui/input'
15-
import { Label } from '@/components/ui/label'
1613
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
1714
import { createLogger } from '@/lib/logs/console-logger'
15+
import { generateSubfolderName } from '@/lib/naming'
1816
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/w/components/providers/workspace-permissions-provider'
1917
import { useFolderStore } from '@/stores/folders/store'
2018

@@ -37,23 +35,53 @@ export function FolderContextMenu({
3735
onStartEdit,
3836
level,
3937
}: FolderContextMenuProps) {
40-
const [showSubfolderDialog, setShowSubfolderDialog] = useState(false)
41-
const [subfolderName, setSubfolderName] = useState('')
4238
const [isCreating, setIsCreating] = useState(false)
4339
const params = useParams()
4440
const workspaceId = params.workspaceId as string
4541

4642
// Get user permissions for the workspace
4743
const userPermissions = useUserPermissionsContext()
4844

49-
const { createFolder, deleteFolder } = useFolderStore()
45+
const { createFolder, deleteFolder, setExpanded } = useFolderStore()
5046

5147
const handleCreateWorkflow = () => {
48+
// Ensure folder is expanded so user can see the new workflow
49+
setExpanded(folderId, true)
5250
onCreateWorkflow(folderId)
5351
}
5452

55-
const handleCreateSubfolder = () => {
56-
setShowSubfolderDialog(true)
53+
const handleCreateSubfolder = async () => {
54+
if (isCreating) {
55+
logger.info('Subfolder creation already in progress, ignoring request')
56+
return
57+
}
58+
59+
if (!workspaceId) {
60+
logger.error('No workspaceId available for subfolder creation')
61+
return
62+
}
63+
64+
try {
65+
setIsCreating(true)
66+
67+
// Ensure parent folder is expanded so user can see the new subfolder
68+
setExpanded(folderId, true)
69+
70+
// Generate subfolder name using fresh data from API
71+
const subfolderName = await generateSubfolderName(workspaceId, folderId)
72+
73+
await createFolder({
74+
name: subfolderName,
75+
workspaceId: workspaceId,
76+
parentId: folderId,
77+
})
78+
79+
logger.info(`Created subfolder: ${subfolderName}`)
80+
} catch (error) {
81+
logger.error('Failed to create subfolder:', { error })
82+
} finally {
83+
setIsCreating(false)
84+
}
5785
}
5886

5987
const handleRename = () => {
@@ -76,31 +104,6 @@ export function FolderContextMenu({
76104
}
77105
}
78106

79-
const handleSubfolderSubmit = async (e: React.FormEvent) => {
80-
e.preventDefault()
81-
if (!subfolderName.trim() || !workspaceId) return
82-
83-
setIsCreating(true)
84-
try {
85-
await createFolder({
86-
name: subfolderName.trim(),
87-
workspaceId: workspaceId,
88-
parentId: folderId,
89-
})
90-
setSubfolderName('')
91-
setShowSubfolderDialog(false)
92-
} catch (error) {
93-
logger.error('Failed to create subfolder:', { error })
94-
} finally {
95-
setIsCreating(false)
96-
}
97-
}
98-
99-
const handleCancel = () => {
100-
setSubfolderName('')
101-
setShowSubfolderDialog(false)
102-
}
103-
104107
return (
105108
<>
106109
<DropdownMenu>
@@ -175,37 +178,6 @@ export function FolderContextMenu({
175178
)}
176179
</DropdownMenuContent>
177180
</DropdownMenu>
178-
179-
{/* Subfolder creation dialog */}
180-
<Dialog open={showSubfolderDialog} onOpenChange={setShowSubfolderDialog}>
181-
<DialogContent className='sm:max-w-[425px]' onClick={(e) => e.stopPropagation()}>
182-
<DialogHeader>
183-
<DialogTitle>Create New Subfolder</DialogTitle>
184-
</DialogHeader>
185-
<form onSubmit={handleSubfolderSubmit} className='space-y-4'>
186-
<div className='space-y-2'>
187-
<Label htmlFor='subfolder-name'>Folder Name</Label>
188-
<Input
189-
id='subfolder-name'
190-
value={subfolderName}
191-
onChange={(e) => setSubfolderName(e.target.value)}
192-
placeholder='Enter folder name...'
193-
maxLength={50}
194-
autoFocus
195-
required
196-
/>
197-
</div>
198-
<div className='flex justify-end space-x-2'>
199-
<Button type='button' variant='outline' onClick={handleCancel}>
200-
Cancel
201-
</Button>
202-
<Button type='submit' disabled={!subfolderName.trim() || isCreating}>
203-
{isCreating ? 'Creating...' : 'Create Folder'}
204-
</Button>
205-
</div>
206-
</form>
207-
</DialogContent>
208-
</Dialog>
209181
</>
210182
)
211183
}

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/folder-tree/components/folder-item.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ export function FolderItem({
304304
onChange={(e) => setEditValue(e.target.value)}
305305
onKeyDown={handleKeyDown}
306306
onBlur={handleInputBlur}
307-
className='flex-1 border-0 bg-transparent p-0 text-muted-foreground text-sm outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0'
307+
className='min-w-0 flex-1 border-0 bg-transparent p-0 text-muted-foreground text-sm outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0'
308308
maxLength={50}
309309
disabled={isRenaming}
310310
onClick={(e) => e.stopPropagation()} // Prevent folder toggle when clicking input
@@ -314,7 +314,9 @@ export function FolderItem({
314314
spellCheck='false'
315315
/>
316316
) : (
317-
<span className='flex-1 select-none truncate text-muted-foreground'>{folder.name}</span>
317+
<span className='min-w-0 flex-1 select-none truncate text-muted-foreground'>
318+
{folder.name}
319+
</span>
318320
)}
319321

320322
{!isEditing && (

0 commit comments

Comments
 (0)