mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 16:14:12 +00:00
feat: add FAQ collection and block
- Add FAQs collection with question/answer, categories, and ordering - Add FAQBlock with collection and inline source modes - Support multiple layouts: accordion, grid, list, two-column - Schema.org FAQPage structured data support for SEO - Multi-tenant enabled via plugin configuration - Update documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9e589b895c
commit
16be4cf553
9 changed files with 16236 additions and 2 deletions
|
|
@ -48,6 +48,7 @@ Internet → 37.24.237.181 → Caddy (443) → Payload (3000)
|
|||
│ │ ├── Categories.ts
|
||||
│ │ ├── Portfolios.ts
|
||||
│ │ ├── PortfolioCategories.ts
|
||||
│ │ ├── FAQs.ts
|
||||
│ │ ├── EmailLogs.ts
|
||||
│ │ ├── AuditLogs.ts
|
||||
│ │ └── ...
|
||||
|
|
@ -400,6 +401,7 @@ SELECT * FROM audit_logs ORDER BY created_at DESC LIMIT 10;
|
|||
| Portfolios | portfolios | Portfolio-Galerien (Fotografie) |
|
||||
| PortfolioCategories | portfolio-categories | Kategorien für Portfolios |
|
||||
| Testimonials | testimonials | Kundenbewertungen |
|
||||
| FAQs | faqs | Häufig gestellte Fragen (FAQ) |
|
||||
| NewsletterSubscribers | newsletter-subscribers | Newsletter mit Double Opt-In |
|
||||
| SocialLinks | social-links | Social Media Links |
|
||||
| Forms | forms | Formular-Builder |
|
||||
|
|
@ -444,4 +446,4 @@ pnpm test:coverage
|
|||
- `docs/anleitungen/TODO.md` - Task-Liste & Roadmap
|
||||
- `docs/anleitungen/SECURITY.md` - Sicherheitsrichtlinien
|
||||
|
||||
*Letzte Aktualisierung: 09.12.2025*
|
||||
*Letzte Aktualisierung: 10.12.2025*
|
||||
|
|
|
|||
258
src/blocks/FAQBlock.ts
Normal file
258
src/blocks/FAQBlock.ts
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
import type { Block } from 'payload'
|
||||
|
||||
/**
|
||||
* FAQ Block
|
||||
*
|
||||
* Zeigt FAQs entweder aus der FAQs Collection oder als inline-definierte Fragen.
|
||||
* Unterstützt verschiedene Layouts (Accordion, Grid, Liste) und
|
||||
* generiert automatisch Schema.org FAQPage Structured Data.
|
||||
*/
|
||||
export const FAQBlock: Block = {
|
||||
slug: 'faq-block',
|
||||
labels: {
|
||||
singular: 'FAQ',
|
||||
plural: 'FAQs',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
defaultValue: 'Häufig gestellte Fragen',
|
||||
label: 'Überschrift',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'subtitle',
|
||||
type: 'text',
|
||||
label: 'Untertitel',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'sourceMode',
|
||||
type: 'select',
|
||||
defaultValue: 'collection',
|
||||
label: 'Quelle',
|
||||
options: [
|
||||
{ label: 'Aus FAQ Collection', value: 'collection' },
|
||||
{ label: 'Inline (nur auf dieser Seite)', value: 'inline' },
|
||||
],
|
||||
},
|
||||
// Collection Mode Fields
|
||||
{
|
||||
name: 'displayMode',
|
||||
type: 'select',
|
||||
defaultValue: 'all',
|
||||
label: 'Auswahl',
|
||||
options: [
|
||||
{ label: 'Alle aktiven FAQs', value: 'all' },
|
||||
{ label: 'Nur hervorgehobene', value: 'featured' },
|
||||
{ label: 'Nach Kategorie', value: 'category' },
|
||||
{ label: 'Handverlesene Auswahl', value: 'selected' },
|
||||
],
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.sourceMode === 'collection',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'category',
|
||||
type: 'text',
|
||||
label: 'Kategorie filtern',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.sourceMode === 'collection' && siblingData?.displayMode === 'category',
|
||||
description: 'Zeigt nur FAQs mit dieser Kategorie',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'selectedFAQs',
|
||||
type: 'relationship',
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
relationTo: 'faqs' as any,
|
||||
hasMany: true,
|
||||
label: 'FAQs auswählen',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.sourceMode === 'collection' && siblingData?.displayMode === 'selected',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
defaultValue: 10,
|
||||
min: 1,
|
||||
max: 50,
|
||||
label: 'Maximale Anzahl',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.sourceMode === 'collection' &&
|
||||
(siblingData?.displayMode === 'all' || siblingData?.displayMode === 'category'),
|
||||
},
|
||||
},
|
||||
// Inline Mode Fields
|
||||
{
|
||||
name: 'inlineFAQs',
|
||||
type: 'array',
|
||||
label: 'FAQs',
|
||||
labels: {
|
||||
singular: 'FAQ',
|
||||
plural: 'FAQs',
|
||||
},
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.sourceMode === 'inline',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'question',
|
||||
type: 'text',
|
||||
required: true,
|
||||
label: 'Frage',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'answer',
|
||||
type: 'richText',
|
||||
required: true,
|
||||
label: 'Antwort',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'answerPlainText',
|
||||
type: 'textarea',
|
||||
label: 'Antwort (Nur-Text für Schema.org)',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Kurzfassung als reiner Text für SEO Structured Data',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// Layout Options
|
||||
{
|
||||
name: 'layout',
|
||||
type: 'select',
|
||||
defaultValue: 'accordion',
|
||||
label: 'Layout',
|
||||
options: [
|
||||
{ label: 'Accordion (aufklappbar)', value: 'accordion' },
|
||||
{ label: 'Grid (Karten)', value: 'grid' },
|
||||
{ label: 'Liste', value: 'list' },
|
||||
{ label: 'Zweispaltig', value: 'two-column' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'columns',
|
||||
type: 'select',
|
||||
defaultValue: '2',
|
||||
label: 'Spalten',
|
||||
options: [
|
||||
{ label: '2 Spalten', value: '2' },
|
||||
{ label: '3 Spalten', value: '3' },
|
||||
],
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.layout === 'grid',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'expandFirst',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Erste Frage automatisch öffnen',
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.layout === 'accordion',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'allowMultipleOpen',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Mehrere gleichzeitig öffnen erlauben',
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.layout === 'accordion',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'showCategory',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Kategorie anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'showIcon',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Icons anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'groupByCategory',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Nach Kategorie gruppieren',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.sourceMode === 'collection' && siblingData?.displayMode !== 'category',
|
||||
},
|
||||
},
|
||||
// Schema.org Options
|
||||
{
|
||||
name: 'enableSchemaOrg',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Schema.org FAQPage generieren',
|
||||
admin: {
|
||||
description: 'Generiert SEO-optimiertes JSON-LD Structured Data',
|
||||
},
|
||||
},
|
||||
// Styling
|
||||
{
|
||||
name: 'backgroundColor',
|
||||
type: 'select',
|
||||
defaultValue: 'white',
|
||||
label: 'Hintergrund',
|
||||
options: [
|
||||
{ label: 'Weiß', value: 'white' },
|
||||
{ label: 'Hell (Grau)', value: 'light' },
|
||||
{ label: 'Dunkel', value: 'dark' },
|
||||
{ label: 'Akzentfarbe', value: 'accent' },
|
||||
],
|
||||
},
|
||||
// CTA
|
||||
{
|
||||
name: 'showContactCTA',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Kontakt-CTA anzeigen',
|
||||
admin: {
|
||||
description: 'Zeigt einen "Frage nicht gefunden? Kontaktieren Sie uns" Button',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'contactCTAText',
|
||||
type: 'text',
|
||||
defaultValue: 'Ihre Frage war nicht dabei?',
|
||||
label: 'CTA Text',
|
||||
localized: true,
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.showContactCTA,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'contactCTALink',
|
||||
type: 'text',
|
||||
defaultValue: '/kontakt',
|
||||
label: 'CTA Link',
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.showContactCTA,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'contactCTAButtonText',
|
||||
type: 'text',
|
||||
defaultValue: 'Kontaktieren Sie uns',
|
||||
label: 'CTA Button Text',
|
||||
localized: true,
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.showContactCTA,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -14,3 +14,4 @@ export { PostsListBlock } from './PostsListBlock'
|
|||
export { TestimonialsBlock } from './TestimonialsBlock'
|
||||
export { NewsletterBlock } from './NewsletterBlock'
|
||||
export { ProcessStepsBlock } from './ProcessStepsBlock'
|
||||
export { FAQBlock } from './FAQBlock'
|
||||
|
|
|
|||
117
src/collections/FAQs.ts
Normal file
117
src/collections/FAQs.ts
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
// src/collections/FAQs.ts
|
||||
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { authenticatedOnly, tenantScopedPublicRead } from '../lib/tenantAccess'
|
||||
|
||||
/**
|
||||
* FAQs Collection
|
||||
*
|
||||
* Häufig gestellte Fragen und Antworten, wiederverwendbar auf allen Seiten.
|
||||
* Tenant-scoped für Multi-Tenant-Betrieb.
|
||||
* Unterstützt Schema.org FAQPage Structured Data für SEO.
|
||||
*/
|
||||
export const FAQs: CollectionConfig = {
|
||||
slug: 'faqs',
|
||||
admin: {
|
||||
useAsTitle: 'question',
|
||||
group: 'Content',
|
||||
defaultColumns: ['question', 'category', 'order', 'isActive'],
|
||||
description: 'Häufig gestellte Fragen (FAQ)',
|
||||
},
|
||||
access: {
|
||||
read: tenantScopedPublicRead,
|
||||
create: authenticatedOnly,
|
||||
update: authenticatedOnly,
|
||||
delete: authenticatedOnly,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'question',
|
||||
type: 'text',
|
||||
required: true,
|
||||
label: 'Frage',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Die Frage, die beantwortet wird',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'answer',
|
||||
type: 'richText',
|
||||
required: true,
|
||||
label: 'Antwort',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Die ausführliche Antwort auf die Frage',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'answerPlainText',
|
||||
type: 'textarea',
|
||||
label: 'Antwort (Nur-Text)',
|
||||
localized: true,
|
||||
admin: {
|
||||
description:
|
||||
'Kurzfassung der Antwort als reiner Text für Schema.org Structured Data. Falls leer, wird die Rich-Text-Antwort verwendet.',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'category',
|
||||
type: 'text',
|
||||
label: 'Kategorie',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Optionale Kategorie zur Gruppierung (z.B. "Allgemein", "Preise", "Lieferung")',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'icon',
|
||||
type: 'text',
|
||||
label: 'Icon',
|
||||
admin: {
|
||||
description: 'Optionaler Icon-Name (z.B. "question-circle", "info")',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'relatedFAQs',
|
||||
type: 'relationship',
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
relationTo: 'faqs' as any,
|
||||
hasMany: true,
|
||||
label: 'Verwandte FAQs',
|
||||
admin: {
|
||||
description: 'Andere FAQs die thematisch zusammenhängen',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'isActive',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Aktiv/Sichtbar',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
description: 'Inaktive FAQs werden nicht angezeigt',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'isFeatured',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Hervorgehoben',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
description: 'Hervorgehobene FAQs werden prominent angezeigt',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'order',
|
||||
type: 'number',
|
||||
defaultValue: 0,
|
||||
label: 'Sortierung',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
description: 'Niedrigere Zahlen werden zuerst angezeigt',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import {
|
|||
TestimonialsBlock,
|
||||
NewsletterBlock,
|
||||
ProcessStepsBlock,
|
||||
FAQBlock,
|
||||
} from '../blocks'
|
||||
|
||||
export const Pages: CollectionConfig = {
|
||||
|
|
@ -97,6 +98,7 @@ export const Pages: CollectionConfig = {
|
|||
TestimonialsBlock,
|
||||
NewsletterBlock,
|
||||
ProcessStepsBlock,
|
||||
FAQBlock,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
15698
src/migrations/20251210_052757_add_faqs_collection.json
Normal file
15698
src/migrations/20251210_052757_add_faqs_collection.json
Normal file
File diff suppressed because it is too large
Load diff
147
src/migrations/20251210_052757_add_faqs_collection.ts
Normal file
147
src/migrations/20251210_052757_add_faqs_collection.ts
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||
|
||||
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
CREATE TYPE "public"."enum_pages_blocks_faq_block_source_mode" AS ENUM('collection', 'inline');
|
||||
CREATE TYPE "public"."enum_pages_blocks_faq_block_display_mode" AS ENUM('all', 'featured', 'category', 'selected');
|
||||
CREATE TYPE "public"."enum_pages_blocks_faq_block_layout" AS ENUM('accordion', 'grid', 'list', 'two-column');
|
||||
CREATE TYPE "public"."enum_pages_blocks_faq_block_columns" AS ENUM('2', '3');
|
||||
CREATE TYPE "public"."enum_pages_blocks_faq_block_background_color" AS ENUM('white', 'light', 'dark', 'accent');
|
||||
CREATE TABLE "pages_blocks_faq_block_inline_f_a_qs" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" varchar NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "pages_blocks_faq_block_inline_f_a_qs_locales" (
|
||||
"question" varchar,
|
||||
"answer" jsonb,
|
||||
"answer_plain_text" varchar,
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" varchar NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "pages_blocks_faq_block" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" integer NOT NULL,
|
||||
"_path" text NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL,
|
||||
"source_mode" "enum_pages_blocks_faq_block_source_mode" DEFAULT 'collection',
|
||||
"display_mode" "enum_pages_blocks_faq_block_display_mode" DEFAULT 'all',
|
||||
"category" varchar,
|
||||
"limit" numeric DEFAULT 10,
|
||||
"layout" "enum_pages_blocks_faq_block_layout" DEFAULT 'accordion',
|
||||
"columns" "enum_pages_blocks_faq_block_columns" DEFAULT '2',
|
||||
"expand_first" boolean DEFAULT true,
|
||||
"allow_multiple_open" boolean DEFAULT false,
|
||||
"show_category" boolean DEFAULT false,
|
||||
"show_icon" boolean DEFAULT false,
|
||||
"group_by_category" boolean DEFAULT false,
|
||||
"enable_schema_org" boolean DEFAULT true,
|
||||
"background_color" "enum_pages_blocks_faq_block_background_color" DEFAULT 'white',
|
||||
"show_contact_c_t_a" boolean DEFAULT false,
|
||||
"contact_c_t_a_link" varchar DEFAULT '/kontakt',
|
||||
"block_name" varchar
|
||||
);
|
||||
|
||||
CREATE TABLE "pages_blocks_faq_block_locales" (
|
||||
"title" varchar DEFAULT 'Häufig gestellte Fragen',
|
||||
"subtitle" varchar,
|
||||
"contact_c_t_a_text" varchar DEFAULT 'Ihre Frage war nicht dabei?',
|
||||
"contact_c_t_a_button_text" varchar DEFAULT 'Kontaktieren Sie uns',
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" varchar NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "faqs" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"tenant_id" integer,
|
||||
"icon" varchar,
|
||||
"is_active" boolean DEFAULT true,
|
||||
"is_featured" boolean DEFAULT false,
|
||||
"order" numeric DEFAULT 0,
|
||||
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "faqs_locales" (
|
||||
"question" varchar NOT NULL,
|
||||
"answer" jsonb NOT NULL,
|
||||
"answer_plain_text" varchar,
|
||||
"category" varchar,
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" integer NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "faqs_rels" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"order" integer,
|
||||
"parent_id" integer NOT NULL,
|
||||
"path" varchar NOT NULL,
|
||||
"faqs_id" integer
|
||||
);
|
||||
|
||||
ALTER TABLE "pages_rels" ADD COLUMN "faqs_id" integer;
|
||||
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "faqs_id" integer;
|
||||
ALTER TABLE "pages_blocks_faq_block_inline_f_a_qs" ADD CONSTRAINT "pages_blocks_faq_block_inline_f_a_qs_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_faq_block"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "pages_blocks_faq_block_inline_f_a_qs_locales" ADD CONSTRAINT "pages_blocks_faq_block_inline_f_a_qs_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_faq_block_inline_f_a_qs"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "pages_blocks_faq_block" ADD CONSTRAINT "pages_blocks_faq_block_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "pages_blocks_faq_block_locales" ADD CONSTRAINT "pages_blocks_faq_block_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_faq_block"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "faqs" ADD CONSTRAINT "faqs_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action;
|
||||
ALTER TABLE "faqs_locales" ADD CONSTRAINT "faqs_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."faqs"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "faqs_rels" ADD CONSTRAINT "faqs_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."faqs"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "faqs_rels" ADD CONSTRAINT "faqs_rels_faqs_fk" FOREIGN KEY ("faqs_id") REFERENCES "public"."faqs"("id") ON DELETE cascade ON UPDATE no action;
|
||||
CREATE INDEX "pages_blocks_faq_block_inline_f_a_qs_order_idx" ON "pages_blocks_faq_block_inline_f_a_qs" USING btree ("_order");
|
||||
CREATE INDEX "pages_blocks_faq_block_inline_f_a_qs_parent_id_idx" ON "pages_blocks_faq_block_inline_f_a_qs" USING btree ("_parent_id");
|
||||
CREATE UNIQUE INDEX "pages_blocks_faq_block_inline_f_a_qs_locales_locale_parent_i" ON "pages_blocks_faq_block_inline_f_a_qs_locales" USING btree ("_locale","_parent_id");
|
||||
CREATE INDEX "pages_blocks_faq_block_order_idx" ON "pages_blocks_faq_block" USING btree ("_order");
|
||||
CREATE INDEX "pages_blocks_faq_block_parent_id_idx" ON "pages_blocks_faq_block" USING btree ("_parent_id");
|
||||
CREATE INDEX "pages_blocks_faq_block_path_idx" ON "pages_blocks_faq_block" USING btree ("_path");
|
||||
CREATE UNIQUE INDEX "pages_blocks_faq_block_locales_locale_parent_id_unique" ON "pages_blocks_faq_block_locales" USING btree ("_locale","_parent_id");
|
||||
CREATE INDEX "faqs_tenant_idx" ON "faqs" USING btree ("tenant_id");
|
||||
CREATE INDEX "faqs_updated_at_idx" ON "faqs" USING btree ("updated_at");
|
||||
CREATE INDEX "faqs_created_at_idx" ON "faqs" USING btree ("created_at");
|
||||
CREATE UNIQUE INDEX "faqs_locales_locale_parent_id_unique" ON "faqs_locales" USING btree ("_locale","_parent_id");
|
||||
CREATE INDEX "faqs_rels_order_idx" ON "faqs_rels" USING btree ("order");
|
||||
CREATE INDEX "faqs_rels_parent_idx" ON "faqs_rels" USING btree ("parent_id");
|
||||
CREATE INDEX "faqs_rels_path_idx" ON "faqs_rels" USING btree ("path");
|
||||
CREATE INDEX "faqs_rels_faqs_id_idx" ON "faqs_rels" USING btree ("faqs_id");
|
||||
ALTER TABLE "pages_rels" ADD CONSTRAINT "pages_rels_faqs_fk" FOREIGN KEY ("faqs_id") REFERENCES "public"."faqs"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_faqs_fk" FOREIGN KEY ("faqs_id") REFERENCES "public"."faqs"("id") ON DELETE cascade ON UPDATE no action;
|
||||
CREATE INDEX "pages_rels_faqs_id_idx" ON "pages_rels" USING btree ("faqs_id");
|
||||
CREATE INDEX "payload_locked_documents_rels_faqs_id_idx" ON "payload_locked_documents_rels" USING btree ("faqs_id");`)
|
||||
}
|
||||
|
||||
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
ALTER TABLE "pages_blocks_faq_block_inline_f_a_qs" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "pages_blocks_faq_block_inline_f_a_qs_locales" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "pages_blocks_faq_block" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "pages_blocks_faq_block_locales" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "faqs" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "faqs_locales" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "faqs_rels" DISABLE ROW LEVEL SECURITY;
|
||||
DROP TABLE "pages_blocks_faq_block_inline_f_a_qs" CASCADE;
|
||||
DROP TABLE "pages_blocks_faq_block_inline_f_a_qs_locales" CASCADE;
|
||||
DROP TABLE "pages_blocks_faq_block" CASCADE;
|
||||
DROP TABLE "pages_blocks_faq_block_locales" CASCADE;
|
||||
DROP TABLE "faqs" CASCADE;
|
||||
DROP TABLE "faqs_locales" CASCADE;
|
||||
DROP TABLE "faqs_rels" CASCADE;
|
||||
ALTER TABLE "pages_rels" DROP CONSTRAINT "pages_rels_faqs_fk";
|
||||
|
||||
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT "payload_locked_documents_rels_faqs_fk";
|
||||
|
||||
DROP INDEX "pages_rels_faqs_id_idx";
|
||||
DROP INDEX "payload_locked_documents_rels_faqs_id_idx";
|
||||
ALTER TABLE "pages_rels" DROP COLUMN "faqs_id";
|
||||
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN "faqs_id";
|
||||
DROP TYPE "public"."enum_pages_blocks_faq_block_source_mode";
|
||||
DROP TYPE "public"."enum_pages_blocks_faq_block_display_mode";
|
||||
DROP TYPE "public"."enum_pages_blocks_faq_block_layout";
|
||||
DROP TYPE "public"."enum_pages_blocks_faq_block_columns";
|
||||
DROP TYPE "public"."enum_pages_blocks_faq_block_background_color";`)
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import * as migration_20251206_071552_portfolio_collections from './20251206_071
|
|||
import * as migration_20251206_134750_tenant_email_config from './20251206_134750_tenant_email_config';
|
||||
import * as migration_20251206_141403_email_logs_collection from './20251206_141403_email_logs_collection';
|
||||
import * as migration_20251207_205727_audit_logs_collection from './20251207_205727_audit_logs_collection';
|
||||
import * as migration_20251210_052757_add_faqs_collection from './20251210_052757_add_faqs_collection';
|
||||
|
||||
export const migrations = [
|
||||
{
|
||||
|
|
@ -34,6 +35,11 @@ export const migrations = [
|
|||
{
|
||||
up: migration_20251207_205727_audit_logs_collection.up,
|
||||
down: migration_20251207_205727_audit_logs_collection.down,
|
||||
name: '20251207_205727_audit_logs_collection'
|
||||
name: '20251207_205727_audit_logs_collection',
|
||||
},
|
||||
{
|
||||
up: migration_20251210_052757_add_faqs_collection.up,
|
||||
down: migration_20251210_052757_add_faqs_collection.down,
|
||||
name: '20251210_052757_add_faqs_collection'
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import { Posts } from './collections/Posts'
|
|||
import { Categories } from './collections/Categories'
|
||||
import { SocialLinks } from './collections/SocialLinks'
|
||||
import { Testimonials } from './collections/Testimonials'
|
||||
import { FAQs } from './collections/FAQs'
|
||||
import { NewsletterSubscribers } from './collections/NewsletterSubscribers'
|
||||
|
||||
// Portfolio Collections
|
||||
|
|
@ -128,6 +129,7 @@ export default buildConfig({
|
|||
Categories,
|
||||
SocialLinks,
|
||||
Testimonials,
|
||||
FAQs,
|
||||
NewsletterSubscribers,
|
||||
// Portfolio
|
||||
PortfolioCategories,
|
||||
|
|
@ -169,6 +171,7 @@ export default buildConfig({
|
|||
// Type assertion für neue Collections bis payload-types.ts regeneriert wird
|
||||
...({
|
||||
testimonials: {},
|
||||
faqs: {},
|
||||
'newsletter-subscribers': {},
|
||||
// Portfolio Collections
|
||||
'portfolio-categories': {},
|
||||
|
|
|
|||
Loading…
Reference in a new issue