fix: added remaining subblock isPreview tag

This commit is contained in:
Adam Gough
2025-06-02 10:00:50 -07:00
parent 590764e5dc
commit a0b27570f7
19 changed files with 488 additions and 105 deletions
@@ -1,21 +1,50 @@
import { Checkbox } from '@/components/ui/checkbox'
import { Label } from '@/components/ui/label'
import { cn } from '@/lib/utils'
import { createLogger } from '@/lib/logs/console-logger'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
const logger = createLogger('CheckboxList')
interface CheckboxListProps {
blockId: string
subBlockId: string
title: string
options: { label: string; id: string }[]
layout?: 'full' | 'half'
isPreview?: boolean
value?: Record<string, boolean>
}
export function CheckboxList({ blockId, subBlockId, title, options, layout }: CheckboxListProps) {
export function CheckboxList({
blockId,
subBlockId,
title,
options,
layout,
isPreview = false,
value: propValues
}: CheckboxListProps) {
return (
<div className={cn('grid gap-4', layout === 'half' ? 'grid-cols-2' : 'grid-cols-1', 'pt-1')}>
{options.map((option) => {
const [value, setValue] = useSubBlockValue(blockId, option.id)
const [value, setValue] = useSubBlockValue(
blockId,
option.id,
false,
isPreview,
propValues?.[option.id]
)
// Log when in preview mode to verify it's working
if (isPreview) {
logger.info(`[PREVIEW] CheckboxList option ${option.id} for ${blockId}`, {
isPreview,
propValue: propValues?.[option.id],
value
});
}
return (
<div key={option.id} className='flex items-center space-x-2'>
<Checkbox
@@ -25,6 +25,8 @@ interface CodeProps {
placeholder?: string
language?: 'javascript' | 'json'
generationType?: 'javascript-function-body' | 'json-schema'
isPreview?: boolean
value?: string
}
if (typeof document !== 'undefined') {
@@ -52,6 +54,8 @@ export function Code({
placeholder = 'Write JavaScript...',
language = 'javascript',
generationType = 'javascript-function-body',
isPreview = false,
value: propValue
}: CodeProps) {
// Determine the AI prompt placeholder based on language
const aiPromptPlaceholder =
@@ -60,7 +64,7 @@ export function Code({
: 'Describe the JavaScript code to generate...'
// State management
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId)
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId, false, isPreview, propValue)
const [code, setCode] = useState<string>('')
const [_lineCount, setLineCount] = useState(1)
const [showTags, setShowTags] = useState(false)
@@ -199,6 +203,17 @@ export function Code({
}
}, [code])
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] Code for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
storeValue
});
}
}, [isPreview, propValue, storeValue, blockId, subBlockId]);
// Handlers
const handleDrop = (e: React.DragEvent) => {
e.preventDefault()
@@ -33,6 +33,8 @@ interface ConditionInputProps {
blockId: string
subBlockId: string
isConnecting: boolean
isPreview?: boolean
value?: string
}
// Generate a stable ID based on the blockId and a suffix
@@ -40,8 +42,8 @@ const generateStableId = (blockId: string, suffix: string): string => {
return `${blockId}-${suffix}`
}
export function ConditionInput({ blockId, subBlockId, isConnecting }: ConditionInputProps) {
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId)
export function ConditionInput({ blockId, subBlockId, isConnecting, isPreview = false, value: propValue }: ConditionInputProps) {
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId, false, isPreview, propValue)
const editorRef = useRef<HTMLDivElement>(null)
const [visualLineHeights, setVisualLineHeights] = useState<{
[key: string]: number[]
@@ -509,6 +511,17 @@ export function ConditionInput({ blockId, subBlockId, isConnecting }: ConditionI
})
}, [conditionalBlocks.length])
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] ConditionInput for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
storeValue
});
}
}, [isPreview, propValue, storeValue, blockId, subBlockId]);
// Show loading or empty state if not ready or no blocks
if (!isReady || conditionalBlocks.length === 0) {
return (
@@ -7,20 +7,36 @@ import { Button } from '@/components/ui/button'
import { Calendar } from '@/components/ui/calendar'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { cn } from '@/lib/utils'
import { createLogger } from '@/lib/logs/console-logger'
import { useNotificationStore } from '@/stores/notifications/store'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
const logger = createLogger('DateInput')
interface DateInputProps {
blockId: string
subBlockId: string
placeholder?: string
isPreview?: boolean
value?: string
}
export function DateInput({ blockId, subBlockId, placeholder }: DateInputProps) {
const [value, setValue] = useSubBlockValue<string>(blockId, subBlockId, true)
export function DateInput({ blockId, subBlockId, placeholder, isPreview = false, value: propValue }: DateInputProps) {
const [value, setValue] = useSubBlockValue<string>(blockId, subBlockId, true, isPreview, propValue)
const addNotification = useNotificationStore((state) => state.addNotification)
const date = value ? new Date(value) : undefined
// Log when in preview mode to verify it's working
React.useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] DateInput for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
value
});
}
}, [isPreview, propValue, value, blockId, subBlockId]);
const isPastDate = React.useMemo(() => {
if (!date) return false
const today = new Date()
@@ -3,8 +3,11 @@ import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { createLogger } from '@/lib/logs/console-logger'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
const logger = createLogger('EvalInput')
interface EvalMetric {
id: string
name: string
@@ -18,6 +21,8 @@ interface EvalMetric {
interface EvalInputProps {
blockId: string
subBlockId: string
isPreview?: boolean
value?: EvalMetric[]
}
// Default values
@@ -28,11 +33,20 @@ const DEFAULT_METRIC: EvalMetric = {
range: { min: 0, max: 1 },
}
export function EvalInput({ blockId, subBlockId }: EvalInputProps) {
export function EvalInput({ blockId, subBlockId, isPreview = false, value: propValue }: EvalInputProps) {
// State hooks
const [value, setValue] = useSubBlockValue<EvalMetric[]>(blockId, subBlockId)
const [value, setValue] = useSubBlockValue<EvalMetric[]>(blockId, subBlockId, false, isPreview, propValue)
const metrics = value || [DEFAULT_METRIC]
// Log when in preview mode to verify it's working
if (isPreview) {
logger.info(`[PREVIEW] EvalInput for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
value
});
}
// Metric operations
const addMetric = () => {
const newMetric: EvalMetric = {
@@ -5,6 +5,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/comp
import { env } from '@/lib/env'
import type { SubBlockConfig } from '@/blocks/types'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { createLogger } from '@/lib/logs/console-logger'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import type { ConfluenceFileInfo } from './components/confluence-file-selector'
import { ConfluenceFileSelector } from './components/confluence-file-selector'
@@ -19,13 +20,23 @@ import { MicrosoftFileSelector } from './components/microsoft-file-selector'
import type { TeamsMessageInfo } from './components/teams-message-selector'
import { TeamsMessageSelector } from './components/teams-message-selector'
const logger = createLogger('FileSelectorInput')
interface FileSelectorInputProps {
blockId: string
subBlock: SubBlockConfig
disabled?: boolean
isPreview?: boolean
value?: string
}
export function FileSelectorInput({ blockId, subBlock, disabled = false }: FileSelectorInputProps) {
export function FileSelectorInput({
blockId,
subBlock,
disabled = false,
isPreview = false,
value: propValue
}: FileSelectorInputProps) {
const { getValue, setValue } = useSubBlockStore()
const { activeWorkflowId } = useWorkflowRegistry()
const [selectedFileId, setSelectedFileId] = useState<string>('')
@@ -37,6 +48,16 @@ export function FileSelectorInput({ blockId, subBlock, disabled = false }: FileS
const [selectedMessageId, setSelectedMessageId] = useState<string>('')
const [messageInfo, setMessageInfo] = useState<TeamsMessageInfo | null>(null)
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] FileSelectorInput for ${blockId}:${subBlock.id}`, {
isPreview,
propValue
});
}
}, [isPreview, propValue, blockId, subBlock.id]);
// Get provider-specific values
const provider = subBlock.provider || 'google-drive'
const isConfluence = provider === 'confluence'
@@ -50,21 +71,34 @@ export function FileSelectorInput({ blockId, subBlock, disabled = false }: FileS
const botToken = isDiscord ? (getValue(blockId, 'botToken') as string) || '' : ''
const serverId = isDiscord ? (getValue(blockId, 'serverId') as string) || '' : ''
// Get the current value from the store
// Get the current value from the store or prop value if in preview mode
useEffect(() => {
const value = getValue(blockId, subBlock.id)
if (value && typeof value === 'string') {
if (isJira) {
setSelectedIssueId(value)
} else if (isDiscord) {
setSelectedChannelId(value)
} else if (isMicrosoftTeams) {
setSelectedMessageId(value)
} else {
setSelectedFileId(value)
if (isPreview && propValue !== undefined) {
const value = propValue;
if (value && typeof value === 'string') {
if (isJira) {
setSelectedIssueId(value);
} else if (isDiscord) {
setSelectedChannelId(value);
} else {
setSelectedFileId(value);
}
}
} else {
const value = getValue(blockId, subBlock.id);
if (value && typeof value === 'string') {
if (isJira) {
setSelectedIssueId(value);
} else if (isDiscord) {
setSelectedChannelId(value);
} else if (isMicrosoftTeams) {
setSelectedMessageId(value);
} else {
setSelectedFileId(value);
}
}
}
}, [blockId, subBlock.id, getValue, isJira, isDiscord, isMicrosoftTeams])
}, [blockId, subBlock.id, getValue, isJira, isDiscord, isMicrosoftTeams, isPreview, propValue]);
// Handle file selection
const handleFileChange = (fileId: string, info?: any) => {
@@ -1,21 +1,26 @@
'use client'
import { useRef, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import { X } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Progress } from '@/components/ui/progress'
import { createLogger } from '@/lib/logs/console-logger'
import { useNotificationStore } from '@/stores/notifications/store'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
const logger = createLogger('FileUpload')
interface FileUploadProps {
blockId: string
subBlockId: string
maxSize?: number // in MB
acceptedTypes?: string // comma separated MIME types
multiple?: boolean // whether to allow multiple file uploads
isPreview?: boolean
value?: UploadedFile | UploadedFile[] | null
}
interface UploadedFile {
@@ -37,12 +42,16 @@ export function FileUpload({
maxSize = 10, // Default 10MB
acceptedTypes = '*',
multiple = false, // Default to single file for backward compatibility
isPreview = false,
value: propValue
}: FileUploadProps) {
// State management - handle both single file and array of files
const [value, setValue] = useSubBlockValue<UploadedFile | UploadedFile[] | null>(
blockId,
subBlockId,
true
true,
isPreview,
propValue
)
const [uploadingFiles, setUploadingFiles] = useState<UploadingFile[]>([])
const [uploadProgress, setUploadProgress] = useState(0)
@@ -57,6 +66,17 @@ export function FileUpload({
const { addNotification } = useNotificationStore()
const { activeWorkflowId } = useWorkflowRegistry()
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] FileUpload for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
value
});
}
}, [isPreview, propValue, value, blockId, subBlockId]);
/**
* Opens file dialog
* Prevents event propagation to avoid ReactFlow capturing the event
@@ -2,41 +2,66 @@
import { useEffect, useState } from 'react'
import type { SubBlockConfig } from '@/blocks/types'
import { createLogger } from '@/lib/logs/console-logger'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import { type FolderInfo, FolderSelector } from '../folder-selector'
const logger = createLogger('FolderSelectorInput')
interface FolderSelectorInputProps {
blockId: string
subBlock: SubBlockConfig
disabled?: boolean
isPreview?: boolean
value?: string
}
export function FolderSelectorInput({
blockId,
subBlock,
disabled = false,
isPreview = false,
value: propValue
}: FolderSelectorInputProps) {
const { getValue, setValue } = useSubBlockStore()
const [selectedFolderId, setSelectedFolderId] = useState<string>('')
const [_folderInfo, setFolderInfo] = useState<FolderInfo | null>(null)
// Get the current value from the store
// Log when in preview mode to verify it's working
useEffect(() => {
const value = getValue(blockId, subBlock.id)
if (value && typeof value === 'string') {
setSelectedFolderId(value)
} else {
const defaultValue = 'INBOX'
setSelectedFolderId(defaultValue)
setValue(blockId, subBlock.id, defaultValue)
if (isPreview) {
logger.info(`[PREVIEW] FolderSelectorInput for ${blockId}:${subBlock.id}`, {
isPreview,
propValue
});
}
}, [blockId, subBlock.id, getValue, setValue])
}, [isPreview, propValue, blockId, subBlock.id]);
// Get the current value from the store or prop value if in preview mode
useEffect(() => {
if (isPreview && propValue !== undefined) {
setSelectedFolderId(propValue);
} else {
const value = getValue(blockId, subBlock.id);
if (value && typeof value === 'string') {
setSelectedFolderId(value);
} else {
const defaultValue = 'INBOX';
setSelectedFolderId(defaultValue);
if (!isPreview) {
setValue(blockId, subBlock.id, defaultValue);
}
}
}
}, [blockId, subBlock.id, getValue, setValue, isPreview, propValue]);
// Handle folder selection
const handleFolderChange = (folderId: string, info?: FolderInfo) => {
setSelectedFolderId(folderId)
setFolderInfo(info || null)
setValue(blockId, subBlock.id, folderId)
setSelectedFolderId(folderId);
setFolderInfo(info || null);
if (!isPreview) {
setValue(blockId, subBlock.id, folderId);
}
}
return (
@@ -3,17 +3,22 @@
import { useEffect, useState } from 'react'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import type { SubBlockConfig } from '@/blocks/types'
import { createLogger } from '@/lib/logs/console-logger'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import { type DiscordServerInfo, DiscordServerSelector } from './components/discord-server-selector'
import { type JiraProjectInfo, JiraProjectSelector } from './components/jira-project-selector'
import { type LinearProjectInfo, LinearProjectSelector } from './components/linear-project-selector'
import { type LinearTeamInfo, LinearTeamSelector } from './components/linear-team-selector'
const logger = createLogger('ProjectSelectorInput')
interface ProjectSelectorInputProps {
blockId: string
subBlock: SubBlockConfig
disabled?: boolean
onProjectSelect?: (projectId: string) => void
isPreview?: boolean
value?: string
}
export function ProjectSelectorInput({
@@ -21,11 +26,23 @@ export function ProjectSelectorInput({
subBlock,
disabled = false,
onProjectSelect,
isPreview = false,
value: propValue
}: ProjectSelectorInputProps) {
const { getValue, setValue } = useSubBlockStore()
const [selectedProjectId, setSelectedProjectId] = useState<string>('')
const [_projectInfo, setProjectInfo] = useState<JiraProjectInfo | DiscordServerInfo | null>(null)
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] ProjectSelectorInput for ${blockId}:${subBlock.id}`, {
isPreview,
propValue
});
}
}, [isPreview, propValue, blockId, subBlock.id]);
// Get provider-specific values
const provider = subBlock.provider || 'jira'
const isDiscord = provider === 'discord'
@@ -35,13 +52,17 @@ export function ProjectSelectorInput({
const domain = !isDiscord ? (getValue(blockId, 'domain') as string) || '' : ''
const botToken = isDiscord ? (getValue(blockId, 'botToken') as string) || '' : ''
// Get the current value from the store
// Get the current value from the store or prop value if in preview mode
useEffect(() => {
const value = getValue(blockId, subBlock.id)
if (value && typeof value === 'string') {
setSelectedProjectId(value)
if (isPreview && propValue !== undefined) {
setSelectedProjectId(propValue);
} else {
const value = getValue(blockId, subBlock.id);
if (value && typeof value === 'string') {
setSelectedProjectId(value);
}
}
}, [blockId, subBlock.id, getValue])
}, [blockId, subBlock.id, getValue, isPreview, propValue]);
// Handle project selection
const handleProjectChange = (
@@ -19,9 +19,17 @@ interface ScheduleConfigProps {
blockId: string
subBlockId?: string
isConnecting: boolean
isPreview?: boolean
value?: any
}
export function ScheduleConfig({ blockId, subBlockId, isConnecting }: ScheduleConfigProps) {
export function ScheduleConfig({
blockId,
subBlockId,
isConnecting,
isPreview = false,
value: propValue
}: ScheduleConfigProps) {
const [error, setError] = useState<string | null>(null)
const [scheduleId, setScheduleId] = useState<string | null>(null)
const [nextRunAt, setNextRunAt] = useState<string | null>(null)
@@ -42,12 +50,24 @@ export function ScheduleConfig({ blockId, subBlockId, isConnecting }: ScheduleCo
const setScheduleStatus = useWorkflowStore((state) => state.setScheduleStatus)
// Get the schedule type from the block state
const [scheduleType] = useSubBlockValue(blockId, 'scheduleType')
const [scheduleType] = useSubBlockValue(blockId, 'scheduleType', false, isPreview, propValue?.scheduleType)
// Get the startWorkflow value to determine if scheduling is enabled
// and expose the setter so we can update it
const [startWorkflow, setStartWorkflow] = useSubBlockValue(blockId, 'startWorkflow')
const _isScheduleEnabled = startWorkflow === 'schedule'
const [startWorkflow, setStartWorkflow] = useSubBlockValue(blockId, 'startWorkflow', false, isPreview, propValue?.startWorkflow)
const isScheduleEnabled = startWorkflow === 'schedule'
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] ScheduleConfig for ${blockId}`, {
isPreview,
propValue,
scheduleType,
startWorkflow
});
}
}, [isPreview, propValue, scheduleType, startWorkflow, blockId]);
// Function to check if schedule exists in the database
const checkSchedule = async () => {
@@ -1,7 +1,10 @@
import { useEffect, useMemo } from 'react'
import { Slider } from '@/components/ui/slider'
import { createLogger } from '@/lib/logs/console-logger'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
const logger = createLogger('SliderInput')
interface SliderInputProps {
min?: number
max?: number
@@ -10,6 +13,8 @@ interface SliderInputProps {
subBlockId: string
step?: number
integer?: boolean
isPreview?: boolean
value?: number
}
export function SliderInput({
@@ -20,8 +25,21 @@ export function SliderInput({
subBlockId,
step = 0.1,
integer = false,
isPreview = false,
value: propValue
}: SliderInputProps) {
const [value, setValue] = useSubBlockValue<number>(blockId, subBlockId)
const [value, setValue] = useSubBlockValue<number>(blockId, subBlockId, false, isPreview, propValue)
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] SliderInput for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
value
});
}
}, [isPreview, propValue, value, blockId, subBlockId]);
// Clamp the value within bounds while preserving relative position when possible
const normalizedValue = useMemo(() => {
@@ -1,3 +1,4 @@
import { useEffect } from 'react'
import { ChevronDown, Plus, Trash } from 'lucide-react'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
@@ -10,8 +11,11 @@ import {
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { cn } from '@/lib/utils'
import { createLogger } from '@/lib/logs/console-logger'
import { useSubBlockValue } from '../../hooks/use-sub-block-value'
const logger = createLogger('InputFormat')
interface InputField {
id: string
name: string
@@ -22,6 +26,8 @@ interface InputField {
interface InputFormatProps {
blockId: string
subBlockId: string
isPreview?: boolean
value?: InputField[]
}
// Default values
@@ -32,11 +38,22 @@ const DEFAULT_FIELD: InputField = {
collapsed: true,
}
export function InputFormat({ blockId, subBlockId }: InputFormatProps) {
export function InputFormat({ blockId, subBlockId, isPreview = false, value: propValue }: InputFormatProps) {
// State hooks
const [value, setValue] = useSubBlockValue<InputField[]>(blockId, subBlockId)
const [value, setValue] = useSubBlockValue<InputField[]>(blockId, subBlockId, false, isPreview, propValue)
const fields = value || [DEFAULT_FIELD]
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] InputFormat for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
value
});
}
}, [isPreview, propValue, value, blockId, subBlockId]);
// Field operations
const addField = () => {
const newField: InputField = {
@@ -1,15 +1,38 @@
import { useEffect } from 'react'
import { Label } from '@/components/ui/label'
import { Switch as UISwitch } from '@/components/ui/switch'
import { createLogger } from '@/lib/logs/console-logger'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
const logger = createLogger('Switch')
interface SwitchProps {
blockId: string
subBlockId: string
title: string
isPreview?: boolean
value?: boolean
}
export function Switch({ blockId, subBlockId, title }: SwitchProps) {
const [value, setValue] = useSubBlockValue(blockId, subBlockId)
export function Switch({
blockId,
subBlockId,
title,
isPreview = false,
value: propValue
}: SwitchProps) {
const [value, setValue] = useSubBlockValue(blockId, subBlockId, false, isPreview, propValue)
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] Switch for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
value
});
}
}, [isPreview, propValue, value, blockId, subBlockId]);
return (
<div className='flex flex-col gap-2'>
@@ -5,13 +5,18 @@ import { checkEnvVarTrigger, EnvVarDropdown } from '@/components/ui/env-var-drop
import { formatDisplayText } from '@/components/ui/formatted-text'
import { Input } from '@/components/ui/input'
import { checkTagTrigger, TagDropdown } from '@/components/ui/tag-dropdown'
import { createLogger } from '@/lib/logs/console-logger'
import { cn } from '@/lib/utils'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
const logger = createLogger('Table')
interface TableProps {
columns: string[]
blockId: string
subBlockId: string
isPreview?: boolean
value?: TableRow[]
}
interface TableRow {
@@ -19,8 +24,19 @@ interface TableRow {
cells: Record<string, string>
}
export function Table({ columns, blockId, subBlockId }: TableProps) {
const [value, setValue] = useSubBlockValue(blockId, subBlockId)
export function Table({ columns, blockId, subBlockId, isPreview = false, value: propValue }: TableProps) {
const [value, setValue] = useSubBlockValue(blockId, subBlockId, false, isPreview, propValue)
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] Table for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
value
});
}
}, [isPreview, propValue, value, blockId, subBlockId]);
// Create refs for input elements
const inputRefs = useRef<Map<string, HTMLInputElement>>(new Map())
@@ -5,20 +5,43 @@ import { Clock } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { createLogger } from '@/lib/logs/console-logger'
import { cn } from '@/lib/utils'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
const logger = createLogger('TimeInput')
interface TimeInputProps {
blockId: string
subBlockId: string
placeholder?: string
className?: string
isPreview?: boolean
value?: string
}
export function TimeInput({ blockId, subBlockId, placeholder, className }: TimeInputProps) {
const [value, setValue] = useSubBlockValue<string>(blockId, subBlockId, true)
export function TimeInput({
blockId,
subBlockId,
placeholder,
className,
isPreview = false,
value: propValue
}: TimeInputProps) {
const [value, setValue] = useSubBlockValue<string>(blockId, subBlockId, true, isPreview, propValue)
const [isOpen, setIsOpen] = React.useState(false)
// Log when in preview mode to verify it's working
React.useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] TimeInput for ${blockId}:${subBlockId}`, {
isPreview,
propValue,
value
});
}
}, [isPreview, propValue, value, blockId, subBlockId]);
// Convert 24h time string to display format (12h with AM/PM)
const formatDisplayTime = (time: string) => {
if (!time) return ''
@@ -1,4 +1,4 @@
import { useCallback, useState } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { PlusIcon, WrenchIcon, XIcon } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
@@ -31,6 +31,8 @@ import { ToolCommand } from './components/tool-command/tool-command'
interface ToolInputProps {
blockId: string
subBlockId: string
isPreview?: boolean
value?: StoredTool[]
}
interface StoredTool {
@@ -270,8 +272,8 @@ const shouldBePasswordField = (blockType: string, paramId: string): boolean => {
return false
}
export function ToolInput({ blockId, subBlockId }: ToolInputProps) {
const [value, setValue] = useSubBlockValue(blockId, subBlockId)
export function ToolInput({ blockId, subBlockId, isPreview = false, value: propValue }: ToolInputProps) {
const [value, setValue] = useSubBlockValue(blockId, subBlockId, false, isPreview, propValue)
const [open, setOpen] = useState(false)
const [customToolModalOpen, setCustomToolModalOpen] = useState(false)
const [editingToolIndex, setEditingToolIndex] = useState<number | null>(null)
@@ -287,9 +287,17 @@ interface WebhookConfigProps {
blockId: string
subBlockId?: string
isConnecting: boolean
isPreview?: boolean
value?: any
}
export function WebhookConfig({ blockId, subBlockId, isConnecting }: WebhookConfigProps) {
export function WebhookConfig({
blockId,
subBlockId,
isConnecting,
isPreview = false,
value: propValue
}: WebhookConfigProps) {
const [isModalOpen, setIsModalOpen] = useState(false)
const [isSaving, setIsSaving] = useState(false)
const [isDeleting, setIsDeleting] = useState(false)
@@ -304,21 +312,34 @@ export function WebhookConfig({ blockId, subBlockId, isConnecting }: WebhookConf
const setWebhookStatus = useWorkflowStore((state) => state.setWebhookStatus)
// Get the webhook provider from the block state
const [webhookProvider, setWebhookProvider] = useSubBlockValue(blockId, 'webhookProvider')
const [webhookProvider, setWebhookProvider] = useSubBlockValue(blockId, 'webhookProvider', false, isPreview, propValue?.webhookProvider)
// Store the webhook path
const [webhookPath, setWebhookPath] = useSubBlockValue(blockId, 'webhookPath')
const [webhookPath, setWebhookPath] = useSubBlockValue(blockId, 'webhookPath', false, isPreview, propValue?.webhookPath)
// Store provider-specific configuration
const [_providerConfig, setProviderConfig] = useSubBlockValue(blockId, 'providerConfig')
const [providerConfig, setProviderConfig] = useSubBlockValue(blockId, 'providerConfig', false, isPreview, propValue?.providerConfig)
// Log when in preview mode to verify it's working
useEffect(() => {
if (isPreview) {
logger.info(`[PREVIEW] WebhookConfig for ${blockId}`, {
isPreview,
propValue,
webhookProvider,
webhookPath,
providerConfig
});
}
}, [isPreview, propValue, webhookProvider, webhookPath, providerConfig, blockId]);
// Reset provider config when provider changes
useEffect(() => {
if (webhookProvider) {
if (webhookProvider && !isPreview) {
// Reset the provider config when the provider changes
setProviderConfig({})
}
}, [webhookProvider, setProviderConfig])
}, [webhookProvider, setProviderConfig, isPreview])
// Store the actual provider from the database
const [actualProvider, setActualProvider] = useState<string | null>(null)
@@ -1,10 +1,7 @@
import { useCallback, useEffect, useRef } from 'react'
import { isEqual } from 'lodash'
<<<<<<< HEAD
import { getProviderFromModel } from '@/providers/utils'
=======
import { createLogger } from '@/lib/logs/console-logger'
>>>>>>> 6f129dfc (fix: subblock rerender fixed)
import { useGeneralStore } from '@/stores/settings/general/store'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
@@ -162,13 +159,9 @@ function storeApiKeyValue(
export function useSubBlockValue<T = any>(
blockId: string,
subBlockId: string,
<<<<<<< HEAD
triggerWorkflowUpdate = false
=======
triggerWorkflowUpdate: boolean = false,
isPreview: boolean = false,
directValue?: T
>>>>>>> 6f129dfc (fix: subblock rerender fixed)
): readonly [T | null, (value: T) => void] {
const blockType = useWorkflowStore(
useCallback((state) => state.blocks?.[blockId]?.type, [blockId])
@@ -2,11 +2,6 @@ import { useEffect } from 'react'
import { Info } from 'lucide-react'
import { Label } from '@/components/ui/label'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
<<<<<<< HEAD
=======
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
import { createLogger } from '@/lib/logs/console-logger'
>>>>>>> 6f129dfc (fix: subblock rerender fixed)
import { getBlock } from '@/blocks/index'
import type { SubBlockConfig } from '@/blocks/types'
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
@@ -34,8 +29,6 @@ import { TimeInput } from './components/time-input'
import { ToolInput } from './components/tool-input/tool-input'
import { WebhookConfig } from './components/webhook/webhook'
// Add logger
const logger = createLogger('SubBlock')
interface SubBlockProps {
blockId: string
@@ -52,18 +45,7 @@ export function SubBlock({
isPreview = false,
previewValue = undefined
}: SubBlockProps) {
// Add debugging logs to trace parent context
useEffect(() => {
logger.info(`[TRACE] SubBlock ${config.id} for block ${blockId}`, {
blockId,
subBlockId: config.id,
subBlockTitle: config.title,
isPreview: isPreview,
previewValue: previewValue,
usingGlobalStore: !isPreview
});
}, [blockId, config.id, config.title, isPreview, previewValue]);
const handleMouseDown = (e: React.MouseEvent) => {
e.stopPropagation()
}
@@ -131,10 +113,18 @@ export function SubBlock({
defaultValue={(config.min || 0) + ((config.max || 100) - (config.min || 0)) / 2}
step={config.step}
integer={config.integer}
isPreview={isPreview}
value={directValue}
/>
)
case 'table':
return <Table blockId={blockId} subBlockId={config.id} columns={config.columns ?? []} />
return <Table
blockId={blockId}
subBlockId={config.id}
columns={config.columns ?? []}
isPreview={isPreview}
value={directValue}
/>
case 'code':
return (
<Code
@@ -144,12 +134,25 @@ export function SubBlock({
placeholder={config.placeholder}
language={config.language}
generationType={config.generationType}
isPreview={isPreview}
value={directValue}
/>
)
case 'switch':
return <Switch blockId={blockId} subBlockId={config.id} title={config.title ?? ''} />
return <Switch
blockId={blockId}
subBlockId={config.id}
title={config.title ?? ''}
isPreview={isPreview}
value={directValue}
/>
case 'tool-input':
return <ToolInput blockId={blockId} subBlockId={config.id} />
return <ToolInput
blockId={blockId}
subBlockId={config.id}
isPreview={isPreview}
value={directValue}
/>
case 'checkbox-list':
return (
<CheckboxList
@@ -158,21 +161,46 @@ export function SubBlock({
title={config.title ?? ''}
options={config.options as { label: string; id: string }[]}
layout={config.layout}
isPreview={isPreview}
value={directValue}
/>
)
case 'condition-input':
return (
<ConditionInput blockId={blockId} subBlockId={config.id} isConnecting={isConnecting} />
<ConditionInput
blockId={blockId}
subBlockId={config.id}
isConnecting={isConnecting}
isPreview={isPreview}
value={directValue}
/>
)
case 'eval-input':
return <EvalInput blockId={blockId} subBlockId={config.id} />
return <EvalInput
blockId={blockId}
subBlockId={config.id}
isPreview={isPreview}
value={directValue}
/>
case 'date-input':
return (
<DateInput blockId={blockId} subBlockId={config.id} placeholder={config.placeholder} />
<DateInput
blockId={blockId}
subBlockId={config.id}
placeholder={config.placeholder}
isPreview={isPreview}
value={directValue}
/>
)
case 'time-input':
return (
<TimeInput blockId={blockId} subBlockId={config.id} placeholder={config.placeholder} />
<TimeInput
blockId={blockId}
subBlockId={config.id}
placeholder={config.placeholder}
isPreview={isPreview}
value={directValue}
/>
)
case 'file-upload':
return (
@@ -182,20 +210,34 @@ export function SubBlock({
acceptedTypes={config.acceptedTypes || '*'}
multiple={config.multiple === true}
maxSize={config.maxSize}
isPreview={isPreview}
value={directValue}
/>
)
case 'webhook-config':
return (
<WebhookConfig blockId={blockId} subBlockId={config.id} isConnecting={isConnecting} />
<WebhookConfig
blockId={blockId}
subBlockId={config.id}
isConnecting={isConnecting}
isPreview={isPreview}
value={directValue}
/>
)
case 'schedule-config':
return (
<ScheduleConfig blockId={blockId} subBlockId={config.id} isConnecting={isConnecting} />
<ScheduleConfig
blockId={blockId}
subBlockId={config.id}
isConnecting={isConnecting}
isPreview={isPreview}
value={directValue}
/>
)
case 'oauth-input':
return (
<CredentialSelector
value={typeof config.value === 'string' ? config.value : ''}
value={isPreview && directValue ? directValue : (typeof config.value === 'string' ? config.value : '')}
onChange={(value) => {
// Use the workflow store to update the value
const event = new CustomEvent('update-subblock-value', {
@@ -214,15 +256,36 @@ export function SubBlock({
/>
)
case 'file-selector':
return <FileSelectorInput blockId={blockId} subBlock={config} disabled={isConnecting} />
return <FileSelectorInput
blockId={blockId}
subBlock={config}
disabled={isConnecting}
isPreview={isPreview}
value={directValue}
/>
case 'project-selector':
return <ProjectSelectorInput blockId={blockId} subBlock={config} disabled={isConnecting} />
case 'channel-selector':
return <ChannelSelectorInput blockId={blockId} subBlock={config} disabled={isConnecting} />
return <ProjectSelectorInput
blockId={blockId}
subBlock={config}
disabled={isConnecting}
isPreview={isPreview}
value={directValue}
/>
case 'folder-selector':
return <FolderSelectorInput blockId={blockId} subBlock={config} disabled={isConnecting} />
return <FolderSelectorInput
blockId={blockId}
subBlock={config}
disabled={isConnecting}
isPreview={isPreview}
value={directValue}
/>
case 'input-format':
return <InputFormat blockId={blockId} subBlockId={config.id} />
return <InputFormat
blockId={blockId}
subBlockId={config.id}
isPreview={isPreview}
value={directValue}
/>
default:
return <div>Unknown input type: {config.type}</div>
}