✨ feat: add comment and tag collections with metadata and mock data
This commit is contained in:
Binary file not shown.
@@ -1,9 +1,9 @@
|
|||||||
name: comments
|
name: comment
|
||||||
meta:
|
meta:
|
||||||
label: { de: "Kommentare", en: "Comments" }
|
label: { de: "Kommentare", en: "Comments" }
|
||||||
muiIcon: chat
|
muiIcon: chat
|
||||||
group: community
|
group: community
|
||||||
imageUrl: "https://images.unsplash.com/photo-1516321318423-f06f85e504b3?auto=format&fit=crop&q=80&w=800"
|
imageUrl: "https://images.unsplash.com/photo-1522096823084-2d1aa8411c13?auto=format&fit=crop&q=80&w=800"
|
||||||
preview:
|
preview:
|
||||||
label: author
|
label: author
|
||||||
secondary: message
|
secondary: message
|
||||||
@@ -6,7 +6,7 @@ name: content
|
|||||||
uploadPath: ../media/content
|
uploadPath: ../media/content
|
||||||
meta:
|
meta:
|
||||||
label: { de: "Inhalte", en: "Content" }
|
label: { de: "Inhalte", en: "Content" }
|
||||||
muiIcon: description
|
muiIcon: file-document-outline
|
||||||
group: content
|
group: content
|
||||||
imageUrl: "https://images.unsplash.com/photo-1499750310107-5fef28a66643?auto=format&fit=crop&q=80&w=800"
|
imageUrl: "https://images.unsplash.com/photo-1499750310107-5fef28a66643?auto=format&fit=crop&q=80&w=800"
|
||||||
preview:
|
preview:
|
||||||
@@ -27,6 +27,7 @@ meta:
|
|||||||
label: { de: "Veröffentlichung", en: "Publishing" }
|
label: { de: "Veröffentlichung", en: "Publishing" }
|
||||||
- group: seo
|
- group: seo
|
||||||
label: { de: "SEO", en: "SEO" }
|
label: { de: "SEO", en: "SEO" }
|
||||||
|
viewHint: cards
|
||||||
|
|
||||||
hooks:
|
hooks:
|
||||||
get:
|
get:
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ name: medialib
|
|||||||
uploadPath: ../media/medialib
|
uploadPath: ../media/medialib
|
||||||
meta:
|
meta:
|
||||||
label: { de: "Mediathek", en: "Media Library" }
|
label: { de: "Mediathek", en: "Media Library" }
|
||||||
muiIcon: perm_media
|
muiIcon: folder-multiple-image
|
||||||
group: content
|
group: content
|
||||||
imageUrl: "https://images.unsplash.com/photo-1542204165-65bf26472b9b?auto=format&fit=crop&q=80&w=800"
|
imageUrl: "https://images.unsplash.com/photo-1452587925148-ce544e77e70d?auto=format&fit=crop&q=80&w=800"
|
||||||
viewHint:
|
viewHint:
|
||||||
media:
|
media:
|
||||||
ai:
|
ai:
|
||||||
@@ -23,7 +23,7 @@ meta:
|
|||||||
file: file
|
file: file
|
||||||
preview:
|
preview:
|
||||||
label: title
|
label: title
|
||||||
secondary: tags
|
secondary: tag
|
||||||
tertiary: description
|
tertiary: description
|
||||||
image: file
|
image: file
|
||||||
mediaFile: file
|
mediaFile: file
|
||||||
@@ -129,13 +129,13 @@ fields:
|
|||||||
inputProps:
|
inputProps:
|
||||||
multiline: true
|
multiline: true
|
||||||
rows: 4
|
rows: 4
|
||||||
- name: tags
|
- name: tag
|
||||||
type: string[]
|
type: string[]
|
||||||
meta:
|
meta:
|
||||||
label: { de: "Schlagwörter", en: "Tags" }
|
label: { de: "Schlagwörter", en: "Tags" }
|
||||||
widget: foreignKey
|
widget: foreignKey
|
||||||
foreign:
|
foreign:
|
||||||
collection: tags
|
collection: tag
|
||||||
- name: _testdata
|
- name: _testdata
|
||||||
type: boolean
|
type: boolean
|
||||||
meta:
|
meta:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ meta:
|
|||||||
label: { de: "Navigation", en: "Navigation" }
|
label: { de: "Navigation", en: "Navigation" }
|
||||||
muiIcon: menu
|
muiIcon: menu
|
||||||
group: content
|
group: content
|
||||||
imageUrl: "https://images.unsplash.com/photo-1506784926709-22f1ec395907?auto=format&fit=crop&q=80&w=800"
|
imageUrl: "https://images.unsplash.com/photo-1452423668729-43a98052d3ee?auto=format&fit=crop&q=80&w=800"
|
||||||
viewHint:
|
viewHint:
|
||||||
navigation:
|
navigation:
|
||||||
nodesField: elements
|
nodesField: elements
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ meta:
|
|||||||
label: { de: "SSR Dummy", en: "ssr dummy" }
|
label: { de: "SSR Dummy", en: "ssr dummy" }
|
||||||
muiIcon: storage
|
muiIcon: storage
|
||||||
group: system
|
group: system
|
||||||
imageUrl: "https://images.unsplash.com/photo-1518770660439-4636190af475?auto=format&fit=crop&q=80&w=800"
|
imageUrl: "https://images.unsplash.com/photo-1558494949-ef010cbdcc31?auto=format&fit=crop&q=80&w=800"
|
||||||
hide: true
|
hide: true
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
# Tags — verwaltete Schlagwörter für Mediathek und andere Collections
|
# Tags — verwaltete Schlagwörter für Mediathek und andere Collections
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
||||||
name: tags
|
name: tag
|
||||||
meta:
|
meta:
|
||||||
label: { de: "Schlagwörter", en: "Tags" }
|
label: { de: "Schlagwörter", en: "Tags" }
|
||||||
muiIcon: tag
|
muiIcon: label
|
||||||
group: content
|
group: content
|
||||||
imageUrl: "https://images.unsplash.com/photo-1543285198-3af15c4592ce?auto=format&fit=crop&w=640&q=80"
|
imageUrl: "https://images.unsplash.com/photo-1555421689-491a97ff2040?auto=format&fit=crop&w=800&q=80"
|
||||||
preview:
|
preview:
|
||||||
select: [name, color]
|
select: [name, color]
|
||||||
label: name
|
label: name
|
||||||
+2
-2
@@ -22,11 +22,11 @@ meta:
|
|||||||
icon: settings
|
icon: settings
|
||||||
|
|
||||||
collections:
|
collections:
|
||||||
- !include collections/tags.yml
|
|
||||||
- !include collections/content.yml
|
- !include collections/content.yml
|
||||||
- !include collections/medialib.yml
|
- !include collections/medialib.yml
|
||||||
- !include collections/navigation.yml
|
- !include collections/navigation.yml
|
||||||
- !include collections/comments.yml
|
- !include collections/tag.yml
|
||||||
|
- !include collections/comment.yml
|
||||||
- !include collections/ssr.yml
|
- !include collections/ssr.yml
|
||||||
|
|
||||||
assets:
|
assets:
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
ADMIN_TOKEN=5bdfjc78hdxn338cuhSJ
|
ADMIN_TOKEN=5bdfjc78hdxn338cuhSJ
|
||||||
ADMIN_ASSET_VERSION=db968ab-dirty-1779031609756
|
ADMIN_ASSET_VERSION=d74964d-dirty-1779040944093
|
||||||
|
|||||||
+12
-12
@@ -24,12 +24,12 @@
|
|||||||
|
|
||||||
const CONTENT_MEDIA_LOOKUP = ["blocks.heroImage.image:medialib", "blocks.image:medialib"].join(",")
|
const CONTENT_MEDIA_LOOKUP = ["blocks.heroImage.image:medialib", "blocks.image:medialib"].join(",")
|
||||||
const NAVIGATION_CONTENT_LOOKUP = "elements.page:content"
|
const NAVIGATION_CONTENT_LOOKUP = "elements.page:content"
|
||||||
const CONTENT_COMMENTS_AGGREGATE = {
|
const CONTENT_COMMENT_AGGREGATE = {
|
||||||
collection: "comments",
|
collection: "comment",
|
||||||
foreignField: "contentId",
|
foreignField: "contentId",
|
||||||
op: "count",
|
op: "count",
|
||||||
filter: { active: true },
|
filter: { active: true },
|
||||||
as: "commentsCount",
|
as: "commentCount",
|
||||||
}
|
}
|
||||||
|
|
||||||
let { url = "" }: { url?: string } = $props()
|
let { url = "" }: { url?: string } = $props()
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
}
|
}
|
||||||
let loading = $state(true)
|
let loading = $state(true)
|
||||||
let notFound = $state(false)
|
let notFound = $state(false)
|
||||||
let comments = $state<any[]>([])
|
let commentList = $state<any[]>([])
|
||||||
|
|
||||||
// Header scroll detection
|
// Header scroll detection
|
||||||
let scrolled = $state(false)
|
let scrolled = $state(false)
|
||||||
@@ -187,7 +187,7 @@
|
|||||||
filter: { lang, path: routePath, active: true },
|
filter: { lang, path: routePath, active: true },
|
||||||
sort: "sort",
|
sort: "sort",
|
||||||
limit: 1,
|
limit: 1,
|
||||||
aggregate: CONTENT_COMMENTS_AGGREGATE,
|
aggregate: CONTENT_COMMENT_AGGREGATE,
|
||||||
lookup: CONTENT_MEDIA_LOOKUP,
|
lookup: CONTENT_MEDIA_LOOKUP,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -200,13 +200,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
comments = await getCachedEntries("comments", {
|
commentList = await getCachedEntries("comment", {
|
||||||
filter: { active: true, contentId: contentEntry.id as string },
|
filter: { active: true, contentId: contentEntry.id as string },
|
||||||
sort: "sort",
|
sort: "sort",
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to load comments", e)
|
console.error("Failed to load comment", e)
|
||||||
comments = []
|
commentList = []
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
notFound = true
|
notFound = true
|
||||||
@@ -396,14 +396,14 @@
|
|||||||
<div class="page-enter">
|
<div class="page-enter">
|
||||||
<BlockRenderer blocks={contentEntry.blocks} />
|
<BlockRenderer blocks={contentEntry.blocks} />
|
||||||
|
|
||||||
{#if (contentEntry as any)?._aggregate?.commentsCount !== undefined}
|
{#if (contentEntry as any)?._aggregate?.commentCount !== undefined}
|
||||||
<div class="max-w-6xl mx-auto px-6 py-8 border-t border-gray-100 my-12">
|
<div class="max-w-6xl mx-auto px-6 py-8 border-t border-gray-100 my-12">
|
||||||
<h3 class="text-xl font-bold mb-6">
|
<h3 class="text-xl font-bold mb-6">
|
||||||
Kommentare ({(contentEntry as any)._aggregate.commentsCount})
|
Kommentare ({(contentEntry as any)._aggregate.commentCount})
|
||||||
</h3>
|
</h3>
|
||||||
{#if comments && comments.length > 0}
|
{#if commentList && commentList.length > 0}
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
{#each comments as comment}
|
{#each commentList as comment}
|
||||||
<div class="bg-gray-50 p-6 rounded-lg">
|
<div class="bg-gray-50 p-6 rounded-lg">
|
||||||
<div class="font-bold text-gray-900 mb-2">{comment.author}</div>
|
<div class="font-bold text-gray-900 mb-2">{comment.author}</div>
|
||||||
<p class="text-gray-700 whitespace-pre-wrap">{comment.message}</p>
|
<p class="text-gray-700 whitespace-pre-wrap">{comment.message}</p>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
import contentData from "../../mocking/content.json"
|
import contentData from "../../mocking/content.json"
|
||||||
import medialibData from "../../mocking/medialib.json"
|
import medialibData from "../../mocking/medialib.json"
|
||||||
import navigationData from "../../mocking/navigation.json"
|
import navigationData from "../../mocking/navigation.json"
|
||||||
import commentsData from "../../mocking/comments.json"
|
import commentsData from "../../mocking/comment.json"
|
||||||
|
|
||||||
type EJsonObjectId = {
|
type EJsonObjectId = {
|
||||||
$oid: string
|
$oid: string
|
||||||
@@ -26,7 +26,7 @@ const mockRegistry: Record<string, Record<string, unknown>[]> = {
|
|||||||
content: normalizeMockCollection(contentData as Record<string, unknown>[]),
|
content: normalizeMockCollection(contentData as Record<string, unknown>[]),
|
||||||
medialib: normalizeMockCollection(medialibData as Record<string, unknown>[]),
|
medialib: normalizeMockCollection(medialibData as Record<string, unknown>[]),
|
||||||
navigation: normalizeMockCollection(navigationData as Record<string, unknown>[]),
|
navigation: normalizeMockCollection(navigationData as Record<string, unknown>[]),
|
||||||
comments: normalizeMockCollection(commentsData as Record<string, unknown>[]),
|
comment: normalizeMockCollection(commentsData as Record<string, unknown>[]),
|
||||||
}
|
}
|
||||||
|
|
||||||
function isEJsonObjectId(value: unknown): value is EJsonObjectId {
|
function isEJsonObjectId(value: unknown): value is EJsonObjectId {
|
||||||
@@ -263,7 +263,7 @@ function applyAggregate(entry: Record<string, unknown>, options?: ApiOptions): R
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// "comments:contentId:count"
|
// "comment:contentId:count"
|
||||||
const parts = spec.split(":")
|
const parts = spec.split(":")
|
||||||
if (parts.length < 3) continue
|
if (parts.length < 3) continue
|
||||||
const targetCollection = parts[0]
|
const targetCollection = parts[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user