feat: convert SiteSettings and Navigation from Globals to tenant-specific Collections

- SiteSettings is now a Collection with multi-tenant support
- Navigation is now Navigations Collection with multi-tenant support
- Both added to multiTenantPlugin collections config
- Allows each tenant to have their own site settings and navigation
- API endpoints change from /api/globals/* to /api/site-settings and /api/navigations

BREAKING CHANGE: Frontends need to update API calls from globals to collections

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Martin Porwoll 2025-12-20 22:24:05 +00:00
parent 9ceef478fa
commit 6aed5a39d3
3 changed files with 77 additions and 13 deletions

View file

@ -1,13 +1,33 @@
import type { GlobalConfig } from 'payload'
import type { CollectionConfig } from 'payload'
export const Navigation: GlobalConfig = {
slug: 'navigation',
label: 'Navigation',
export const Navigations: CollectionConfig = {
slug: 'navigations',
labels: {
singular: 'Navigation',
plural: 'Navigationen',
},
admin: {
useAsTitle: 'title',
group: 'Einstellungen',
description: 'Navigationsmenüs pro Tenant',
},
access: {
read: () => true,
update: ({ req }) => !!req.user,
create: ({ req }) => Boolean(req.user?.isSuperAdmin),
update: ({ req }) => Boolean(req.user),
delete: ({ req }) => Boolean(req.user?.isSuperAdmin),
},
fields: [
{
name: 'title',
type: 'text',
label: 'Titel',
required: true,
defaultValue: 'Hauptnavigation',
admin: {
description: 'Interner Name zur Identifikation',
},
},
{
name: 'mainMenu',
type: 'array',
@ -16,12 +36,14 @@ export const Navigation: GlobalConfig = {
{
name: 'label',
type: 'text',
label: 'Bezeichnung',
required: true,
localized: true,
},
{
name: 'type',
type: 'select',
label: 'Typ',
defaultValue: 'page',
options: [
{ label: 'Seite', value: 'page' },
@ -32,6 +54,7 @@ export const Navigation: GlobalConfig = {
{
name: 'page',
type: 'relationship',
label: 'Seite',
relationTo: 'pages',
admin: {
condition: (data, siblingData) => siblingData?.type === 'page',
@ -40,6 +63,7 @@ export const Navigation: GlobalConfig = {
{
name: 'url',
type: 'text',
label: 'URL',
admin: {
condition: (data, siblingData) => siblingData?.type === 'custom',
},
@ -47,11 +71,13 @@ export const Navigation: GlobalConfig = {
{
name: 'openInNewTab',
type: 'checkbox',
label: 'In neuem Tab öffnen',
defaultValue: false,
},
{
name: 'submenu',
type: 'array',
label: 'Untermenü',
admin: {
condition: (data, siblingData) => siblingData?.type === 'submenu',
},
@ -59,12 +85,14 @@ export const Navigation: GlobalConfig = {
{
name: 'label',
type: 'text',
label: 'Bezeichnung',
required: true,
localized: true,
},
{
name: 'linkType',
type: 'select',
label: 'Link-Typ',
defaultValue: 'page',
options: [
{ label: 'Seite', value: 'page' },
@ -74,6 +102,7 @@ export const Navigation: GlobalConfig = {
{
name: 'page',
type: 'relationship',
label: 'Seite',
relationTo: 'pages',
admin: {
condition: (data, siblingData) => siblingData?.linkType === 'page',
@ -82,6 +111,7 @@ export const Navigation: GlobalConfig = {
{
name: 'url',
type: 'text',
label: 'URL',
admin: {
condition: (data, siblingData) => siblingData?.linkType === 'custom',
},
@ -98,12 +128,14 @@ export const Navigation: GlobalConfig = {
{
name: 'label',
type: 'text',
label: 'Bezeichnung',
required: true,
localized: true,
},
{
name: 'linkType',
type: 'select',
label: 'Link-Typ',
defaultValue: 'page',
options: [
{ label: 'Seite', value: 'page' },
@ -113,6 +145,7 @@ export const Navigation: GlobalConfig = {
{
name: 'page',
type: 'relationship',
label: 'Seite',
relationTo: 'pages',
admin: {
condition: (data, siblingData) => siblingData?.linkType === 'page',
@ -121,6 +154,7 @@ export const Navigation: GlobalConfig = {
{
name: 'url',
type: 'text',
label: 'URL',
admin: {
condition: (data, siblingData) => siblingData?.linkType === 'custom',
},

View file

@ -1,64 +1,85 @@
import type { GlobalConfig } from 'payload'
import type { CollectionConfig } from 'payload'
export const SiteSettings: GlobalConfig = {
export const SiteSettings: CollectionConfig = {
slug: 'site-settings',
label: 'Site Settings',
labels: {
singular: 'Site Settings',
plural: 'Site Settings',
},
admin: {
useAsTitle: 'siteName',
group: 'Einstellungen',
description: 'Allgemeine Website-Einstellungen pro Tenant',
},
access: {
read: () => true,
update: ({ req }) => !!req.user,
create: ({ req }) => Boolean(req.user?.isSuperAdmin),
update: ({ req }) => Boolean(req.user),
delete: ({ req }) => Boolean(req.user?.isSuperAdmin),
},
fields: [
{
name: 'siteName',
type: 'text',
defaultValue: 'porwoll.de',
label: 'Website-Name',
required: true,
localized: true,
},
{
name: 'siteTagline',
type: 'text',
label: 'Tagline',
localized: true,
},
{
name: 'logo',
type: 'upload',
label: 'Logo',
relationTo: 'media',
},
{
name: 'favicon',
type: 'upload',
label: 'Favicon',
relationTo: 'media',
},
{
name: 'contact',
type: 'group',
label: 'Kontakt',
fields: [
{
name: 'email',
type: 'email',
label: 'E-Mail',
},
{
name: 'phone',
type: 'text',
label: 'Telefon',
},
{
name: 'address',
type: 'textarea',
label: 'Adresse',
},
],
},
{
name: 'footer',
type: 'group',
label: 'Footer',
fields: [
{
name: 'copyrightText',
type: 'text',
label: 'Copyright-Text',
localized: true,
},
{
name: 'showSocialLinks',
type: 'checkbox',
label: 'Social Links anzeigen',
defaultValue: true,
},
],

View file

@ -70,8 +70,11 @@ import { CookieInventory } from './collections/CookieInventory'
import { ConsentLogs } from './collections/ConsentLogs'
import { PrivacyPolicySettings } from './collections/PrivacyPolicySettings'
import { SiteSettings } from './globals/SiteSettings'
import { Navigation } from './globals/Navigation'
// Tenant-specific Settings Collections (converted from Globals)
import { SiteSettings } from './collections/SiteSettings'
import { Navigations } from './collections/Navigations'
// Global Settings (system-wide, not tenant-specific)
import { SEOSettings } from './globals/SEOSettings'
// Hooks
@ -202,8 +205,11 @@ export default buildConfig({
// System
EmailLogs,
AuditLogs,
// Tenant-specific Settings (converted from Globals)
SiteSettings,
Navigations,
],
globals: [SiteSettings, Navigation, SEOSettings],
globals: [SEOSettings],
editor: lexicalEditor(),
secret: env.PAYLOAD_SECRET,
typescript: {
@ -265,6 +271,9 @@ export default buildConfig({
'cookie-inventory': { customTenantField: true },
'consent-logs': { customTenantField: true },
'privacy-policy-settings': { customTenantField: true },
// Tenant-specific Settings (converted from Globals)
'site-settings': {},
navigations: {},
} as Record<string, { customTenantField?: boolean }>),
},
// Super Admins haben Zugriff auf alle Tenants