diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/export-controls/export-controls.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/export-controls/export-controls.tsx index e116cb4a19..79182bbf91 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/export-controls/export-controls.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/control-bar/components/export-controls/export-controls.tsx @@ -12,8 +12,8 @@ import { } from '@/components/ui/dropdown-menu' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' import { createLogger } from '@/lib/logs/console-logger' -import { useWorkflowStore } from '@/stores/workflows/workflow/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' +import { useWorkflowStore } from '@/stores/workflows/workflow/store' import { useWorkflowYamlStore } from '@/stores/workflows/yaml/store' const logger = createLogger('ExportControls') @@ -26,7 +26,7 @@ export function ExportControls({ disabled = false }: ExportControlsProps) { const [isExporting, setIsExporting] = useState(false) const workflowState = useWorkflowStore() const { workflows, activeWorkflowId } = useWorkflowRegistry() - const getYaml = useWorkflowYamlStore(state => state.getYaml) + const getYaml = useWorkflowYamlStore((state) => state.getYaml) const currentWorkflow = activeWorkflowId ? workflows[activeWorkflowId] : null @@ -68,12 +68,12 @@ export function ExportControls({ disabled = false }: ExportControlsProps) { parallels: workflowState.parallels, }, exportedAt: new Date().toISOString(), - version: '1.0' + version: '1.0', } const jsonContent = JSON.stringify(exportData, null, 2) const filename = `${currentWorkflow.name.replace(/[^a-z0-9]/gi, '_')}_workflow.json` - + downloadFile(jsonContent, filename, 'application/json') logger.info('Workflow exported as JSON') } catch (error) { @@ -93,7 +93,7 @@ export function ExportControls({ disabled = false }: ExportControlsProps) { try { const yamlContent = getYaml() const filename = `${currentWorkflow.name.replace(/[^a-z0-9]/gi, '_')}_workflow.yaml` - + downloadFile(yamlContent, filename, 'text/yaml') logger.info('Workflow exported as YAML') } catch (error) { @@ -108,9 +108,9 @@ export function ExportControls({ disabled = false }: ExportControlsProps) { - @@ -120,46 +120,41 @@ export function ExportControls({ disabled = false }: ExportControlsProps) { - {disabled - ? 'Export not available' - : !currentWorkflow + {disabled + ? 'Export not available' + : !currentWorkflow ? 'No workflow to export' - : 'Export Workflow' - } + : 'Export Workflow'} - Export as JSON - - Full workflow data - + Full workflow data - + - - Export as YAML - - Condensed workflow language - + Condensed workflow language ) -} \ No newline at end of file +} diff --git a/apps/sim/stores/workflows/yaml/store.ts b/apps/sim/stores/workflows/yaml/store.ts index 37f17fe89b..8baea4649c 100644 --- a/apps/sim/stores/workflows/yaml/store.ts +++ b/apps/sim/stores/workflows/yaml/store.ts @@ -1,12 +1,12 @@ +import { dump as yamlDump } from 'js-yaml' import { create } from 'zustand' import { devtools } from 'zustand/middleware' -import { dump as yamlDump } from 'js-yaml' -import { getBlock } from '@/blocks' import { createLogger } from '@/lib/logs/console-logger' -import { useWorkflowStore } from '../workflow/store' -import { useSubBlockStore } from '../subblock/store' -import type { BlockState, WorkflowState } from '../workflow/types' +import { getBlock } from '@/blocks' import type { SubBlockConfig } from '@/blocks/types' +import { useSubBlockStore } from '../subblock/store' +import { useWorkflowStore } from '../workflow/store' +import type { BlockState, WorkflowState } from '../workflow/types' const logger = createLogger('WorkflowYamlStore') @@ -58,13 +58,13 @@ function extractBlockInputs(blockState: BlockState, blockId: string): Record { const subBlockId = subBlockConfig.id - + // Skip hidden or conditional fields that aren't active if (subBlockConfig.hidden) return - + // Get value from subblock store or fallback to block state - const value = subBlockStore.getValue(blockId, subBlockId) ?? - blockState.subBlocks[subBlockId]?.value + const value = + subBlockStore.getValue(blockId, subBlockId) ?? blockState.subBlocks[subBlockId]?.value // Include value if it exists and isn't empty if (value !== undefined && value !== null && value !== '') { @@ -76,14 +76,14 @@ function extractBlockInputs(blockState: BlockState, blockId: string): Record 0) { inputs[subBlockId] = value } break - + case 'code': // Code blocks should preserve formatting if (typeof value === 'string' && value.trim()) { @@ -92,24 +92,31 @@ function extractBlockInputs(blockState: BlockState, blockId: string): Record edge.target === blockId) - .map(edge => edge.source) + .filter((edge) => edge.target === blockId) + .map((edge) => edge.source) .filter((source, index, arr) => arr.indexOf(source) === index) // Remove duplicates } @@ -135,8 +142,8 @@ function findPrecedingBlocks(blockId: string, edges: any[]): string[] { */ function findFollowingBlocks(blockId: string, edges: any[]): string[] { return edges - .filter(edge => edge.source === blockId) - .map(edge => edge.target) + .filter((edge) => edge.source === blockId) + .map((edge) => edge.target) .filter((target, index, arr) => arr.indexOf(target) === index) // Remove duplicates } @@ -147,7 +154,7 @@ function generateWorkflowYaml(workflowState: WorkflowState): string { try { const yamlWorkflow: YamlWorkflow = { version: '1.0', - blocks: {} + blocks: {}, } // Process each block @@ -158,7 +165,7 @@ function generateWorkflowYaml(workflowState: WorkflowState): string { const yamlBlock: YamlBlock = { type: blockState.type, - name: blockState.name + name: blockState.name, } // Only include inputs if they exist @@ -170,7 +177,7 @@ function generateWorkflowYaml(workflowState: WorkflowState): string { if (preceding.length > 0) { yamlBlock.preceding = preceding } - + if (following.length > 0) { yamlBlock.following = following } @@ -183,7 +190,7 @@ function generateWorkflowYaml(workflowState: WorkflowState): string { indent: 2, lineWidth: -1, // Disable line wrapping noRefs: true, - sortKeys: false + sortKeys: false, }) } catch (error) { logger.error('Failed to generate workflow YAML:', error) @@ -200,32 +207,32 @@ export const useWorkflowYamlStore = create()( generateYaml: () => { const workflowState = useWorkflowStore.getState() const yaml = generateWorkflowYaml(workflowState) - + set({ yaml, - lastGenerated: Date.now() + lastGenerated: Date.now(), }) }, getYaml: () => { const currentTime = Date.now() const { yaml, lastGenerated } = get() - + // Auto-refresh if data is stale (older than 1 second) or never generated if (!lastGenerated || currentTime - lastGenerated > 1000) { get().generateYaml() return get().yaml } - + return yaml }, refreshYaml: () => { get().generateYaml() - } + }, }), { - name: 'workflow-yaml-store' + name: 'workflow-yaml-store', } ) ) @@ -236,16 +243,17 @@ let lastWorkflowState: { blockCount: number; edgeCount: number } | null = null useWorkflowStore.subscribe((state) => { const currentState = { blockCount: Object.keys(state.blocks).length, - edgeCount: state.edges.length + edgeCount: state.edges.length, } - + // Only refresh if the structure has changed - if (!lastWorkflowState || - lastWorkflowState.blockCount !== currentState.blockCount || - lastWorkflowState.edgeCount !== currentState.edgeCount) { - + if ( + !lastWorkflowState || + lastWorkflowState.blockCount !== currentState.blockCount || + lastWorkflowState.edgeCount !== currentState.edgeCount + ) { lastWorkflowState = currentState - + // Debounce the refresh to avoid excessive updates const refreshYaml = useWorkflowYamlStore.getState().refreshYaml setTimeout(refreshYaml, 100) @@ -257,12 +265,12 @@ let lastSubBlockChangeTime = 0 useSubBlockStore.subscribe((state) => { const currentTime = Date.now() - + // Debounce rapid changes if (currentTime - lastSubBlockChangeTime > 100) { lastSubBlockChangeTime = currentTime - + const refreshYaml = useWorkflowYamlStore.getState().refreshYaml setTimeout(refreshYaml, 100) } -}) \ No newline at end of file +})