add post fix

This commit is contained in:
2026-01-15 17:41:53 +09:00
parent 64457460eb
commit e2d324500d
4 changed files with 191 additions and 8 deletions

View File

@@ -1,4 +1,5 @@
import type { BlogPost } from '../types.js' import type { BlogPost } from '../types.js'
import { putRecord } from '../lib/auth.js'
function formatDate(dateStr: string): string { function formatDate(dateStr: string): string {
const date = new Date(dateStr) const date = new Date(dateStr)
@@ -38,17 +39,77 @@ export function mountPostList(container: HTMLElement, posts: BlogPost[]): void {
container.innerHTML = `<ul class="post-list">${html}</ul>` container.innerHTML = `<ul class="post-list">${html}</ul>`
} }
export function mountPostDetail(container: HTMLElement, post: BlogPost, handle: string): void { export function mountPostDetail(container: HTMLElement, post: BlogPost, handle: string, collection: string, canEdit: boolean = false): void {
const rkey = post.uri.split('/').pop() || ''
const jsonUrl = `?mode=browser&handle=${handle}&collection=${encodeURIComponent(collection)}&rkey=${rkey}`
const editBtn = canEdit ? `<button class="edit-btn" id="edit-btn">edit</button>` : ''
container.innerHTML = ` container.innerHTML = `
<article class="post-detail"> <article class="post-detail">
<header class="post-header"> <header class="post-header">
<h1 class="post-title">${escapeHtml(post.title)}</h1> <h1 class="post-title" id="post-title">${escapeHtml(post.title)}</h1>
<time class="post-date">${formatDate(post.createdAt)}</time> <div class="post-meta">
<time class="post-date">${formatDate(post.createdAt)}</time>
<a href="${jsonUrl}" class="json-btn">json</a>
${editBtn}
</div>
</header> </header>
<div class="post-content">${escapeHtml(post.content)}</div> <div class="post-content" id="post-content">${escapeHtml(post.content)}</div>
<footer class="post-footer">
<a href="?handle=${handle}" class="back-link">← Back to posts</a>
</footer>
</article> </article>
<div class="edit-form-container" id="edit-form-container" style="display: none;">
<h3>Edit Post</h3>
<form class="edit-form" id="edit-form">
<input type="text" id="edit-title" class="edit-form-title" value="${escapeHtml(post.title)}" placeholder="Title" required>
<textarea id="edit-content" class="edit-form-body" placeholder="Content" required>${escapeHtml(post.content)}</textarea>
<div class="edit-form-footer">
<button type="button" id="edit-cancel" class="edit-cancel-btn">Cancel</button>
<button type="submit" id="edit-submit" class="edit-submit-btn">Save</button>
</div>
</form>
</div>
` `
if (canEdit) {
const editBtnEl = document.getElementById('edit-btn')
const editFormContainer = document.getElementById('edit-form-container')
const editForm = document.getElementById('edit-form') as HTMLFormElement
const editCancel = document.getElementById('edit-cancel')
const postArticle = container.querySelector('.post-detail') as HTMLElement
editBtnEl?.addEventListener('click', () => {
postArticle.style.display = 'none'
editFormContainer!.style.display = 'block'
})
editCancel?.addEventListener('click', () => {
postArticle.style.display = 'block'
editFormContainer!.style.display = 'none'
})
editForm?.addEventListener('submit', async (e) => {
e.preventDefault()
const title = (document.getElementById('edit-title') as HTMLInputElement).value
const content = (document.getElementById('edit-content') as HTMLTextAreaElement).value
const submitBtn = document.getElementById('edit-submit') as HTMLButtonElement
try {
submitBtn.disabled = true
submitBtn.textContent = 'Saving...'
await putRecord(collection, rkey, {
title,
content,
createdAt: post.createdAt,
})
window.location.reload()
} catch (err) {
alert('Save failed: ' + err)
submitBtn.disabled = false
submitBtn.textContent = 'Save'
}
})
}
} }

View File

@@ -161,3 +161,27 @@ export async function deleteRecord(collection: string, rkey: string): Promise<bo
throw err throw err
} }
} }
export async function putRecord(
collection: string,
rkey: string,
record: Record<string, unknown>
): Promise<{ uri: string; cid: string } | null> {
if (!agent) return null
try {
const result = await agent.com.atproto.repo.putRecord({
repo: agent.assertDid,
collection,
rkey,
record: {
$type: collection,
...record,
},
})
return { uri: result.data.uri, cid: result.data.cid }
} catch (err) {
console.error('Put record error:', err)
throw err
}
}

View File

@@ -142,7 +142,8 @@ async function init(): Promise<void> {
if (rkey) { if (rkey) {
const post = await getRecord(profile.did, config.collection, rkey) const post = await getRecord(profile.did, config.collection, rkey)
if (post) { if (post) {
mountPostDetail(contentEl, post, handle) const canEdit = isLoggedIn && authSession?.did === profile.did
mountPostDetail(contentEl, post, handle, config.collection, canEdit)
} else { } else {
contentEl.innerHTML = '<p>Post not found</p>' contentEl.innerHTML = '<p>Post not found</p>'
} }

View File

@@ -288,6 +288,97 @@ body {
color: #333; color: #333;
} }
.edit-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 4px 8px;
background: #28a745;
color: #fff;
border: none;
border-radius: 4px;
text-decoration: none;
font-family: monospace;
font-size: 12px;
cursor: pointer;
}
.edit-btn:hover {
background: #218838;
}
/* Edit Form */
.edit-form-container {
padding: 20px 0;
}
.edit-form-container h3 {
font-size: 18px;
margin-bottom: 16px;
}
.edit-form {
display: flex;
flex-direction: column;
gap: 12px;
}
.edit-form-title {
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 16px;
}
.edit-form-body {
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
resize: vertical;
min-height: 200px;
font-family: inherit;
}
.edit-form-footer {
display: flex;
justify-content: flex-end;
gap: 8px;
}
.edit-cancel-btn {
padding: 10px 24px;
background: #6c757d;
color: #fff;
border: none;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
}
.edit-cancel-btn:hover {
background: #5a6268;
}
.edit-submit-btn {
padding: 10px 24px;
background: #28a745;
color: #fff;
border: none;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
}
.edit-submit-btn:hover {
background: #218838;
}
.edit-submit-btn:disabled {
background: #ccc;
cursor: not-allowed;
}
.post-content { .post-content {
font-size: 16px; font-size: 16px;
line-height: 1.8; line-height: 1.8;
@@ -549,6 +640,12 @@ body {
background: #333; background: #333;
color: #e0e0e0; color: #e0e0e0;
} }
.edit-form-title,
.edit-form-body {
background: #1a1a1a;
border-color: #333;
color: #e0e0e0;
}
.tab:hover { .tab:hover {
background: #333; background: #333;
} }