From 0d3e8ce0cec4c2c5a6592e3947d07c51ed08f3ab Mon Sep 17 00:00:00 2001 From: Woody Date: Sun, 26 Apr 2026 18:48:52 +0800 Subject: [PATCH] fix(frontend): save button always disabled on System Prompts page Root cause: PromptEditor useEffect synced localPrompts back to match prompts after every keystroke, making isDirty() always false. - Delegate disabled control to parent via hasChanges prop (no local sync) - Derive currentPrompts synchronously to avoid empty-textarea flash - Add key={selectedProfile} for clean remount on profile switch - Update PromptEditor tests for new hasChanges prop Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- frontend/src/components/PromptEditor.tsx | 14 ++++++-------- frontend/src/pages/SystemPromptsPage.tsx | 8 ++++++-- frontend/src/test/components/PromptEditor.test.tsx | 7 ++----- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/PromptEditor.tsx b/frontend/src/components/PromptEditor.tsx index 0dfc702..02b9c87 100644 --- a/frontend/src/components/PromptEditor.tsx +++ b/frontend/src/components/PromptEditor.tsx @@ -1,9 +1,10 @@ -import React, { useState, useEffect, useCallback } from 'react' +import React, { useState } from 'react' import { RotateCcw, AlertTriangle } from 'lucide-react' export interface PromptEditorProps { profileName: string prompts: Record + hasChanges: boolean isSaving: boolean onUpdate: (step: string, template: string) => void onSave: () => void @@ -33,6 +34,7 @@ const findUnknownPlaceholders = (template: string, stepKey: string): string[] => export const PromptEditor: React.FC = ({ profileName, prompts, + hasChanges, isSaving, onUpdate, onSave, @@ -40,9 +42,9 @@ export const PromptEditor: React.FC = ({ onResetAll, onCancel, }) => { - const [localPrompts, setLocalPrompts] = useState>({}) + const [localPrompts, setLocalPrompts] = useState>({ ...prompts }) - useEffect(() => { + React.useEffect(() => { setLocalPrompts({ ...prompts }) }, [prompts]) @@ -63,10 +65,6 @@ export const PromptEditor: React.FC = ({ } } - const isDirty = useCallback(() => { - return STEPS.some((step) => localPrompts[step.key] !== prompts[step.key]) - }, [localPrompts, prompts]) - return (
@@ -136,7 +134,7 @@ export const PromptEditor: React.FC = ({