From 36cd271984f2a0b3fa942dc833b1f82184e3ea3d Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Sun, 18 May 2025 09:48:35 -0400 Subject: [PATCH] fix: added greptile comments --- .../app/api/workflows/[id]/deployed/route.ts | 2 +- .../deployment-info/deployment-info.tsx | 4 +- .../components/deployed-workflow-card.tsx | 2 +- .../components/deployed-workflow-modal.tsx | 2 +- .../components/control-bar/control-bar.tsx | 90 +++++++------------ .../components/starter/input-format.tsx | 1 - .../sub-block/hooks/use-sub-block-value.ts | 46 +--------- .../workflow-preview/workflow-preview.tsx | 3 +- 8 files changed, 44 insertions(+), 106 deletions(-) diff --git a/apps/sim/app/api/workflows/[id]/deployed/route.ts b/apps/sim/app/api/workflows/[id]/deployed/route.ts index d0e0d724c2..b7b460502a 100644 --- a/apps/sim/app/api/workflows/[id]/deployed/route.ts +++ b/apps/sim/app/api/workflows/[id]/deployed/route.ts @@ -17,7 +17,7 @@ function addNoCacheHeaders(response: NextResponse): NextResponse { return response } -export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { +export async function GET(request: NextRequest, { params }: { params: { id: string } }) { const requestId = crypto.randomUUID().slice(0, 8) const { id } = await params diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx b/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx index 731e1f2739..596bdcdeef 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx +++ b/apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/deployment-info.tsx @@ -39,7 +39,6 @@ interface DeploymentInfoProps { onUndeploy: () => void isSubmitting: boolean isUndeploying: boolean - needsRedeployment: boolean workflowId: string | null deployedState: any isLoadingDeployedState: boolean @@ -52,7 +51,6 @@ export function DeploymentInfo({ onUndeploy, isSubmitting, isUndeploying, - needsRedeployment, workflowId, deployedState, isLoadingDeployedState @@ -71,7 +69,7 @@ export function DeploymentInfo({ logger.info(`Using cached deployed state for workflow: ${workflowId}`) setIsViewingDeployed(true) return - } else { + } else if (!isLoadingDeployedState) { logger.debug(`[${workflowId}] No deployed state found`) addNotification('error', 'Cannot view deployment: No deployed state available', workflowId) } diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx b/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx index 2ee4f25d72..a458fddfbd 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx +++ b/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-card.tsx @@ -55,7 +55,7 @@ export function DeployedWorkflowCard({ // Generate a unique key for the workflow preview const previewKey = useMemo(() => { - return `${showingDeployed ? 'deployed' : 'current'}-preview-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`; + return `${showingDeployed ? 'deployed' : 'current'}-preview`; }, [showingDeployed]); return ( diff --git a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx b/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx index 868323970d..071d1522c3 100644 --- a/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx +++ b/apps/sim/app/w/[id]/components/control-bar/components/deployment-controls/components/deployed-workflow-modal.tsx @@ -109,7 +109,7 @@ export function DeployedWorkflowModal({ ======= if (activeWorkflowId) { logger.info(`Reverting to deployed state for workflow: ${activeWorkflowId}`) - revertToDeployedState(deployedWorkflowState) + revertToDeployedState(sanitizedDeployedState) setShowRevertDialog(false) onClose() } diff --git a/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx b/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx index defb8165e4..ed15ebe1fb 100644 --- a/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx +++ b/apps/sim/app/w/[id]/components/control-bar/control-bar.tsx @@ -329,16 +329,27 @@ export function ControlBar() { checkStatus() }, [activeWorkflowId, setDeploymentStatus]) - // Add a function to explicitly fetch deployed state that can be called after redeployment - const refetchDeployedState = async () => { - if (!activeWorkflowId || !isDeployed) { - setDeployedState(null) + /** + * Fetches the deployed state of the workflow from the server + * This is the single source of truth for deployed workflow state + * @param options.forceRefetch Force a refetch even if conditions wouldn't normally trigger it + * @returns Promise that resolves when the deployed state is fetched + */ + const fetchDeployedState = async (options = { forceRefetch: false }) => { + // Skip fetching if we don't have an active workflow ID or it's not deployed + // unless we're explicitly forcing a refetch + if ((!activeWorkflowId || !isDeployed) && !options.forceRefetch) { + setDeployedState(null); return; } try { setIsLoadingDeployedState(true); - logger.info(`[CENTRAL] Explicitly refetching deployed state for workflow: ${activeWorkflowId}`); + const logMessage = options.forceRefetch + ? `[CENTRAL] Explicitly refetching deployed state for workflow: ${activeWorkflowId}` + : `[CENTRAL] Fetching deployed state for workflow: ${activeWorkflowId} (Control Bar - Single Source of Truth)`; + + logger.info(logMessage); const response = await fetch(`/api/workflows/${activeWorkflowId}/deployed`); if (!response.ok) { @@ -348,62 +359,39 @@ export function ControlBar() { const data = await response.json(); if (data.deployedState) { - logger.info('Successfully refetched deployed state from DB after redeployment'); + const successMessage = options.forceRefetch + ? 'Successfully refetched deployed state from DB after redeployment' + : 'Successfully fetched deployed state from DB - This is the only place that should fetch deployed state'; + + logger.info(successMessage); + // Create a deep clone to ensure no reference sharing with current state const deepClonedState = JSON.parse(JSON.stringify(data.deployedState)); - logger.info('deepClonedState', deepClonedState) + logger.info('deepClonedState', deepClonedState); setDeployedState(deepClonedState); } else { - logger.warn('No deployed state found in the database after refetch'); + const warningMessage = options.forceRefetch + ? 'No deployed state found in the database after refetch' + : 'No deployed state found in the database'; + + logger.warn(warningMessage); setDeployedState(null); } } catch (error) { - logger.error('Error refetching deployed state:', error); + logger.error('Error fetching deployed state:', error); setDeployedState(null); } finally { setIsLoadingDeployedState(false); } }; + // Alias for clarity when explicitly triggering a refetch + const refetchDeployedState = () => fetchDeployedState({ forceRefetch: true }); + // Fetch deployed state when the workflow ID changes or deployment status changes useEffect(() => { - async function fetchDeployedState() { - if (!activeWorkflowId || !isDeployed) { - setDeployedState(null) - return - } - - try { - setIsLoadingDeployedState(true) - logger.info(`[CENTRAL] Fetching deployed state for workflow: ${activeWorkflowId} (Control Bar - Single Source of Truth)`) - - const response = await fetch(`/api/workflows/${activeWorkflowId}/deployed`) - if (!response.ok) { - throw new Error(`Failed to fetch deployed state: ${response.status}`) - } - - const data = await response.json() - - if (data.deployedState) { - logger.info('Successfully fetched deployed state from DB - This is the only place that should fetch deployed state') - // Create a deep clone to ensure no reference sharing with current state - const deepClonedState = JSON.parse(JSON.stringify(data.deployedState)) - logger.info('deepClonedState', deepClonedState) - setDeployedState(deepClonedState) - } else { - logger.warn('No deployed state found in the database') - setDeployedState(null) - } - } catch (error) { - logger.error('Error fetching deployed state:', error) - setDeployedState(null) - } finally { - setIsLoadingDeployedState(false) - } - } - - fetchDeployedState() - }, [activeWorkflowId, isDeployed]) + fetchDeployedState(); + }, [activeWorkflowId, isDeployed]); // Listen for deployment status changes useEffect(() => { @@ -423,16 +411,6 @@ export function ControlBar() { } }, [isDeployed, activeWorkflowId]) - // Listen for deployment status changes - useEffect(() => { - // When deployment status changes and isDeployed becomes true, - // that means a deployment just occurred, so reset the needsRedeployment flag - if (isDeployed) { - setNeedsRedeployment(false) - useWorkflowStore.getState().setNeedsRedeploymentFlag(false) - } - }, [isDeployed]) - // Add a listener for the needsRedeployment flag in the workflow store useEffect(() => { const unsubscribe = useWorkflowStore.subscribe((state) => { diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx index dd6a60d6c2..62c835224a 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/starter/input-format.tsx @@ -1,4 +1,3 @@ -import { useEffect } from 'react' import { ChevronDown, Plus, Trash } from 'lucide-react' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts index f032dcbcec..c5a3e686d8 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/hooks/use-sub-block-value.ts @@ -207,50 +207,12 @@ export function useSubBlockValue( directValue, isPreview }); + } else if (!isPreview && previewDataRef.current.isInPreview) { + // Reset preview flag when isPreview prop changes to false + previewDataRef.current.isInPreview = false; } }, [isPreview, directValue, blockId, subBlockId]); - // Check for preview mode first and get direct subblock values if available - useEffect(() => { - // Skip DOM-based detection if already in preview mode with direct values - if (isPreview && directValue !== undefined) return; - - try { - // Try to find if this component is within a preview parent - const parentBlock = document.querySelector(`[data-id="${blockId}"]`); - if (parentBlock) { - const isPreviewContext = parentBlock.closest('.preview-mode') != null; - - // Get direct subblock values from parent's data props if in preview mode - if (isPreviewContext) { - const dataProps = parentBlock.getAttribute('data-props'); - if (dataProps) { - const parsedProps = JSON.parse(dataProps); - const directValue = parsedProps?.data?.subBlockValues?.[subBlockId]; - - // If we have direct values in preview mode, use them - if (directValue !== undefined && directValue !== null) { - // Save the values in our ref - previewDataRef.current = { - isInPreview: true, - directValue: directValue - }; - - // Update valueRef directly to use the preview value - valueRef.current = directValue; - - } - } - } else { - // Reset preview flag if we're no longer in preview mode - previewDataRef.current.isInPreview = false; - } - } - } catch (e) { - // Ignore errors in preview detection - } - }, [blockId, subBlockId, isPreview, directValue, storeValue]); - // Check if this is an API key field that could be auto-filled const isApiKey = subBlockId === 'apiKey' || (subBlockId?.toLowerCase().includes('apikey') ?? false) @@ -279,7 +241,7 @@ export function useSubBlockValue( // Otherwise use the store value or initial value valueRef.current = storeValue !== undefined ? storeValue : initialValue; } - }, []) + }, [storeValue, initialValue]) // Update the ref if the store value changes // This ensures we're always working with the latest value diff --git a/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx b/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx index 1e5f3d7cbd..4b6f4e3463 100644 --- a/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx +++ b/apps/sim/app/w/components/workflow-preview/workflow-preview.tsx @@ -1,6 +1,7 @@ 'use client' import { useMemo, useEffect } from 'react' +import { cloneDeep } from 'lodash' import ReactFlow, { Background, ConnectionLineType, @@ -126,7 +127,7 @@ export function WorkflowPreview({ } // Create a deep clone of subBlocks to avoid any references to the original state - const subBlocksClone = block.subBlocks ? JSON.parse(JSON.stringify(block.subBlocks)) : {}; + const subBlocksClone = block.subBlocks ? cloneDeep(block.subBlocks) : {}; nodeArray.push({ id: blockId,