add post fix
This commit is contained in:
@@ -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>
|
||||||
|
<div class="post-meta">
|
||||||
<time class="post-date">${formatDate(post.createdAt)}</time>
|
<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'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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>'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user