Skip to content

Commit fe07e23

Browse files
committed
Rework Task Action Buttons into Action Framework
1 parent b5bc3a7 commit fe07e23

File tree

5 files changed

+83
-85
lines changed

5 files changed

+83
-85
lines changed

src/components/shared/Dialogs/ComponentDetailsDialog.tsx

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import { useHydrateComponentReference } from "@/hooks/useHydrateComponentReferen
1717
import type { ComponentReference } from "@/utils/componentSpec";
1818

1919
import InfoIconButton from "../Buttons/InfoIconButton";
20-
import TooltipButton from "../Buttons/TooltipButton";
2120
import { ComponentEditorDialog } from "../ComponentEditor/ComponentEditorDialog";
21+
import type { Action } from "../ContextPanel/Blocks/ActionBlock";
2222
import { ComponentFavoriteToggle } from "../FavoriteComponentToggle";
2323
import { InfoBox } from "../InfoBox";
2424
import { PublishComponent } from "../ManageComponent/PublishComponent";
@@ -32,7 +32,7 @@ interface ComponentDetailsProps {
3232
component: ComponentReference;
3333
displayName: string;
3434
trigger?: ReactNode;
35-
actions?: ReactNode[];
35+
customActions?: Action[];
3636
onClose?: () => void;
3737
onDelete?: () => void;
3838
}
@@ -67,7 +67,7 @@ const ComponentDetailsDialogContent = withSuspenseWrapper(
6767
({
6868
component,
6969
displayName,
70-
actions = [],
70+
customActions = [],
7171
onDelete,
7272
}: ComponentDetailsProps) => {
7373
const remoteComponentLibrarySearchEnabled = useBetaFlagValue(
@@ -138,7 +138,7 @@ const ComponentDetailsDialogContent = withSuspenseWrapper(
138138
componentSpec={componentSpec}
139139
componentDigest={componentDigest}
140140
url={url}
141-
actions={actions}
141+
customActions={customActions}
142142
onDelete={onDelete}
143143
/>
144144
</TabsContent>
@@ -175,7 +175,7 @@ const ComponentDetails = ({
175175
component,
176176
displayName,
177177
trigger,
178-
actions = [],
178+
customActions = [],
179179
onClose,
180180
onDelete,
181181
}: ComponentDetailsProps) => {
@@ -212,22 +212,12 @@ const ComponentDetails = ({
212212
setIsEditDialogOpen(true);
213213
}, []);
214214

215-
const actionsWithEdit = useMemo(() => {
216-
if (!hasEnabledInAppEditor) return actions;
217-
218-
const EditButton = (
219-
<TooltipButton
220-
variant="secondary"
221-
onClick={handleEditComponent}
222-
tooltip="Edit Component Definition"
223-
key={`${displayName}-edit-button`}
224-
>
225-
<Icon name="FilePenLine" />
226-
</TooltipButton>
227-
);
228-
229-
return [...actions, EditButton];
230-
}, [actions, hasEnabledInAppEditor, handleEditComponent]);
215+
customActions.push({
216+
label: "Edit Component Definition",
217+
icon: "FilePenLine",
218+
hidden: !hasEnabledInAppEditor,
219+
onClick: handleEditComponent,
220+
});
231221

232222
return (
233223
<>
@@ -256,7 +246,7 @@ const ComponentDetails = ({
256246
component={component}
257247
displayName={displayName}
258248
trigger={dialogTriggerButton}
259-
actions={actionsWithEdit}
249+
customActions={customActions}
260250
onClose={onClose}
261251
onDelete={onDelete}
262252
/>

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

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { useNavigate } from "@tanstack/react-router";
22
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
33

4-
import type { TooltipButtonProps } from "@/components/shared/Buttons/TooltipButton";
54
import { ComponentEditorDialog } from "@/components/shared/ComponentEditor/ComponentEditorDialog";
5+
import type { Action } from "@/components/shared/ContextPanel/Blocks/ActionBlock";
66
import { PublishedComponentBadge } from "@/components/shared/ManageComponent/PublishedComponentBadge";
77
import { trimDigest } from "@/components/shared/ManageComponent/utils/digest";
88
import { useBetaFlagValue } from "@/components/shared/Settings/useBetaFlags";
@@ -113,6 +113,20 @@ const TaskNodeCard = () => {
113113
}
114114
}, []);
115115

116+
const handleDuplicateTask = useCallback(() => {
117+
callbacks.onDuplicate?.();
118+
}, [callbacks]);
119+
120+
const handleUpgradeTask = useCallback(() => {
121+
callbacks.onUpgrade?.();
122+
}, [callbacks]);
123+
124+
const handleEnterSubgraph = useCallback(() => {
125+
if (taskId) {
126+
navigateToSubgraph(taskId);
127+
}
128+
}, [navigateToSubgraph, taskId]);
129+
116130
const handleEditComponent = useCallback(() => {
117131
setIsEditDialogOpen(true);
118132
}, []);
@@ -122,45 +136,40 @@ const TaskNodeCard = () => {
122136
}, []);
123137

124138
const taskConfigMarkup = useMemo(() => {
125-
const actions: Array<TooltipButtonProps> = [];
126-
127-
if (!readOnly) {
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-
});
143-
}
144-
145-
if (isSubgraphNode && taskId && isSubgraphNavigationEnabled) {
146-
actions.push({
147-
children: <Icon name="Workflow" size="sm" />,
148-
variant: "outline",
149-
tooltip: `Enter Subgraph: ${subgraphDescription}`,
150-
onClick: () => navigateToSubgraph(taskId),
151-
});
152-
}
153-
154-
if (isInAppEditorEnabled) {
155-
actions.push({
156-
children: <Icon name="FilePenLine" size="sm" />,
157-
variant: "outline",
158-
tooltip: "Edit Component Definition",
139+
const customActions: Action[] = [
140+
{
141+
label: "Duplicate Task",
142+
icon: "Copy",
143+
hidden: readOnly,
144+
onClick: handleDuplicateTask,
145+
},
146+
{
147+
label: "Update Task from Source URL",
148+
icon: "CircleFadingArrowUp",
149+
hidden: readOnly || isCustomComponent,
150+
onClick: handleUpgradeTask,
151+
},
152+
{
153+
label: `Enter Subgraph: ${subgraphDescription}`,
154+
icon: "Workflow",
155+
hidden: !isSubgraphNode || !isSubgraphNavigationEnabled,
156+
onClick: handleEnterSubgraph,
157+
},
158+
{
159+
label: "Edit Component Definition",
160+
icon: "FilePenLine",
161+
hidden: !isInAppEditorEnabled,
159162
onClick: handleEditComponent,
160-
});
161-
}
162-
163-
return <TaskOverview taskNode={taskNode} key={nodeId} actions={actions} />;
163+
},
164+
];
165+
166+
return (
167+
<TaskOverview
168+
key={nodeId}
169+
taskNode={taskNode}
170+
customActions={customActions}
171+
/>
172+
);
164173
}, [
165174
nodeId,
166175
readOnly,

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

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ import {
77
} from "lucide-react";
88
import { useState } from "react";
99

10-
import type { TooltipButtonProps } from "@/components/shared/Buttons/TooltipButton";
11-
import TooltipButton from "@/components/shared/Buttons/TooltipButton";
1210
import { CodeViewer } from "@/components/shared/CodeViewer";
11+
import type { Action } from "@/components/shared/ContextPanel/Blocks/ActionBlock";
1312
import { ComponentDetailsDialog } from "@/components/shared/Dialogs";
1413
import { ComponentFavoriteToggle } from "@/components/shared/FavoriteComponentToggle";
1514
import { StatusIcon } from "@/components/shared/Status";
@@ -32,10 +31,10 @@ import RenameTask from "./RenameTask";
3231

3332
interface TaskOverviewProps {
3433
taskNode: TaskNodeContextType;
35-
actions?: TooltipButtonProps[];
34+
customActions?: Action[];
3635
}
3736

38-
const TaskOverview = ({ taskNode, actions }: TaskOverviewProps) => {
37+
const TaskOverview = ({ taskNode, customActions }: TaskOverviewProps) => {
3938
const { name, taskSpec, taskId, state, callbacks } = taskNode;
4039

4140
const [isYamlFullscreen, setIsYamlFullscreen] = useState(false);
@@ -63,18 +62,17 @@ const TaskOverview = ({ taskNode, actions }: TaskOverviewProps) => {
6362
const executionId = details?.child_task_execution_ids?.[taskId];
6463
const canRename = !readOnly && isSubgraph;
6564

66-
const detailActions = [
67-
...(actions?.map((action) => (
68-
<TooltipButton {...action} key={action.tooltip?.toString()} />
69-
)) ?? []),
70-
<TooltipButton
71-
variant="outline"
72-
tooltip="View YAML"
73-
onClick={() => setIsYamlFullscreen(true)}
74-
>
75-
<Icon name="FileCodeCorner" />
76-
</TooltipButton>,
77-
];
65+
const customActionsExtended: Action[] = [];
66+
67+
if (customActions) {
68+
customActionsExtended.push(...customActions);
69+
}
70+
71+
customActionsExtended.push({
72+
label: "View YAML",
73+
icon: "FileCodeCorner",
74+
onClick: () => setIsYamlFullscreen(true),
75+
});
7876

7977
return (
8078
<>
@@ -136,7 +134,7 @@ const TaskOverview = ({ taskNode, actions }: TaskOverviewProps) => {
136134
onDelete={callbacks.onDelete}
137135
status={status}
138136
readOnly={readOnly}
139-
actions={detailActions}
137+
customActions={customActionsExtended}
140138
/>
141139
</TabsContent>
142140
<TabsContent value="io">

src/components/shared/TaskDetails/Actions.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { type ReactNode } from "react";
21
import { FaPython } from "react-icons/fa";
32

43
import useToastNotification from "@/hooks/useToastNotification";
@@ -8,13 +7,14 @@ import copyToYaml from "@/utils/yaml";
87

98
import {
109
ActionBlock,
10+
type Action,
1111
type ActionOrReactNode,
1212
} from "../ContextPanel/Blocks/ActionBlock";
1313

1414
interface TaskActionsProps {
1515
displayName: string;
1616
componentSpec: ComponentSpec;
17-
actions?: ReactNode[];
17+
customActions?: Action[];
1818
onDelete?: () => void;
1919
readOnly?: boolean;
2020
className?: string;
@@ -23,7 +23,7 @@ interface TaskActionsProps {
2323
const TaskActions = ({
2424
displayName,
2525
componentSpec,
26-
actions = [],
26+
customActions = [],
2727
onDelete,
2828
readOnly = false,
2929
className,
@@ -85,7 +85,7 @@ const TaskActions = ({
8585
icon: "Clipboard",
8686
onClick: handleCopyYaml,
8787
},
88-
...actions,
88+
...customActions,
8989
{
9090
label: "Delete Component",
9191
icon: "Trash",

src/components/shared/TaskDetails/Details.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { TextBlock } from "../ContextPanel/Blocks/TextBlock";
88
import TaskActions from "./Actions";
99
import { ExecutionDetails } from "./ExecutionDetails";
1010
import { GithubDetails } from "./GithubDetails";
11+
import type { Action } from "../ContextPanel/Blocks/ActionBlock";
1112

1213
interface TaskDetailsProps {
1314
displayName: string;
@@ -16,7 +17,7 @@ interface TaskDetailsProps {
1617
taskId?: string;
1718
componentDigest?: string;
1819
url?: string;
19-
actions?: ReactNode[];
20+
customActions?: Action[];
2021
onDelete?: () => void;
2122
status?: string;
2223
readOnly?: boolean;
@@ -36,7 +37,7 @@ const TaskDetails = ({
3637
taskId,
3738
componentDigest,
3839
url,
39-
actions = [],
40+
customActions = [],
4041
onDelete,
4142
status,
4243
readOnly = false,
@@ -128,7 +129,7 @@ const TaskDetails = ({
128129
<TaskActions
129130
displayName={displayName}
130131
componentSpec={componentSpec}
131-
actions={actions}
132+
customActions={customActions}
132133
onDelete={onDelete}
133134
readOnly={readOnly}
134135
className={BASE_BLOCK_CLASS}

0 commit comments

Comments
 (0)