fix: added greptile changes

This commit is contained in:
Adam Gough
2025-05-22 10:40:23 -07:00
parent 060b676313
commit 44c8f0556a
8 changed files with 62 additions and 101 deletions

View File

@@ -68,12 +68,12 @@ export function DeployedWorkflowCard({
.filter(([_, block]) => block && block.type) // Filter out invalid blocks
.map(([id, block]) => {
// Deep clone the block to avoid any reference sharing
const clonedBlock = JSON.parse(JSON.stringify(block));
const clonedBlock = structuredClone(block);
return [id, clonedBlock];
})
),
edges: workflowToShow.edges ? JSON.parse(JSON.stringify(workflowToShow.edges)) : [],
loops: workflowToShow.loops ? JSON.parse(JSON.stringify(workflowToShow.loops)) : {},
edges: workflowToShow.edges ? structuredClone(workflowToShow.edges) : [],
loops: workflowToShow.loops ? structuredClone(workflowToShow.loops) : {},
_metadata: {
...(workflowToShow._metadata || {}),
workflowId: activeWorkflowId,
@@ -87,7 +87,7 @@ export function DeployedWorkflowCard({
// Generate a unique key for the workflow preview
const previewKey = useMemo(() => {
return `${showingDeployed ? 'deployed' : 'current'}-preview-${activeWorkflowId}-${Date.now()}`;
return `${showingDeployed ? 'deployed' : 'current'}-preview-${activeWorkflowId}}`;
}, [showingDeployed, activeWorkflowId]);
return (

View File

@@ -53,30 +53,17 @@ export function DeployedWorkflowModal({
deployedWorkflowState,
}: DeployedWorkflowModalProps) {
const [showRevertDialog, setShowRevertDialog] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const { revertToDeployedState } = useWorkflowStore()
const activeWorkflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
// Add instance ID to track component lifecycle
const instanceId = useRef(Date.now());
const modalOpenCount = useRef(0);
// Keep track of the original deployed state when modal opens
const initialDeployedStateRef = useRef<any>(null);
useEffect(() => {
if (isOpen) {
modalOpenCount.current += 1;
// Store the initial deployed state when modal first opens
if (!initialDeployedStateRef.current) {
initialDeployedStateRef.current = deployedWorkflowState;
}
} else if (initialDeployedStateRef.current) {
// Reset the initial state reference when modal closes
initialDeployedStateRef.current = null;
}
}, [isOpen, deployedWorkflowState, activeWorkflowId]);
}, [isOpen]);
// Get current workflow state to compare with deployed state
const currentWorkflowState = useWorkflowStore((state) => ({
@@ -96,7 +83,7 @@ export function DeployedWorkflowModal({
.filter(([_, block]) => block && block.type)
.map(([id, block]) => {
// Deep clone the block to avoid any reference sharing
return [id, JSON.parse(JSON.stringify(block))];
return [id, structuredClone(block)];
})
),
edges: currentWorkflowState.edges ? [...currentWorkflowState.edges] : [],
@@ -154,7 +141,7 @@ export function DeployedWorkflowModal({
.filter(([_, block]) => block && block.type)
.map(([id, block]) => {
// Deep clone the block to avoid any reference sharing
return [id, JSON.parse(JSON.stringify(block))];
return [id, structuredClone(block)];
})
),
edges: deployedWorkflowState.edges ? [...deployedWorkflowState.edges] : [],
@@ -189,17 +176,10 @@ export function DeployedWorkflowModal({
<DialogTitle>Deployed Workflow</DialogTitle>
</DialogHeader>
</div>
{isLoading ? (
<div className="flex justify-center items-center h-[500px]">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
</div>
) : (
<DeployedWorkflowCard
currentWorkflowState={sanitizedCurrentState}
deployedWorkflowState={sanitizedDeployedState}
/>
)}
<DeployedWorkflowCard
currentWorkflowState={sanitizedCurrentState}
deployedWorkflowState={sanitizedDeployedState}
/>
<div className="flex justify-between mt-6">
{needsRedeployment && (

View File

@@ -1,25 +1,19 @@
'use client'
<<<<<<< HEAD
import { useEffect, useState } from 'react'
=======
import { useState, useEffect, useRef } from 'react'
>>>>>>> 2d314bcc (fix: deployed state preview persists across workflows)
import { Loader2, Rocket } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { createLogger } from '@/lib/logs/console-logger'
import { cn } from '@/lib/utils'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { WorkflowState } from '@/stores/workflows/workflow/types'
import { DeployModal } from '../deploy-modal/deploy-modal'
const _logger = createLogger('DeploymentControls')
interface DeploymentControlsProps {
activeWorkflowId: string | null
needsRedeployment: boolean
setNeedsRedeployment: (value: boolean) => void
deployedState: any
deployedState: WorkflowState | null
isLoadingDeployedState: boolean
refetchDeployedState: () => Promise<void>
}
@@ -47,65 +41,24 @@ export function DeploymentControls({
const [isDeploying, _setIsDeploying] = useState(false)
const [isModalOpen, setIsModalOpen] = useState(false)
// Add a ref to track the last seen workflow ID and deployed state
// Track the last seen workflow ID
const lastWorkflowIdRef = useRef<string | null>(null)
const lastDeployedStateRef = useRef<any>(null)
// Log when workflow ID changes
// Update last seen workflow ID
useEffect(() => {
if (activeWorkflowId !== lastWorkflowIdRef.current) {
logger.info('Workflow ID changed in DeploymentControls', {
previousId: lastWorkflowIdRef.current,
currentId: activeWorkflowId,
timestamp: Date.now()
});
lastWorkflowIdRef.current = activeWorkflowId;
}
}, [activeWorkflowId]);
// Log when deployed state changes
useEffect(() => {
if (deployedState && deployedState !== lastDeployedStateRef.current) {
const blockIds = Object.keys(deployedState?.blocks || {});
logger.info('Deployed state changed in DeploymentControls', {
workflowId: activeWorkflowId,
blockCount: blockIds.length,
blockIds: JSON.stringify(blockIds.slice(0, 3)),
isLoadingState: isLoadingDeployedState,
timestamp: Date.now(),
stateHash: JSON.stringify(deployedState).length
});
lastDeployedStateRef.current = deployedState;
}
}, [deployedState, activeWorkflowId, isLoadingDeployedState]);
// Add wrapper around refetchDeployedState to track timing
const refetchWithLogging = async () => {
// Refetch deployed state wrapper
const refetchWithErrorHandling = async () => {
if (!activeWorkflowId) return;
const fetchId = Date.now();
logger.info('Starting deployedState refetch', {
workflowId: activeWorkflowId,
fetchId,
timestamp: Date.now()
});
try {
await refetchDeployedState();
logger.info('Completed deployedState refetch', {
workflowId: activeWorkflowId,
fetchId,
timestamp: Date.now(),
duration: Date.now() - fetchId
});
} catch (error) {
logger.error('Error in deployedState refetch', {
workflowId: activeWorkflowId,
fetchId,
error,
timestamp: Date.now()
});
// Silent error handling
}
};
@@ -174,7 +127,7 @@ export function DeploymentControls({
setNeedsRedeployment={setNeedsRedeployment}
deployedState={deployedState}
isLoadingDeployedState={isLoadingDeployedState}
refetchDeployedState={refetchWithLogging}
refetchDeployedState={refetchWithErrorHandling}
/>
</>
)

View File

@@ -218,11 +218,10 @@ export function ControlBar() {
// Function to check if redeployment is needed
const checkForChanges = async () => {
// Skip if we're already showing needsRedeployment
if (needsRedeployment) return
// Reset the pending changes counter
pendingChanges = 0
lastCheckTime = Date.now()
pendingChanges = 0;
lastCheckTime = Date.now();
try {
// Get the deployed state from the API
@@ -235,6 +234,10 @@ export function ControlBar() {
setNeedsRedeployment(true)
// Also update the store state so other components can access this flag
useWorkflowStore.getState().setNeedsRedeploymentFlag(true)
} else {
// Add this else branch to handle the case when changes are reverted
setNeedsRedeployment(false)
useWorkflowStore.getState().setNeedsRedeploymentFlag(false)
}
}
} catch (error) {
@@ -397,11 +400,6 @@ export function ControlBar() {
if (isDeployed) {
setNeedsRedeployment(false)
useWorkflowStore.getState().setNeedsRedeploymentFlag(false)
// When a workflow is newly deployed, we need to fetch the deployed state
if (activeWorkflowId && deployedState === null) {
// We'll fetch the deployed state in the other useEffect
}
} else {
// If workflow is undeployed, clear the deployed state
setDeployedState(null)

View File

@@ -37,12 +37,21 @@ export function ShortInput({
const [isFocused, setIsFocused] = useState(false)
const [showEnvVars, setShowEnvVars] = useState(false)
const [showTags, setShowTags] = useState(false)
const validatePropValue = (value: any): string => {
if (value === undefined || value === null) return '';
if (typeof value === 'string') return value;
try {
return String(value);
} catch {
return '';
}
}
const [storeValue, setStoreValue] = useSubBlockValue(
blockId,
subBlockId,
false, // No workflow update needed
isPreview,
propValue
validatePropValue(propValue)
)
const [searchTerm, setSearchTerm] = useState('')
const [cursorPosition, setCursorPosition] = useState(0)

View File

@@ -288,7 +288,11 @@ interface WebhookConfigProps {
subBlockId?: string
isConnecting: boolean
isPreview?: boolean
value?: any
value?: {
webhookProvider?: string
webhookPath?: string
providerConfig?: ProviderConfig
}
}
export function WebhookConfig({

View File

@@ -237,7 +237,7 @@ export function useSubBlockValue<T = any>(
// Otherwise use the store value or initial value
valueRef.current = storeValue !== undefined ? storeValue : initialValue;
}
}, [storeValue, initialValue])
}, [storeValue, initialValue, isPreview])
// Update the ref if the store value changes
// This ensures we're always working with the latest value

View File

@@ -1,6 +1,6 @@
'use client'
import { useMemo, useEffect } from 'react'
import { useMemo } from 'react'
import { cloneDeep } from 'lodash'
import ReactFlow, {
Background,
@@ -78,6 +78,22 @@ export function WorkflowPreview({
defaultPosition,
defaultZoom,
}: WorkflowPreviewProps) {
// Track structure changes efficiently
const blocksStructure = useMemo(() => ({
count: Object.keys(workflowState.blocks || {}).length,
ids: Object.keys(workflowState.blocks || {}).join(',')
}), [workflowState.blocks]);
const loopsStructure = useMemo(() => ({
count: Object.keys(workflowState.loops || {}).length,
ids: Object.keys(workflowState.loops || {}).join(',')
}), [workflowState.loops]);
const edgesStructure = useMemo(() => ({
count: workflowState.edges.length,
ids: workflowState.edges.map(e => e.id).join(',')
}), [workflowState.edges]);
// Transform blocks and loops into ReactFlow nodes
const nodes: Node[] = useMemo(() => {
const nodeArray: Node[] = []
@@ -167,8 +183,9 @@ export function WorkflowPreview({
});
})
return nodeArray
}, [JSON.stringify(workflowState.blocks), JSON.stringify(workflowState.loops), showSubBlocks])
}, [blocksStructure, loopsStructure, showSubBlocks, workflowState.blocks, workflowState.loops])
// Transform edges
const edges: Edge[] = useMemo(() => {
@@ -180,7 +197,7 @@ export function WorkflowPreview({
targetHandle: edge.targetHandle,
type: 'workflowEdge',
}))
}, [JSON.stringify(workflowState.edges)])
}, [edgesStructure, workflowState.edges])
return (
<ReactFlowProvider>