feat: add sequential progression and video watch lesson completion
Gate student content by completion order, track per-video watch progress with seek enforcement, and auto-complete lessons at the configured threshold. Show ring progress in the lesson header, keep watch progress on rewatch, and sync progression locks client-side so the next item unlocks after completion.
This commit is contained in:
@@ -36,6 +36,8 @@ import { courseMemberMiddleware } from '@api/middlewares/course-member';
|
||||
import { courseMemberOrAutomationKeyMiddleware } from '@api/middlewares/course-member-or-automation-key';
|
||||
import { assertMcpAutomationUsageAllowed, recordMcpAutomationUsage } from '@api/services/organization/automation-usage';
|
||||
import { createSubmissionService, listExerciseSubmissionsOverview } from '@api/services/submission';
|
||||
import { assertEnrolledStudentContentAccess } from '@api/services/course/access';
|
||||
import { ContentType } from '@cio/utils/constants';
|
||||
import { zValidator } from '@hono/zod-validator';
|
||||
|
||||
export const exerciseRouter = new Hono()
|
||||
@@ -95,6 +97,15 @@ export const exerciseRouter = new Hono()
|
||||
await assertMcpAutomationUsageAllowed(automationKey, 'get_course_exercise');
|
||||
}
|
||||
|
||||
if (user?.id && !automationKey) {
|
||||
await assertEnrolledStudentContentAccess({
|
||||
courseId: c.req.param('courseId')!,
|
||||
profileId: user.id,
|
||||
contentId: exerciseId,
|
||||
type: ContentType.Exercise
|
||||
});
|
||||
}
|
||||
|
||||
const exercise = await getExercise(exerciseId, undefined, user?.id);
|
||||
|
||||
if (automationKey?.type === 'mcp') {
|
||||
@@ -260,6 +271,13 @@ export const exerciseRouter = new Hono()
|
||||
return c.json({ success: false, error: 'User is not a member of this course' }, 403);
|
||||
}
|
||||
|
||||
await assertEnrolledStudentContentAccess({
|
||||
courseId,
|
||||
profileId: user.id,
|
||||
contentId: exerciseId,
|
||||
type: ContentType.Exercise
|
||||
});
|
||||
|
||||
const submission = await createSubmissionService(courseId, exerciseId, groupMemberId, answers);
|
||||
|
||||
return c.json({ success: true, data: submission }, 201);
|
||||
|
||||
Reference in New Issue
Block a user