Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions src/components/Editor/Context/PipelineDetails.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -83,12 +83,7 @@ const PipelineDetails = () => {

const actions = [
<RenamePipeline key="rename-pipeline-action" />,
<TaskImplementation
key="pipeline-implementation-action"
displayName={componentSpec.name ?? "Pipeline"}
componentSpec={componentSpec}
showInlineContent={false}
/>,
<ViewYamlButton key="view-pipeline-yaml" componentSpec={componentSpec} />,
];

return (
Expand Down
15 changes: 4 additions & 11 deletions src/components/PipelineRun/RunDetails.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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";
Expand All @@ -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";
Expand Down Expand Up @@ -93,14 +90,10 @@ export const RunDetails = () => {

const annotations = componentSpec.metadata?.annotations || {};

const actions: ActionOrReactNode[] = [];
const actions = [];

actions.push(
<TaskImplementation
displayName={componentSpec.name ?? "Pipeline"}
componentSpec={componentSpec}
showInlineContent={false}
/>,
<ViewYamlButton key="view-pipeline-yaml" componentSpec={componentSpec} />,
);

if (canAccessEditorSpec && componentSpec.name) {
Expand Down
56 changes: 56 additions & 0 deletions src/components/shared/Buttons/ViewYamlButton.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<>
<TooltipButton
variant="outline"
tooltip="View YAML"
onClick={handleClick}
>
<Icon name="FileCodeCorner" />
</TooltipButton>

{showCodeViewer && (
<TaskImplementation
componentRef={componentRef}
componentSpec={componentSpec}
displayName={name}
fullscreen
onClose={handleClose}
/>
)}
</>
);
};
107 changes: 40 additions & 67 deletions src/components/shared/CodeViewer/CodeViewer.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
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";

interface CodeViewerProps {
code: string;
language?: string;
filename?: string;
showInlineContent?: boolean;
fullscreen?: boolean;
onClose?: () => void;
}

const DEFAULT_CODE_VIEWER_HEIGHT = 128;
Expand All @@ -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 = (
<TooltipButton
type="button"
variant="outline"
size="icon"
tooltip="View YAML"
onClick={handleEnterFullscreen}
aria-label="View YAML"
>
<FileCode2 className="size-4" />
</TooltipButton>
);

useEffect(() => {
const handleEscapeKey = (e: KeyboardEvent) => {
if (isFullscreen && e.key === "Escape") {
Expand All @@ -61,54 +51,37 @@ const CodeViewer = ({

return (
<FullscreenElement fullscreen={isFullscreen}>
<div
className={cn(
"flex flex-col transition-shadow duration-150",
shouldRenderInlineCode
? "bg-slate-900 h-full rounded-md"
: "bg-transparent",
)}
>
{shouldRenderInlineCode ? (
<div className="flex items-center justify-between gap-2 bg-slate-800 sticky top-0 z-10 rounded-t-md px-3 py-2.5">
<div className="flex items-baseline gap-2">
<span className="font-semibold text-base text-secondary">
{filename}
</span>
<span className="text-sm text-secondary">(Read Only)</span>
</div>
<Button
type="button"
variant="ghost"
size="icon"
onClick={handleEnterFullscreen}
className="text-gray-200 hover:text-white"
title={isFullscreen ? "Exit fullscreen" : "View fullscreen"}
aria-label={isFullscreen ? "Exit fullscreen" : "View fullscreen"}
>
{isFullscreen ? (
<XIcon className="size-4" />
) : (
<Maximize2 className="size-4" />
)}
</Button>
<div className="flex flex-col transition-shadow duration-150 bg-slate-900 h-full rounded-md">
<div className="flex items-center justify-between gap-2 bg-slate-800 sticky top-0 z-10 rounded-t-md px-3 py-2.5">
<div className="flex items-baseline gap-2">
<span className="font-semibold text-base text-secondary">
{filename}
</span>
<span className="text-sm text-secondary">(Read Only)</span>
</div>
) : (
<div className="flex">{compactButton}</div>
)}
{shouldRenderInlineCode && (
<div className="flex-1 relative">
<div
className="absolute inset-0 overflow-y-auto bg-slate-900"
style={{
willChange: "transform",
minHeight: DEFAULT_CODE_VIEWER_HEIGHT,
}}
>
<CodeSyntaxHighlighter code={code} language={language} />
</div>
<Button
type="button"
variant="ghost"
size="icon"
onClick={handleToggleFullscreen}
className="text-gray-200 hover:text-black"
title={isFullscreen ? "Exit fullscreen" : "View fullscreen"}
aria-label={isFullscreen ? "Exit fullscreen" : "View fullscreen"}
>
{isFullscreen ? <Icon name="X" /> : <Icon name="Maximize2" />}
</Button>
</div>
<div className="flex-1 relative">
<div
className="absolute inset-0 overflow-y-auto bg-slate-900"
style={{
willChange: "transform",
minHeight: DEFAULT_CODE_VIEWER_HEIGHT,
}}
>
<CodeSyntaxHighlighter code={code} language={language} />
</div>
)}
</div>
</div>
</FullscreenElement>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -66,12 +64,7 @@ const TaskOverview = ({ taskNode, actions }: TaskOverviewProps) => {
...(actions?.map((action) => (
<TooltipButton {...action} key={action.tooltip?.toString()} />
)) ?? []),
<TaskImplementation
key="task-implementation-action"
displayName={name}
componentRef={taskSpec.componentRef}
showInlineContent={false}
/>,
<ViewYamlButton key="view-task-yaml" componentSpec={componentSpec} />,
];

return (
Expand Down
28 changes: 18 additions & 10 deletions src/components/shared/TaskDetails/Implementation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,25 @@ interface TaskImplementationProps {
displayName: string;
componentRef?: ComponentReference;
componentSpec?: ComponentSpec;
showInlineContent?: boolean;
fullscreen?: boolean;
onClose?: () => void;
}

const TaskImplementation = withSuspenseWrapper(
({
displayName,
componentRef,
componentSpec,
showInlineContent = true,
fullscreen,
onClose,
}: TaskImplementationProps) => {
if (componentRef) {
return (
<ComponentRefCodeViewer
componentRef={componentRef}
displayName={displayName}
showInlineContent={showInlineContent}
fullscreen={fullscreen}
onClose={onClose}
/>
);
}
Expand All @@ -34,7 +37,8 @@ const TaskImplementation = withSuspenseWrapper(
<ComponentSpecCodeViewer
componentSpec={componentSpec}
displayName={displayName}
showInlineContent={showInlineContent}
fullscreen={fullscreen}
onClose={onClose}
/>
);
}
Expand All @@ -51,8 +55,9 @@ const ComponentRefCodeViewer = withSuspenseWrapper(
({
componentRef,
displayName,
showInlineContent = true,
}: Pick<TaskImplementationProps, "displayName" | "showInlineContent"> & {
fullscreen,
onClose,
}: Omit<TaskImplementationProps, "componentSpec"> & {
componentRef: ComponentReference;
}) => {
const hydratedComponentRef = useHydrateComponentReference(componentRef);
Expand All @@ -66,7 +71,8 @@ const ComponentRefCodeViewer = withSuspenseWrapper(
code={hydratedComponentRef.text}
language="yaml"
filename={displayName}
showInlineContent={showInlineContent}
fullscreen={fullscreen}
onClose={onClose}
/>
);
},
Expand All @@ -75,8 +81,9 @@ const ComponentRefCodeViewer = withSuspenseWrapper(
const ComponentSpecCodeViewer = ({
componentSpec,
displayName,
showInlineContent = true,
}: Pick<TaskImplementationProps, "displayName" | "showInlineContent"> & {
fullscreen,
onClose,
}: Omit<TaskImplementationProps, "componentRef"> & {
componentSpec: ComponentSpec;
}) => {
const code = componentSpecToText(componentSpec);
Expand All @@ -86,7 +93,8 @@ const ComponentSpecCodeViewer = ({
code={code}
language="yaml"
filename={displayName}
showInlineContent={showInlineContent}
fullscreen={fullscreen}
onClose={onClose}
/>
);
};
Expand Down