diff --git a/src/components/Editor/Context/PipelineDetails.tsx b/src/components/Editor/Context/PipelineDetails.tsx index 9bcc91417..8b09856ff 100644 --- a/src/components/Editor/Context/PipelineDetails.tsx +++ b/src/components/Editor/Context/PipelineDetails.tsx @@ -1,12 +1,12 @@ import { useEffect, useState } from "react"; import { useValidationIssueNavigation } from "@/components/Editor/hooks/useValidationIssueNavigation"; +import { ViewYamlButton } from "@/components/shared/Buttons/ViewYamlButton"; import { ActionBlock } from "@/components/shared/ContextPanel/Blocks/ActionBlock"; import { ContentBlock } from "@/components/shared/ContextPanel/Blocks/ContentBlock"; import { ListBlock } from "@/components/shared/ContextPanel/Blocks/ListBlock"; import { TextBlock } from "@/components/shared/ContextPanel/Blocks/TextBlock"; import { CopyText } from "@/components/shared/CopyText/CopyText"; -import { TaskImplementation } from "@/components/shared/TaskDetails"; import { BlockStack } from "@/components/ui/layout"; import useToastNotification from "@/hooks/useToastNotification"; import { useComponentSpec } from "@/providers/ComponentSpecProvider"; @@ -83,12 +83,7 @@ const PipelineDetails = () => { const actions = [ , - , + , ]; return ( diff --git a/src/components/PipelineRun/RunDetails.tsx b/src/components/PipelineRun/RunDetails.tsx index cc207b46a..75f545640 100644 --- a/src/components/PipelineRun/RunDetails.tsx +++ b/src/components/PipelineRun/RunDetails.tsx @@ -1,7 +1,4 @@ -import { - ActionBlock, - type ActionOrReactNode, -} from "@/components/shared/ContextPanel/Blocks/ActionBlock"; +import { ActionBlock } from "@/components/shared/ContextPanel/Blocks/ActionBlock"; import { ContentBlock } from "@/components/shared/ContextPanel/Blocks/ContentBlock"; import { ListBlock } from "@/components/shared/ContextPanel/Blocks/ListBlock"; import { TextBlock } from "@/components/shared/ContextPanel/Blocks/TextBlock"; @@ -10,7 +7,6 @@ import PipelineIO from "@/components/shared/Execution/PipelineIO"; import { InfoBox } from "@/components/shared/InfoBox"; import { LoadingScreen } from "@/components/shared/LoadingScreen"; import { StatusBar } from "@/components/shared/Status"; -import { TaskImplementation } from "@/components/shared/TaskDetails"; import { BlockStack, InlineStack } from "@/components/ui/layout"; import { Text } from "@/components/ui/typography"; import { useCheckComponentSpecFromPath } from "@/hooks/useCheckComponentSpecFromPath"; @@ -26,6 +22,7 @@ import { isExecutionComplete, } from "@/utils/executionStatus"; +import { ViewYamlButton } from "../shared/Buttons/ViewYamlButton"; import { CancelPipelineRunButton } from "./components/CancelPipelineRunButton"; import { ClonePipelineButton } from "./components/ClonePipelineButton"; import { InspectPipelineButton } from "./components/InspectPipelineButton"; @@ -93,14 +90,10 @@ export const RunDetails = () => { const annotations = componentSpec.metadata?.annotations || {}; - const actions: ActionOrReactNode[] = []; + const actions = []; actions.push( - , + , ); if (canAccessEditorSpec && componentSpec.name) { diff --git a/src/components/shared/Buttons/ViewYamlButton.tsx b/src/components/shared/Buttons/ViewYamlButton.tsx new file mode 100644 index 000000000..76430fd85 --- /dev/null +++ b/src/components/shared/Buttons/ViewYamlButton.tsx @@ -0,0 +1,56 @@ +import { useState } from "react"; + +import { Icon } from "@/components/ui/icon"; +import type { + ComponentSpec, + HydratedComponentReference, +} from "@/utils/componentSpec"; +import { getComponentName } from "@/utils/getComponentName"; + +import TaskImplementation from "../TaskDetails/Implementation"; +import TooltipButton from "./TooltipButton"; + +type ViewYamlButtonProps = + | { componentRef: HydratedComponentReference; componentSpec?: never } + | { componentSpec: ComponentSpec; componentRef?: never }; + +export const ViewYamlButton = ({ + componentRef, + componentSpec, +}: ViewYamlButtonProps) => { + const [showCodeViewer, setShowCodeViewer] = useState(false); + + const name = componentRef + ? getComponentName(componentRef) + : componentSpec.name || "Component"; + + const handleClick = () => { + setShowCodeViewer(true); + }; + + const handleClose = () => { + setShowCodeViewer(false); + }; + + return ( + <> + + + + + {showCodeViewer && ( + + )} + + ); +}; diff --git a/src/components/shared/CodeViewer/CodeViewer.tsx b/src/components/shared/CodeViewer/CodeViewer.tsx index f138e667d..b02e034e4 100644 --- a/src/components/shared/CodeViewer/CodeViewer.tsx +++ b/src/components/shared/CodeViewer/CodeViewer.tsx @@ -1,10 +1,8 @@ -import { FileCode2, Maximize2, X as XIcon } from "lucide-react"; import { useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; -import { cn } from "@/lib/utils"; +import { Icon } from "@/components/ui/icon"; -import TooltipButton from "../Buttons/TooltipButton"; import { FullscreenElement } from "../FullscreenElement"; import CodeSyntaxHighlighter from "./CodeSyntaxHighlighter"; @@ -12,7 +10,8 @@ interface CodeViewerProps { code: string; language?: string; filename?: string; - showInlineContent?: boolean; + fullscreen?: boolean; + onClose?: () => void; } const DEFAULT_CODE_VIEWER_HEIGHT = 128; @@ -21,28 +20,19 @@ const CodeViewer = ({ code, language = "yaml", filename = "", - showInlineContent = true, + fullscreen = false, + onClose, }: CodeViewerProps) => { - const [isFullscreen, setIsFullscreen] = useState(false); - const shouldRenderInlineCode = showInlineContent || isFullscreen; + const [isFullscreen, setIsFullscreen] = useState(fullscreen); + + const handleToggleFullscreen = () => { + if (isFullscreen && onClose) { + onClose(); + } - const handleEnterFullscreen = () => { setIsFullscreen((prev) => !prev); }; - const compactButton = ( - - - - ); - useEffect(() => { const handleEscapeKey = (e: KeyboardEvent) => { if (isFullscreen && e.key === "Escape") { @@ -61,54 +51,37 @@ const CodeViewer = ({ return ( -
- {shouldRenderInlineCode ? ( -
-
- - {filename} - - (Read Only) -
- +
+
+
+ + {filename} + + (Read Only)
- ) : ( -
{compactButton}
- )} - {shouldRenderInlineCode && ( -
-
- -
+ +
+
+
+
- )} +
); diff --git a/src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskOverview/TaskOverview.tsx b/src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskOverview/TaskOverview.tsx index ad15f23ef..d724fd675 100644 --- a/src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskOverview/TaskOverview.tsx +++ b/src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskOverview/TaskOverview.tsx @@ -8,13 +8,11 @@ import { import type { TooltipButtonProps } from "@/components/shared/Buttons/TooltipButton"; import TooltipButton from "@/components/shared/Buttons/TooltipButton"; +import { ViewYamlButton } from "@/components/shared/Buttons/ViewYamlButton"; import { ComponentDetailsDialog } from "@/components/shared/Dialogs"; import { ComponentFavoriteToggle } from "@/components/shared/FavoriteComponentToggle"; import { StatusIcon } from "@/components/shared/Status"; -import { - TaskDetails, - TaskImplementation, -} from "@/components/shared/TaskDetails"; +import { TaskDetails } from "@/components/shared/TaskDetails"; import { Icon } from "@/components/ui/icon"; import { BlockStack, InlineStack } from "@/components/ui/layout"; import { Separator } from "@/components/ui/separator"; @@ -66,12 +64,7 @@ const TaskOverview = ({ taskNode, actions }: TaskOverviewProps) => { ...(actions?.map((action) => ( )) ?? []), - , + , ]; return ( diff --git a/src/components/shared/TaskDetails/Implementation.tsx b/src/components/shared/TaskDetails/Implementation.tsx index 1360ad0ab..ac84b132e 100644 --- a/src/components/shared/TaskDetails/Implementation.tsx +++ b/src/components/shared/TaskDetails/Implementation.tsx @@ -9,7 +9,8 @@ interface TaskImplementationProps { displayName: string; componentRef?: ComponentReference; componentSpec?: ComponentSpec; - showInlineContent?: boolean; + fullscreen?: boolean; + onClose?: () => void; } const TaskImplementation = withSuspenseWrapper( @@ -17,14 +18,16 @@ const TaskImplementation = withSuspenseWrapper( displayName, componentRef, componentSpec, - showInlineContent = true, + fullscreen, + onClose, }: TaskImplementationProps) => { if (componentRef) { return ( ); } @@ -34,7 +37,8 @@ const TaskImplementation = withSuspenseWrapper( ); } @@ -51,8 +55,9 @@ const ComponentRefCodeViewer = withSuspenseWrapper( ({ componentRef, displayName, - showInlineContent = true, - }: Pick & { + fullscreen, + onClose, + }: Omit & { componentRef: ComponentReference; }) => { const hydratedComponentRef = useHydrateComponentReference(componentRef); @@ -66,7 +71,8 @@ const ComponentRefCodeViewer = withSuspenseWrapper( code={hydratedComponentRef.text} language="yaml" filename={displayName} - showInlineContent={showInlineContent} + fullscreen={fullscreen} + onClose={onClose} /> ); }, @@ -75,8 +81,9 @@ const ComponentRefCodeViewer = withSuspenseWrapper( const ComponentSpecCodeViewer = ({ componentSpec, displayName, - showInlineContent = true, -}: Pick & { + fullscreen, + onClose, +}: Omit & { componentSpec: ComponentSpec; }) => { const code = componentSpecToText(componentSpec); @@ -86,7 +93,8 @@ const ComponentSpecCodeViewer = ({ code={code} language="yaml" filename={displayName} - showInlineContent={showInlineContent} + fullscreen={fullscreen} + onClose={onClose} /> ); };