feat: add resilient cover previews and zoom
All checks were successful
CI / Validate frontend and API (push) Successful in 1m10s
CI / Build and publish Docker images (push) Successful in 50s

This commit is contained in:
Cauê Faleiros
2026-09-04 14:29:07 -03:00
parent 1d5eafbbd0
commit ad860074fd
10 changed files with 86 additions and 17 deletions

View File

@@ -21,6 +21,7 @@ export const courseSelect = (publicOnly = false, includeUnreadyMedia = false) =>
coalesce(c.cover_image_url, (
select value #>> '{}' from platform_settings where key = 'media.defaultCoverImageUrl'
)) as "coverImageUrl",
c.cover_image_zoom as "coverImageZoom",
c.status,
c.published_at as "publishedAt",
jsonb_build_object(

View File

@@ -45,6 +45,7 @@ const courseSchema = z.object({
description: z.string().max(10000).default(''),
category: z.string().trim().min(1).max(120),
coverImageUrl: coverImageUrlSchema.nullable().optional(),
coverImageZoom: z.number().min(1).max(2.5).default(1),
status: z.enum(['draft', 'published']).default('draft'),
lessons: z.array(lessonSchema).min(1),
assets: z.array(assetSchema).default([]),
@@ -213,10 +214,10 @@ export const manageCourseRoutes: FastifyPluginAsync = async (app) => {
await client.query('begin');
const slug = await uniqueSlug(client, input.slug, input.title);
const course = await client.query<{ id: string }>(
`insert into courses (slug, title, description, category, cover_image_url, status, instructor_id, published_at)
values ($1, $2, $3, $4, $5, $6::course_status, $7, case when $6::course_status = 'published'::course_status then now() else null end)
`insert into courses (slug, title, description, category, cover_image_url, cover_image_zoom, status, instructor_id, published_at)
values ($1, $2, $3, $4, $5, $6, $7::course_status, $8, case when $7::course_status = 'published'::course_status then now() else null end)
returning id`,
[slug, input.title, input.description, input.category, input.coverImageUrl ?? null, input.status, request.user.id],
[slug, input.title, input.description, input.category, input.coverImageUrl ?? null, input.coverImageZoom, input.status, request.user.id],
);
await replaceCourseContents(client, course.rows[0].id, input);
await client.query('commit');
@@ -245,10 +246,10 @@ export const manageCourseRoutes: FastifyPluginAsync = async (app) => {
const slug = await uniqueSlug(client, input.slug, input.title, courseId);
await client.query(
`update courses
set slug = $2, title = $3, description = $4, category = $5, cover_image_url = $6,
status = $7::course_status, published_at = case when $7::course_status = 'published'::course_status then coalesce(published_at, now()) else null end
set slug = $2, title = $3, description = $4, category = $5, cover_image_url = $6, cover_image_zoom = $7,
status = $8::course_status, published_at = case when $8::course_status = 'published'::course_status then coalesce(published_at, now()) else null end
where id = $1`,
[courseId, slug, input.title, input.description, input.category, input.coverImageUrl ?? null, input.status],
[courseId, slug, input.title, input.description, input.category, input.coverImageUrl ?? null, input.coverImageZoom, input.status],
);
await replaceCourseContents(client, courseId, input);
await client.query('commit');
@@ -280,8 +281,8 @@ export const manageCourseRoutes: FastifyPluginAsync = async (app) => {
const client = await pool.connect();
try {
await client.query('begin');
const original = await client.query<{ title: string; description: string; category: string; cover_image_url: string | null; instructor_id: string }>(
`select title, description, category, cover_image_url, instructor_id from courses where id = $1`, [courseId],
const original = await client.query<{ title: string; description: string; category: string; cover_image_url: string | null; cover_image_zoom: number; instructor_id: string }>(
`select title, description, category, cover_image_url, cover_image_zoom, instructor_id from courses where id = $1`, [courseId],
);
if (!original.rows[0]) {
await client.query('rollback');
@@ -291,9 +292,9 @@ export const manageCourseRoutes: FastifyPluginAsync = async (app) => {
const title = `${source.title} (cópia)`;
const slug = await uniqueSlug(client, undefined, title);
const copiedCourse = await client.query<{ id: string }>(
`insert into courses (slug, title, description, category, cover_image_url, status, instructor_id)
values ($1, $2, $3, $4, $5, 'draft', $6) returning id`,
[slug, title, source.description, source.category, source.cover_image_url, source.instructor_id],
`insert into courses (slug, title, description, category, cover_image_url, cover_image_zoom, status, instructor_id)
values ($1, $2, $3, $4, $5, $6, 'draft', $7) returning id`,
[slug, title, source.description, source.category, source.cover_image_url, source.cover_image_zoom, source.instructor_id],
);
const newCourseId = copiedCourse.rows[0].id;
await client.query(