|
| 1 | +/** |
| 2 | + * One-off, idempotent content seed for the "Unsere Förderer und Sponsoren" |
| 3 | + * (/foerderer) page and the "Ihre Spende" (/unterstuetzung/spende) page. |
| 4 | + * |
| 5 | + * Runs in the migrator container on the server (live DATABASE_URL from compose |
| 6 | + * env_file). Self-contained — NO imports from src/ (the migrator image only |
| 7 | + * copies prisma/ + node_modules), so the page markdown is embedded here. |
| 8 | + * |
| 9 | + * docker compose --profile migrate run --rm --build eventschau-migrate \ |
| 10 | + * npx tsx prisma/seed-foerderer-page.ts |
| 11 | + * |
| 12 | + * The markdown below MUST stay in sync with src/content/foerderer.md and |
| 13 | + * src/content/spende.md (the canonical re-seed sources). Set DRY_RUN=1 to log |
| 14 | + * the planned markdown without writing. |
| 15 | + * |
| 16 | + * Overwrites page.content and resets contentJson/editorMode so the new markdown |
| 17 | + * is authoritative in both the public renderer and the admin editor. |
| 18 | + */ |
| 19 | +import { PrismaClient, Prisma } from '@prisma/client' |
| 20 | + |
| 21 | +const prisma = new PrismaClient() |
| 22 | +const DRY = process.env.DRY_RUN === '1' |
| 23 | +const TENANT_SLUG = process.env.TENANT_SLUG || 'e-ventschau' |
| 24 | + |
| 25 | +type Entry = { name: string; url?: string | null; logo?: string | null } |
| 26 | + |
| 27 | +// Förderer (Hauptunterstützer) |
| 28 | +const FOERDERER: Entry[] = [ |
| 29 | + { |
| 30 | + name: 'Sparkassenstiftung Lüneburg', |
| 31 | + url: 'http://www.sparkassenstiftung-lueneburg.de/aktuell.html', |
| 32 | + logo: '/foerderer-sparkassenstiftung.png', |
| 33 | + }, |
| 34 | +] |
| 35 | + |
| 36 | +// Sponsoren. `logo` is a self-hosted path under /public (see public/foerderer/*) |
| 37 | +// or null when no logo was found — then only name + link are shown. |
| 38 | +const SPONSORS: Entry[] = [ |
| 39 | + { name: 'Fips', url: 'https://www.fips-laden.de/', logo: '/foerderer/fips.svg' }, |
| 40 | + { name: 'GFA Lüneburg', url: 'http://www.gfa-lueneburg.de', logo: '/foerderer/gfa-lueneburg.png' }, |
| 41 | + { name: 'BWC Lüneburg', url: 'http://www.bwc-lueneburg.de', logo: '/foerderer/bwc-lueneburg.png' }, |
| 42 | + { name: 'Lübelner Mühle', url: null, logo: null }, |
| 43 | + { name: 'Haustechnik Will', url: 'http://www.haustechnik-will.de/', logo: null }, |
| 44 | + { name: 'CONTIGO Lüneburg', url: 'http://www.lueneburg.contigo.de', logo: '/foerderer/contigo.png' }, |
| 45 | + { name: 'Butenschön Design', url: 'http://www.ackermann-leder.de/', logo: null }, |
| 46 | + { name: 'Event Manufaktur', url: 'http://www.naturdirekt.de', logo: null }, |
| 47 | + { name: 'Stadtlichter', url: 'http://www.stadtlichter.com', logo: null }, |
| 48 | + { name: 'Zimmerei Jacob', url: 'https://zimmerei-jacob.de/', logo: '/foerderer/zimmerei-jacob.png' }, |
| 49 | + { name: 'SONIC SOUND', url: 'https://sonicsound.business.site', logo: null }, |
| 50 | + { name: 'Delinat', url: 'https://www.delinat.com/', logo: '/foerderer/delinat.svg' }, |
| 51 | + { name: 'Biomarkt Vitalis', url: 'http://www.biomarkt-vitalis.de/', logo: null }, |
| 52 | + { name: 'Lünestrom', url: 'http://www.evdbag.de', logo: null }, |
| 53 | + { name: 'PROTONES Veranstaltungstechnik', url: 'http://www.protones-veranstaltungstechnik.de/', logo: null }, |
| 54 | + { name: 'Autohaus Kurt Niehoff', url: 'http://autohaus-niehoff.de/', logo: '/foerderer/autohaus-niehoff.png' }, |
| 55 | + { name: 'PROFI MUSIK', url: 'http://www.profimusik.de/', logo: '/foerderer/profimusik.png' }, |
| 56 | + { name: 'VGH Michael Steisgerski', url: null, logo: null }, |
| 57 | +] |
| 58 | + |
| 59 | +function cell(e: Entry): string { |
| 60 | + const parts: string[] = [] |
| 61 | + if (e.logo) parts.push(``) |
| 62 | + parts.push(e.url ? `**[${e.name}](${e.url})**` : `**${e.name}**`) |
| 63 | + return parts.join('\n\n') |
| 64 | +} |
| 65 | + |
| 66 | +function columns2(entries: Entry[]): string { |
| 67 | + return `:::columns-2\n${entries.map(cell).join('\n---\n')}\n:::` |
| 68 | +} |
| 69 | + |
| 70 | +const FOERDERER_CONTENT = `# Unsere Förderer und Sponsoren |
| 71 | +
|
| 72 | +e-Ventschau ist ein Benefiz-Open-Air – möglich nur durch die Unterstützung von Förderern, Sponsoren und vielen Spender:innen. Ihnen allen gilt unser herzlicher Dank. Jeder Beitrag fließt in den guten Zweck. |
| 73 | +
|
| 74 | +Sie möchten das Festival unterstützen? Jede Spende hilft: |
| 75 | +
|
| 76 | +:::donate |
| 77 | +::: |
| 78 | +
|
| 79 | +## Unsere Förderer |
| 80 | +
|
| 81 | +${columns2(FOERDERER)} |
| 82 | +
|
| 83 | +## Unsere Sponsoren |
| 84 | +
|
| 85 | +${columns2(SPONSORS)} |
| 86 | +` |
| 87 | + |
| 88 | +const SPENDE_CONTENT = `# Unterstützen Sie e-Ventschau |
| 89 | +
|
| 90 | +e-Ventschau lebt von Menschen, die mit anpacken – und von finanzieller Unterstützung. Jeder überschüssige Euro fließt in den Benefiz-Zweck. |
| 91 | +
|
| 92 | +:::donate |
| 93 | +::: |
| 94 | +
|
| 95 | +## Volontäre |
| 96 | +e-Ventschau ist darauf angewiesen, dass Menschen bereit sind, ihr Knowhow und ihre Arbeitskraft zur Vorbereitung und Durchführung des Festivals einzubringen. Freiwilligenarbeit im Sinne von selbstbestimmtem Zupacken. |
| 97 | +
|
| 98 | +## Sponsoren |
| 99 | +Sponsoring- und Präsentationsmöglichkeiten rund um das Benefiz-Open-Air e-Ventschau. Sponsoren erleben Image-Transfer und helfen, das Fest in der regionalen Kulturlandschaft zu etablieren. |
| 100 | +
|
| 101 | +## Förderer / Patenschaften |
| 102 | +Jeder kann ein Förderer sein und die gute Sache mit einer finanziellen Zuwendung unterstützen. |
| 103 | +
|
| 104 | +Alle bisherigen Förderer und Sponsoren finden Sie auf der Seite [Unsere Förderer](/foerderer). |
| 105 | +` |
| 106 | + |
| 107 | +const PAGES = [ |
| 108 | + { |
| 109 | + slug: 'foerderer', |
| 110 | + path: '/foerderer', |
| 111 | + title: 'Unsere Förderer und Sponsoren', |
| 112 | + description: 'Die Unterstützer und Sponsoren des Benefiz-Open-Air-Festivals e-Ventschau.', |
| 113 | + content: FOERDERER_CONTENT, |
| 114 | + }, |
| 115 | + { |
| 116 | + slug: 'spende', |
| 117 | + path: '/unterstuetzung/spende', |
| 118 | + title: 'Ihre Spende', |
| 119 | + description: 'Unterstützen Sie e-Ventschau durch Spenden, Sponsoring oder freiwilliges Engagement.', |
| 120 | + content: SPENDE_CONTENT, |
| 121 | + }, |
| 122 | +] |
| 123 | + |
| 124 | +async function main() { |
| 125 | + const tenant = await prisma.tenant.findUnique({ where: { slug: TENANT_SLUG } }) |
| 126 | + if (!tenant) throw new Error(`Tenant '${TENANT_SLUG}' not found`) |
| 127 | + console.log(`Tenant: ${tenant.slug} (${tenant.id})${DRY ? ' [DRY RUN]' : ''}\n`) |
| 128 | + |
| 129 | + for (const p of PAGES) { |
| 130 | + if (DRY) { |
| 131 | + console.log(`--- ${p.slug} (${p.path}) ---\n${p.content}\n`) |
| 132 | + continue |
| 133 | + } |
| 134 | + await prisma.page.upsert({ |
| 135 | + where: { tenantId_slug: { tenantId: tenant.id, slug: p.slug } }, |
| 136 | + update: { |
| 137 | + title: p.title, |
| 138 | + path: p.path, |
| 139 | + content: p.content, |
| 140 | + contentJson: Prisma.DbNull, |
| 141 | + editorMode: 'markdown', |
| 142 | + metaTitle: p.title, |
| 143 | + metaDescription: p.description, |
| 144 | + isPublished: true, |
| 145 | + }, |
| 146 | + create: { |
| 147 | + tenantId: tenant.id, |
| 148 | + slug: p.slug, |
| 149 | + path: p.path, |
| 150 | + title: p.title, |
| 151 | + content: p.content, |
| 152 | + editorMode: 'markdown', |
| 153 | + metaTitle: p.title, |
| 154 | + metaDescription: p.description, |
| 155 | + isPublished: true, |
| 156 | + }, |
| 157 | + }) |
| 158 | + console.log(`✓ ${p.slug}: updated (${p.content.length} chars)`) |
| 159 | + } |
| 160 | + |
| 161 | + console.log(`\n=== ${DRY ? 'DRY RUN — ' : ''}done: ${PAGES.length} page(s) ===`) |
| 162 | +} |
| 163 | + |
| 164 | +main() |
| 165 | + .then(() => prisma.$disconnect()) |
| 166 | + .then(() => process.exit(0)) |
| 167 | + .catch(async (e) => { |
| 168 | + console.error(e) |
| 169 | + await prisma.$disconnect() |
| 170 | + process.exit(1) |
| 171 | + }) |
0 commit comments