From db366367b84ce5b3b4cf3f9bc58d8deb66aa1f1d Mon Sep 17 00:00:00 2001 From: mbeaulne Date: Mon, 23 Mar 2026 14:39:26 -0400 Subject: [PATCH] feat_favorites_toggle_ui --- .../Editor/Context/PipelineDetails.tsx | 11 +++++ .../Home/PipelineSection/PipelineRow.tsx | 32 ++++++++------ src/components/Home/RunSection/RunRow.tsx | 4 ++ src/components/PipelineRun/RunToolbar.tsx | 4 ++ src/components/shared/FavoriteToggle.tsx | 43 +++++++++++++++++++ 5 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 src/components/shared/FavoriteToggle.tsx diff --git a/src/components/Editor/Context/PipelineDetails.tsx b/src/components/Editor/Context/PipelineDetails.tsx index f268e4df0..e75ae1c3f 100644 --- a/src/components/Editor/Context/PipelineDetails.tsx +++ b/src/components/Editor/Context/PipelineDetails.tsx @@ -7,6 +7,7 @@ import { ContentBlock } from "@/components/shared/ContextPanel/Blocks/ContentBlo import { KeyValueList } from "@/components/shared/ContextPanel/Blocks/KeyValueList"; import { TextBlock } from "@/components/shared/ContextPanel/Blocks/TextBlock"; import { CopyText } from "@/components/shared/CopyText/CopyText"; +import { FavoriteToggle } from "@/components/shared/FavoriteToggle"; import { PipelineDescription } from "@/components/shared/PipelineDescription/PipelineDescription"; import { PipelineRunNameTemplateEditor } from "@/components/shared/PipelineRunNameTemplate/PipelineRunNameTemplateEditor"; import { useFlagValue } from "@/components/shared/Settings/useFlags"; @@ -102,6 +103,16 @@ const PipelineDetails = () => { const actions = [ , , + ...(componentSpec.name + ? [ + , + ] + : []), ]; return ( diff --git a/src/components/Home/PipelineSection/PipelineRow.tsx b/src/components/Home/PipelineSection/PipelineRow.tsx index d41da79d8..cb7273d60 100644 --- a/src/components/Home/PipelineSection/PipelineRow.tsx +++ b/src/components/Home/PipelineSection/PipelineRow.tsx @@ -2,6 +2,7 @@ import { useNavigate } from "@tanstack/react-router"; import { type MouseEvent } from "react"; import { ConfirmationDialog } from "@/components/shared/Dialogs"; +import { FavoriteToggle } from "@/components/shared/FavoriteToggle"; import { HighlightText } from "@/components/shared/HighlightText"; import { PipelineRunInfoCondensed } from "@/components/shared/PipelineRunDisplay/PipelineRunInfoCondensed"; import { PipelineRunsList } from "@/components/shared/PipelineRunDisplay/PipelineRunsList"; @@ -161,20 +162,23 @@ const PipelineRow = withSuspenseWrapper( {name && } - - - - } - title={`Delete pipeline "${name}"?`} - description="Are you sure you want to delete this pipeline? Existing pipeline runs will not be impacted. This action cannot be undone." - onConfirm={confirmPipelineDelete} - /> + + {name && } + + + + } + title={`Delete pipeline "${name}"?`} + description="Are you sure you want to delete this pipeline? Existing pipeline runs will not be impacted. This action cannot be undone." + onConfirm={confirmPipelineDelete} + /> + ); diff --git a/src/components/Home/RunSection/RunRow.tsx b/src/components/Home/RunSection/RunRow.tsx index 0ad1b139b..5f3a5c78d 100644 --- a/src/components/Home/RunSection/RunRow.tsx +++ b/src/components/Home/RunSection/RunRow.tsx @@ -4,6 +4,7 @@ import { type MouseEvent } from "react"; import type { PipelineRunResponse } from "@/api/types.gen"; import { CopyText } from "@/components/shared/CopyText/CopyText"; +import { FavoriteToggle } from "@/components/shared/FavoriteToggle"; import { StatusBar, StatusIcon } from "@/components/shared/Status"; import { TagList } from "@/components/shared/Tags/TagList"; import { Button } from "@/components/ui/button"; @@ -127,6 +128,9 @@ const RunRow = ({ run }: { run: PipelineRunResponse }) => { {tags && tags.length > 0 && } + + + ); }; diff --git a/src/components/PipelineRun/RunToolbar.tsx b/src/components/PipelineRun/RunToolbar.tsx index eef46dfe1..38b637db9 100644 --- a/src/components/PipelineRun/RunToolbar.tsx +++ b/src/components/PipelineRun/RunToolbar.tsx @@ -1,3 +1,4 @@ +import { FavoriteToggle } from "@/components/shared/FavoriteToggle"; import { InlineStack } from "@/components/ui/layout"; import { useCheckComponentSpecFromPath } from "@/hooks/useCheckComponentSpecFromPath"; import { useUserDetails } from "@/hooks/useUserDetails"; @@ -66,6 +67,9 @@ export const RunToolbar = () => { isViewingSubgraph ? "top-23" : "top-14", )} > + {runId && pipelineName && ( + + )} {canAccessEditorSpec && pipelineName && ( diff --git a/src/components/shared/FavoriteToggle.tsx b/src/components/shared/FavoriteToggle.tsx new file mode 100644 index 000000000..a34eeee5b --- /dev/null +++ b/src/components/shared/FavoriteToggle.tsx @@ -0,0 +1,43 @@ +import { Star } from "lucide-react"; +import { type MouseEvent, useCallback } from "react"; + +import { Button } from "@/components/ui/button"; +import { type FavoriteType, useFavorites } from "@/hooks/useFavorites"; +import { cn } from "@/lib/utils"; + +interface FavoriteToggleProps { + type: FavoriteType; + id: string; + name: string; +} + +export const FavoriteToggle = ({ type, id, name }: FavoriteToggleProps) => { + const { isFavorite, toggleFavorite } = useFavorites(); + const active = isFavorite(type, id); + + const handleClick = useCallback( + (e: MouseEvent) => { + e.stopPropagation(); + toggleFavorite({ type, id, name }); + }, + [type, id, name, toggleFavorite], + ); + + return ( + + ); +};