mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-10 23:48:09 -05:00
Lint
This commit is contained in:
@@ -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) {
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant='ghost'
|
||||
size='icon'
|
||||
<Button
|
||||
variant='ghost'
|
||||
size='icon'
|
||||
disabled={disabled || isExporting || !currentWorkflow}
|
||||
className='hover:text-foreground'
|
||||
>
|
||||
@@ -120,46 +120,41 @@ export function ExportControls({ disabled = false }: ExportControlsProps) {
|
||||
</DropdownMenuTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{disabled
|
||||
? 'Export not available'
|
||||
: !currentWorkflow
|
||||
{disabled
|
||||
? 'Export not available'
|
||||
: !currentWorkflow
|
||||
? 'No workflow to export'
|
||||
: 'Export Workflow'
|
||||
}
|
||||
: 'Export Workflow'}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<DropdownMenuContent align='end' className='w-48'>
|
||||
<DropdownMenuItem
|
||||
<DropdownMenuItem
|
||||
onClick={handleExportJson}
|
||||
disabled={isExporting || !currentWorkflow}
|
||||
className='flex items-center gap-2 cursor-pointer'
|
||||
className='flex cursor-pointer items-center gap-2'
|
||||
>
|
||||
<FileText className='h-4 w-4' />
|
||||
<div className='flex flex-col'>
|
||||
<span>Export as JSON</span>
|
||||
<span className='text-muted-foreground text-xs'>
|
||||
Full workflow data
|
||||
</span>
|
||||
<span className='text-muted-foreground text-xs'>Full workflow data</span>
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuItem
|
||||
|
||||
<DropdownMenuItem
|
||||
onClick={handleExportYaml}
|
||||
disabled={isExporting || !currentWorkflow}
|
||||
className='flex items-center gap-2 cursor-pointer'
|
||||
className='flex cursor-pointer items-center gap-2'
|
||||
>
|
||||
<FileText className='h-4 w-4' />
|
||||
<div className='flex flex-col'>
|
||||
<span>Export as YAML</span>
|
||||
<span className='text-muted-foreground text-xs'>
|
||||
Condensed workflow language
|
||||
</span>
|
||||
<span className='text-muted-foreground text-xs'>Condensed workflow language</span>
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<str
|
||||
// Process each subBlock configuration
|
||||
blockConfig.subBlocks.forEach((subBlockConfig: SubBlockConfig) => {
|
||||
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<str
|
||||
inputs[subBlockId] = value
|
||||
}
|
||||
break
|
||||
|
||||
|
||||
case 'checkbox-list':
|
||||
// Checkbox lists return arrays
|
||||
if (Array.isArray(value) && value.length > 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<str
|
||||
inputs[subBlockId] = value
|
||||
}
|
||||
break
|
||||
|
||||
|
||||
case 'switch':
|
||||
// Boolean values
|
||||
inputs[subBlockId] = Boolean(value)
|
||||
break
|
||||
|
||||
|
||||
case 'slider':
|
||||
// Numeric values
|
||||
if (typeof value === 'number' || (typeof value === 'string' && !isNaN(Number(value)))) {
|
||||
if (
|
||||
typeof value === 'number' ||
|
||||
(typeof value === 'string' && !Number.isNaN(Number(value)))
|
||||
) {
|
||||
inputs[subBlockId] = Number(value)
|
||||
}
|
||||
break
|
||||
|
||||
|
||||
default:
|
||||
// Text inputs, dropdowns, etc.
|
||||
if (typeof value === 'string' && value.trim()) {
|
||||
inputs[subBlockId] = value.trim()
|
||||
} else if (typeof value === 'object' || typeof value === 'number' || typeof value === 'boolean') {
|
||||
} else if (
|
||||
typeof value === 'object' ||
|
||||
typeof value === 'number' ||
|
||||
typeof value === 'boolean'
|
||||
) {
|
||||
inputs[subBlockId] = value
|
||||
}
|
||||
break
|
||||
@@ -125,8 +132,8 @@ function extractBlockInputs(blockState: BlockState, blockId: string): Record<str
|
||||
*/
|
||||
function findPrecedingBlocks(blockId: string, edges: any[]): string[] {
|
||||
return edges
|
||||
.filter(edge => 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<WorkflowYamlStore>()(
|
||||
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)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user