feat(sprint-5.5): add block version snapshots with switching between versions

- Add BlockSnapshot Prisma model (html, css, version, changelog) + migration
- Add API endpoints: POST/GET /blocks/snapshots, GET /blocks/snapshots/:id
- BlockMetaBar: version dropdown, HTML capture on save, onSnapshotSelect prop
- "Сохранить версию" now captures innerHTML snapshot + CSS and stores in DB
- Selecting archived version shows stored HTML snapshot instead of live component
- Yellow banner "Архивная версия" with link to return to current
- Split all 8 block pages into Server Component (metadata) + Client Component
- Add data-block-capture attribute for snapshot capture targeting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AR 15 M4
2026-03-25 00:17:25 +05:00
parent 196526ffc4
commit 5b54ad5c23
21 changed files with 1962 additions and 1554 deletions
+19 -1
View File
@@ -1,4 +1,4 @@
import { Controller, Get, Patch, Query, Body } from '@nestjs/common';
import { Controller, Get, Post, Patch, Param, Query, Body } from '@nestjs/common';
import { BlocksService } from './blocks.service';
@Controller('blocks')
@@ -22,4 +22,22 @@ export class BlocksController {
) {
return this.blocks.update(path, body);
}
@Post('snapshots')
createSnapshot(
@Query('path') path: string,
@Body() body: { version: string; changelog: object[]; html: string; css: string },
) {
return this.blocks.createSnapshot(path, body);
}
@Get('snapshots')
listSnapshots(@Query('path') path: string) {
return this.blocks.listSnapshots(path);
}
@Get('snapshots/:id')
getSnapshot(@Param('id') id: string) {
return this.blocks.getSnapshot(id);
}
}
+20
View File
@@ -20,4 +20,24 @@ export class BlocksService {
update(path: string, data: { version?: string; isInPreview?: boolean; changelog?: object[] }) {
return this.prisma.block.update({ where: { path }, data });
}
createSnapshot(blockPath: string, data: { version: string; changelog: object[]; html: string; css: string }) {
return this.prisma.blockSnapshot.upsert({
where: { blockPath_version: { blockPath, version: data.version } },
update: { html: data.html, css: data.css, changelog: data.changelog },
create: { blockPath, ...data },
});
}
listSnapshots(blockPath: string) {
return this.prisma.blockSnapshot.findMany({
where: { blockPath },
select: { id: true, version: true, createdAt: true },
orderBy: { createdAt: 'desc' },
});
}
getSnapshot(id: string) {
return this.prisma.blockSnapshot.findUniqueOrThrow({ where: { id } });
}
}