Remove old post types to reduce confusion

This commit is contained in:
Justin Edmund 2025-06-11 00:06:44 -07:00
parent 318f33709f
commit 3d993d76ed
13 changed files with 45 additions and 227 deletions

0
prisma/dev.db Normal file
View file

View file

@ -0,0 +1,24 @@
/*
Warnings:
- You are about to drop the column `albumId` on the `Post` table. All the data in the column will be lost.
- You are about to drop the column `linkDescription` on the `Post` table. All the data in the column will be lost.
- You are about to drop the column `linkUrl` on the `Post` table. All the data in the column will be lost.
- You are about to drop the column `photoId` on the `Post` table. All the data in the column will be lost.
- You are about to drop the `_db_initialization` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropForeignKey
ALTER TABLE "Post" DROP CONSTRAINT "Post_albumId_fkey";
-- DropForeignKey
ALTER TABLE "Post" DROP CONSTRAINT "Post_photoId_fkey";
-- AlterTable
ALTER TABLE "Post" DROP COLUMN "albumId",
DROP COLUMN "linkDescription",
DROP COLUMN "linkUrl",
DROP COLUMN "photoId";
-- DropTable
DROP TABLE "_db_initialization";

View file

@ -43,16 +43,10 @@ model Project {
model Post { model Post {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
slug String @unique @db.VarChar(255) slug String @unique @db.VarChar(255)
postType String @db.VarChar(50) // blog, microblog, link, photo, album postType String @db.VarChar(50) // blog, microblog
title String? @db.VarChar(255) // Optional for microblog posts title String? @db.VarChar(255) // Optional for microblog posts
content Json? // BlockNote JSON for blog/microblog content Json? // BlockNote JSON for blog/microblog
// Type-specific fields
linkUrl String? @db.VarChar(500)
linkDescription String? @db.Text
photoId Int?
albumId Int?
featuredImage String? @db.VarChar(500) featuredImage String? @db.VarChar(500)
attachments Json? // Array of media IDs for photo attachments attachments Json? // Array of media IDs for photo attachments
tags Json? // Array of tags tags Json? // Array of tags
@ -61,10 +55,6 @@ model Post {
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
// Relations
photo Photo? @relation(fields: [photoId], references: [id])
album Album? @relation(fields: [albumId], references: [id])
@@index([slug]) @@index([slug])
@@index([status]) @@index([status])
@@index([postType]) @@index([postType])
@ -87,7 +77,6 @@ model Album {
// Relations // Relations
photos Photo[] photos Photo[]
posts Post[]
@@index([slug]) @@index([slug])
@@index([status]) @@index([status])
@ -118,7 +107,6 @@ model Photo {
// Relations // Relations
album Album? @relation(fields: [albumId], references: [id], onDelete: Cascade) album Album? @relation(fields: [albumId], references: [id], onDelete: Cascade)
posts Post[]
@@index([slug]) @@index([slug])
@@index([status]) @@index([status])

View file

@ -25,17 +25,6 @@
{/if} {/if}
</header> </header>
{#if post.linkUrl}
<div class="post-link-preview">
<LinkCard
link={{
url: post.linkUrl,
title: post.title,
description: post.linkDescription
}}
/>
</div>
{/if}
{#if post.album && post.album.photos && post.album.photos.length > 0} {#if post.album && post.album.photos && post.album.photos.length > 0}
<!-- Album slideshow --> <!-- Album slideshow -->

View file

@ -23,17 +23,6 @@
</h2> </h2>
{/if} {/if}
{#if post.linkUrl}
<!-- Link post type -->
<div class="link-preview">
<a href={post.linkUrl} target="_blank" rel="noopener noreferrer" class="link-url">
{post.linkUrl}
</a>
{#if post.linkDescription}
<p class="link-description">{post.linkDescription}</p>
{/if}
</div>
{/if}
{#if post.content} {#if post.content}
<div class="post-excerpt"> <div class="post-excerpt">

View file

@ -11,8 +11,6 @@
excerpt: string | null excerpt: string | null
status: string status: string
tags: string[] | null tags: string[] | null
linkUrl: string | null
linkDescription: string | null
featuredImage: string | null featuredImage: string | null
publishedAt: string | null publishedAt: string | null
createdAt: string createdAt: string
@ -28,12 +26,9 @@
const postTypeLabels: Record<string, string> = { const postTypeLabels: Record<string, string> = {
post: 'Post', post: 'Post',
essay: 'Essay', essay: 'Essay',
// Legacy types for backward compatibility // Map database types to display names
blog: 'Essay', blog: 'Essay',
microblog: 'Post', microblog: 'Post'
link: 'Post',
photo: 'Post',
album: 'Album'
} }
function handlePostClick() { function handlePostClick() {
@ -108,9 +103,6 @@
{/if} {/if}
<div class="post-content"> <div class="post-content">
{#if post.linkUrl}
<p class="post-link-url">{post.linkUrl}</p>
{/if}
<p class="post-preview">{getPostSnippet(post)}</p> <p class="post-preview">{getPostSnippet(post)}</p>
</div> </div>

View file

@ -28,10 +28,6 @@
type: 'doc', type: 'doc',
content: [{ type: 'paragraph' }] content: [{ type: 'paragraph' }]
} }
let linkUrl = ''
let linkTitle = ''
let linkDescription = ''
let showLinkFields = false
let characterCount = 0 let characterCount = 0
let editorInstance: Editor let editorInstance: Editor
@ -64,7 +60,7 @@
} }
function hasContent(): boolean { function hasContent(): boolean {
return characterCount > 0 || linkUrl.length > 0 || attachedPhotos.length > 0 return characterCount > 0 || attachedPhotos.length > 0
} }
function resetComposer() { function resetComposer() {
@ -73,10 +69,6 @@
type: 'doc', type: 'doc',
content: [{ type: 'paragraph' }] content: [{ type: 'paragraph' }]
} }
linkUrl = ''
linkTitle = ''
linkDescription = ''
showLinkFields = false
characterCount = 0 characterCount = 0
attachedPhotos = [] attachedPhotos = []
if (editorInstance) { if (editorInstance) {
@ -100,9 +92,6 @@
essaySlug = generateSlug(essayTitle) essaySlug = generateSlug(essayTitle)
} }
function toggleLinkFields() {
showLinkFields = !showLinkFields
}
function handlePhotoUpload() { function handlePhotoUpload() {
fileInput.click() fileInput.click()
@ -219,18 +208,11 @@
tags: essayTags ? essayTags.split(',').map((tag) => tag.trim()) : [] tags: essayTags ? essayTags.split(',').map((tag) => tag.trim()) : []
} }
} else { } else {
// All other content is just a "post" with optional link data and attachments // All other content is just a "post" with attachments
postData = { postData = {
...postData, ...postData,
type: 'microblog' // 'microblog' is for shorter posts type: 'microblog' // 'microblog' is for shorter posts
} }
// Add link fields if present
if (showLinkFields) {
postData.link_url = linkUrl
postData.linkTitle = linkTitle
postData.linkDescription = linkDescription
}
} }
try { try {
@ -266,7 +248,6 @@
$: isOverLimit = characterCount > CHARACTER_LIMIT $: isOverLimit = characterCount > CHARACTER_LIMIT
$: canSave = $: canSave =
(postType === 'post' && (characterCount > 0 || attachedPhotos.length > 0) && !isOverLimit) || (postType === 'post' && (characterCount > 0 || attachedPhotos.length > 0) && !isOverLimit) ||
(showLinkFields && linkUrl.length > 0) ||
(postType === 'essay' && essayTitle.length > 0 && content) (postType === 'essay' && essayTitle.length > 0 && content)
</script> </script>
@ -320,23 +301,6 @@
class="composer-editor" class="composer-editor"
/> />
{#if showLinkFields}
<div class="link-fields">
<Input
type="url"
bind:value={linkUrl}
placeholder="https://example.com"
autocomplete="off"
/>
<Input bind:value={linkTitle} placeholder="Link title (optional)" autocomplete="off" />
<Input
type="textarea"
bind:value={linkDescription}
placeholder="Add context..."
rows={2}
/>
</div>
{/if}
{#if attachedPhotos.length > 0} {#if attachedPhotos.length > 0}
<div class="attached-photos"> <div class="attached-photos">
@ -371,36 +335,6 @@
<div class="composer-footer"> <div class="composer-footer">
<div class="footer-left"> <div class="footer-left">
<Button
variant="ghost"
iconOnly
buttonSize="icon"
onclick={toggleLinkFields}
active={showLinkFields}
title="Add link"
class="tool-button"
>
<svg slot="icon" width="18" height="18" viewBox="0 0 18 18" fill="none">
<path
d="M8 10a3 3 0 0 1 0-5l2.5-2.5a3 3 0 0 1 4.243 4.243l-1.25 1.25"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M10 8a3 3 0 0 1 0 5l-2.5 2.5a3 3 0 0 1-4.243-4.243l1.25-1.25"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M11 7l-4 4"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
/>
</svg>
</Button>
<Button <Button
variant="ghost" variant="ghost"
@ -452,7 +386,7 @@
</div> </div>
<div class="footer-right"> <div class="footer-right">
{#if postType === 'post' && !showLinkFields} {#if postType === 'post'}
<span <span
class="character-count" class="character-count"
class:warning={characterCount > CHARACTER_LIMIT * 0.9} class:warning={characterCount > CHARACTER_LIMIT * 0.9}
@ -565,23 +499,6 @@
class="inline-composer-editor" class="inline-composer-editor"
/> />
{#if showLinkFields}
<div class="link-fields">
<Input
type="url"
bind:value={linkUrl}
placeholder="https://example.com"
autocomplete="off"
/>
<Input bind:value={linkTitle} placeholder="Link title (optional)" autocomplete="off" />
<Input
type="textarea"
bind:value={linkDescription}
placeholder="Add context..."
rows={2}
/>
</div>
{/if}
{#if attachedPhotos.length > 0} {#if attachedPhotos.length > 0}
<div class="attached-photos"> <div class="attached-photos">
@ -616,36 +533,6 @@
<div class="composer-footer"> <div class="composer-footer">
<div class="footer-left"> <div class="footer-left">
<Button
variant="ghost"
iconOnly
buttonSize="icon"
onclick={toggleLinkFields}
active={showLinkFields}
title="Add link"
class="tool-button"
>
<svg slot="icon" width="18" height="18" viewBox="0 0 18 18" fill="none">
<path
d="M8 10a3 3 0 0 1 0-5l2.5-2.5a3 3 0 0 1 4.243 4.243l-1.25 1.25"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M10 8a3 3 0 0 1 0 5l-2.5 2.5a3 3 0 0 1-4.243-4.243l1.25-1.25"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M11 7l-4 4"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
/>
</svg>
</Button>
<Button <Button
variant="ghost" variant="ghost"
@ -697,15 +584,13 @@
</div> </div>
<div class="footer-right"> <div class="footer-right">
{#if !showLinkFields} <span
<span class="character-count"
class="character-count" class:warning={characterCount > CHARACTER_LIMIT * 0.9}
class:warning={characterCount > CHARACTER_LIMIT * 0.9} class:error={isOverLimit}
class:error={isOverLimit} >
> {CHARACTER_LIMIT - characterCount}
{CHARACTER_LIMIT - characterCount} </span>
</span>
{/if}
<Button variant="primary" onclick={handleSave} disabled={!canSave}>Post</Button> <Button variant="primary" onclick={handleSave} disabled={!canSave}>Post</Button>
</div> </div>
</div> </div>

View file

@ -18,8 +18,6 @@
excerpt: string | null excerpt: string | null
status: string status: string
tags: string[] | null tags: string[] | null
linkUrl: string | null
linkDescription: string | null
featuredImage: string | null featuredImage: string | null
publishedAt: string | null publishedAt: string | null
createdAt: string createdAt: string
@ -130,7 +128,7 @@
filteredPosts = posts filteredPosts = posts
} else if (selectedFilter === 'post') { } else if (selectedFilter === 'post') {
filteredPosts = posts.filter((post) => filteredPosts = posts.filter((post) =>
['post', 'microblog', 'link', 'photo'].includes(post.postType) ['post', 'microblog'].includes(post.postType)
) )
} else if (selectedFilter === 'essay') { } else if (selectedFilter === 'essay') {
filteredPosts = posts.filter((post) => ['essay', 'blog'].includes(post.postType)) filteredPosts = posts.filter((post) => ['essay', 'blog'].includes(post.postType))

View file

@ -97,27 +97,8 @@ export const POST: RequestHandler = async (event) => {
featuredImageId = data.attachedPhotos[0] featuredImageId = data.attachedPhotos[0]
} }
// Handle album gallery - use first image as featured image // Use content as-is (no special handling needed)
if (data.gallery && data.gallery.length > 0 && !featuredImageId) {
// Get the media URL for the first gallery item
const firstMedia = await prisma.media.findUnique({
where: { id: data.gallery[0] },
select: { url: true }
})
if (firstMedia) {
featuredImageId = firstMedia.url
}
}
// For albums, store gallery IDs in content field as a special structure
let postContent = data.content let postContent = data.content
if (data.type === 'album' && data.gallery) {
postContent = {
type: 'album',
gallery: data.gallery,
description: data.content
}
}
const post = await prisma.post.create({ const post = await prisma.post.create({
data: { data: {
@ -126,8 +107,6 @@ export const POST: RequestHandler = async (event) => {
postType: data.type, postType: data.type,
status: data.status, status: data.status,
content: postContent, content: postContent,
linkUrl: data.link_url,
linkDescription: data.linkDescription,
featuredImage: featuredImageId, featuredImage: featuredImageId,
attachments: attachments:
data.attachedPhotos && data.attachedPhotos.length > 0 ? data.attachedPhotos : null, data.attachedPhotos && data.attachedPhotos.length > 0 ? data.attachedPhotos : null,

View file

@ -64,28 +64,9 @@ export const PUT: RequestHandler = async (event) => {
} }
} }
// Handle album gallery updates // Use content as-is (no special handling needed)
let featuredImageId = data.featuredImage let featuredImageId = data.featuredImage
if (data.gallery && data.gallery.length > 0 && !featuredImageId) {
// Get the media URL for the first gallery item
const firstMedia = await prisma.media.findUnique({
where: { id: data.gallery[0] },
select: { url: true }
})
if (firstMedia) {
featuredImageId = firstMedia.url
}
}
// For albums, store gallery IDs in content field as a special structure
let postContent = data.content let postContent = data.content
if (data.type === 'album' && data.gallery) {
postContent = {
type: 'album',
gallery: data.gallery,
description: data.content
}
}
const post = await prisma.post.update({ const post = await prisma.post.update({
where: { id }, where: { id },
@ -95,8 +76,6 @@ export const PUT: RequestHandler = async (event) => {
postType: data.type, postType: data.type,
status: data.status, status: data.status,
content: postContent, content: postContent,
linkUrl: data.link_url,
linkDescription: data.linkDescription,
featuredImage: featuredImageId, featuredImage: featuredImageId,
attachments: attachments:
data.attachedPhotos && data.attachedPhotos.length > 0 ? data.attachedPhotos : null, data.attachedPhotos && data.attachedPhotos.length > 0 ? data.attachedPhotos : null,

View file

@ -14,9 +14,8 @@ export interface UniverseItem {
// Post-specific fields // Post-specific fields
postType?: string postType?: string
linkUrl?: string
linkDescription?: string
attachments?: any attachments?: any
featuredImage?: string
// Album-specific fields // Album-specific fields
description?: string description?: string
@ -46,9 +45,8 @@ export const GET: RequestHandler = async (event) => {
postType: true, postType: true,
title: true, title: true,
content: true, content: true,
linkUrl: true,
linkDescription: true,
attachments: true, attachments: true,
featuredImage: true,
publishedAt: true, publishedAt: true,
createdAt: true createdAt: true
}, },
@ -96,9 +94,8 @@ export const GET: RequestHandler = async (event) => {
title: post.title || undefined, title: post.title || undefined,
content: post.content, content: post.content,
postType: post.postType, postType: post.postType,
linkUrl: post.linkUrl || undefined,
linkDescription: post.linkDescription || undefined,
attachments: post.attachments, attachments: post.attachments,
featuredImage: post.featuredImage || undefined,
publishedAt: post.publishedAt!.toISOString(), publishedAt: post.publishedAt!.toISOString(),
createdAt: post.createdAt.toISOString() createdAt: post.createdAt.toISOString()
})) }))

View file

@ -134,7 +134,7 @@ export const GET: RequestHandler = async (event) => {
pubDate: post.publishedAt || post.createdAt, pubDate: post.publishedAt || post.createdAt,
updatedDate: post.updatedAt, updatedDate: post.updatedAt,
postType: post.postType, postType: post.postType,
linkUrl: post.linkUrl || null featuredImage: post.featuredImage || null
})), })),
...universeAlbums.map((album) => ({ ...universeAlbums.map((album) => ({
type: 'album', type: 'album',
@ -206,7 +206,6 @@ ${item.content ? `<content:encoded><![CDATA[${item.content}]]></content:encoded>
${item.updatedDate ? `<atom:updated>${new Date(item.updatedDate).toISOString()}</atom:updated>` : ''} ${item.updatedDate ? `<atom:updated>${new Date(item.updatedDate).toISOString()}</atom:updated>` : ''}
<category>${item.section}</category> <category>${item.section}</category>
<category>${item.type === 'post' ? item.postType : 'album'}</category> <category>${item.type === 'post' ? item.postType : 'album'}</category>
${item.type === 'post' && item.linkUrl ? `<comments>${item.linkUrl}</comments>` : ''}
${ ${
item.type === 'album' && item.coverPhoto item.type === 'album' && item.coverPhoto
? ` ? `

View file

@ -95,7 +95,7 @@ export const GET: RequestHandler = async (event) => {
pubDate: post.publishedAt || post.createdAt, pubDate: post.publishedAt || post.createdAt,
updatedDate: post.updatedAt, updatedDate: post.updatedAt,
postType: post.postType, postType: post.postType,
linkUrl: post.linkUrl || null featuredImage: post.featuredImage || null
})), })),
...albums.map((album) => ({ ...albums.map((album) => ({
type: 'album', type: 'album',
@ -143,7 +143,6 @@ ${item.content ? `<content:encoded><![CDATA[${item.content}]]></content:encoded>
<pubDate>${formatRFC822Date(new Date(item.pubDate))}</pubDate> <pubDate>${formatRFC822Date(new Date(item.pubDate))}</pubDate>
${item.updatedDate ? `<atom:updated>${new Date(item.updatedDate).toISOString()}</atom:updated>` : ''} ${item.updatedDate ? `<atom:updated>${new Date(item.updatedDate).toISOString()}</atom:updated>` : ''}
<category>${item.type === 'post' ? item.postType : 'album'}</category> <category>${item.type === 'post' ? item.postType : 'album'}</category>
${item.type === 'post' && item.linkUrl ? `<comments>${item.linkUrl}</comments>` : ''}
<author>noreply@jedmund.com (Justin Edmund)</author> <author>noreply@jedmund.com (Justin Edmund)</author>
</item>` </item>`
) )