From ac175010fa652c8faa895e1ad70535455bbe426a Mon Sep 17 00:00:00 2001 From: Taylor Ho Date: Wed, 12 Aug 2026 23:06:33 -0700 Subject: [PATCH] Polish workflow landing cards Signed-off-by: Taylor Ho --- .../src/app/routes/WorkflowsRouteScreen.tsx | 5 +- .../features/workflows/ui/WorkflowCard.tsx | 227 ++++++++++++------ .../features/workflows/ui/WorkflowsScreen.tsx | 3 - .../features/workflows/ui/WorkflowsView.tsx | 82 ++++--- .../workflows/ui/workflowDefinition.test.mjs | 60 +++++ .../workflows/ui/workflowDefinition.ts | 138 ++++++++++- desktop/tests/e2e/workflows.spec.ts | 34 +-- 7 files changed, 404 insertions(+), 145 deletions(-) create mode 100644 desktop/src/features/workflows/ui/workflowDefinition.test.mjs diff --git a/desktop/src/app/routes/WorkflowsRouteScreen.tsx b/desktop/src/app/routes/WorkflowsRouteScreen.tsx index 0a0a4dfb3..ce72e5080 100644 --- a/desktop/src/app/routes/WorkflowsRouteScreen.tsx +++ b/desktop/src/app/routes/WorkflowsRouteScreen.tsx @@ -9,7 +9,7 @@ type WorkflowsRouteScreenProps = { export function WorkflowsRouteScreen({ selectedWorkflowId, }: WorkflowsRouteScreenProps) { - const { closeWorkflowDetail, goWorkflow } = useAppNavigation(); + const { closeWorkflowDetail } = useAppNavigation(); const channelsQuery = useChannelsQuery(); const channels = channelsQuery.data ?? []; const memberChannels = channels.filter((channel) => channel.isMember); @@ -18,9 +18,6 @@ export function WorkflowsRouteScreen({ { - void goWorkflow(workflowId); - }} selectedWorkflowId={selectedWorkflowId} /> ); diff --git a/desktop/src/features/workflows/ui/WorkflowCard.tsx b/desktop/src/features/workflows/ui/WorkflowCard.tsx index cd15a0f52..2f5462186 100644 --- a/desktop/src/features/workflows/ui/WorkflowCard.tsx +++ b/desktop/src/features/workflows/ui/WorkflowCard.tsx @@ -1,15 +1,27 @@ import { - Clock, + ArrowRight, + CalendarClock, + CircleCheckBig, + Clock3, Copy, + GitPullRequest, + Hash, + MessageCircle, + MessageSquare, MoreHorizontal, Pencil, Play, + Send, + SmilePlus, + Timer, Trash2, + Webhook, Zap, } from "lucide-react"; +import type { LucideIcon } from "lucide-react"; import type { Workflow } from "@/shared/api/types"; -import { Badge } from "@/shared/ui/badge"; +import { cn } from "@/shared/lib/cn"; import { Button } from "@/shared/ui/button"; import { DropdownMenu, @@ -18,40 +30,69 @@ import { DropdownMenuTrigger, } from "@/shared/ui/dropdown-menu"; import { + getWorkflowCardLabel, getWorkflowDescription, getWorkflowDisplayStatus, + getWorkflowPrimaryAction, getWorkflowTriggerSummary, + getWorkflowTriggerType, } from "./workflowDefinition"; type WorkflowCardProps = { workflow: Workflow; channelName?: string; isActive?: boolean; - onSelect: (workflowId: string) => void; onTrigger: (workflowId: string) => void; onEdit: (workflow: Workflow) => void; onDuplicate: (workflow: Workflow) => void; onDelete: (workflow: Workflow) => void; }; -function StatusBadge({ status }: { status: Workflow["status"] }) { - const variants: Record< - Workflow["status"], - "success" | "secondary" | "warning" - > = { - active: "success", - disabled: "secondary", - archived: "warning", - }; +const TRIGGER_ICONS: Record = { + diff_posted: GitPullRequest, + message_posted: MessageSquare, + reaction_added: SmilePlus, + schedule: CalendarClock, + webhook: Webhook, +}; - return {status}; +const ACTION_ICONS: Record = { + add_reaction: SmilePlus, + call_webhook: Webhook, + delay: Timer, + request_approval: CircleCheckBig, + send_dm: MessageCircle, + send_message: Send, + set_channel_topic: Hash, +}; + +const TRIGGER_THEMES: Record = { + diff_posted: "border-violet-400/30 bg-violet-600 text-white", + message_posted: "border-blue-400/30 bg-blue-600 text-white", + reaction_added: "border-pink-400/30 bg-pink-600 text-white", + schedule: "border-emerald-400/30 bg-emerald-600 text-white", + webhook: "border-orange-300/30 bg-orange-500 text-white", +}; + +function StatusBadge({ status }: { status: Workflow["status"] }) { + return ( + + {status} + + ); } export function WorkflowCard({ workflow, channelName, isActive = false, - onSelect, onTrigger, onEdit, onDuplicate, @@ -60,79 +101,121 @@ export function WorkflowCard({ const displayStatus = getWorkflowDisplayStatus(workflow); const description = getWorkflowDescription(workflow.definition); const triggerSummary = getWorkflowTriggerSummary(workflow.definition); + const triggerType = getWorkflowTriggerType(workflow.definition); + const actionType = getWorkflowPrimaryAction(workflow.definition); + const cardLabel = getWorkflowCardLabel(workflow.definition); + const TriggerIcon = triggerType ? TRIGGER_ICONS[triggerType] : undefined; + const ActionIcon = actionType ? ACTION_ICONS[actionType] : undefined; + const theme = triggerType ? TRIGGER_THEMES[triggerType] : undefined; return (
+