diff --git a/posts/welcome.md b/posts/welcome.md index 53e175b..62dda9e 100644 --- a/posts/welcome.md +++ b/posts/welcome.md @@ -1,8 +1,11 @@ --- -title: "Read Me . Markdown!" -date: "2025-06-17" -tags: ["welcome", "introduction"] -summary: "Read Me Please" +title: Read Me . Markdown! +date: '2025-06-19' +tags: + - welcome + - introduction +summary: Read Me Please +author: Rattatwinko's --- # Welcome to the Blog @@ -97,9 +100,7 @@ You can pin a post both in the UI and in the backend of the server. | Status | Task | |:---------------------------------------------:|:-------------------------------------------------:| -|NOT DONE! | GitHub's Caution/Error Stuff | -|IN WORK | Docker Building ; broke during recent update | -|Maybe Future | Easy deployment of this shit | +|DONE|Code Editor in Admin Panel with saving! --- @@ -117,4 +118,4 @@ Yeah fuck JavaScript, TypeScript is better. - Thanks Rattatwinko ; 17.05.2025 - \ No newline at end of file + diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 034d828..fe140e0 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation'; import Link from 'next/link'; import { marked } from 'marked'; import hljs from 'highlight.js'; +import matter from 'gray-matter'; interface Post { slug: string; @@ -70,6 +71,7 @@ export default function AdminPage() { const [changePwConfirm, setChangePwConfirm] = useState(''); const [changePwFeedback, setChangePwFeedback] = useState(null); const [previewHtml, setPreviewHtml] = useState(''); + const [editingPost, setEditingPost] = useState<{ slug: string, path: string } | null>(null); const router = useRouter(); const usernameRef = useRef(null); const passwordRef = useRef(null); @@ -416,6 +418,62 @@ export default function AdminPage() { } }; + // Function to load a post's raw markdown + const loadPostRaw = async (slug: string, folderPath: string) => { + const params = new URLSearchParams({ slug, path: folderPath }); + const res = await fetch(`/api/admin/posts/raw?${params.toString()}`); + if (!res.ok) { + alert('Error loading post'); + return; + } + const text = await res.text(); + const parsed = matter(text); + setNewPost({ + title: parsed.data.title || '', + date: parsed.data.date || new Date().toISOString().split('T')[0], + tags: Array.isArray(parsed.data.tags) ? parsed.data.tags.join(', ') : (parsed.data.tags || ''), + summary: parsed.data.summary || '', + content: parsed.content || '', + }); + setEditingPost({ slug, path: folderPath }); + }; + + // Function to save edits + const handleEditPost = async (e: React.FormEvent) => { + e.preventDefault(); + if (!editingPost) return; + try { + // Always update date to today if changed + const today = new Date().toISOString().split('T')[0]; + const newDate = newPost.date !== today ? today : newPost.date; + const newFrontmatter = matter.stringify(newPost.content, { + title: newPost.title, + date: newDate, + tags: newPost.tags.split(',').map(tag => tag.trim()), + summary: newPost.summary, + author: process.env.NEXT_PUBLIC_BLOG_OWNER + "'s" || 'Anonymous', + }); + const response = await fetch('/api/admin/posts', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + slug: editingPost.slug, + path: editingPost.path, + content: newFrontmatter, + }), + }); + if (response.ok) { + setEditingPost(null); + setNewPost({ title: '', date: today, tags: '', summary: '', content: '' }); + loadContent(); + } else { + alert('Error saving post'); + } + } catch (error) { + alert('Error saving post'); + } + }; + return (
{pinFeedback && ( @@ -633,7 +691,7 @@ export default function AdminPage() { {/* Create Post Form */}

Create New Post

-
+
- Create Post + {editingPost ? 'Save Changes' : 'Create Post'}
@@ -727,11 +785,19 @@ export default function AdminPage() { const pinnedPosts = posts.filter(post => post.pinned); const unpinnedPosts = posts.filter(post => !post.pinned); return [...pinnedPosts, ...unpinnedPosts].map((post) => ( -
- {post.pinned && ( - 📌 - )} -

{post.title}

+
+
+

{post.title}

+ + {post.pinned && ( + 📌 + )} +

{post.date}

{post.summary}

diff --git a/src/app/api/admin/posts/raw/route.ts b/src/app/api/admin/posts/raw/route.ts new file mode 100644 index 0000000..0b0ea93 --- /dev/null +++ b/src/app/api/admin/posts/raw/route.ts @@ -0,0 +1,22 @@ +import { NextRequest, NextResponse } from 'next/server'; +import fs from 'fs'; +import path from 'path'; + +const postsDirectory = path.join(process.cwd(), 'posts'); + +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url); + const slug = searchParams.get('slug'); + const folderPath = searchParams.get('path') || ''; + if (!slug) { + return NextResponse.json({ error: 'Missing slug' }, { status: 400 }); + } + const filePath = folderPath && folderPath.trim() !== '' + ? path.join(postsDirectory, folderPath, `${slug}.md`) + : path.join(postsDirectory, `${slug}.md`); + if (!fs.existsSync(filePath)) { + return NextResponse.json({ error: 'File does not exist' }, { status: 404 }); + } + const content = fs.readFileSync(filePath, 'utf8'); + return new NextResponse(content, { status: 200 }); +} \ No newline at end of file diff --git a/src/app/api/admin/posts/route.ts b/src/app/api/admin/posts/route.ts index b08eea0..329920b 100644 --- a/src/app/api/admin/posts/route.ts +++ b/src/app/api/admin/posts/route.ts @@ -63,4 +63,26 @@ export async function PATCH(request: Request) { { status: 500 } ); } +} + +export async function PUT(request: Request) { + try { + const body = await request.json(); + const { slug, path: folderPath, content } = body; + if (!slug || typeof content !== 'string') { + return NextResponse.json({ error: 'Missing slug or content' }, { status: 400 }); + } + // Compute file path + const filePath = folderPath && folderPath.trim() !== '' + ? path.join(postsDirectory, folderPath, `${slug}.md`) + : path.join(postsDirectory, `${slug}.md`); + if (!fs.existsSync(filePath)) { + return NextResponse.json({ error: 'File does not exist' }, { status: 404 }); + } + fs.writeFileSync(filePath, content, 'utf8'); + return NextResponse.json({ success: true }); + } catch (error) { + console.error('Error editing post:', error); + return NextResponse.json({ error: 'Error editing post' }, { status: 500 }); + } } \ No newline at end of file