Skip to content

Commit 0c0c6bf

Browse files
waleedlatif1Sg312
authored andcommitted
fix(workflows): fixed workflow loading in without start block, added templates RQ hook, cleaned up unused templates code (#2035)
1 parent 86b383b commit 0c0c6bf

File tree

14 files changed

+525
-1257
lines changed

14 files changed

+525
-1257
lines changed

apps/sim/app/(landing)/components/nav/nav.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ interface NavProps {
2020
}
2121

2222
export default function Nav({ hideAuthButtons = false, variant = 'landing' }: NavProps = {}) {
23-
const [githubStars, setGithubStars] = useState('18k')
23+
const [githubStars, setGithubStars] = useState('18.5k')
2424
const [isHovered, setIsHovered] = useState(false)
2525
const [isLoginHovered, setIsLoginHovered] = useState(false)
2626
const router = useRouter()

apps/sim/app/templates/[id]/template.tsx

Lines changed: 13 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ import { createLogger } from '@/lib/logs/console/logger'
3434
import { getBaseUrl } from '@/lib/urls/utils'
3535
import { cn } from '@/lib/utils'
3636
import type { CredentialRequirement } from '@/lib/workflows/credential-extractor'
37-
import type { Template } from '@/app/templates/templates'
3837
import { WorkflowPreview } from '@/app/workspace/[workspaceId]/w/components/workflow-preview/workflow-preview'
3938
import { getBlock } from '@/blocks/registry'
39+
import { useStarTemplate, useTemplate } from '@/hooks/queries/templates'
4040

4141
const logger = createLogger('TemplateDetails')
4242

@@ -52,16 +52,14 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
5252
const workspaceId = isWorkspaceContext ? (params?.workspaceId as string) : null
5353
const { data: session } = useSession()
5454

55-
const [template, setTemplate] = useState<Template | null>(null)
55+
const { data: template, isLoading: loading } = useTemplate(templateId)
56+
const starTemplate = useStarTemplate()
57+
5658
const [currentUserOrgs, setCurrentUserOrgs] = useState<string[]>([])
5759
const [currentUserOrgRoles, setCurrentUserOrgRoles] = useState<
5860
Array<{ organizationId: string; role: string }>
5961
>([])
6062
const [isSuperUser, setIsSuperUser] = useState(false)
61-
const [loading, setLoading] = useState(true)
62-
const [isStarred, setIsStarred] = useState(false)
63-
const [starCount, setStarCount] = useState(0)
64-
const [isStarring, setIsStarring] = useState(false)
6563
const [isUsing, setIsUsing] = useState(false)
6664
const [isEditing, setIsEditing] = useState(false)
6765
const [isApproving, setIsApproving] = useState(false)
@@ -76,29 +74,7 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
7674

7775
const currentUserId = session?.user?.id || null
7876

79-
// Fetch template data on client side
8077
useEffect(() => {
81-
if (!templateId) {
82-
setLoading(false)
83-
return
84-
}
85-
86-
const fetchTemplate = async () => {
87-
try {
88-
const response = await fetch(`/api/templates/${templateId}`)
89-
if (response.ok) {
90-
const data = await response.json()
91-
setTemplate(data.data)
92-
setIsStarred(data.data.isStarred || false)
93-
setStarCount(data.data.stars || 0)
94-
}
95-
} catch (error) {
96-
logger.error('Error fetching template:', error)
97-
} finally {
98-
setLoading(false)
99-
}
100-
}
101-
10278
const fetchUserOrganizations = async () => {
10379
if (!currentUserId) return
10480

@@ -134,12 +110,10 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
134110
}
135111
}
136112

137-
fetchTemplate()
138113
fetchSuperUserStatus()
139114
fetchUserOrganizations()
140-
}, [templateId, currentUserId])
115+
}, [currentUserId])
141116

