feat: expose editor state via ref in BlogEditor and integrate with CreatePost
All checks were successful
CI - Build and Push / Build and Push Docker Image (push) Successful in 28s

This commit is contained in:
2025-10-25 21:54:04 +08:00
parent e299694f22
commit 1071c784f8
2 changed files with 37 additions and 8 deletions

View File

@@ -15,6 +15,8 @@ import { LinkNode, AutoLinkNode } from '@lexical/link';
import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin'; import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
import { AutoLinkPlugin } from '@lexical/react/LexicalAutoLinkPlugin'; import { AutoLinkPlugin } from '@lexical/react/LexicalAutoLinkPlugin';
import { HashtagNode } from '@lexical/hashtag'; import { HashtagNode } from '@lexical/hashtag';
import { forwardRef, useImperativeHandle } from 'react';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { ImageNode } from './nodes/ImageNode'; import { ImageNode } from './nodes/ImageNode';
import { MentionNode } from './nodes/MentionNode'; import { MentionNode } from './nodes/MentionNode';
@@ -87,7 +89,24 @@ const editorConfig = {
], ],
}; };
export default function BlogEditor() { export interface BlogEditorRef {
getEditorState: () => string;
}
// Plugin to expose editor instance via ref
function EditorRefPlugin({ editorRef }: { editorRef: React.Ref<BlogEditorRef> }) {
const [editor] = useLexicalComposerContext();
useImperativeHandle(editorRef, () => ({
getEditorState: () => {
return JSON.stringify(editor.getEditorState().toJSON());
},
}));
return null;
}
const BlogEditor = forwardRef<BlogEditorRef>((_, ref) => {
return ( return (
<LexicalComposer initialConfig={editorConfig}> <LexicalComposer initialConfig={editorConfig}>
<div className="editor-container"> <div className="editor-container">
@@ -113,8 +132,13 @@ export default function BlogEditor() {
<HashtagPlugin /> <HashtagPlugin />
<MentionsPlugin /> <MentionsPlugin />
<MarkdownPlugin /> <MarkdownPlugin />
<EditorRefPlugin editorRef={ref} />
</div> </div>
</div> </div>
</LexicalComposer> </LexicalComposer>
); );
} });
BlogEditor.displayName = 'BlogEditor';
export default BlogEditor;

View File

@@ -1,12 +1,13 @@
import { useState, useRef } from 'react'; import { useState, useRef } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import Layout from '../components/Layout'; import Layout from '../components/Layout';
import BlogEditor from '../blog/BlogEditor'; import BlogEditor, { type BlogEditorRef } from '../blog/BlogEditor';
import { uploadImage, createBlogPost } from '../blog/api'; import { uploadImage, createBlogPost } from '../blog/api';
import '../App.css'; import '../App.css';
function CreatePost() { function CreatePost() {
const navigate = useNavigate(); const navigate = useNavigate();
const editorRef = useRef<BlogEditorRef>(null);
const [title, setTitle] = useState(''); const [title, setTitle] = useState('');
const [coverImage, setCoverImage] = useState<string | null>(null); const [coverImage, setCoverImage] = useState<string | null>(null);
const [coverImageKey, setCoverImageKey] = useState<string>(''); const [coverImageKey, setCoverImageKey] = useState<string>('');
@@ -66,13 +67,17 @@ function CreatePost() {
return; return;
} }
// Get editor content
if (!editorRef.current) {
alert('Editor not initialized');
return;
}
setIsSubmitting(true); setIsSubmitting(true);
try { try {
// Get editor content // Get the actual editor state as JSON
// Note: You'll need to export the editor content from the BlogEditor component const content = editorRef.current.getEditorState();
// For now, we'll use a placeholder
const content = JSON.stringify({ editorState: 'placeholder' });
const response = await createBlogPost(title, content, coverImageKey); const response = await createBlogPost(title, content, coverImageKey);
@@ -286,7 +291,7 @@ function CreatePost() {
overflow: 'hidden', overflow: 'hidden',
background: 'var(--bg-card)' background: 'var(--bg-card)'
}}> }}>
<BlogEditor /> <BlogEditor ref={editorRef} />
</div> </div>
</div> </div>