diff --git a/skyvern-frontend/src/routes/workflows/editor/Workspace.tsx b/skyvern-frontend/src/routes/workflows/editor/Workspace.tsx
index 1d26f313..c933839c 100644
--- a/skyvern-frontend/src/routes/workflows/editor/Workspace.tsx
+++ b/skyvern-frontend/src/routes/workflows/editor/Workspace.tsx
@@ -1,5 +1,11 @@
import { AxiosError } from "axios";
-import { useEffect, useRef, useState, MutableRefObject } from "react";
+import {
+ useCallback,
+ useEffect,
+ useRef,
+ useState,
+ MutableRefObject,
+} from "react";
import { nanoid } from "nanoid";
import {
ChevronRightIcon,
@@ -300,6 +306,33 @@ function Workspace({
closeWorkflowPanel();
});
+ // Centralized function to manage comparison and panel states
+ const clearComparisonViewAndShowFreshIfActive = useCallback(
+ (active: boolean) => {
+ setWorkflowPanelState({
+ active,
+ content: "history",
+ data: {
+ showComparison: false,
+ version1: undefined,
+ version2: undefined,
+ },
+ });
+ },
+ [setWorkflowPanelState],
+ );
+
+ // Clear comparison view when switching between browser mode and editor mode
+ useEffect(() => {
+ if (workflowPanelState.data?.showComparison) {
+ clearComparisonViewAndShowFreshIfActive(false);
+ setShowAllCode(false);
+ }
+ // We intentionally omit workflowPanelState.data?.showComparison from deps
+ // to avoid clearing comparison immediately when it's set
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [showBrowser, clearComparisonViewAndShowFreshIfActive]);
+
useMountEffect(() => {
const closePanelsWhenEscapeIsPressed = (e: KeyboardEvent) => {
if (e.key === "Escape") {
@@ -572,19 +605,6 @@ function Workspace({
}
}
- // Centralized function to manage comparison and panel states
- function clearComparisonViewAndShowFreshIfActive(active: boolean) {
- setWorkflowPanelState({
- active,
- content: "history",
- data: {
- showComparison: false,
- version1: undefined,
- version2: undefined,
- },
- });
- }
-
function toggleHistoryPanel() {
// Capture current state before making changes
const wasInComparisonMode = workflowPanelState.data?.showComparison;
@@ -895,39 +915,26 @@ function Workspace({
/>
- {/* infinite canvas and sub panels when not in debug mode */}
- {!showBrowser && (
+ {/* comparison view (takes precedence over both browser and non-browser modes) */}
+ {workflowPanelState.data?.showComparison &&
+ workflowPanelState.data?.version1 &&
+ workflowPanelState.data?.version2 ? (
- {/* infinite canvas or comparison view */}
- {workflowPanelState.data?.showComparison &&
- workflowPanelState.data?.version1 &&
- workflowPanelState.data?.version2 ? (
-
-
-
- ) : (
-
+
- )}
+
{/* sub panels */}
{workflowPanelState.active && (
@@ -984,46 +991,122 @@ function Workspace({
)}
+ ) : (
+ <>
+ {/* infinite canvas and sub panels when not in debug mode */}
+ {!showBrowser && (
+
+ {/* infinite canvas */}
+
+
+ {/* sub panels */}
+ {workflowPanelState.active && (
+
+ {workflowPanelState.content === "cacheKeyValues" && (
+
{
+ setToDeleteCacheKeyValue(cacheKeyValue);
+ setOpenConfirmCacheKeyValueDeleteDialogue(true);
+ }}
+ onPaginate={(page) => {
+ setPage(page);
+ }}
+ onSelect={(cacheKeyValue) => {
+ setCacheKeyValue(cacheKeyValue);
+ setCacheKeyValueFilter("");
+ closeWorkflowPanel();
+ }}
+ />
+ )}
+ {workflowPanelState.content === "parameters" && (
+
+
+
+ )}
+ {workflowPanelState.content === "history" && (
+
+
+
+ )}
+ {workflowPanelState.content === "nodeLibrary" && (
+
+ {
+ addNode(props);
+ }}
+ />
+
+ )}
+
+ )}
+
+ )}
+ >
)}
{/* sub panels when in debug mode */}
- {showBrowser && workflowPanelState.active && (
-
- {workflowPanelState.content === "cacheKeyValues" && (
- {
- setToDeleteCacheKeyValue(cacheKeyValue);
- setOpenConfirmCacheKeyValueDeleteDialogue(true);
- }}
- onPaginate={(page) => {
- setPage(page);
- }}
- onSelect={(cacheKeyValue) => {
- setCacheKeyValue(cacheKeyValue);
- setCacheKeyValueFilter("");
- closeWorkflowPanel();
- }}
- />
- )}
- {workflowPanelState.content === "parameters" && (
-
- )}
-
- )}
+ {showBrowser &&
+ !workflowPanelState.data?.showComparison &&
+ workflowPanelState.active && (
+
+ {workflowPanelState.content === "cacheKeyValues" && (
+ {
+ setToDeleteCacheKeyValue(cacheKeyValue);
+ setOpenConfirmCacheKeyValueDeleteDialogue(true);
+ }}
+ onPaginate={(page) => {
+ setPage(page);
+ }}
+ onSelect={(cacheKeyValue) => {
+ setCacheKeyValue(cacheKeyValue);
+ setCacheKeyValueFilter("");
+ closeWorkflowPanel();
+ }}
+ />
+ )}
+ {workflowPanelState.content === "parameters" && (
+
+ )}
+
+ )}
{/* code, infinite canvas, browser, and timeline when in debug mode */}
- {showBrowser && (
+ {showBrowser && !workflowPanelState.data?.showComparison && (
setContainerResizeTrigger((prev) => prev + 1)}
>
- {/* code and infinite canvas or comparison view */}
+ {/* code and infinite canvas */}
- {workflowPanelState.data?.showComparison &&
- workflowPanelState.data?.version1 &&
- workflowPanelState.data?.version2 ? (
+
+ {/* code */}
-
-
- ) : (
-
- {/* code */}
-
-
-
-
-
-
+
- {/* infinite canvas */}
-
-
- )}
+ {/* infinite canvas */}
+
+
+
+
{/* browser & timeline */}
diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowComparisonPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowComparisonPanel.tsx
index 2f2bc4ba..10c58f3f 100644
--- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowComparisonPanel.tsx
+++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowComparisonPanel.tsx
@@ -1,5 +1,4 @@
import { useCallback, useMemo } from "react";
-import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import {
@@ -171,7 +170,6 @@ function getWorkflowElements(version: WorkflowVersion) {
function WorkflowComparisonRenderer({
version,
- onSelectState,
blockColors,
}: {
version: WorkflowVersion;
@@ -239,45 +237,19 @@ function WorkflowComparisonRenderer({
);
return (
-
-
-
-
-
- {version.title}, version: {version.version}
-
-
- {version.workflow_definition?.blocks?.length || 0} block
- {(version.workflow_definition?.blocks?.length || 0) !== 1
- ? "s"
- : ""}
-
- {onSelectState && (
-
- )}
-
-
-
-
-
-
+
+
);
}
@@ -349,23 +321,70 @@ function WorkflowComparisonPanel({ version1, version2, onSelectState }: Props) {
{/* Header */}
-
Version Comparison
-
-
-
-
Identical ({stats.identical})
+ {/* 3x3 Grid Layout */}
+
+ {/* Row 1: Workflow Names and Title */}
+
+ {version1.title}
+
+
+ Version Comparison
+
+
+ {version2.title}
+
+
+ {/* Row 2: Version Details and Statistics */}
+
+ [Version {version1.version}] •{" "}
+ {new Date(version1.modified_at).toLocaleDateString()}
-
-
-
Modified ({stats.modified})
+
+
+
+
Identical ({stats.identical})
+
+
+
+
Modified ({stats.modified})
+
+
+
+
Added ({stats.added})
+
+
+
+
Removed ({stats.removed})
+
-
-
-
Added ({stats.added})
+
+ [Version {version2.version}] •{" "}
+ {new Date(version2.modified_at).toLocaleDateString()}
-
-
-
Removed ({stats.removed})
+
+ {/* Row 3: Select Buttons */}
+
+ {onSelectState && (
+
+ )}
+
+
+
+ {onSelectState && (
+
+ )}
diff --git a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowHistoryPanel.tsx b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowHistoryPanel.tsx
index c23fe213..2be60dba 100644
--- a/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowHistoryPanel.tsx
+++ b/skyvern-frontend/src/routes/workflows/editor/panels/WorkflowHistoryPanel.tsx
@@ -101,6 +101,27 @@ function WorkflowHistoryPanel({ workflowPermanentId, onCompare }: Props) {
+ {/* Compare Buttons */}
+
+
+
+
+
+
+
{/* Version List */}
@@ -166,29 +187,6 @@ function WorkflowHistoryPanel({ workflowPermanentId, onCompare }: Props) {
)}
-
-
-
- {/* Footer */}
-
-
-
-
-
-
);
}