142-
// Fetch workspaces when user is logged in
143117
useEffect(() => {
144118
if (!currentUserId) return
145119

@@ -149,7 +123,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
149123
const response = await fetch('/api/workspaces')
150124
if (response.ok) {
151125
const data = await response.json()
152-
// Filter workspaces where user has write/admin permissions
153126
const availableWorkspaces = data.workspaces
154127
.filter((ws: any) => ws.permissions === 'write' || ws.permissions === 'admin')
155128
.map((ws: any) => ({
@@ -169,7 +142,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
169142
fetchWorkspaces()
170143
}, [currentUserId])
171144

172-
// Clean up URL when returning from login
173145
useEffect(() => {
174146
if (template && searchParams?.get('use') === 'true' && currentUserId) {
175147
if (isWorkspaceContext && workspaceId) {
@@ -181,26 +153,20 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
181153
}
182154
}, [searchParams, currentUserId, template, isWorkspaceContext, workspaceId, router])
183155

184-
// Check if user can edit template
185156
const canEditTemplate = (() => {
186157
if (!currentUserId || !template?.creator) return false
187158

188-
// For user creator profiles: must be the user themselves
189159
if (template.creator.referenceType === 'user') {
190160
return template.creator.referenceId === currentUserId
191161
}
192162

193-
// For organization creator profiles:
194163
if (template.creator.referenceType === 'organization' && template.creator.referenceId) {
195164
const isOrgMember = currentUserOrgs.includes(template.creator.referenceId)
196165

197-
// If template has a connected workflow, any org member with workspace access can edit
198166
if (template.workflowId) {
199167
return isOrgMember
200168
}
201169

202-
// If template is orphaned, only admin/owner can edit
203-
// We need to check the user's role in the organization
204170
const orgMembership = currentUserOrgRoles.find(
205171
(org) => org.organizationId === template.creator?.referenceId
206172
)
@@ -212,7 +178,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
212178
return false
213179
})()
214180

215-
// Check workspace access for connected workflow
216181
useEffect(() => {
217182
const checkWorkspaceAccess = async () => {
218183
if (!template?.workflowId || !currentUserId || !canEditTemplate) {
@@ -227,7 +192,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
227192
} else if (checkResponse.ok) {
228193
setHasWorkspaceAccess(true)
229194
} else {
230-
// Workflow doesn't exist
231195
setHasWorkspaceAccess(null)
232196
}
233197
} catch (error) {
@@ -319,32 +283,20 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
319283
* @param event - The wheel event fired when the user scrolls over the preview area.
320284
*/
321285
const handleCanvasWheelCapture = (event: React.WheelEvent<HTMLDivElement>) => {
322-
// Allow pinch/zoom gestures (e.g., ctrl/cmd + wheel) to continue to the canvas.
323286
if (event.ctrlKey || event.metaKey) {
324287
return
325288
}
326289

327-
// Prevent React Flow from handling the wheel; let the page scroll naturally.
328290
event.stopPropagation()
329291
}
330292

331293
const handleStarToggle = async () => {
332-
if (isStarring || !currentUserId) return
333-
334-
setIsStarring(true)
335-
try {
336-
const method = isStarred ? 'DELETE' : 'POST'
337-
const response = await fetch(`/api/templates/${template.id}/star`, { method })
294+
if (!currentUserId || !template) return
338295

339-
if (response.ok) {
340-
setIsStarred(!isStarred)
341-
setStarCount((prev) => (isStarred ? prev - 1 : prev + 1))
342-
}
343-
} catch (error) {
344-
logger.error('Error toggling star:', error)
345-
} finally {
346-
setIsStarring(false)
347-
}
296+
starTemplate.mutate({
297+
templateId: template.id,
298+
action: template.isStarred ? 'remove' : 'add',
299+
})
348300
}
349301

350302
const handleUseTemplate = () => {
@@ -357,7 +309,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
357309
return
358310
}
359311

360-
// In workspace context, use current workspace directly
361312
if (isWorkspaceContext && workspaceId) {
362313
handleWorkspaceSelectForUse(workspaceId)
363314
}
@@ -366,7 +317,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
366317
const handleEditTemplate = async () => {
367318
if (!currentUserId || !template) return
368319

369-
// In workspace context with existing workflow, navigate directly
370320
if (isWorkspaceContext && workspaceId && template.workflowId) {
371321
setIsEditing(true)
372322
try {
@@ -381,10 +331,8 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
381331
} finally {
382332
setIsEditing(false)
383333
}
384-
// If workflow doesn't exist, fall through to workspace selector
385334
}
386335

387-
// Check if workflow exists and user has access (global context)
388336
if (template.workflowId && !isWorkspaceContext) {
389337
setIsEditing(true)
390338
try {
@@ -410,7 +358,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
410358
}
411359
}
412360

413-
// Workflow doesn't exist - show workspace selector or use current workspace
414361
if (isWorkspaceContext && workspaceId) {
415362
handleWorkspaceSelectForEdit(workspaceId)
416363
} else {
@@ -435,7 +382,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
435382

436383
const { workflowId } = await response.json()
437384

438-
// Navigate to the new workflow with full page load
439385
window.location.href = `/workspace/${workspaceId}/w/${workflowId}`
440386
} catch (error) {
441387
logger.error('Error using template:', error)
@@ -450,7 +396,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
450396
setIsUsing(true)
451397
setShowWorkspaceSelectorForEdit(false)
452398
try {
453-
// Import template as a new workflow and connect it to the template
454399
const response = await fetch(`/api/templates/${template.id}/use`, {
455400
method: 'POST',
456401
headers: { 'Content-Type': 'application/json' },
@@ -463,7 +408,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
463408

464409
const { workflowId } = await response.json()
465410

466-
// Navigate to the new workflow with full page load
467411
window.location.href = `/workspace/${workspaceId}/w/${workflowId}`
468412
} catch (error) {
469413
logger.error('Error importing template for editing:', error)
@@ -482,9 +426,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
482426
})
483427

484428
if (response.ok) {
485-
// Update template status optimistically
486-
setTemplate({ ...template, status: 'approved' })
487-
// Redirect back to templates page after approval
488429
if (isWorkspaceContext && workspaceId) {
489430
router.push(`/workspace/${workspaceId}/templates`)
490431
} else {
@@ -508,9 +449,6 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
508449
})
509450

510451
if (response.ok) {
511-
// Update template status optimistically
512-
setTemplate({ ...template, status: 'rejected' })
513-
// Redirect back to templates page after rejection
514452
if (isWorkspaceContext && workspaceId) {
515453
router.push(`/workspace/${workspaceId}/templates`)
516454
} else {
@@ -752,11 +690,11 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template
752690
onClick={handleStarToggle}
753691
className={cn(
754692
'h-[14px] w-[14px] cursor-pointer transition-colors',
755-
isStarred ? 'fill-yellow-500 text-yellow-500' : 'text-[#888888]',
756-
isStarring && 'opacity-50'
693+
template.isStarred ? 'fill-yellow-500 text-yellow-500' : 'text-[#888888]',
694+
starTemplate.isPending && 'opacity-50'
757695
)}
758696
/>
759-
<span className='font-medium text-[#888888] text-[14px]'>{starCount}</span>
697+
<span className='font-medium text-[#888888] text-[14px]'>{template.stars || 0}</span>
760698

761699
{/* Users icon and count */}
762700
<ChartNoAxesColumn className='h-[16px] w-[16px] text-[#888888]' />

0 commit comments

Comments
 (0)