mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 19:44:12 +00:00
feat: add Team collection and block
- Add Team collection with comprehensive member profiles - Support for role, department, bio, contact info, social links - Qualifications, specializations, and language skills - Optional link to User account for author attribution - Add TeamBlock with multiple layouts (grid, list, slider, compact, detailed) - Filter by department, featured, or manual selection - 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
16be4cf553
commit
261a126f08
9 changed files with 17822 additions and 1 deletions
|
|
@ -49,6 +49,7 @@ Internet → 37.24.237.181 → Caddy (443) → Payload (3000)
|
|||
│ │ ├── Portfolios.ts
|
||||
│ │ ├── PortfolioCategories.ts
|
||||
│ │ ├── FAQs.ts
|
||||
│ │ ├── Team.ts
|
||||
│ │ ├── EmailLogs.ts
|
||||
│ │ ├── AuditLogs.ts
|
||||
│ │ └── ...
|
||||
|
|
@ -402,6 +403,7 @@ SELECT * FROM audit_logs ORDER BY created_at DESC LIMIT 10;
|
|||
| PortfolioCategories | portfolio-categories | Kategorien für Portfolios |
|
||||
| Testimonials | testimonials | Kundenbewertungen |
|
||||
| FAQs | faqs | Häufig gestellte Fragen (FAQ) |
|
||||
| Team | team | Team-Mitglieder und Mitarbeiter |
|
||||
| NewsletterSubscribers | newsletter-subscribers | Newsletter mit Double Opt-In |
|
||||
| SocialLinks | social-links | Social Media Links |
|
||||
| Forms | forms | Formular-Builder |
|
||||
|
|
|
|||
266
src/blocks/TeamBlock.ts
Normal file
266
src/blocks/TeamBlock.ts
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
import type { Block } from 'payload'
|
||||
|
||||
/**
|
||||
* Team Block
|
||||
*
|
||||
* Zeigt Team-Mitglieder aus der Team Collection.
|
||||
* Unterstützt verschiedene Layouts und Filteroptionen.
|
||||
*/
|
||||
export const TeamBlock: Block = {
|
||||
slug: 'team-block',
|
||||
labels: {
|
||||
singular: 'Team',
|
||||
plural: 'Team',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
defaultValue: 'Unser Team',
|
||||
label: 'Überschrift',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'subtitle',
|
||||
type: 'text',
|
||||
label: 'Untertitel',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'introduction',
|
||||
type: 'richText',
|
||||
label: 'Einleitungstext',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Optionaler Text vor der Team-Anzeige',
|
||||
},
|
||||
},
|
||||
// Auswahl-Modus
|
||||
{
|
||||
name: 'displayMode',
|
||||
type: 'select',
|
||||
defaultValue: 'all',
|
||||
label: 'Auswahl',
|
||||
options: [
|
||||
{ label: 'Alle aktiven Mitglieder', value: 'all' },
|
||||
{ label: 'Nur hervorgehobene', value: 'featured' },
|
||||
{ label: 'Nach Abteilung', value: 'department' },
|
||||
{ label: 'Handverlesene Auswahl', value: 'selected' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'department',
|
||||
type: 'text',
|
||||
label: 'Abteilung filtern',
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.displayMode === 'department',
|
||||
description: 'Zeigt nur Mitglieder dieser Abteilung',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'selectedMembers',
|
||||
type: 'relationship',
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
relationTo: 'team' as any,
|
||||
hasMany: true,
|
||||
label: 'Team-Mitglieder auswählen',
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.displayMode === 'selected',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
defaultValue: 12,
|
||||
min: 1,
|
||||
max: 50,
|
||||
label: 'Maximale Anzahl',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.displayMode === 'all' || siblingData?.displayMode === 'department',
|
||||
},
|
||||
},
|
||||
// Layout
|
||||
{
|
||||
name: 'layout',
|
||||
type: 'select',
|
||||
defaultValue: 'grid',
|
||||
label: 'Layout',
|
||||
options: [
|
||||
{ label: 'Grid (Karten)', value: 'grid' },
|
||||
{ label: 'Liste', value: 'list' },
|
||||
{ label: 'Slider/Karussell', value: 'slider' },
|
||||
{ label: 'Kompakt (nur Foto + Name)', value: 'compact' },
|
||||
{ label: 'Detailliert (mit Bio)', value: 'detailed' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'columns',
|
||||
type: 'select',
|
||||
defaultValue: '3',
|
||||
label: 'Spalten',
|
||||
options: [
|
||||
{ label: '2 Spalten', value: '2' },
|
||||
{ label: '3 Spalten', value: '3' },
|
||||
{ label: '4 Spalten', value: '4' },
|
||||
],
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.layout === 'grid' || siblingData?.layout === 'compact',
|
||||
},
|
||||
},
|
||||
// Anzeigeoptionen
|
||||
{
|
||||
name: 'showRole',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Position/Rolle anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'showDepartment',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Abteilung anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'showBio',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Biografie anzeigen',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.layout !== 'compact',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'showContact',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Kontaktdaten anzeigen',
|
||||
admin: {
|
||||
description: 'Nur wenn beim Mitglied "Kontaktdaten öffentlich anzeigen" aktiviert ist',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'showSocialLinks',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Social Media Links anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'showQualifications',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Qualifikationen anzeigen',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.layout === 'detailed' || siblingData?.layout === 'list',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'showSpecializations',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Fachgebiete anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'showLanguages',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Sprachkenntnisse anzeigen',
|
||||
},
|
||||
// Gruppierung
|
||||
{
|
||||
name: 'groupByDepartment',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Nach Abteilung gruppieren',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.displayMode !== 'department' && siblingData?.layout !== 'slider',
|
||||
},
|
||||
},
|
||||
// Slider-Optionen
|
||||
{
|
||||
name: 'autoplay',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Automatisch wechseln',
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.layout === 'slider',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'autoplaySpeed',
|
||||
type: 'number',
|
||||
defaultValue: 5000,
|
||||
min: 2000,
|
||||
max: 15000,
|
||||
label: 'Wechselintervall (ms)',
|
||||
admin: {
|
||||
condition: (data, siblingData) =>
|
||||
siblingData?.layout === 'slider' && siblingData?.autoplay,
|
||||
},
|
||||
},
|
||||
// Detail-Ansicht
|
||||
{
|
||||
name: 'enableDetailView',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Detail-Ansicht aktivieren',
|
||||
admin: {
|
||||
description: 'Klick auf Mitglied öffnet Modal/Lightbox mit allen Details',
|
||||
},
|
||||
},
|
||||
// Styling
|
||||
{
|
||||
name: 'imageStyle',
|
||||
type: 'select',
|
||||
defaultValue: 'rounded',
|
||||
label: 'Foto-Stil',
|
||||
options: [
|
||||
{ label: 'Rund', value: 'circle' },
|
||||
{ label: 'Abgerundet', value: 'rounded' },
|
||||
{ label: 'Eckig', value: 'square' },
|
||||
],
|
||||
},
|
||||
{
|
||||
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: 'showCTA',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'CTA-Button anzeigen',
|
||||
},
|
||||
{
|
||||
name: 'ctaText',
|
||||
type: 'text',
|
||||
defaultValue: 'Jetzt bewerben',
|
||||
label: 'CTA Text',
|
||||
localized: true,
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.showCTA,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ctaLink',
|
||||
type: 'text',
|
||||
defaultValue: '/karriere',
|
||||
label: 'CTA Link',
|
||||
admin: {
|
||||
condition: (data, siblingData) => siblingData?.showCTA,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -15,3 +15,4 @@ export { TestimonialsBlock } from './TestimonialsBlock'
|
|||
export { NewsletterBlock } from './NewsletterBlock'
|
||||
export { ProcessStepsBlock } from './ProcessStepsBlock'
|
||||
export { FAQBlock } from './FAQBlock'
|
||||
export { TeamBlock } from './TeamBlock'
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
NewsletterBlock,
|
||||
ProcessStepsBlock,
|
||||
FAQBlock,
|
||||
TeamBlock,
|
||||
} from '../blocks'
|
||||
|
||||
export const Pages: CollectionConfig = {
|
||||
|
|
@ -99,6 +100,7 @@ export const Pages: CollectionConfig = {
|
|||
NewsletterBlock,
|
||||
ProcessStepsBlock,
|
||||
FAQBlock,
|
||||
TeamBlock,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
277
src/collections/Team.ts
Normal file
277
src/collections/Team.ts
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
// src/collections/Team.ts
|
||||
|
||||
import type { CollectionConfig } from 'payload'
|
||||
import { authenticatedOnly, tenantScopedPublicRead } from '../lib/tenantAccess'
|
||||
|
||||
/**
|
||||
* Team Collection
|
||||
*
|
||||
* Mitarbeiter und Team-Mitglieder, wiederverwendbar auf allen Seiten.
|
||||
* Tenant-scoped für Multi-Tenant-Betrieb.
|
||||
*/
|
||||
export const Team: CollectionConfig = {
|
||||
slug: 'team',
|
||||
admin: {
|
||||
useAsTitle: 'name',
|
||||
group: 'Content',
|
||||
defaultColumns: ['name', 'role', 'department', 'order', 'isActive'],
|
||||
description: 'Team-Mitglieder und Mitarbeiter',
|
||||
},
|
||||
access: {
|
||||
read: tenantScopedPublicRead,
|
||||
create: authenticatedOnly,
|
||||
update: authenticatedOnly,
|
||||
delete: authenticatedOnly,
|
||||
},
|
||||
fields: [
|
||||
// Basis-Informationen
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
label: 'Name',
|
||||
admin: {
|
||||
description: 'Vollständiger Name',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'role',
|
||||
type: 'text',
|
||||
required: true,
|
||||
label: 'Position/Rolle',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'z.B. "Geschäftsführer", "Pflegedienstleitung", "Fotograf"',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'department',
|
||||
type: 'text',
|
||||
label: 'Abteilung',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'z.B. "Verwaltung", "Pflege", "Marketing"',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'image',
|
||||
type: 'upload',
|
||||
relationTo: 'media',
|
||||
label: 'Foto',
|
||||
admin: {
|
||||
description: 'Portrait-Foto (empfohlen: quadratisch, min. 400x400px)',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'bio',
|
||||
type: 'richText',
|
||||
label: 'Biografie',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Kurze Beschreibung zur Person',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'bioShort',
|
||||
type: 'textarea',
|
||||
label: 'Kurzbiografie',
|
||||
localized: true,
|
||||
admin: {
|
||||
description: 'Ein-Satz-Beschreibung für kompakte Darstellung',
|
||||
},
|
||||
},
|
||||
// Kontaktdaten
|
||||
{
|
||||
type: 'collapsible',
|
||||
label: 'Kontaktdaten',
|
||||
admin: {
|
||||
initCollapsed: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'email',
|
||||
type: 'email',
|
||||
label: 'E-Mail',
|
||||
admin: {
|
||||
description: 'Öffentliche Kontakt-E-Mail (optional)',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'phone',
|
||||
type: 'text',
|
||||
label: 'Telefon',
|
||||
admin: {
|
||||
description: 'Öffentliche Telefonnummer (optional)',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'showContactInfo',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Kontaktdaten öffentlich anzeigen',
|
||||
},
|
||||
],
|
||||
},
|
||||
// Social Links
|
||||
{
|
||||
name: 'socialLinks',
|
||||
type: 'array',
|
||||
label: 'Social Media',
|
||||
admin: {
|
||||
initCollapsed: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'platform',
|
||||
type: 'select',
|
||||
required: true,
|
||||
label: 'Plattform',
|
||||
options: [
|
||||
{ label: 'LinkedIn', value: 'linkedin' },
|
||||
{ label: 'Xing', value: 'xing' },
|
||||
{ label: 'Twitter/X', value: 'twitter' },
|
||||
{ label: 'Instagram', value: 'instagram' },
|
||||
{ label: 'Facebook', value: 'facebook' },
|
||||
{ label: 'Website', value: 'website' },
|
||||
{ label: 'GitHub', value: 'github' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'url',
|
||||
type: 'text',
|
||||
required: true,
|
||||
label: 'URL',
|
||||
},
|
||||
],
|
||||
},
|
||||
// Qualifikationen
|
||||
{
|
||||
name: 'qualifications',
|
||||
type: 'array',
|
||||
label: 'Qualifikationen',
|
||||
admin: {
|
||||
initCollapsed: true,
|
||||
description: 'Ausbildungen, Zertifikate, Abschlüsse',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
label: 'Bezeichnung',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'year',
|
||||
type: 'number',
|
||||
label: 'Jahr',
|
||||
min: 1950,
|
||||
max: 2100,
|
||||
},
|
||||
{
|
||||
name: 'institution',
|
||||
type: 'text',
|
||||
label: 'Institution',
|
||||
},
|
||||
],
|
||||
},
|
||||
// Fachgebiete
|
||||
{
|
||||
name: 'specializations',
|
||||
type: 'array',
|
||||
label: 'Fachgebiete/Schwerpunkte',
|
||||
admin: {
|
||||
initCollapsed: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
label: 'Fachgebiet',
|
||||
localized: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
// Sprachen (besonders für C2S/Pflege relevant)
|
||||
{
|
||||
name: 'languages',
|
||||
type: 'array',
|
||||
label: 'Sprachkenntnisse',
|
||||
admin: {
|
||||
initCollapsed: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'language',
|
||||
type: 'text',
|
||||
required: true,
|
||||
label: 'Sprache',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'level',
|
||||
type: 'select',
|
||||
label: 'Niveau',
|
||||
options: [
|
||||
{ label: 'Muttersprache', value: 'native' },
|
||||
{ label: 'Fließend', value: 'fluent' },
|
||||
{ label: 'Gut', value: 'good' },
|
||||
{ label: 'Grundkenntnisse', value: 'basic' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// Verknüpfung mit User (optional)
|
||||
{
|
||||
name: 'linkedUser',
|
||||
type: 'relationship',
|
||||
relationTo: 'users',
|
||||
label: 'Verknüpfter Benutzer',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
description: 'Optional: Verknüpfung mit Login-User (z.B. für Autoren-Zuordnung)',
|
||||
},
|
||||
},
|
||||
// Status & Sortierung
|
||||
{
|
||||
name: 'isActive',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
label: 'Aktiv/Sichtbar',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
description: 'Inaktive Mitglieder werden nicht angezeigt',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'isFeatured',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
label: 'Hervorgehoben',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
description: 'Für Startseiten-Anzeige oder besondere Hervorhebung',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'order',
|
||||
type: 'number',
|
||||
defaultValue: 0,
|
||||
label: 'Sortierung',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
description: 'Niedrigere Zahlen werden zuerst angezeigt',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'startDate',
|
||||
type: 'date',
|
||||
label: 'Im Team seit',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
description: 'Eintrittsdatum (optional)',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
17055
src/migrations/20251210_071506_add_team_collection.json
Normal file
17055
src/migrations/20251210_071506_add_team_collection.json
Normal file
File diff suppressed because it is too large
Load diff
209
src/migrations/20251210_071506_add_team_collection.ts
Normal file
209
src/migrations/20251210_071506_add_team_collection.ts
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
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_team_block_display_mode" AS ENUM('all', 'featured', 'department', 'selected');
|
||||
CREATE TYPE "public"."enum_pages_blocks_team_block_layout" AS ENUM('grid', 'list', 'slider', 'compact', 'detailed');
|
||||
CREATE TYPE "public"."enum_pages_blocks_team_block_columns" AS ENUM('2', '3', '4');
|
||||
CREATE TYPE "public"."enum_pages_blocks_team_block_image_style" AS ENUM('circle', 'rounded', 'square');
|
||||
CREATE TYPE "public"."enum_pages_blocks_team_block_background_color" AS ENUM('white', 'light', 'dark', 'accent');
|
||||
CREATE TYPE "public"."enum_team_social_links_platform" AS ENUM('linkedin', 'xing', 'twitter', 'instagram', 'facebook', 'website', 'github');
|
||||
CREATE TYPE "public"."enum_team_languages_level" AS ENUM('native', 'fluent', 'good', 'basic');
|
||||
CREATE TABLE "pages_blocks_team_block" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" integer NOT NULL,
|
||||
"_path" text NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL,
|
||||
"display_mode" "enum_pages_blocks_team_block_display_mode" DEFAULT 'all',
|
||||
"department" varchar,
|
||||
"limit" numeric DEFAULT 12,
|
||||
"layout" "enum_pages_blocks_team_block_layout" DEFAULT 'grid',
|
||||
"columns" "enum_pages_blocks_team_block_columns" DEFAULT '3',
|
||||
"show_role" boolean DEFAULT true,
|
||||
"show_department" boolean DEFAULT false,
|
||||
"show_bio" boolean DEFAULT true,
|
||||
"show_contact" boolean DEFAULT false,
|
||||
"show_social_links" boolean DEFAULT true,
|
||||
"show_qualifications" boolean DEFAULT false,
|
||||
"show_specializations" boolean DEFAULT false,
|
||||
"show_languages" boolean DEFAULT false,
|
||||
"group_by_department" boolean DEFAULT false,
|
||||
"autoplay" boolean DEFAULT true,
|
||||
"autoplay_speed" numeric DEFAULT 5000,
|
||||
"enable_detail_view" boolean DEFAULT false,
|
||||
"image_style" "enum_pages_blocks_team_block_image_style" DEFAULT 'rounded',
|
||||
"background_color" "enum_pages_blocks_team_block_background_color" DEFAULT 'white',
|
||||
"show_c_t_a" boolean DEFAULT false,
|
||||
"cta_link" varchar DEFAULT '/karriere',
|
||||
"block_name" varchar
|
||||
);
|
||||
|
||||
CREATE TABLE "pages_blocks_team_block_locales" (
|
||||
"title" varchar DEFAULT 'Unser Team',
|
||||
"subtitle" varchar,
|
||||
"introduction" jsonb,
|
||||
"cta_text" varchar DEFAULT 'Jetzt bewerben',
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" varchar NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "team_social_links" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" integer NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL,
|
||||
"platform" "enum_team_social_links_platform" NOT NULL,
|
||||
"url" varchar NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "team_qualifications" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" integer NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL,
|
||||
"year" numeric,
|
||||
"institution" varchar
|
||||
);
|
||||
|
||||
CREATE TABLE "team_qualifications_locales" (
|
||||
"title" varchar NOT NULL,
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" varchar NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "team_specializations" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" integer NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "team_specializations_locales" (
|
||||
"title" varchar NOT NULL,
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" varchar NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "team_languages" (
|
||||
"_order" integer NOT NULL,
|
||||
"_parent_id" integer NOT NULL,
|
||||
"id" varchar PRIMARY KEY NOT NULL,
|
||||
"level" "enum_team_languages_level"
|
||||
);
|
||||
|
||||
CREATE TABLE "team_languages_locales" (
|
||||
"language" varchar NOT NULL,
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" varchar NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "team" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"tenant_id" integer,
|
||||
"name" varchar NOT NULL,
|
||||
"image_id" integer,
|
||||
"email" varchar,
|
||||
"phone" varchar,
|
||||
"show_contact_info" boolean DEFAULT false,
|
||||
"linked_user_id" integer,
|
||||
"is_active" boolean DEFAULT true,
|
||||
"is_featured" boolean DEFAULT false,
|
||||
"order" numeric DEFAULT 0,
|
||||
"start_date" timestamp(3) with time zone,
|
||||
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "team_locales" (
|
||||
"role" varchar NOT NULL,
|
||||
"department" varchar,
|
||||
"bio" jsonb,
|
||||
"bio_short" varchar,
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"_locale" "_locales" NOT NULL,
|
||||
"_parent_id" integer NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE "pages_rels" ADD COLUMN "team_id" integer;
|
||||
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "team_id" integer;
|
||||
ALTER TABLE "pages_blocks_team_block" ADD CONSTRAINT "pages_blocks_team_block_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "pages_blocks_team_block_locales" ADD CONSTRAINT "pages_blocks_team_block_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."pages_blocks_team_block"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "team_social_links" ADD CONSTRAINT "team_social_links_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "team_qualifications" ADD CONSTRAINT "team_qualifications_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "team_qualifications_locales" ADD CONSTRAINT "team_qualifications_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team_qualifications"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "team_specializations" ADD CONSTRAINT "team_specializations_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "team_specializations_locales" ADD CONSTRAINT "team_specializations_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team_specializations"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "team_languages" ADD CONSTRAINT "team_languages_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "team_languages_locales" ADD CONSTRAINT "team_languages_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team_languages"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "team" ADD CONSTRAINT "team_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action;
|
||||
ALTER TABLE "team" ADD CONSTRAINT "team_image_id_media_id_fk" FOREIGN KEY ("image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||
ALTER TABLE "team" ADD CONSTRAINT "team_linked_user_id_users_id_fk" FOREIGN KEY ("linked_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
||||
ALTER TABLE "team_locales" ADD CONSTRAINT "team_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
|
||||
CREATE INDEX "pages_blocks_team_block_order_idx" ON "pages_blocks_team_block" USING btree ("_order");
|
||||
CREATE INDEX "pages_blocks_team_block_parent_id_idx" ON "pages_blocks_team_block" USING btree ("_parent_id");
|
||||
CREATE INDEX "pages_blocks_team_block_path_idx" ON "pages_blocks_team_block" USING btree ("_path");
|
||||
CREATE UNIQUE INDEX "pages_blocks_team_block_locales_locale_parent_id_unique" ON "pages_blocks_team_block_locales" USING btree ("_locale","_parent_id");
|
||||
CREATE INDEX "team_social_links_order_idx" ON "team_social_links" USING btree ("_order");
|
||||
CREATE INDEX "team_social_links_parent_id_idx" ON "team_social_links" USING btree ("_parent_id");
|
||||
CREATE INDEX "team_qualifications_order_idx" ON "team_qualifications" USING btree ("_order");
|
||||
CREATE INDEX "team_qualifications_parent_id_idx" ON "team_qualifications" USING btree ("_parent_id");
|
||||
CREATE UNIQUE INDEX "team_qualifications_locales_locale_parent_id_unique" ON "team_qualifications_locales" USING btree ("_locale","_parent_id");
|
||||
CREATE INDEX "team_specializations_order_idx" ON "team_specializations" USING btree ("_order");
|
||||
CREATE INDEX "team_specializations_parent_id_idx" ON "team_specializations" USING btree ("_parent_id");
|
||||
CREATE UNIQUE INDEX "team_specializations_locales_locale_parent_id_unique" ON "team_specializations_locales" USING btree ("_locale","_parent_id");
|
||||
CREATE INDEX "team_languages_order_idx" ON "team_languages" USING btree ("_order");
|
||||
CREATE INDEX "team_languages_parent_id_idx" ON "team_languages" USING btree ("_parent_id");
|
||||
CREATE UNIQUE INDEX "team_languages_locales_locale_parent_id_unique" ON "team_languages_locales" USING btree ("_locale","_parent_id");
|
||||
CREATE INDEX "team_tenant_idx" ON "team" USING btree ("tenant_id");
|
||||
CREATE INDEX "team_image_idx" ON "team" USING btree ("image_id");
|
||||
CREATE INDEX "team_linked_user_idx" ON "team" USING btree ("linked_user_id");
|
||||
CREATE INDEX "team_updated_at_idx" ON "team" USING btree ("updated_at");
|
||||
CREATE INDEX "team_created_at_idx" ON "team" USING btree ("created_at");
|
||||
CREATE UNIQUE INDEX "team_locales_locale_parent_id_unique" ON "team_locales" USING btree ("_locale","_parent_id");
|
||||
ALTER TABLE "pages_rels" ADD CONSTRAINT "pages_rels_team_fk" FOREIGN KEY ("team_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
|
||||
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_team_fk" FOREIGN KEY ("team_id") REFERENCES "public"."team"("id") ON DELETE cascade ON UPDATE no action;
|
||||
CREATE INDEX "pages_rels_team_id_idx" ON "pages_rels" USING btree ("team_id");
|
||||
CREATE INDEX "payload_locked_documents_rels_team_id_idx" ON "payload_locked_documents_rels" USING btree ("team_id");`)
|
||||
}
|
||||
|
||||
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
ALTER TABLE "pages_blocks_team_block" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "pages_blocks_team_block_locales" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team_social_links" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team_qualifications" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team_qualifications_locales" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team_specializations" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team_specializations_locales" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team_languages" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team_languages_locales" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team" DISABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE "team_locales" DISABLE ROW LEVEL SECURITY;
|
||||
DROP TABLE "pages_blocks_team_block" CASCADE;
|
||||
DROP TABLE "pages_blocks_team_block_locales" CASCADE;
|
||||
DROP TABLE "team_social_links" CASCADE;
|
||||
DROP TABLE "team_qualifications" CASCADE;
|
||||
DROP TABLE "team_qualifications_locales" CASCADE;
|
||||
DROP TABLE "team_specializations" CASCADE;
|
||||
DROP TABLE "team_specializations_locales" CASCADE;
|
||||
DROP TABLE "team_languages" CASCADE;
|
||||
DROP TABLE "team_languages_locales" CASCADE;
|
||||
DROP TABLE "team" CASCADE;
|
||||
DROP TABLE "team_locales" CASCADE;
|
||||
ALTER TABLE "pages_rels" DROP CONSTRAINT "pages_rels_team_fk";
|
||||
|
||||
ALTER TABLE "payload_locked_documents_rels" DROP CONSTRAINT "payload_locked_documents_rels_team_fk";
|
||||
|
||||
DROP INDEX "pages_rels_team_id_idx";
|
||||
DROP INDEX "payload_locked_documents_rels_team_id_idx";
|
||||
ALTER TABLE "pages_rels" DROP COLUMN "team_id";
|
||||
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN "team_id";
|
||||
DROP TYPE "public"."enum_pages_blocks_team_block_display_mode";
|
||||
DROP TYPE "public"."enum_pages_blocks_team_block_layout";
|
||||
DROP TYPE "public"."enum_pages_blocks_team_block_columns";
|
||||
DROP TYPE "public"."enum_pages_blocks_team_block_image_style";
|
||||
DROP TYPE "public"."enum_pages_blocks_team_block_background_color";
|
||||
DROP TYPE "public"."enum_team_social_links_platform";
|
||||
DROP TYPE "public"."enum_team_languages_level";`)
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import * as migration_20251206_134750_tenant_email_config from './20251206_13475
|
|||
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';
|
||||
import * as migration_20251210_071506_add_team_collection from './20251210_071506_add_team_collection';
|
||||
|
||||
export const migrations = [
|
||||
{
|
||||
|
|
@ -40,6 +41,11 @@ export const migrations = [
|
|||
{
|
||||
up: migration_20251210_052757_add_faqs_collection.up,
|
||||
down: migration_20251210_052757_add_faqs_collection.down,
|
||||
name: '20251210_052757_add_faqs_collection'
|
||||
name: '20251210_052757_add_faqs_collection',
|
||||
},
|
||||
{
|
||||
up: migration_20251210_071506_add_team_collection.up,
|
||||
down: migration_20251210_071506_add_team_collection.down,
|
||||
name: '20251210_071506_add_team_collection'
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { Categories } from './collections/Categories'
|
|||
import { SocialLinks } from './collections/SocialLinks'
|
||||
import { Testimonials } from './collections/Testimonials'
|
||||
import { FAQs } from './collections/FAQs'
|
||||
import { Team } from './collections/Team'
|
||||
import { NewsletterSubscribers } from './collections/NewsletterSubscribers'
|
||||
|
||||
// Portfolio Collections
|
||||
|
|
@ -130,6 +131,7 @@ export default buildConfig({
|
|||
SocialLinks,
|
||||
Testimonials,
|
||||
FAQs,
|
||||
Team,
|
||||
NewsletterSubscribers,
|
||||
// Portfolio
|
||||
PortfolioCategories,
|
||||
|
|
@ -172,6 +174,7 @@ export default buildConfig({
|
|||
...({
|
||||
testimonials: {},
|
||||
faqs: {},
|
||||
team: {},
|
||||
'newsletter-subscribers': {},
|
||||
// Portfolio Collections
|
||||
'portfolio-categories': {},
|
||||
|
|
|
|||
Loading…
Reference in a new issue