feat(sprint-5.5): store block metadata (version, changelog) in PostgreSQL
- Prisma schema: added `changelog Json @default("[]")` to Block model
- Migration: 20260324141120_add_changelog_field
- Seed: 8 blocks with actual versions (v1.0–v1.2) and changelog entries
- API: PATCH /blocks/by-path accepts changelog field
- CORS: accept any localhost port (regex pattern)
- BlockChangelog component: renders version history from API or fallback
- BlockMetaBar: loads changelog from API, passes to BlockChangelog
- Removed "API офлайн" text, replaced with subtle gray dot
- Added defaultChangelog prop for offline fallback
- Block pages: removed hardcoded changelog JSX, use defaultChangelog prop
- Updated SPRINTS.md with completed tasks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Block" ADD COLUMN "changelog" JSONB NOT NULL DEFAULT '[]';
|
||||
@@ -46,6 +46,7 @@ model Block {
|
||||
name String
|
||||
version String
|
||||
isInPreview Boolean @default(false)
|
||||
changelog Json @default("[]")
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
+108
-9
@@ -6,21 +6,120 @@ const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
|
||||
const BLOCKS = [
|
||||
{ path: '/components/navigation', name: 'Шапка / Навигация', version: 'v1.0', isInPreview: true },
|
||||
{ path: '/blocks/hero', name: 'Hero-баннер', version: 'v1.1', isInPreview: true },
|
||||
{ path: '/blocks/ceo', name: 'Вводный текст (CEO-блок)', version: 'v0.1', isInPreview: false },
|
||||
{ path: '/blocks/doctors', name: 'Наши врачи', version: 'v1.1', isInPreview: true },
|
||||
{ path: '/blocks/reviews', name: 'Отзывы', version: 'v0.1', isInPreview: false },
|
||||
{ path: '/blocks/contact-forms', name: 'Формы записи', version: 'v0.1', isInPreview: false },
|
||||
{ path: '/blocks/news', name: 'Новости', version: 'v0.1', isInPreview: false },
|
||||
{ path: '/blocks/contact', name: 'Подвал / Контакт', version: 'v0.1', isInPreview: false },
|
||||
{
|
||||
path: '/components/navigation',
|
||||
name: 'Шапка / Навигация',
|
||||
version: 'v1.0',
|
||||
isInPreview: true,
|
||||
changelog: [
|
||||
{ version: 'v1.0', date: '23.03.2026', changes: ['Топ-бар, логотип, главное меню из 8 пунктов'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/blocks/hero',
|
||||
name: 'Hero-баннер',
|
||||
version: 'v1.2',
|
||||
isInPreview: true,
|
||||
changelog: [
|
||||
{ version: 'v1.2', date: '24.03.2026', changes: [
|
||||
'H1: цвет #cb9768, размер 36px (было ~20px #53514e)',
|
||||
'Заголовок баннера: 22px #333 (было 16px #111827)',
|
||||
'CTA-кнопка: pill-стиль (было outline)',
|
||||
'Дефис в H1: «–» → «-»',
|
||||
]},
|
||||
{ version: 'v1.1', date: '23.03.2026', changes: [
|
||||
'Единый фон #f9f4e7 (ранее разбит на две зоны)',
|
||||
'Реальное фото врача с пациентом',
|
||||
]},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/blocks/ceo',
|
||||
name: 'Вводный текст (CEO-блок)',
|
||||
version: 'v1.0',
|
||||
isInPreview: false,
|
||||
changelog: [
|
||||
{ version: 'v1.0', date: '23.03.2026', changes: ['Текст специализации клиники, вопросы-стимулы'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/blocks/doctors',
|
||||
name: 'Наши врачи',
|
||||
version: 'v1.2',
|
||||
isInPreview: true,
|
||||
changelog: [
|
||||
{ version: 'v1.2', date: '24.03.2026', changes: [
|
||||
'H2: 36px #000000 (было ~30px #111827)',
|
||||
'line-height: 38px',
|
||||
]},
|
||||
{ version: 'v1.1', date: '23.03.2026', changes: [
|
||||
'6 реальных фото врачей с сайта',
|
||||
'Статистика без фона, только border-bottom #60959c',
|
||||
]},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/blocks/reviews',
|
||||
name: 'Отзывы',
|
||||
version: 'v1.1',
|
||||
isInPreview: true,
|
||||
changelog: [
|
||||
{ version: 'v1.1', date: '24.03.2026', changes: [
|
||||
'H2: 36px #000000 (было ~20px #111827)',
|
||||
'line-height: 38px',
|
||||
]},
|
||||
{ version: 'v1.0', date: '23.03.2026', changes: [
|
||||
'Карусель отзывов: кавычка, текст, стрелки',
|
||||
]},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/blocks/contact-forms',
|
||||
name: 'Формы записи',
|
||||
version: 'v1.1',
|
||||
isInPreview: true,
|
||||
changelog: [
|
||||
{ version: 'v1.1', date: '24.03.2026', changes: [
|
||||
'H2: 36px #000000',
|
||||
'Фон формы 1: #b8e6ed → #d4f6f8',
|
||||
'Фон формы 2: #ffffff → #d4f6f8 (обе формы на одном фоне)',
|
||||
]},
|
||||
{ version: 'v1.0', date: '23.03.2026', changes: [
|
||||
'Две формы записи: «Будьте здоровы!» и «Узнайте стоимость операции»',
|
||||
]},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/blocks/news',
|
||||
name: 'Новости',
|
||||
version: 'v1.1',
|
||||
isInPreview: true,
|
||||
changelog: [
|
||||
{ version: 'v1.1', date: '24.03.2026', changes: [
|
||||
'H2: 36px #000000',
|
||||
'Фон секции: #fff → #f2fee6 (светло-зелёный)',
|
||||
]},
|
||||
{ version: 'v1.0', date: '23.03.2026', changes: [
|
||||
'4 карточки новостей в ряд, кнопка «Все новости»',
|
||||
]},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/blocks/contact',
|
||||
name: 'Подвал / Контакт',
|
||||
version: 'v1.0',
|
||||
isInPreview: false,
|
||||
changelog: [
|
||||
{ version: 'v1.0', date: '23.03.2026', changes: ['4 колонки ссылок, адрес, часы работы'] },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
async function main() {
|
||||
for (const block of BLOCKS) {
|
||||
await prisma.block.upsert({
|
||||
where: { path: block.path },
|
||||
update: {},
|
||||
update: { version: block.version, isInPreview: block.isInPreview, changelog: block.changelog },
|
||||
create: block,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user