fix(seed): write Lexical JSON to richText fields instead of plain strings
makeLexical moved to module scope and applied to locations.shortDesc, home-page subtitle/whyParents/birthdayIntro/news, dinosaur-page descriptions; seed-legal.mjs wraps legal texts for jsonb columns. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
03cd2e39ab
commit
43b8da73aa
2 changed files with 92 additions and 42 deletions
|
|
@ -33,15 +33,49 @@ const client = new pg.Client({
|
|||
})
|
||||
await client.connect()
|
||||
|
||||
// Content columns are jsonb (Lexical) since migration 0021 — wrap plain text.
|
||||
function textToLexical(text) {
|
||||
return JSON.stringify({
|
||||
root: {
|
||||
type: 'root',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
direction: 'ltr',
|
||||
children: text.split('\n').map((line) => ({
|
||||
type: 'paragraph',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
direction: 'ltr',
|
||||
children:
|
||||
line === ''
|
||||
? []
|
||||
: [
|
||||
{
|
||||
type: 'text',
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: line,
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
})),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
await client.query(
|
||||
`UPDATE legal_pages SET
|
||||
privacy_content = $1,
|
||||
terms_content = $2,
|
||||
offer_content = $3,
|
||||
data_processing_content = $4,
|
||||
privacy_content = $1::jsonb,
|
||||
terms_content = $2::jsonb,
|
||||
offer_content = $3::jsonb,
|
||||
data_processing_content = $4::jsonb,
|
||||
updated_at = now()
|
||||
WHERE id = 1`,
|
||||
[PRIVACY_DEFAULT, TERMS_DEFAULT, OFFER_DEFAULT, DATA_PROCESSING_DEFAULT]
|
||||
[PRIVACY_DEFAULT, TERMS_DEFAULT, OFFER_DEFAULT, DATA_PROCESSING_DEFAULT].map(textToLexical)
|
||||
)
|
||||
|
||||
console.log('✓ Legal pages seeded')
|
||||
|
|
|
|||
|
|
@ -4,6 +4,30 @@ import config from '@payload-config'
|
|||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
|
||||
// Wraps plain paragraphs into a Lexical editor state — required for all
|
||||
// richText fields (shortDesc, descriptions, subtitles, blog body).
|
||||
function makeLexical(paragraphs: string[]) {
|
||||
return {
|
||||
root: {
|
||||
type: 'root',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
direction: 'ltr',
|
||||
children: paragraphs.map((text) => ({
|
||||
type: 'paragraph',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
direction: 'ltr',
|
||||
children: [
|
||||
{ type: 'text', detail: 0, format: 0, mode: 'normal', style: '', text, version: 1 },
|
||||
],
|
||||
})),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function getMimeType(filename: string): string {
|
||||
if (filename.endsWith('.jpg') || filename.endsWith('.jpeg')) return 'image/jpeg'
|
||||
if (filename.endsWith('.png')) return 'image/png'
|
||||
|
|
@ -174,7 +198,7 @@ export async function POST(req: NextRequest) {
|
|||
name: loc.name,
|
||||
slug: loc.slug,
|
||||
tagline: loc.tagline,
|
||||
shortDesc: loc.shortDesc,
|
||||
shortDesc: makeLexical([loc.shortDesc]),
|
||||
image: imageId ?? undefined,
|
||||
showInMenu: true,
|
||||
showOnHome: true,
|
||||
|
|
@ -362,8 +386,9 @@ export async function POST(req: NextRequest) {
|
|||
data: {
|
||||
hero: {
|
||||
title: 'ШУМІЛЕНД –\nСВІТ, ДЕ КАЗКА\nОЖИВАЄ',
|
||||
subtitle:
|
||||
subtitle: makeLexical([
|
||||
'Сімейний тематичний парк, де гра допомагає пізнавати світ, а кожна прогулянка перетворюється на незабутню пригоду.',
|
||||
]),
|
||||
ctaLabel: 'Купити квиток',
|
||||
ctaHref: '/payments',
|
||||
foregroundOverlay: heroBg1Media ?? undefined,
|
||||
|
|
@ -384,33 +409,39 @@ export async function POST(req: NextRequest) {
|
|||
items: [
|
||||
{
|
||||
title: 'Подорож кількома світами за один день',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'ДиноПарк, Диво Ліс, Дзеркальний лабіринт — кожна локація це окремий всесвіт пригод для дітей і батьків.',
|
||||
]),
|
||||
},
|
||||
{
|
||||
title: 'Свіже повітря та затишок лісу',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'Ми оновлюємо тематику та декорації до кожного сезону, тому тут буде цікаво кожного візиту.',
|
||||
]),
|
||||
},
|
||||
{
|
||||
title: 'Нова казка кожної пори року',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'Зима, весна, літо, осінь — кожен сезон у парку неповторний. Святкові декорації та тематичні заходи чекають на вас.',
|
||||
]),
|
||||
},
|
||||
{
|
||||
title: 'Безпека понад усе',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'Всі атракції та зони проходять регулярну перевірку. Охоронці, медичний персонал та чіткі правила безпеки.',
|
||||
]),
|
||||
},
|
||||
{
|
||||
title: 'Все необхідне — поруч і без пошуків',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'Паркування, вбиральні, зона для годування немовлят, укриття, фудкорт — все на місці.',
|
||||
]),
|
||||
},
|
||||
{
|
||||
title: 'Фудкорт — смачно для всієї родини',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'Хот-доги, піца, кава, лимонади та багато іншого. Є дитяче меню та здорові перекуси.',
|
||||
]),
|
||||
},
|
||||
],
|
||||
sideGallery: wpMediaIds.filter(Boolean).map((id) => ({ image: id })),
|
||||
|
|
@ -425,11 +456,13 @@ export async function POST(req: NextRequest) {
|
|||
src: null,
|
||||
},
|
||||
birthdayIntro: {
|
||||
text: 'Незабутнє свято для вашої дитини. Ми подбаємо про все: від декорацій до аніматорів!',
|
||||
text: makeLexical([
|
||||
'Незабутнє свято для вашої дитини. Ми подбаємо про все: від декорацій до аніматорів!',
|
||||
]),
|
||||
},
|
||||
news: {
|
||||
title: 'Новини',
|
||||
subtitle: 'Свіжі події, акції та оновлення парку.',
|
||||
subtitle: makeLexical(['Свіжі події, акції та оновлення парку.']),
|
||||
limit: 3,
|
||||
},
|
||||
map: {
|
||||
|
|
@ -485,28 +518,6 @@ export async function POST(req: NextRequest) {
|
|||
results.push('Seeded site-settings global')
|
||||
|
||||
// === BLOG POSTS ===
|
||||
function makeLexical(paragraphs: string[]) {
|
||||
return {
|
||||
root: {
|
||||
type: 'root',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
direction: 'ltr',
|
||||
children: paragraphs.map((text) => ({
|
||||
type: 'paragraph',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
direction: 'ltr',
|
||||
children: [
|
||||
{ type: 'text', detail: 0, format: 0, mode: 'normal', style: '', text, version: 1 },
|
||||
],
|
||||
})),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const { totalDocs: postCount } = await payload.find({
|
||||
collection: 'blog-posts',
|
||||
limit: 1,
|
||||
|
|
@ -937,8 +948,9 @@ export async function POST(req: NextRequest) {
|
|||
slug: 'dinosaur-page' as never,
|
||||
data: {
|
||||
heroTitle: 'Динопарк — портал у світ динозаврів',
|
||||
heroDescription:
|
||||
heroDescription: makeLexical([
|
||||
'Великі динозаври, що рухаються та гарчать, справжнє роздоволлє, цікаві екскурсії та динородео — тут є все, щоб ваша дитина не нудьгувала.',
|
||||
]),
|
||||
heroStat: '26',
|
||||
heroStatLabel: 'унікальних експонатів',
|
||||
heroFeatures: [
|
||||
|
|
@ -956,8 +968,9 @@ export async function POST(req: NextRequest) {
|
|||
{ name: 'Анкілозавр', epoch: 'Крейдяний', length: '8 м', weight: '7 т' },
|
||||
],
|
||||
activitiesTitle: 'Додаткові розваги у динопарку',
|
||||
activitiesDescription:
|
||||
activitiesDescription: makeLexical([
|
||||
'Хочете дізнатись ще більше про динозаврів? Замовте екскурсію з гідом, поринь у світ палеонтологічних розкопок або підкорюй справжнього динозавра!',
|
||||
]),
|
||||
activities: [
|
||||
{ name: 'Звичайна екскурсія', price: '150 грн', href: '#tickets' },
|
||||
{ name: 'Палеонтологічна екскурсія', price: '300 грн', href: '#tickets' },
|
||||
|
|
@ -967,18 +980,21 @@ export async function POST(req: NextRequest) {
|
|||
whyVisitItems: [
|
||||
{
|
||||
title: 'Навчання через гру',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'Дітки дізнаються про стародавніх тварин через захопливі ігри та інтерактивні вправи з гідом.',
|
||||
]),
|
||||
},
|
||||
{
|
||||
title: 'Дитячі очі, що палають захватом',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'Реалістичні рухи та звуки динозаврів створюють ефект повного занурення — дитина точно не забуде цього дня.',
|
||||
]),
|
||||
},
|
||||
{
|
||||
title: 'Неймовірні фотографії',
|
||||
description:
|
||||
description: makeLexical([
|
||||
'Сфотографуйтесь поруч із улюбленим динозавром або зробіть фото з екскурсоводом — тепла згадка для всієї родини.',
|
||||
]),
|
||||
},
|
||||
],
|
||||
workingHours: "п'ятниця-субота-неділя з 11:00 до 20:00",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue