Remove old post types to reduce confusion
This commit is contained in:
parent
318f33709f
commit
3d993d76ed
13 changed files with 45 additions and 227 deletions
0
prisma/dev.db
Normal file
0
prisma/dev.db
Normal 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";
|
||||
|
|
@ -43,16 +43,10 @@ model Project {
|
|||
model Post {
|
||||
id Int @id @default(autoincrement())
|
||||
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
|
||||
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)
|
||||
attachments Json? // Array of media IDs for photo attachments
|
||||
tags Json? // Array of tags
|
||||
|
|
@ -61,10 +55,6 @@ model Post {
|
|||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
photo Photo? @relation(fields: [photoId], references: [id])
|
||||
album Album? @relation(fields: [albumId], references: [id])
|
||||
|
||||
@@index([slug])
|
||||
@@index([status])
|
||||
@@index([postType])
|
||||
|
|
@ -87,7 +77,6 @@ model Album {
|
|||
|
||||
// Relations
|
||||
photos Photo[]
|
||||
posts Post[]
|
||||
|
||||
@@index([slug])
|
||||
@@index([status])
|
||||
|
|
@ -118,7 +107,6 @@ model Photo {
|
|||
|
||||
// Relations
|
||||
album Album? @relation(fields: [albumId], references: [id], onDelete: Cascade)
|
||||
posts Post[]
|
||||
|
||||
@@index([slug])
|
||||
@@index([status])
|
||||
|
|
|
|||
|
|
@ -25,17 +25,6 @@
|
|||
{/if}
|
||||
</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}
|
||||
<!-- Album slideshow -->
|
||||
|
|
|
|||
|
|
@ -23,17 +23,6 @@
|
|||
</h2>
|
||||
{/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}
|
||||
<div class="post-excerpt">
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@
|
|||
excerpt: string | null
|
||||
status: string
|
||||
tags: string[] | null
|
||||
linkUrl: string | null
|
||||
linkDescription: string | null
|
||||
featuredImage: string | null
|
||||
publishedAt: string | null
|
||||
createdAt: string
|
||||
|
|
@ -28,12 +26,9 @@
|
|||
const postTypeLabels: Record<string, string> = {
|
||||
post: 'Post',
|
||||
essay: 'Essay',
|
||||
// Legacy types for backward compatibility
|
||||
// Map database types to display names
|
||||
blog: 'Essay',
|
||||
microblog: 'Post',
|
||||
link: 'Post',
|
||||
photo: 'Post',
|
||||
album: 'Album'
|
||||
microblog: 'Post'
|
||||
}
|
||||
|
||||
function handlePostClick() {
|
||||
|
|
@ -108,9 +103,6 @@
|
|||
{/if}
|
||||
|
||||
<div class="post-content">
|
||||
{#if post.linkUrl}
|
||||
<p class="post-link-url">{post.linkUrl}</p>
|
||||
{/if}
|
||||
<p class="post-preview">{getPostSnippet(post)}</p>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -28,10 +28,6 @@
|
|||
type: 'doc',
|
||||
content: [{ type: 'paragraph' }]
|
||||
}
|
||||
let linkUrl = ''
|
||||
let linkTitle = ''
|
||||
let linkDescription = ''
|
||||
let showLinkFields = false
|
||||
let characterCount = 0
|
||||
let editorInstance: Editor
|
||||
|
||||
|
|
@ -64,7 +60,7 @@
|
|||
}
|
||||
|
||||
function hasContent(): boolean {
|
||||
return characterCount > 0 || linkUrl.length > 0 || attachedPhotos.length > 0
|
||||
return characterCount > 0 || attachedPhotos.length > 0
|
||||
}
|
||||
|
||||
function resetComposer() {
|
||||
|
|
@ -73,10 +69,6 @@
|
|||
type: 'doc',
|
||||
content: [{ type: 'paragraph' }]
|
||||
}
|
||||
linkUrl = ''
|
||||
linkTitle = ''
|
||||
linkDescription = ''
|
||||
showLinkFields = false
|
||||
characterCount = 0
|
||||
attachedPhotos = []
|
||||
if (editorInstance) {
|
||||
|
|
@ -100,9 +92,6 @@
|
|||
essaySlug = generateSlug(essayTitle)
|
||||
}
|
||||
|
||||
function toggleLinkFields() {
|
||||
showLinkFields = !showLinkFields
|
||||
}
|
||||
|
||||
function handlePhotoUpload() {
|
||||
fileInput.click()
|
||||
|
|
@ -219,18 +208,11 @@
|
|||
tags: essayTags ? essayTags.split(',').map((tag) => tag.trim()) : []
|
||||
}
|
||||
} 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,
|
||||
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 {
|
||||
|
|
@ -266,7 +248,6 @@
|
|||
$: isOverLimit = characterCount > CHARACTER_LIMIT
|
||||
$: canSave =
|
||||
(postType === 'post' && (characterCount > 0 || attachedPhotos.length > 0) && !isOverLimit) ||
|
||||
(showLinkFields && linkUrl.length > 0) ||
|
||||
(postType === 'essay' && essayTitle.length > 0 && content)
|
||||
</script>
|
||||
|
||||
|
|
@ -320,23 +301,6 @@
|
|||
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}
|
||||
<div class="attached-photos">
|
||||
|
|
@ -371,36 +335,6 @@
|
|||
|
||||
<div class="composer-footer">
|
||||
<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
|
||||
variant="ghost"
|
||||
|
|
@ -452,7 +386,7 @@
|
|||
</div>
|
||||
|
||||
<div class="footer-right">
|
||||
{#if postType === 'post' && !showLinkFields}
|
||||
{#if postType === 'post'}
|
||||
<span
|
||||
class="character-count"
|
||||
class:warning={characterCount > CHARACTER_LIMIT * 0.9}
|
||||
|
|
@ -565,23 +499,6 @@
|
|||
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}
|
||||
<div class="attached-photos">
|
||||
|
|
@ -616,36 +533,6 @@
|
|||
|
||||
<div class="composer-footer">
|
||||
<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
|
||||
variant="ghost"
|
||||
|
|
@ -697,15 +584,13 @@
|
|||
</div>
|
||||
|
||||
<div class="footer-right">
|
||||
{#if !showLinkFields}
|
||||
<span
|
||||
class="character-count"
|
||||
class:warning={characterCount > CHARACTER_LIMIT * 0.9}
|
||||
class:error={isOverLimit}
|
||||
>
|
||||
{CHARACTER_LIMIT - characterCount}
|
||||
</span>
|
||||
{/if}
|
||||
<span
|
||||
class="character-count"
|
||||
class:warning={characterCount > CHARACTER_LIMIT * 0.9}
|
||||
class:error={isOverLimit}
|
||||
>
|
||||
{CHARACTER_LIMIT - characterCount}
|
||||
</span>
|
||||
<Button variant="primary" onclick={handleSave} disabled={!canSave}>Post</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
excerpt: string | null
|
||||
status: string
|
||||
tags: string[] | null
|
||||
linkUrl: string | null
|
||||
linkDescription: string | null
|
||||
featuredImage: string | null
|
||||
publishedAt: string | null
|
||||
createdAt: string
|
||||
|
|
@ -130,7 +128,7 @@
|
|||
filteredPosts = posts
|
||||
} else if (selectedFilter === 'post') {
|
||||
filteredPosts = posts.filter((post) =>
|
||||
['post', 'microblog', 'link', 'photo'].includes(post.postType)
|
||||
['post', 'microblog'].includes(post.postType)
|
||||
)
|
||||
} else if (selectedFilter === 'essay') {
|
||||
filteredPosts = posts.filter((post) => ['essay', 'blog'].includes(post.postType))
|
||||
|
|
|
|||
|
|
@ -97,27 +97,8 @@ export const POST: RequestHandler = async (event) => {
|
|||
featuredImageId = data.attachedPhotos[0]
|
||||
}
|
||||
|
||||
// Handle album gallery - use first image as featured image
|
||||
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
|
||||
// Use content as-is (no special handling needed)
|
||||
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({
|
||||
data: {
|
||||
|
|
@ -126,8 +107,6 @@ export const POST: RequestHandler = async (event) => {
|
|||
postType: data.type,
|
||||
status: data.status,
|
||||
content: postContent,
|
||||
linkUrl: data.link_url,
|
||||
linkDescription: data.linkDescription,
|
||||
featuredImage: featuredImageId,
|
||||
attachments:
|
||||
data.attachedPhotos && data.attachedPhotos.length > 0 ? data.attachedPhotos : null,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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
|
||||
if (data.type === 'album' && data.gallery) {
|
||||
postContent = {
|
||||
type: 'album',
|
||||
gallery: data.gallery,
|
||||
description: data.content
|
||||
}
|
||||
}
|
||||
|
||||
const post = await prisma.post.update({
|
||||
where: { id },
|
||||
|
|
@ -95,8 +76,6 @@ export const PUT: RequestHandler = async (event) => {
|
|||
postType: data.type,
|
||||
status: data.status,
|
||||
content: postContent,
|
||||
linkUrl: data.link_url,
|
||||
linkDescription: data.linkDescription,
|
||||
featuredImage: featuredImageId,
|
||||
attachments:
|
||||
data.attachedPhotos && data.attachedPhotos.length > 0 ? data.attachedPhotos : null,
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ export interface UniverseItem {
|
|||
|
||||
// Post-specific fields
|
||||
postType?: string
|
||||
linkUrl?: string
|
||||
linkDescription?: string
|
||||
attachments?: any
|
||||
featuredImage?: string
|
||||
|
||||
// Album-specific fields
|
||||
description?: string
|
||||
|
|
@ -46,9 +45,8 @@ export const GET: RequestHandler = async (event) => {
|
|||
postType: true,
|
||||
title: true,
|
||||
content: true,
|
||||
linkUrl: true,
|
||||
linkDescription: true,
|
||||
attachments: true,
|
||||
featuredImage: true,
|
||||
publishedAt: true,
|
||||
createdAt: true
|
||||
},
|
||||
|
|
@ -96,9 +94,8 @@ export const GET: RequestHandler = async (event) => {
|
|||
title: post.title || undefined,
|
||||
content: post.content,
|
||||
postType: post.postType,
|
||||
linkUrl: post.linkUrl || undefined,
|
||||
linkDescription: post.linkDescription || undefined,
|
||||
attachments: post.attachments,
|
||||
featuredImage: post.featuredImage || undefined,
|
||||
publishedAt: post.publishedAt!.toISOString(),
|
||||
createdAt: post.createdAt.toISOString()
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ export const GET: RequestHandler = async (event) => {
|
|||
pubDate: post.publishedAt || post.createdAt,
|
||||
updatedDate: post.updatedAt,
|
||||
postType: post.postType,
|
||||
linkUrl: post.linkUrl || null
|
||||
featuredImage: post.featuredImage || null
|
||||
})),
|
||||
...universeAlbums.map((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>` : ''}
|
||||
<category>${item.section}</category>
|
||||
<category>${item.type === 'post' ? item.postType : 'album'}</category>
|
||||
${item.type === 'post' && item.linkUrl ? `<comments>${item.linkUrl}</comments>` : ''}
|
||||
${
|
||||
item.type === 'album' && item.coverPhoto
|
||||
? `
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export const GET: RequestHandler = async (event) => {
|
|||
pubDate: post.publishedAt || post.createdAt,
|
||||
updatedDate: post.updatedAt,
|
||||
postType: post.postType,
|
||||
linkUrl: post.linkUrl || null
|
||||
featuredImage: post.featuredImage || null
|
||||
})),
|
||||
...albums.map((album) => ({
|
||||
type: 'album',
|
||||
|
|
@ -143,7 +143,6 @@ ${item.content ? `<content:encoded><![CDATA[${item.content}]]></content:encoded>
|
|||
<pubDate>${formatRFC822Date(new Date(item.pubDate))}</pubDate>
|
||||
${item.updatedDate ? `<atom:updated>${new Date(item.updatedDate).toISOString()}</atom:updated>` : ''}
|
||||
<category>${item.type === 'post' ? item.postType : 'album'}</category>
|
||||
${item.type === 'post' && item.linkUrl ? `<comments>${item.linkUrl}</comments>` : ''}
|
||||
<author>noreply@jedmund.com (Justin Edmund)</author>
|
||||
</item>`
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue