mirror of
https://github.com/Skyvern-AI/skyvern.git
synced 2026-07-09 16:09:13 +00:00
fix(SKY-11826): gate the legacy Visual/Code toggle to /edit and anchor it under the header (#7065)
Co-authored-by: AronPerez <aperez0295@gmail.com>
This commit is contained in:
parent
babe19b186
commit
86e31de917
3 changed files with 29 additions and 50 deletions
|
|
@ -165,6 +165,7 @@ import { WorkflowHistoryPanel } from "./panels/WorkflowHistoryPanel";
|
|||
import { WorkflowSchedulePanel } from "./panels/schedulePanel/WorkflowSchedulePanel";
|
||||
import { WorkflowVersion } from "../hooks/useWorkflowVersionsQuery";
|
||||
import { WorkflowDefinition, WorkflowSettings } from "../types/workflowTypes";
|
||||
import { useAgentsPathMatch } from "../useAgentsPathMatch";
|
||||
import { shouldKeepExistingEdgeForInsertion } from "./workflowInsertion";
|
||||
|
||||
import { constructCacheKeyValue, getInitialParameters } from "./utils";
|
||||
|
|
@ -402,6 +403,7 @@ function Workspace({
|
|||
selectedBlockId,
|
||||
isNodeLibraryOpen,
|
||||
);
|
||||
const isEditRoute = useAgentsPathMatch("/:workflowPermanentId/edit") !== null;
|
||||
// While collapsed, the pill is offscreen but its WorkflowHeaderCollapseTab
|
||||
// (chevron) sits at the bottom edge, centered on the pill. If we let the
|
||||
// pill's right inset track blockSidebarOpen while collapsed, the tab snaps
|
||||
|
|
@ -2155,6 +2157,31 @@ function Workspace({
|
|||
historyApplyTrigger={historyApplyTrigger}
|
||||
/>
|
||||
|
||||
{/* Studio hosts the toggle in the Editor pane header; legacy
|
||||
anchors it under the header on /edit only (the debugger
|
||||
mounts this Workspace too). */}
|
||||
{!yamlEditorActive &&
|
||||
!isGlobalWorkflow &&
|
||||
!embedded &&
|
||||
isEditRoute ? (
|
||||
<div
|
||||
className={cn(
|
||||
"absolute top-[8.5rem] z-30 transition-all duration-300 ease-out",
|
||||
blockSidebarOpen
|
||||
? HEADER_RIGHT_INSET_OPEN
|
||||
: HEADER_RIGHT_INSET_CLOSED,
|
||||
)}
|
||||
style={{
|
||||
transform: headerCollapsed
|
||||
? "translateY(calc(-100% - 8.5rem))"
|
||||
: "translateY(0)",
|
||||
opacity: headerCollapsed ? 0 : 1,
|
||||
}}
|
||||
>
|
||||
<YamlModeToggle mode="visual" onCode={enterYamlMode} />
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* sub panels */}
|
||||
{workflowPanelState.active && (
|
||||
<>
|
||||
|
|
@ -2988,12 +3015,6 @@ function Workspace({
|
|||
}}
|
||||
/>
|
||||
|
||||
{/* Studio hosts the toggle in the Editor pane header instead. */}
|
||||
{!yamlEditorActive && !isGlobalWorkflow && !embedded ? (
|
||||
<div className="absolute right-4 top-3 z-30">
|
||||
<YamlModeToggle mode="visual" onCode={enterYamlMode} />
|
||||
</div>
|
||||
) : null}
|
||||
{/* Studio: the cache key/value panel escapes the Editor pane via the
|
||||
shell-level portal, so the Overview pane's Code view can open it (and
|
||||
close it) even with the Editor pane hidden. */}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
formatDuration,
|
||||
normalizeJsonParameterFormValue,
|
||||
parseJsonWorkflowParameterValue,
|
||||
toDuration,
|
||||
validateJsonWorkflowParameterValue,
|
||||
} from "./utils";
|
||||
|
||||
|
|
@ -80,44 +78,3 @@ describe("validateJsonWorkflowParameterValue", () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("toDuration", () => {
|
||||
it("converts sub-minute durations", () => {
|
||||
expect(toDuration(45)).toEqual({ hour: 0, minute: 0, second: 45 });
|
||||
});
|
||||
|
||||
it("converts minutes and seconds", () => {
|
||||
expect(toDuration(125)).toEqual({ hour: 0, minute: 2, second: 5 });
|
||||
});
|
||||
|
||||
it("converts hours, minutes, and seconds", () => {
|
||||
expect(toDuration(3661)).toEqual({ hour: 1, minute: 1, second: 1 });
|
||||
});
|
||||
|
||||
it("floors fractional seconds", () => {
|
||||
expect(toDuration(90.7)).toEqual({ hour: 0, minute: 1, second: 30 });
|
||||
});
|
||||
|
||||
it("preserves hours beyond 24 instead of wrapping", () => {
|
||||
// 25h exactly — `hours % 24` used to report this as 1h since Duration
|
||||
// has no day field to carry the overflow.
|
||||
expect(toDuration(90000)).toEqual({ hour: 25, minute: 0, second: 0 });
|
||||
});
|
||||
|
||||
it("preserves multi-day durations in the hour field", () => {
|
||||
// 49h 1m 5s
|
||||
expect(toDuration(176465)).toEqual({ hour: 49, minute: 1, second: 5 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatDuration", () => {
|
||||
it("omits empty leading units", () => {
|
||||
expect(formatDuration(toDuration(45))).toBe("45s");
|
||||
expect(formatDuration(toDuration(125))).toBe("2m 5s");
|
||||
expect(formatDuration(toDuration(3661))).toBe("1h 1m 1s");
|
||||
});
|
||||
|
||||
it("renders durations longer than a day without losing hours", () => {
|
||||
expect(formatDuration(toDuration(90000))).toBe("25h 0m 0s");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -169,9 +169,10 @@ export interface Duration {
|
|||
|
||||
export const toDuration = (seconds: number): Duration => {
|
||||
let minutes = Math.floor(seconds / 60);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
let hours = Math.floor(minutes / 60);
|
||||
seconds = seconds % 60;
|
||||
minutes = minutes % 60;
|
||||
hours = hours % 24;
|
||||
|
||||
return {
|
||||
hour: Math.floor(hours),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue