diff --git a/web/app/components/base/prompt-editor/__tests__/index.spec.tsx b/web/app/components/base/prompt-editor/__tests__/index.spec.tsx index 31e25ab19e1..4faf88f0595 100644 --- a/web/app/components/base/prompt-editor/__tests__/index.spec.tsx +++ b/web/app/components/base/prompt-editor/__tests__/index.spec.tsx @@ -36,6 +36,7 @@ const mocks = vi.hoisted(() => { })), parseEditorState: vi.fn(() => ({ state: 'parsed' })), setEditorState: vi.fn(), + setEditable: vi.fn(), focus: vi.fn(), update: vi.fn((fn: () => void) => fn()), }, @@ -328,6 +329,20 @@ describe('PromptEditor', () => { expect(screen.getByTestId('lexical-composer')).toBeInTheDocument() }) + it('should update lexical editable state when editable prop changes', () => { + const { rerender } = render() + + expect(mocks.editor.setEditable).toHaveBeenLastCalledWith(true) + + rerender() + + expect(mocks.editor.setEditable).toHaveBeenLastCalledWith(false) + + rerender() + + expect(mocks.editor.setEditable).toHaveBeenLastCalledWith(true) + }) + it('should render with isSupportFileVar=true', () => { render() expect(screen.getByTestId('lexical-composer')).toBeInTheDocument() diff --git a/web/app/components/base/prompt-editor/index.tsx b/web/app/components/base/prompt-editor/index.tsx index 29d0d717157..eab61f4729e 100644 --- a/web/app/components/base/prompt-editor/index.tsx +++ b/web/app/components/base/prompt-editor/index.tsx @@ -20,6 +20,7 @@ import type { VariableBlockType, WorkflowVariableBlockType, } from './types' +import type { EventEmitterValue } from '@/context/event-emitter' import { cn } from '@langgenius/dify-ui/cn' import { CodeNode } from '@lexical/code' import { LexicalComposer } from '@lexical/react/LexicalComposer' @@ -97,6 +98,16 @@ const ValueSyncPlugin: FC<{ value?: string }> = ({ value }) => { return null } +const EditableSyncPlugin: FC<{ editable: boolean }> = ({ editable }) => { + const [editor] = useLexicalComposerContext() + + useEffect(() => { + editor.setEditable(editable) + }, [editable, editor]) + + return null +} + export type PromptEditorProps = { instanceId?: string compact?: boolean @@ -122,7 +133,7 @@ export type PromptEditorProps = { errorMessageBlock?: ErrorMessageBlockType lastRunBlock?: LastRunBlockType isSupportFileVar?: boolean - shortcutPopups?: Array<{ hotkey: Hotkey, Popup: React.ComponentType<{ onClose: () => void, onInsert: (command: LexicalCommand, params: any[]) => void }> }> + shortcutPopups?: Array<{ hotkey: Hotkey, Popup: React.ComponentType<{ onClose: () => void, onInsert: (command: LexicalCommand, params: unknown[]) => void }> }> } const PromptEditor: FC = ({ @@ -191,16 +202,18 @@ const PromptEditor: FC = ({ } useEffect(() => { - eventEmitter?.emit({ + const event: EventEmitterValue = { type: UPDATE_DATASETS_EVENT_EMITTER, payload: contextBlock?.datasets, - } as any) + } + eventEmitter?.emit(event) }, [eventEmitter, contextBlock?.datasets]) useEffect(() => { - eventEmitter?.emit({ + const event: EventEmitterValue = { type: UPDATE_HISTORY_EVENT_EMITTER, payload: historyBlock?.history, - } as any) + } + eventEmitter?.emit(event) }, [eventEmitter, historyBlock?.history]) const [floatingAnchorElem, setFloatingAnchorElem] = useState(null) @@ -243,6 +256,7 @@ const PromptEditor: FC = ({ onEditorChange={handleEditorChange} /> + )