11'use client'
22
33import { useState } from 'react'
4- import { useParams , useRouter } from 'next/navigation'
5- import { useQueryClient } from '@tanstack/react-query'
6- import { AlertTriangle , Download , ExternalLink , Loader2 } from 'lucide-react'
74import { createLogger } from '@sim/logger'
8- import { Button } from '@/components/ui/button '
9- import { Input } from '@/components/ui/input '
10- import { Label } from '@/components/ui/label '
5+ import { useQueryClient } from '@tanstack/react-query '
6+ import { useParams } from 'next/navigation '
7+ import { Button , Input as EmcnInput } from '@/components/emcn '
118import { workflowKeys } from '@/hooks/queries/workflows'
129
1310const logger = createLogger ( 'DebugSettings' )
1411
15- interface ImportResult {
16- success : boolean
17- newWorkflowId ?: string
18- copilotChatsImported ?: number
19- error ?: string
20- }
21-
2212/**
2313 * Debug settings component for superusers.
2414 * Allows importing workflows by ID for debugging purposes.
2515 */
2616export function Debug ( ) {
2717 const params = useParams ( )
28- const router = useRouter ( )
2918 const queryClient = useQueryClient ( )
3019 const workspaceId = params ?. workspaceId as string
3120
3221 const [ workflowId , setWorkflowId ] = useState ( '' )
3322 const [ isImporting , setIsImporting ] = useState ( false )
34- const [ result , setResult ] = useState < ImportResult | null > ( null )
3523
3624 const handleImport = async ( ) => {
3725 if ( ! workflowId . trim ( ) ) return
3826
3927 setIsImporting ( true )
40- setResult ( null )
4128
4229 try {
4330 const response = await fetch ( '/api/superuser/import-workflow' , {
@@ -51,126 +38,42 @@ export function Debug() {
5138
5239 const data = await response . json ( )
5340
54- if ( ! response . ok ) {
55- setResult ( { success : false , error : data . error || 'Failed to import workflow' } )
56- return
41+ if ( response . ok ) {
42+ await queryClient . invalidateQueries ( { queryKey : workflowKeys . list ( workspaceId ) } )
43+ setWorkflowId ( '' )
44+ logger . info ( 'Workflow imported successfully' , {
45+ originalWorkflowId : workflowId . trim ( ) ,
46+ newWorkflowId : data . newWorkflowId ,
47+ copilotChatsImported : data . copilotChatsImported ,
48+ } )
5749 }
58-
59- // Invalidate workflow list cache to show the new workflow immediately
60- await queryClient . invalidateQueries ( { queryKey : workflowKeys . list ( workspaceId ) } )
61-
62- setResult ( {
63- success : true ,
64- newWorkflowId : data . newWorkflowId ,
65- copilotChatsImported : data . copilotChatsImported ,
66- } )
67-
68- setWorkflowId ( '' )
69- logger . info ( 'Workflow imported successfully' , {
70- originalWorkflowId : workflowId . trim ( ) ,
71- newWorkflowId : data . newWorkflowId ,
72- copilotChatsImported : data . copilotChatsImported ,
73- } )
7450 } catch ( error ) {
7551 logger . error ( 'Failed to import workflow' , error )
76- setResult ( { success : false , error : 'An unexpected error occurred' } )
7752 } finally {
7853 setIsImporting ( false )
7954 }
8055 }
8156
82- const handleNavigateToWorkflow = ( ) => {
83- if ( result ?. newWorkflowId ) {
84- router . push ( `/workspace/${ workspaceId } /w/${ result . newWorkflowId } ` )
85- }
86- }
87-
88- const handleKeyDown = ( e : React . KeyboardEvent ) => {
89- if ( e . key === 'Enter' && ! isImporting && workflowId . trim ( ) ) {
90- handleImport ( )
91- }
92- }
93-
9457 return (
95- < div className = "flex flex-col gap-6 p-1" >
96- < div className = "flex items-center gap-2 rounded-lg border border-amber-500/20 bg-amber-500/10 p-4" >
97- < AlertTriangle className = "h-5 w-5 flex-shrink-0 text-amber-500" />
98- < p className = "text-sm text-amber-200" >
99- This is a superuser debug feature. Use with caution. Imported workflows and copilot chats
100- will be copied to your current workspace.
101- </ p >
102- </ div >
103-
104- < div className = "flex flex-col gap-4" >
105- < div >
106- < h3 className = "mb-1 text-base font-medium text-white" > Import Workflow by ID</ h3 >
107- < p className = "text-sm text-muted-foreground" >
108- Enter a workflow ID to import it along with its associated copilot chats into your
109- current workspace. Only the workflow structure and copilot conversations will be copied
110- - no deployments, webhooks, or triggers.
111- </ p >
112- </ div >
113-
114- < div className = "flex flex-col gap-2" >
115- < Label htmlFor = "workflow-id" > Workflow ID</ Label >
116- < div className = "flex gap-2" >
117- < Input
118- id = "workflow-id"
119- value = { workflowId }
120- onChange = { ( e ) => setWorkflowId ( e . target . value ) }
121- onKeyDown = { handleKeyDown }
122- placeholder = "Enter workflow ID (e.g., abc123-def456-...)"
123- disabled = { isImporting }
124- className = "flex-1"
125- />
126- < Button onClick = { handleImport } disabled = { isImporting || ! workflowId . trim ( ) } >
127- { isImporting ? (
128- < >
129- < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
130- Importing...
131- </ >
132- ) : (
133- < >
134- < Download className = "mr-2 h-4 w-4" />
135- Import
136- </ >
137- ) }
138- </ Button >
139- </ div >
140- </ div >
141-
142- { result && (
143- < div
144- className = { `rounded-lg border p-4 ${
145- result . success
146- ? 'border-green-500/20 bg-green-500/10'
147- : 'border-red-500/20 bg-red-500/10'
148- } `}
149- >
150- { result . success ? (
151- < div className = "flex flex-col gap-2" >
152- < p className = "font-medium text-green-400" > Workflow imported successfully!</ p >
153- < p className = "text-sm text-green-300" >
154- New workflow ID: < code className = "font-mono" > { result . newWorkflowId } </ code >
155- </ p >
156- < p className = "text-sm text-green-300" >
157- Copilot chats imported: { result . copilotChatsImported }
158- </ p >
159- < Button
160- variant = "outline"
161- size = "sm"
162- onClick = { handleNavigateToWorkflow }
163- className = "mt-2 w-fit"
164- >
165- < ExternalLink className = "mr-2 h-4 w-4" />
166- Open Workflow
167- </ Button >
168- </ div >
169- ) : (
170- < p className = "text-red-400" > { result . error } </ p >
171- ) }
172- </ div >
173- ) }
58+ < div className = 'flex h-full flex-col gap-[16px]' >
59+ < p className = 'text-[13px] text-[var(--text-secondary)]' >
60+ Import a workflow by ID along with its associated copilot chats.
61+ </ p >
62+
63+ < div className = 'flex gap-[8px]' >
64+ < EmcnInput
65+ value = { workflowId }
66+ onChange = { ( e ) => setWorkflowId ( e . target . value ) }
67+ placeholder = 'Enter workflow ID'
68+ disabled = { isImporting }
69+ />
70+ < Button
71+ variant = 'tertiary'
72+ onClick = { handleImport }
73+ disabled = { isImporting || ! workflowId . trim ( ) }
74+ >
75+ { isImporting ? 'Importing...' : 'Import' }
76+ </ Button >
17477 </ div >
17578 </ div >
17679 )
0 commit comments