diff --git a/frontend/src/app/pages/Workflows/WorkflowCard.tsx b/frontend/src/app/pages/Workflows/WorkflowCard.tsx index d099f0b2..132b8146 100644 --- a/frontend/src/app/pages/Workflows/WorkflowCard.tsx +++ b/frontend/src/app/pages/Workflows/WorkflowCard.tsx @@ -9,7 +9,6 @@ import CloseIcon from '@mui/icons-material/Close'; import HistoryIcon from '@mui/icons-material/HistoryRounded'; import PlayArrowIcon from '@mui/icons-material/PlayArrowRounded'; import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; -import AutoAwesomeOutlinedIcon from '@mui/icons-material/AutoAwesomeOutlined'; import InputBase from '@mui/material/InputBase'; import { useClaudeTokens } from '@/shared/styles/ThemeContext'; import { useAppDispatch, useAppSelector } from '@/shared/hooks'; @@ -196,25 +195,13 @@ const WorkflowCard: React.FC = ({ const isDraft = card?.view === 'preview' && !workflow; const steps = (workflow?.steps || card?.draft?.steps || []) as Workflow['steps']; - // Edit-agent chrome lives in the card header: the model/time subtitle and - // the Save Workflow button. EditAgentView owns the live session and reports - // its id up here. The Save button pulses once when a turn finishes adding a - // step, nudging the user that there's something worth saving. + // Edit-agent chrome lives in the card header: the model/time subtitle. + // EditAgentView owns the live session and reports its id up here so the + // subtitle can render the live model + work time. Saving is handled by the + // Discard/Save controls inside EditAgentView itself. const isEditAgentView = card?.view === 'edit_agent' || card?.view === 'fix_agent'; - const showHeaderSaveWorkflow = isEditAgentView && !(card?.view === 'edit_agent' && workflow?.source_session_id); const [editSessionId, setEditSessionId] = useState(null); const editSession = useAppSelector((s) => editSessionId ? s.agents.sessions[editSessionId] : undefined); - const [savePulseNonce, setSavePulseNonce] = useState(0); - const prevEditStatusRef = useRef(undefined); - useEffect(() => { - const status = editSession?.status; - const prev = prevEditStatusRef.current; - const wasRunning = prev === 'running' || prev === 'waiting_approval'; - if (wasRunning && status === 'completed' && steps.length > 0) { - setSavePulseNonce((n) => n + 1); - } - prevEditStatusRef.current = status; - }, [editSession?.status, steps.length]); // ---- Card drag via title bar ---- const DRAG_THRESHOLD = 3; @@ -517,47 +504,6 @@ const WorkflowCard: React.FC = ({ )} {runs && runs.length > 0 && } - {!isDraft && workflow && showHeaderSaveWorkflow && ( - 0 ? 'Save the workflow and close the editor' : 'Add at least one step before saving'}> - { - e.stopPropagation(); - if (steps.length === 0) { setRunToast('Add at least one step to your workflow first.'); return; } - dispatch(updateWorkflowCard({ workflowId, patch: { view: 'saved' } })); - }} - onPointerDown={(e) => e.stopPropagation()} - sx={{ - display: 'inline-flex', alignItems: 'center', gap: 0.5, - fontSize: '0.78rem', fontWeight: 700, - px: 1.1, py: 0.5, - borderRadius: `${c.radius.md}px`, - cursor: 'pointer', - ...(steps.length > 0 ? { - color: '#fff', - bgcolor: c.accent.primary, - border: `1px solid ${c.accent.primary}`, - boxShadow: `0 0 0 0 ${c.accent.primary}00`, - animation: savePulseNonce > 0 ? `workflow-save-pulse-${savePulseNonce} 0.95s ease-out 1` : 'none', - [`@keyframes workflow-save-pulse-${savePulseNonce}`]: { - '0%': { boxShadow: `0 0 0 0 ${c.accent.primary}55`, transform: 'scale(1)' }, - '55%': { boxShadow: `0 0 0 8px ${c.accent.primary}00`, transform: 'scale(1.035)' }, - '100%': { boxShadow: `0 0 0 0 ${c.accent.primary}00`, transform: 'scale(1)' }, - }, - '&:hover': { filter: 'brightness(1.05)' }, - } : { - color: c.text.muted, - bgcolor: c.bg.elevated, - border: `1px solid ${c.border.subtle}`, - }), - }} - > - - Save Workflow - - - )}