1+ 'use client'
2+
3+ import { useState } from 'react'
4+ import { Download , FileText } from 'lucide-react'
5+ import { Button } from '@/components/ui/button'
6+ import {
7+ DropdownMenu ,
8+ DropdownMenuContent ,
9+ DropdownMenuItem ,
10+ DropdownMenuSeparator ,
11+ DropdownMenuTrigger ,
12+ } from '@/components/ui/dropdown-menu'
13+ import { Tooltip , TooltipContent , TooltipTrigger } from '@/components/ui/tooltip'
14+ import { createLogger } from '@/lib/logs/console-logger'
15+ import { useWorkflowStore } from '@/stores/workflows/workflow/store'
16+ import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
17+ import { useWorkflowYamlStore } from '@/stores/workflows/yaml/store'
18+
19+ const logger = createLogger ( 'ExportControls' )
20+
21+ interface ExportControlsProps {
22+ disabled ?: boolean
23+ }
24+
25+ export function ExportControls ( { disabled = false } : ExportControlsProps ) {
26+ const [ isExporting , setIsExporting ] = useState ( false )
27+ const workflowState = useWorkflowStore ( )
28+ const { workflows, activeWorkflowId } = useWorkflowRegistry ( )
29+ const getYaml = useWorkflowYamlStore ( state => state . getYaml )
30+
31+ const currentWorkflow = activeWorkflowId ? workflows [ activeWorkflowId ] : null
32+
33+ const downloadFile = ( content : string , filename : string , mimeType : string ) => {
34+ try {
35+ const blob = new Blob ( [ content ] , { type : mimeType } )
36+ const url = URL . createObjectURL ( blob )
37+ const a = document . createElement ( 'a' )
38+ a . href = url
39+ a . download = filename
40+ document . body . appendChild ( a )
41+ a . click ( )
42+ document . body . removeChild ( a )
43+ URL . revokeObjectURL ( url )
44+ } catch ( error ) {
45+ logger . error ( 'Failed to download file:' , error )
46+ }
47+ }
48+
49+ const handleExportJson = async ( ) => {
50+ if ( ! currentWorkflow || ! activeWorkflowId ) {
51+ logger . warn ( 'No active workflow to export' )
52+ return
53+ }
54+
55+ setIsExporting ( true )
56+ try {
57+ const exportData = {
58+ workflow : {
59+ id : activeWorkflowId ,
60+ name : currentWorkflow . name ,
61+ description : currentWorkflow . description ,
62+ color : currentWorkflow . color ,
63+ } ,
64+ state : {
65+ blocks : workflowState . blocks ,
66+ edges : workflowState . edges ,
67+ loops : workflowState . loops ,
68+ parallels : workflowState . parallels ,
69+ } ,
70+ exportedAt : new Date ( ) . toISOString ( ) ,
71+ version : '1.0'
72+ }
73+
74+ const jsonContent = JSON . stringify ( exportData , null , 2 )
75+ const filename = `${ currentWorkflow . name . replace ( / [ ^ a - z 0 - 9 ] / gi, '_' ) } _workflow.json`
76+
77+ downloadFile ( jsonContent , filename , 'application/json' )
78+ logger . info ( 'Workflow exported as JSON' )
79+ } catch ( error ) {
80+ logger . error ( 'Failed to export workflow as JSON:' , error )
81+ } finally {
82+ setIsExporting ( false )
83+ }
84+ }
85+
86+ const handleExportYaml = async ( ) => {
87+ if ( ! currentWorkflow || ! activeWorkflowId ) {
88+ logger . warn ( 'No active workflow to export' )
89+ return
90+ }
91+
92+ setIsExporting ( true )
93+ try {
94+ const yamlContent = getYaml ( )
95+ const filename = `${ currentWorkflow . name . replace ( / [ ^ a - z 0 - 9 ] / gi, '_' ) } _workflow.yaml`
96+
97+ downloadFile ( yamlContent , filename , 'text/yaml' )
98+ logger . info ( 'Workflow exported as YAML' )
99+ } catch ( error ) {
100+ logger . error ( 'Failed to export workflow as YAML:' , error )
101+ } finally {
102+ setIsExporting ( false )
103+ }
104+ }
105+
106+ return (
107+ < DropdownMenu >
108+ < Tooltip >
109+ < TooltipTrigger asChild >
110+ < DropdownMenuTrigger asChild >
111+ < Button
112+ variant = 'ghost'
113+ size = 'icon'
114+ disabled = { disabled || isExporting || ! currentWorkflow }
115+ className = 'hover:text-foreground'
116+ >
117+ < Download className = 'h-5 w-5' />
118+ < span className = 'sr-only' > Export Workflow</ span >
119+ </ Button >
120+ </ DropdownMenuTrigger >
121+ </ TooltipTrigger >
122+ < TooltipContent >
123+ { disabled
124+ ? 'Export not available'
125+ : ! currentWorkflow
126+ ? 'No workflow to export'
127+ : 'Export Workflow'
128+ }
129+ </ TooltipContent >
130+ </ Tooltip >
131+
132+ < DropdownMenuContent align = 'end' className = 'w-48' >
133+ < DropdownMenuItem
134+ onClick = { handleExportJson }
135+ disabled = { isExporting || ! currentWorkflow }
136+ className = 'flex items-center gap-2 cursor-pointer'
137+ >
138+ < FileText className = 'h-4 w-4' />
139+ < div className = 'flex flex-col' >
140+ < span > Export as JSON</ span >
141+ < span className = 'text-muted-foreground text-xs' >
142+ Full workflow data
143+ </ span >
144+ </ div >
145+ </ DropdownMenuItem >
146+
147+ < DropdownMenuSeparator />
148+
149+ < DropdownMenuItem
150+ onClick = { handleExportYaml }
151+ disabled = { isExporting || ! currentWorkflow }
152+ className = 'flex items-center gap-2 cursor-pointer'
153+ >
154+ < FileText className = 'h-4 w-4' />
155+ < div className = 'flex flex-col' >
156+ < span > Export as YAML</ span >
157+ < span className = 'text-muted-foreground text-xs' >
158+ Condensed workflow language
159+ </ span >
160+ </ div >
161+ </ DropdownMenuItem >
162+ </ DropdownMenuContent >
163+ </ DropdownMenu >
164+ )
165+ }
0 commit comments