Skip to content

Commit fcd7152

Browse files
committed
Rework Task Action Buttons into Action Framework
1 parent 17a86e0 commit fcd7152

File tree

6 files changed

+224
-280
lines changed

6 files changed

+224
-280
lines changed

src/components/shared/Buttons/TooltipButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
TooltipTrigger,
99
} from "@/components/ui/tooltip";
1010

11-
export interface TooltipButtonProps extends ButtonProps {
11+
interface TooltipButtonProps extends ButtonProps {
1212
tooltip: React.ReactNode;
1313
tooltipSide?: "top" | "right" | "bottom" | "left";
1414
tooltipAlign?: "start" | "center" | "end";

src/components/shared/Dialogs/ComponentDetailsDialog.tsx

Lines changed: 31 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ 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";
21-
import { ComponentEditorDialog } from "../ComponentEditor/ComponentEditorDialog";
2220
import { ComponentFavoriteToggle } from "../FavoriteComponentToggle";
2321
import { InfoBox } from "../InfoBox";
2422
import { PublishComponent } from "../ManageComponent/PublishComponent";
@@ -32,7 +30,6 @@ interface ComponentDetailsProps {
3230
component: ComponentReference;
3331
displayName: string;
3432
trigger?: ReactNode;
35-
actions?: ReactNode[];
3633
onClose?: () => void;
3734
onDelete?: () => void;
3835
}
@@ -64,12 +61,7 @@ const ComponentDetailsDialogContentSkeleton = () => {
6461
};
6562

6663
const ComponentDetailsDialogContent = withSuspenseWrapper(
67-
({
68-
component,
69-
displayName,
70-
actions = [],
71-
onDelete,
72-
}: ComponentDetailsProps) => {
64+
({ component, displayName, onDelete }: ComponentDetailsProps) => {
7365
const remoteComponentLibrarySearchEnabled = useBetaFlagValue(
7466
"remote-component-library-search",
7567
);
@@ -138,7 +130,6 @@ const ComponentDetailsDialogContent = withSuspenseWrapper(
138130
componentSpec={componentSpec}
139131
componentDigest={componentDigest}
140132
url={url}
141-
actions={actions}
142133
onDelete={onDelete}
143134
/>
144135
</TabsContent>
@@ -175,18 +166,12 @@ const ComponentDetails = ({
175166
component,
176167
displayName,
177168
trigger,
178-
actions = [],
179169
onClose,
180170
onDelete,
181171
}: ComponentDetailsProps) => {
182-
const hasEnabledInAppEditor = useBetaFlagValue("in-app-component-editor");
183-
184-
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
185172
const [open, setOpen] = useState(false);
186173
const dialogTriggerButton = trigger || <InfoIconButton />;
187174

188-
const componentText = component.text;
189-
190175
const dialogContextValue = useMemo(
191176
() => ({
192177
name: "ComponentDetails",
@@ -197,79 +182,45 @@ const ComponentDetails = ({
197182
[],
198183
);
199184

200-
const handleCloseEditDialog = useCallback(() => {
201-
setIsEditDialogOpen(false);
202-
}, []);
203-
204185
const onOpenChange = useCallback((open: boolean) => {
205186
setOpen(open);
206187
if (!open) {
207188
onClose?.();
208189
}
209190
}, []);
210191

211-
const handleEditComponent = useCallback(() => {
212-
setIsEditDialogOpen(true);
213-
}, []);
214-
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]);
231-
232192
return (
233-
<>
234-
<Dialog modal open={open} onOpenChange={onOpenChange}>
235-
<DialogTrigger asChild>{dialogTriggerButton}</DialogTrigger>
193+
<Dialog modal open={open} onOpenChange={onOpenChange}>
194+
<DialogTrigger asChild>{dialogTriggerButton}</DialogTrigger>
236195

237-
<DialogDescription
238-
className="hidden"
239-
aria-label={`${displayName} component details`}
240-
>
241-
{`${displayName} component details`}
242-
</DialogDescription>
243-
<DialogContent
244-
className="max-w-2xl min-w-2xl overflow-hidden"
245-
aria-label={`${displayName} component details`}
246-
>
247-
<DialogHeader>
248-
<DialogTitle className="flex items-center gap-2 mr-5">
249-
<span>{displayName}</span>
250-
<ComponentFavoriteToggle component={component} />
251-
</DialogTitle>
252-
</DialogHeader>
253-
254-
<DialogContext.Provider value={dialogContextValue}>
255-
<ComponentDetailsDialogContent
256-
component={component}
257-
displayName={displayName}
258-
trigger={dialogTriggerButton}
259-
actions={actionsWithEdit}
260-
onClose={onClose}
261-
onDelete={onDelete}
262-
/>
263-
</DialogContext.Provider>
264-
</DialogContent>
265-
</Dialog>
266-
{isEditDialogOpen && (
267-
<ComponentEditorDialog
268-
text={componentText}
269-
onClose={handleCloseEditDialog}
270-
/>
271-
)}
272-
</>
196+
<DialogDescription
197+
className="hidden"
198+
aria-label={`${displayName} component details`}
199+
>
200+
{`${displayName} component details`}
201+
</DialogDescription>
202+
<DialogContent
203+
className="max-w-2xl min-w-2xl overflow-hidden"
204+
aria-label={`${displayName} component details`}
205+
>
206+
<DialogHeader>
207+
<DialogTitle className="flex items-center gap-2 mr-5">
208+
<span>{displayName}</span>
209+
<ComponentFavoriteToggle component={component} />
210+
</DialogTitle>
211+
</DialogHeader>
212+
213+
<DialogContext.Provider value={dialogContextValue}>
214+
<ComponentDetailsDialogContent
215+
component={component}
216+
displayName={displayName}
217+
trigger={dialogTriggerButton}
218+
onClose={onClose}
219+
onDelete={onDelete}
220+
/>
221+
</DialogContext.Provider>
222+
</DialogContent>
223+
</Dialog>
273224
);
274225
};
275226

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

Lines changed: 56 additions & 58 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";
5-
import { ComponentEditorDialog } from "@/components/shared/ComponentEditor/ComponentEditorDialog";
4+
import { CodeViewer } from "@/components/shared/CodeViewer";
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";
@@ -36,7 +36,6 @@ const TaskNodeCard = () => {
3636
"remote-component-library-search",
3737
);
3838
const isSubgraphNavigationEnabled = useBetaFlagValue("subgraph-navigation");
39-
const isInAppEditorEnabled = useBetaFlagValue("in-app-component-editor");
4039
const { registerNode } = useNodesOverlay();
4140
const taskNode = useTaskNode();
4241
const {
@@ -52,7 +51,7 @@ const TaskNodeCard = () => {
5251
const nodeRef = useRef<HTMLDivElement | null>(null);
5352
const contentRef = useRef<HTMLDivElement>(null);
5453

55-
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
54+
const [isYamlFullscreen, setIsYamlFullscreen] = useState(false);
5655
const [updateOverlayDialogOpen, setUpdateOverlayDialogOpen] = useState<
5756
UpdateOverlayMessage["data"] | undefined
5857
>();
@@ -113,69 +112,63 @@ const TaskNodeCard = () => {
113112
}
114113
}, []);
115114

116-
const handleEditComponent = useCallback(() => {
117-
setIsEditDialogOpen(true);
118-
}, []);
119-
120-
const handleCloseEditDialog = useCallback(() => {
121-
setIsEditDialogOpen(false);
122-
}, []);
123-
124-
const { onDuplicate, onUpgrade } = callbacks;
125-
126-
const taskConfigMarkup = useMemo(() => {
127-
const actions: Array<TooltipButtonProps> = [];
128-
129-
if (!readOnly) {
130-
actions.push({
131-
children: <Icon name="Copy" size="sm" />,
132-
variant: "outline",
133-
tooltip: "Duplicate Task",
134-
onClick: onDuplicate,
135-
});
136-
}
115+
const handleDuplicateTask = useCallback(() => {
116+
callbacks.onDuplicate?.();
117+
}, [callbacks]);
137118

138-
if (!readOnly && !isCustomComponent) {
139-
actions.push({
140-
children: <Icon name="CircleFadingArrowUp" size="sm" />,
141-
variant: "outline",
142-
tooltip: "Update Task from Source URL",
143-
onClick: onUpgrade,
144-
});
145-
}
146-
147-
if (isSubgraphNode && taskId && isSubgraphNavigationEnabled) {
148-
actions.push({
149-
children: <Icon name="Workflow" size="sm" />,
150-
variant: "outline",
151-
tooltip: `Enter Subgraph: ${subgraphDescription}`,
152-
onClick: () => navigateToSubgraph(taskId),
153-
});
154-
}
119+
const handleUpgradeTask = useCallback(() => {
120+
callbacks.onUpgrade?.();
121+
}, [callbacks]);
155122

156-
if (isInAppEditorEnabled) {
157-
actions.push({
158-
children: <Icon name="FilePenLine" size="sm" />,
159-
variant: "outline",
160-
tooltip: "Edit Component Definition",
161-
onClick: handleEditComponent,
162-
});
123+
const handleEnterSubgraph = useCallback(() => {
124+
if (taskId) {
125+
navigateToSubgraph(taskId);
163126
}
127+
}, [navigateToSubgraph, taskId]);
164128

165-
return <TaskOverview taskNode={taskNode} key={nodeId} actions={actions} />;
129+
const taskConfigMarkup = useMemo(() => {
130+
const customActions: Action[] = [
131+
{
132+
label: "Duplicate Task",
133+
icon: "Copy",
134+
hidden: readOnly,
135+
onClick: handleDuplicateTask,
136+
},
137+
{
138+
label: "Update Task from Source URL",
139+
icon: "CircleFadingArrowUp",
140+
hidden: readOnly || isCustomComponent,
141+
onClick: handleUpgradeTask,
142+
},
143+
{
144+
label: `Enter Subgraph: ${subgraphDescription}`,
145+
icon: "Workflow",
146+
hidden: !isSubgraphNode || !isSubgraphNavigationEnabled,
147+
onClick: handleEnterSubgraph,
148+
},
149+
{
150+
label: "View YAML",
151+
icon: "FileCodeCorner",
152+
onClick: () => setIsYamlFullscreen(true),
153+
},
154+
];
155+
156+
return (
157+
<TaskOverview
158+
key={nodeId}
159+
taskNode={taskNode}
160+
customActions={customActions}
161+
/>
162+
);
166163
}, [
167164
taskNode,
168165
nodeId,
169166
readOnly,
170-
isInAppEditorEnabled,
171167
isCustomComponent,
172168
isSubgraphNode,
173169
taskId,
174170
subgraphDescription,
175171
navigateToSubgraph,
176-
handleEditComponent,
177-
onDuplicate,
178-
onUpgrade,
179172
]);
180173

181174
const handleInputSectionClick = useCallback(() => {
@@ -256,6 +249,8 @@ const TaskNodeCard = () => {
256249
</QuickTooltip>
257250
);
258251

252+
const componentText = taskSpec.componentRef?.text;
253+
259254
return (
260255
<>
261256
<Card
@@ -342,10 +337,13 @@ const TaskNodeCard = () => {
342337
) : null}
343338
</CardContent>
344339
</Card>
345-
{isEditDialogOpen && (
346-
<ComponentEditorDialog
347-
text={taskSpec.componentRef?.text}
348-
onClose={handleCloseEditDialog}
340+
{isYamlFullscreen && componentText && (
341+
<CodeViewer
342+
code={componentText}
343+
language="yaml"
344+
filename={name}
345+
isFullscreen={isYamlFullscreen}
346+
onClose={() => setIsYamlFullscreen(false)}
349347
/>
350348
)}
351349
</>

0 commit comments

Comments
 (0)