Skip to content

Commit 2a594fc

Browse files
committed
Cleanup TaskDetails
1 parent 6630e43 commit 2a594fc

File tree

9 files changed

+261
-422
lines changed

9 files changed

+261
-422
lines changed

src/components/shared/ContextPanel/Blocks/ActionBlock.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export type Action = {
2121
);
2222

2323
// Temporary: ReactNode included for backward compatibility with some existing buttons. In the long-term we should strive for only Action types.
24-
type ActionOrReactNode = Action | ReactNode;
24+
export type ActionOrReactNode = Action | ReactNode;
2525

2626
interface ActionBlockProps {
2727
title?: string;

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNodeCard/TaskNodeCard.tsx

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useNavigate } from "@tanstack/react-router";
2-
import { CircleFadingArrowUp, CopyIcon } from "lucide-react";
32
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
43

54
import type { TooltipButtonProps } from "@/components/shared/Buttons/TooltipButton";
@@ -126,38 +125,26 @@ const TaskNodeCard = () => {
126125
const actions: Array<TooltipButtonProps> = [];
127126

128127
if (!readOnly) {
129-
actions.push(
130-
{
131-
children: (
132-
<div className="flex items-center gap-2">
133-
<CopyIcon />
134-
</div>
135-
),
136-
variant: "outline",
137-
tooltip: "Duplicate Task",
138-
onClick: callbacks.onDuplicate,
139-
},
140-
{
141-
children: (
142-
<div className="flex items-center gap-2">
143-
<CircleFadingArrowUp />
144-
</div>
145-
),
146-
variant: "outline",
147-
className: cn(isCustomComponent && "hidden"),
148-
tooltip: "Update Task from Source URL",
149-
onClick: callbacks.onUpgrade,
150-
},
151-
);
128+
actions.push({
129+
children: <Icon name="Copy" size="sm" />,
130+
variant: "outline",
131+
tooltip: "Duplicate Task",
132+
onClick: callbacks.onDuplicate,
133+
});
134+
}
135+
136+
if (!readOnly && !isCustomComponent) {
137+
actions.push({
138+
children: <Icon name="CircleFadingArrowUp" size="sm" />,
139+
variant: "outline",
140+
tooltip: "Update Task from Source URL",
141+
onClick: callbacks.onUpgrade,
142+
});
152143
}
153144

154145
if (isSubgraphNode && taskId && isSubgraphNavigationEnabled) {
155146
actions.push({
156-
children: (
157-
<div className="flex items-center gap-2">
158-
<Icon name="Workflow" size="sm" />
159-
</div>
160-
),
147+
children: <Icon name="Workflow" size="sm" />,
161148
variant: "outline",
162149
tooltip: `Enter Subgraph: ${subgraphDescription}`,
163150
onClick: () => navigateToSubgraph(taskId),
@@ -166,11 +153,7 @@ const TaskNodeCard = () => {
166153

167154
if (isInAppEditorEnabled) {
168155
actions.push({
169-
children: (
170-
<div className="flex items-center gap-2">
171-
<Icon name="FilePenLine" size="sm" />
172-
</div>
173-
),
156+
children: <Icon name="FilePenLine" size="sm" />,
174157
variant: "outline",
175158
tooltip: "Edit Component Definition",
176159
onClick: handleEditComponent,

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskOverview/TaskOverview.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ const TaskOverview = ({ taskNode, actions }: TaskOverviewProps) => {
128128
url={taskSpec.componentRef.url}
129129
onDelete={callbacks.onDelete}
130130
status={status}
131-
hasDeletionConfirmation={false}
132131
readOnly={readOnly}
133132
actions={detailActions}
134133
/>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { type ReactNode } from "react";
2+
import { FaPython } from "react-icons/fa";
3+
4+
import useToastNotification from "@/hooks/useToastNotification";
5+
import type { ComponentSpec } from "@/utils/componentSpec";
6+
import {
7+
downloadStringAsFile,
8+
downloadYamlFromComponentText,
9+
} from "@/utils/URL";
10+
import { componentSpecToText } from "@/utils/yaml";
11+
12+
import {
13+
ActionBlock,
14+
type ActionOrReactNode,
15+
} from "../ContextPanel/Blocks/ActionBlock";
16+
17+
interface TaskActionsProps {
18+
displayName: string;
19+
componentSpec: ComponentSpec;
20+
actions?: ReactNode[];
21+
onDelete?: () => void;
22+
readOnly?: boolean;
23+
className?: string;
24+
}
25+
26+
const TaskActions = ({
27+
displayName,
28+
componentSpec,
29+
actions = [],
30+
onDelete,
31+
readOnly = false,
32+
className,
33+
}: TaskActionsProps) => {
34+
const notify = useToastNotification();
35+
36+
const pythonOriginalCode =
37+
componentSpec?.metadata?.annotations?.original_python_code;
38+
39+
const stringToPythonCodeDownload = () => {
40+
if (!pythonOriginalCode) return;
41+
42+
downloadStringAsFile(
43+
pythonOriginalCode,
44+
`${componentSpec?.name || displayName}.py`,
45+
"text/x-python",
46+
);
47+
};
48+
49+
const handleDownloadYaml = () => {
50+
downloadYamlFromComponentText(componentSpec, displayName);
51+
};
52+
53+
const handleCopyYaml = () => {
54+
const code = componentSpecToText(componentSpec);
55+
56+
navigator.clipboard.writeText(code).then(
57+
() => notify("YAML copied to clipboard", "success"),
58+
(err) => notify("Failed to copy YAML: " + err, "error"),
59+
);
60+
};
61+
62+
const handleDelete = () => {
63+
try {
64+
onDelete?.();
65+
} catch (error) {
66+
console.error("Error deleting component:", error);
67+
notify(`Error deleting component`, "error");
68+
}
69+
};
70+
71+
const orderedActions: ActionOrReactNode[] = [
72+
{
73+
label: "Download YAML",
74+
icon: "Download",
75+
onClick: handleDownloadYaml,
76+
},
77+
{
78+
label: "Download Python Code",
79+
content: <FaPython />,
80+
hidden: !pythonOriginalCode,
81+
onClick: stringToPythonCodeDownload,
82+
},
83+
{
84+
label: "Copy YAML",
85+
icon: "Clipboard",
86+
onClick: handleCopyYaml,
87+
},
88+
...actions,
89+
{
90+
label: "Delete Component",
91+
icon: "Trash",
92+
destructive: true,
93+
hidden: !onDelete || readOnly,
94+
onClick: handleDelete,
95+
},
96+
];
97+
98+
return <ActionBlock actions={orderedActions} className={className} />;
99+
};
100+
101+
export default TaskActions;

0 commit comments

Comments
 (0)