@hed-hog/lms 0.0.361 → 0.0.365
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bitcode-wallet/bitcode-wallet.service.d.ts +66 -0
- package/dist/bitcode-wallet/bitcode-wallet.service.d.ts.map +1 -1
- package/dist/bitcode-wallet/bitcode-wallet.service.js +91 -0
- package/dist/bitcode-wallet/bitcode-wallet.service.js.map +1 -1
- package/dist/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.d.ts +8 -0
- package/dist/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.d.ts.map +1 -0
- package/dist/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.js +40 -0
- package/dist/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.js.map +1 -0
- package/dist/class-group/class-group.controller.d.ts +16 -16
- package/dist/class-group/class-group.service.d.ts +12 -12
- package/dist/course/course-audio-transcription.service.d.ts +3 -2
- package/dist/course/course-audio-transcription.service.d.ts.map +1 -1
- package/dist/course/course-audio-transcription.service.js +49 -8
- package/dist/course/course-audio-transcription.service.js.map +1 -1
- package/dist/course/course-export-scorm12-worker.service.d.ts +21 -0
- package/dist/course/course-export-scorm12-worker.service.d.ts.map +1 -0
- package/dist/course/course-export-scorm12-worker.service.js +109 -0
- package/dist/course/course-export-scorm12-worker.service.js.map +1 -0
- package/dist/course/course-export-scorm12.service.d.ts +42 -0
- package/dist/course/course-export-scorm12.service.d.ts.map +1 -0
- package/dist/course/course-export-scorm12.service.js +628 -0
- package/dist/course/course-export-scorm12.service.js.map +1 -0
- package/dist/course/course-export.service.d.ts +84 -0
- package/dist/course/course-export.service.d.ts.map +1 -0
- package/dist/course/course-export.service.js +237 -0
- package/dist/course/course-export.service.js.map +1 -0
- package/dist/course/course-lesson.controller.d.ts +4 -0
- package/dist/course/course-lesson.controller.d.ts.map +1 -1
- package/dist/course/course-lesson.controller.js +10 -0
- package/dist/course/course-lesson.controller.js.map +1 -1
- package/dist/course/course-structure.controller.d.ts +24 -9
- package/dist/course/course-structure.controller.d.ts.map +1 -1
- package/dist/course/course-structure.controller.js +30 -3
- package/dist/course/course-structure.controller.js.map +1 -1
- package/dist/course/course-structure.service.d.ts +25 -3
- package/dist/course/course-structure.service.d.ts.map +1 -1
- package/dist/course/course-structure.service.js +234 -24
- package/dist/course/course-structure.service.js.map +1 -1
- package/dist/course/course-video-conversion.service.d.ts +8 -0
- package/dist/course/course-video-conversion.service.d.ts.map +1 -1
- package/dist/course/course-video-conversion.service.js +87 -51
- package/dist/course/course-video-conversion.service.js.map +1 -1
- package/dist/course/course-video-hls.service.d.ts +57 -0
- package/dist/course/course-video-hls.service.d.ts.map +1 -0
- package/dist/course/course-video-hls.service.js +767 -0
- package/dist/course/course-video-hls.service.js.map +1 -0
- package/dist/course/course.controller.d.ts +115 -11
- package/dist/course/course.controller.d.ts.map +1 -1
- package/dist/course/course.controller.js +66 -28
- package/dist/course/course.controller.js.map +1 -1
- package/dist/course/course.mcp-tools.js +1 -1
- package/dist/course/course.mcp-tools.js.map +1 -1
- package/dist/course/course.module.d.ts.map +1 -1
- package/dist/course/course.module.js +13 -0
- package/dist/course/course.module.js.map +1 -1
- package/dist/course/course.service.d.ts +112 -11
- package/dist/course/course.service.d.ts.map +1 -1
- package/dist/course/course.service.js +682 -72
- package/dist/course/course.service.js.map +1 -1
- package/dist/course/dto/cleanup-course-storage.dto.d.ts +6 -0
- package/dist/course/dto/cleanup-course-storage.dto.d.ts.map +1 -0
- package/dist/course/dto/cleanup-course-storage.dto.js +34 -0
- package/dist/course/dto/cleanup-course-storage.dto.js.map +1 -0
- package/dist/course/dto/cleanup-upload-history.dto.d.ts +9 -0
- package/dist/course/dto/cleanup-upload-history.dto.d.ts.map +1 -0
- package/dist/course/dto/cleanup-upload-history.dto.js +36 -0
- package/dist/course/dto/cleanup-upload-history.dto.js.map +1 -0
- package/dist/course/dto/create-course-bulk-job.dto.d.ts +5 -0
- package/dist/course/dto/create-course-bulk-job.dto.d.ts.map +1 -0
- package/dist/course/dto/create-course-bulk-job.dto.js +26 -0
- package/dist/course/dto/create-course-bulk-job.dto.js.map +1 -0
- package/dist/course/dto/create-course-export.dto.d.ts +14 -0
- package/dist/course/dto/create-course-export.dto.d.ts.map +1 -0
- package/dist/course/dto/create-course-export.dto.js +71 -0
- package/dist/course/dto/create-course-export.dto.js.map +1 -0
- package/dist/course/dto/create-course-structure-lesson.dto.d.ts +2 -2
- package/dist/course/dto/create-course-structure-lesson.dto.d.ts.map +1 -1
- package/dist/course/dto/create-course-structure-lesson.dto.js +3 -2
- package/dist/course/dto/create-course-structure-lesson.dto.js.map +1 -1
- package/dist/course/lms-bulk-upload-automation.service.d.ts +54 -0
- package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -0
- package/dist/course/lms-bulk-upload-automation.service.js +537 -0
- package/dist/course/lms-bulk-upload-automation.service.js.map +1 -0
- package/dist/course/lms-bulk-upload-infra.service.d.ts +32 -0
- package/dist/course/lms-bulk-upload-infra.service.d.ts.map +1 -0
- package/dist/course/lms-bulk-upload-infra.service.js +301 -0
- package/dist/course/lms-bulk-upload-infra.service.js.map +1 -0
- package/dist/course/lms-bulk-upload.constants.d.ts +4 -0
- package/dist/course/lms-bulk-upload.constants.d.ts.map +1 -0
- package/dist/course/lms-bulk-upload.constants.js +7 -0
- package/dist/course/lms-bulk-upload.constants.js.map +1 -0
- package/dist/course/lms-bulk-upload.controller.d.ts +144 -1
- package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.controller.js +114 -4
- package/dist/course/lms-bulk-upload.controller.js.map +1 -1
- package/dist/course/lms-bulk-upload.service.d.ts +153 -3
- package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.service.js +659 -21
- package/dist/course/lms-bulk-upload.service.js.map +1 -1
- package/dist/course/lms-setting.controller.d.ts +6 -2
- package/dist/course/lms-setting.controller.d.ts.map +1 -1
- package/dist/course/lms-setting.controller.js +25 -8
- package/dist/course/lms-setting.controller.js.map +1 -1
- package/dist/course/scorm12-schemas.d.ts +4 -0
- package/dist/course/scorm12-schemas.d.ts.map +1 -0
- package/dist/course/scorm12-schemas.js +9 -0
- package/dist/course/scorm12-schemas.js.map +1 -0
- package/dist/enterprise/enterprise.controller.d.ts +20 -20
- package/dist/enterprise/enterprise.service.d.ts +20 -20
- package/dist/enterprise/training/training-admin.controller.d.ts +11 -11
- package/dist/enterprise/training/training-admin.service.d.ts +11 -11
- package/dist/enterprise/training/training-instructor.controller.d.ts +2 -2
- package/dist/enterprise/training/training-instructor.service.d.ts +2 -2
- package/dist/enterprise/training/training-student.controller.d.ts +1 -1
- package/dist/enterprise/training/training-student.service.d.ts +52 -1
- package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
- package/dist/enterprise/training/training-student.service.js +217 -4
- package/dist/enterprise/training/training-student.service.js.map +1 -1
- package/dist/enterprise/training/training-viewer.controller.d.ts +2 -2
- package/dist/evaluation/evaluation.controller.d.ts +8 -8
- package/dist/evaluation/evaluation.service.d.ts +26 -8
- package/dist/evaluation/evaluation.service.d.ts.map +1 -1
- package/dist/evaluation/evaluation.service.js +125 -0
- package/dist/evaluation/evaluation.service.js.map +1 -1
- package/dist/exam/dto/create-standalone-question.dto.d.ts +12 -0
- package/dist/exam/dto/create-standalone-question.dto.d.ts.map +1 -0
- package/dist/exam/dto/create-standalone-question.dto.js +70 -0
- package/dist/exam/dto/create-standalone-question.dto.js.map +1 -0
- package/dist/exam/exam.module.d.ts.map +1 -1
- package/dist/exam/exam.module.js +2 -1
- package/dist/exam/exam.module.js.map +1 -1
- package/dist/exam/exam.service.d.ts +21 -0
- package/dist/exam/exam.service.d.ts.map +1 -1
- package/dist/exam/exam.service.js +80 -0
- package/dist/exam/exam.service.js.map +1 -1
- package/dist/exam/question.controller.d.ts +27 -0
- package/dist/exam/question.controller.d.ts.map +1 -0
- package/dist/exam/question.controller.js +53 -0
- package/dist/exam/question.controller.js.map +1 -0
- package/dist/lesson-xp-map/dto/create-lesson-xp-map.dto.d.ts +6 -0
- package/dist/lesson-xp-map/dto/create-lesson-xp-map.dto.d.ts.map +1 -0
- package/dist/lesson-xp-map/dto/create-lesson-xp-map.dto.js +34 -0
- package/dist/lesson-xp-map/dto/create-lesson-xp-map.dto.js.map +1 -0
- package/dist/lesson-xp-map/dto/create-lesson-xp-segment.dto.d.ts +28 -0
- package/dist/lesson-xp-map/dto/create-lesson-xp-segment.dto.d.ts.map +1 -0
- package/dist/lesson-xp-map/dto/create-lesson-xp-segment.dto.js +123 -0
- package/dist/lesson-xp-map/dto/create-lesson-xp-segment.dto.js.map +1 -0
- package/dist/lesson-xp-map/dto/review-lesson-xp-map.dto.d.ts +4 -0
- package/dist/lesson-xp-map/dto/review-lesson-xp-map.dto.d.ts.map +1 -0
- package/dist/lesson-xp-map/dto/review-lesson-xp-map.dto.js +22 -0
- package/dist/lesson-xp-map/dto/review-lesson-xp-map.dto.js.map +1 -0
- package/dist/lesson-xp-map/dto/update-lesson-xp-map.dto.d.ts +10 -0
- package/dist/lesson-xp-map/dto/update-lesson-xp-map.dto.d.ts.map +1 -0
- package/dist/lesson-xp-map/dto/update-lesson-xp-map.dto.js +52 -0
- package/dist/lesson-xp-map/dto/update-lesson-xp-map.dto.js.map +1 -0
- package/dist/lesson-xp-map/dto/update-lesson-xp-segment.dto.d.ts +15 -0
- package/dist/lesson-xp-map/dto/update-lesson-xp-segment.dto.d.ts.map +1 -0
- package/dist/lesson-xp-map/dto/update-lesson-xp-segment.dto.js +86 -0
- package/dist/lesson-xp-map/dto/update-lesson-xp-segment.dto.js.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts +30 -0
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js +440 -0
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-map.controller.d.ts +87 -0
- package/dist/lesson-xp-map/lesson-xp-map.controller.d.ts.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-map.controller.js +185 -0
- package/dist/lesson-xp-map/lesson-xp-map.controller.js.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-map.module.d.ts +3 -0
- package/dist/lesson-xp-map/lesson-xp-map.module.d.ts.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-map.module.js +34 -0
- package/dist/lesson-xp-map/lesson-xp-map.module.js.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-map.service.d.ts +84 -0
- package/dist/lesson-xp-map/lesson-xp-map.service.d.ts.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-map.service.js +353 -0
- package/dist/lesson-xp-map/lesson-xp-map.service.js.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-segment.controller.d.ts +10 -0
- package/dist/lesson-xp-map/lesson-xp-segment.controller.d.ts.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-segment.controller.js +63 -0
- package/dist/lesson-xp-map/lesson-xp-segment.controller.js.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-segment.service.d.ts +27 -0
- package/dist/lesson-xp-map/lesson-xp-segment.service.d.ts.map +1 -0
- package/dist/lesson-xp-map/lesson-xp-segment.service.js +194 -0
- package/dist/lesson-xp-map/lesson-xp-segment.service.js.map +1 -0
- package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -0
- package/dist/lms-commerce-access.subscriber.d.ts +11 -0
- package/dist/lms-commerce-access.subscriber.d.ts.map +1 -0
- package/dist/lms-commerce-access.subscriber.js +74 -0
- package/dist/lms-commerce-access.subscriber.js.map +1 -0
- package/dist/lms.module.d.ts.map +1 -1
- package/dist/lms.module.js +21 -5
- package/dist/lms.module.js.map +1 -1
- package/dist/platforma/dto/update-profile.dto.d.ts +17 -0
- package/dist/platforma/dto/update-profile.dto.d.ts.map +1 -0
- package/dist/platforma/dto/update-profile.dto.js +87 -0
- package/dist/platforma/dto/update-profile.dto.js.map +1 -0
- package/dist/platforma/platforma-video.service.d.ts +39 -0
- package/dist/platforma/platforma-video.service.d.ts.map +1 -0
- package/dist/platforma/platforma-video.service.js +301 -0
- package/dist/platforma/platforma-video.service.js.map +1 -0
- package/dist/platforma/platforma.controller.d.ts +182 -1
- package/dist/platforma/platforma.controller.d.ts.map +1 -1
- package/dist/platforma/platforma.controller.js +243 -2
- package/dist/platforma/platforma.controller.js.map +1 -1
- package/dist/platforma/platforma.service.d.ts +27 -0
- package/dist/platforma/platforma.service.d.ts.map +1 -0
- package/dist/platforma/platforma.service.js +274 -0
- package/dist/platforma/platforma.service.js.map +1 -0
- package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts +5 -0
- package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts.map +1 -0
- package/dist/student-xp/dto/grant-skill-card-xp.dto.js +26 -0
- package/dist/student-xp/dto/grant-skill-card-xp.dto.js.map +1 -0
- package/dist/student-xp/student-xp.controller.d.ts +56 -0
- package/dist/student-xp/student-xp.controller.d.ts.map +1 -0
- package/dist/student-xp/student-xp.controller.js +138 -0
- package/dist/student-xp/student-xp.controller.js.map +1 -0
- package/dist/student-xp/student-xp.module.d.ts +3 -0
- package/dist/student-xp/student-xp.module.d.ts.map +1 -0
- package/dist/student-xp/student-xp.module.js +25 -0
- package/dist/student-xp/student-xp.module.js.map +1 -0
- package/dist/student-xp/student-xp.service.d.ts +81 -0
- package/dist/student-xp/student-xp.service.d.ts.map +1 -0
- package/dist/student-xp/student-xp.service.js +247 -0
- package/dist/student-xp/student-xp.service.js.map +1 -0
- package/dist/xp-catalog/dto/create-xp-area.dto.d.ts +12 -0
- package/dist/xp-catalog/dto/create-xp-area.dto.d.ts.map +1 -0
- package/dist/xp-catalog/dto/create-xp-area.dto.js +63 -0
- package/dist/xp-catalog/dto/create-xp-area.dto.js.map +1 -0
- package/dist/xp-catalog/dto/create-xp-learning-type.dto.d.ts +11 -0
- package/dist/xp-catalog/dto/create-xp-learning-type.dto.d.ts.map +1 -0
- package/dist/xp-catalog/dto/create-xp-learning-type.dto.js +57 -0
- package/dist/xp-catalog/dto/create-xp-learning-type.dto.js.map +1 -0
- package/dist/xp-catalog/dto/create-xp-skill.dto.d.ts +11 -0
- package/dist/xp-catalog/dto/create-xp-skill.dto.d.ts.map +1 -0
- package/dist/xp-catalog/dto/create-xp-skill.dto.js +57 -0
- package/dist/xp-catalog/dto/create-xp-skill.dto.js.map +1 -0
- package/dist/xp-catalog/dto/update-xp-area.dto.d.ts +12 -0
- package/dist/xp-catalog/dto/update-xp-area.dto.d.ts.map +1 -0
- package/dist/xp-catalog/dto/update-xp-area.dto.js +66 -0
- package/dist/xp-catalog/dto/update-xp-area.dto.js.map +1 -0
- package/dist/xp-catalog/dto/update-xp-learning-type.dto.d.ts +11 -0
- package/dist/xp-catalog/dto/update-xp-learning-type.dto.d.ts.map +1 -0
- package/dist/xp-catalog/dto/update-xp-learning-type.dto.js +60 -0
- package/dist/xp-catalog/dto/update-xp-learning-type.dto.js.map +1 -0
- package/dist/xp-catalog/dto/update-xp-skill.dto.d.ts +11 -0
- package/dist/xp-catalog/dto/update-xp-skill.dto.d.ts.map +1 -0
- package/dist/xp-catalog/dto/update-xp-skill.dto.js +60 -0
- package/dist/xp-catalog/dto/update-xp-skill.dto.js.map +1 -0
- package/dist/xp-catalog/xp-area.controller.d.ts +25 -0
- package/dist/xp-catalog/xp-area.controller.d.ts.map +1 -0
- package/dist/xp-catalog/xp-area.controller.js +105 -0
- package/dist/xp-catalog/xp-area.controller.js.map +1 -0
- package/dist/xp-catalog/xp-area.service.d.ts +35 -0
- package/dist/xp-catalog/xp-area.service.d.ts.map +1 -0
- package/dist/xp-catalog/xp-area.service.js +168 -0
- package/dist/xp-catalog/xp-area.service.js.map +1 -0
- package/dist/xp-catalog/xp-catalog.module.d.ts +3 -0
- package/dist/xp-catalog/xp-catalog.module.d.ts.map +1 -0
- package/dist/xp-catalog/xp-catalog.module.js +29 -0
- package/dist/xp-catalog/xp-catalog.module.js.map +1 -0
- package/dist/xp-catalog/xp-learning-type.controller.d.ts +20 -0
- package/dist/xp-catalog/xp-learning-type.controller.d.ts.map +1 -0
- package/dist/xp-catalog/xp-learning-type.controller.js +96 -0
- package/dist/xp-catalog/xp-learning-type.controller.js.map +1 -0
- package/dist/xp-catalog/xp-learning-type.service.d.ts +30 -0
- package/dist/xp-catalog/xp-learning-type.service.d.ts.map +1 -0
- package/dist/xp-catalog/xp-learning-type.service.js +146 -0
- package/dist/xp-catalog/xp-learning-type.service.js.map +1 -0
- package/dist/xp-catalog/xp-skill.controller.d.ts +26 -0
- package/dist/xp-catalog/xp-skill.controller.d.ts.map +1 -0
- package/dist/xp-catalog/xp-skill.controller.js +113 -0
- package/dist/xp-catalog/xp-skill.controller.js.map +1 -0
- package/dist/xp-catalog/xp-skill.service.d.ts +37 -0
- package/dist/xp-catalog/xp-skill.service.d.ts.map +1 -0
- package/dist/xp-catalog/xp-skill.service.js +174 -0
- package/dist/xp-catalog/xp-skill.service.js.map +1 -0
- package/hedhog/data/evaluation_topic.yaml +17 -0
- package/hedhog/data/menu.yaml +91 -7
- package/hedhog/data/queue_definition.yaml +48 -0
- package/hedhog/data/route.yaml +511 -29
- package/hedhog/data/setting_group.yaml +20 -20
- package/hedhog/data/xp_area.yaml +164 -0
- package/hedhog/data/xp_learning_type.yaml +131 -0
- package/hedhog/data/xp_skill.yaml +1834 -0
- package/hedhog/frontend/app/achievements/page.tsx.ejs +108 -118
- package/hedhog/frontend/app/bitcodes/page.tsx.ejs +22 -34
- package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +1749 -0
- package/hedhog/frontend/app/certificates/models/page.tsx.ejs +21 -45
- package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +40 -74
- package/hedhog/frontend/app/classes/page.tsx.ejs +56 -85
- package/hedhog/frontend/app/courses/[id]/_components/CourseDangerZoneCard.tsx.ejs +3 -2
- package/hedhog/frontend/app/courses/[id]/_components/CourseMediaCard.tsx.ejs +48 -5
- package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +73 -8
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-export-sheet.tsx.ejs +420 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-exports-tab.tsx.ejs +308 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-operations-tab.tsx.ejs +19 -2
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-overview-tab.tsx.ejs +1172 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-dnd.tsx.ejs +16 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree.tsx.ejs +2 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-xp-overview-tab.tsx.ejs +623 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson-xp-tab.tsx.ejs +1458 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +87 -46
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-panel.tsx.ejs +8 -3
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +31 -8
- package/hedhog/frontend/app/courses/[id]/structure/_components/drag-overlay.tsx.ejs +16 -9
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +618 -480
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +672 -737
- package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -2
- package/hedhog/frontend/app/courses/[id]/structure/_components/sortable-tree-row.tsx.ejs +3 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/store.ts.ejs +1 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-display-settings-popover.tsx.ejs +101 -85
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +24 -10
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row.tsx.ejs +3 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +1 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/use-tree-display-settings.ts.ejs +7 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/xp-premium-pills.tsx.ejs +44 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +6 -10
- package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +49 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +4 -3
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-content-overview.ts.ejs +53 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-exports.ts.ejs +106 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +80 -1
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-xp-overview.ts.ejs +76 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-lesson-xp-map.ts.ejs +128 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-lms-settings-query.ts.ejs +0 -2
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-transcription-segments.ts.ejs +30 -0
- package/hedhog/frontend/app/courses/[id]/structure/_utils/xp-color-config.ts.ejs +115 -0
- package/hedhog/frontend/app/courses/_components/CourseDeleteDialog.tsx.ejs +223 -0
- package/hedhog/frontend/app/courses/_components/CourseRowActions.tsx.ejs +89 -0
- package/hedhog/frontend/app/courses/page.tsx.ejs +445 -230
- package/hedhog/frontend/app/enterprise/page.tsx.ejs +39 -63
- package/hedhog/frontend/app/exams/[id]/questions/page.tsx.ejs +53 -77
- package/hedhog/frontend/app/exams/page.tsx.ejs +54 -90
- package/hedhog/frontend/app/instructor-skills/page.tsx.ejs +23 -36
- package/hedhog/frontend/app/instructors/page.tsx.ejs +72 -81
- package/hedhog/frontend/app/paths/page.tsx.ejs +40 -68
- package/hedhog/frontend/app/training/page.tsx.ejs +40 -68
- package/hedhog/frontend/app/xp/areas/page.tsx.ejs +782 -0
- package/hedhog/frontend/app/xp/learning-types/page.tsx.ejs +690 -0
- package/hedhog/frontend/app/xp/skills/page.tsx.ejs +811 -0
- package/hedhog/frontend/messages/en.json +412 -31
- package/hedhog/frontend/messages/pt.json +412 -31
- package/hedhog/table/course_export.yaml +62 -0
- package/hedhog/table/lesson_xp_map.yaml +50 -0
- package/hedhog/table/lesson_xp_segment.yaml +40 -0
- package/hedhog/table/lesson_xp_segment_area.yaml +24 -0
- package/hedhog/table/lesson_xp_segment_learning_type.yaml +24 -0
- package/hedhog/table/lesson_xp_segment_skill.yaml +24 -0
- package/hedhog/table/lms_bulk_upload_item.yaml +44 -0
- package/hedhog/table/lms_bulk_upload_session.yaml +42 -0
- package/hedhog/table/student_area_xp.yaml +30 -0
- package/hedhog/table/student_learning_type_xp.yaml +30 -0
- package/hedhog/table/student_skill_xp.yaml +30 -0
- package/hedhog/table/student_xp_event.yaml +34 -0
- package/hedhog/table/xp_area.yaml +39 -0
- package/hedhog/table/xp_learning_type.yaml +34 -0
- package/hedhog/table/xp_skill.yaml +39 -0
- package/package.json +13 -8
- package/src/bitcode-wallet/bitcode-wallet.service.ts +152 -0
- package/src/bitcode-wallet/dto/create-current-bitcode-wallet-transaction.dto.ts +32 -0
- package/src/course/course-audio-transcription.service.ts +58 -21
- package/src/course/course-export-scorm12-worker.service.ts +124 -0
- package/src/course/course-export-scorm12.service.ts +668 -0
- package/src/course/course-export.service.ts +280 -0
- package/src/course/course-lesson.controller.ts +6 -1
- package/src/course/course-structure.controller.ts +23 -1
- package/src/course/course-structure.service.ts +273 -7
- package/src/course/course-video-conversion.service.ts +113 -75
- package/src/course/course-video-hls.service.ts +946 -0
- package/src/course/course.controller.ts +54 -21
- package/src/course/course.mcp-tools.ts +1 -1
- package/src/course/course.module.ts +13 -0
- package/src/course/course.service.ts +906 -76
- package/src/course/dto/cleanup-course-storage.dto.ts +23 -0
- package/src/course/dto/cleanup-upload-history.dto.ts +26 -0
- package/src/course/dto/create-course-bulk-job.dto.ts +10 -0
- package/src/course/dto/create-course-export.dto.ts +56 -0
- package/src/course/dto/create-course-structure-lesson.dto.ts +4 -3
- package/src/course/lms-bulk-upload-automation.service.ts +707 -0
- package/src/course/lms-bulk-upload-infra.service.ts +360 -0
- package/src/course/lms-bulk-upload.constants.ts +5 -0
- package/src/course/lms-bulk-upload.controller.ts +110 -4
- package/src/course/lms-bulk-upload.service.ts +1092 -204
- package/src/course/lms-setting.controller.ts +26 -8
- package/src/course/scorm12-schemas.ts +9 -0
- package/src/enterprise/training/training-student.service.ts +221 -2
- package/src/evaluation/evaluation.service.ts +123 -0
- package/src/exam/dto/create-standalone-question.dto.ts +66 -0
- package/src/exam/exam.module.ts +2 -1
- package/src/exam/exam.service.ts +86 -0
- package/src/exam/question.controller.ts +28 -0
- package/src/lesson-xp-map/dto/create-lesson-xp-map.dto.ts +17 -0
- package/src/lesson-xp-map/dto/create-lesson-xp-segment.dto.ts +102 -0
- package/src/lesson-xp-map/dto/review-lesson-xp-map.dto.ts +7 -0
- package/src/lesson-xp-map/dto/update-lesson-xp-map.dto.ts +36 -0
- package/src/lesson-xp-map/dto/update-lesson-xp-segment.dto.ts +78 -0
- package/src/lesson-xp-map/lesson-xp-ai-calculation.service.ts +570 -0
- package/src/lesson-xp-map/lesson-xp-map.controller.ts +116 -0
- package/src/lesson-xp-map/lesson-xp-map.module.ts +21 -0
- package/src/lesson-xp-map/lesson-xp-map.service.ts +442 -0
- package/src/lesson-xp-map/lesson-xp-segment.controller.ts +36 -0
- package/src/lesson-xp-map/lesson-xp-segment.service.ts +229 -0
- package/src/lms-commerce-access.subscriber.ts +88 -0
- package/src/lms.module.ts +21 -5
- package/src/platforma/dto/update-profile.dto.ts +59 -0
- package/src/platforma/platforma-video.service.ts +346 -0
- package/src/platforma/platforma.controller.ts +152 -3
- package/src/platforma/platforma.service.ts +268 -0
- package/src/student-xp/dto/grant-skill-card-xp.dto.ts +10 -0
- package/src/student-xp/student-xp.controller.ts +92 -0
- package/src/student-xp/student-xp.module.ts +12 -0
- package/src/student-xp/student-xp.service.ts +318 -0
- package/src/xp-catalog/dto/create-xp-area.dto.ts +40 -0
- package/src/xp-catalog/dto/create-xp-learning-type.dto.ts +35 -0
- package/src/xp-catalog/dto/create-xp-skill.dto.ts +35 -0
- package/src/xp-catalog/dto/update-xp-area.dto.ts +43 -0
- package/src/xp-catalog/dto/update-xp-learning-type.dto.ts +38 -0
- package/src/xp-catalog/dto/update-xp-skill.dto.ts +38 -0
- package/src/xp-catalog/xp-area.controller.ts +64 -0
- package/src/xp-catalog/xp-area.service.ts +196 -0
- package/src/xp-catalog/xp-catalog.module.ts +16 -0
- package/src/xp-catalog/xp-learning-type.controller.ts +59 -0
- package/src/xp-catalog/xp-learning-type.service.ts +170 -0
- package/src/xp-catalog/xp-skill.controller.ts +71 -0
- package/src/xp-catalog/xp-skill.service.ts +205 -0
- package/hedhog/data/video_resolution_profile.yaml +0 -7
- package/hedhog/frontend/app/video-resolution-profiles/page.tsx.ejs +0 -607
- package/hedhog/table/course_video_resolution_profile.yaml +0 -22
- package/hedhog/table/video_resolution_profile.yaml +0 -18
- package/src/video-resolution-profile/dto/create-video-resolution-profile.dto.ts +0 -16
- package/src/video-resolution-profile/dto/update-video-resolution-profile.dto.ts +0 -16
- package/src/video-resolution-profile/video-resolution-profile.controller.ts +0 -62
- package/src/video-resolution-profile/video-resolution-profile.mcp-tools.ts +0 -128
- package/src/video-resolution-profile/video-resolution-profile.module.ts +0 -13
- package/src/video-resolution-profile/video-resolution-profile.service.ts +0 -117
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { PrismaService } from '@hed-hog/api-prisma';
|
|
2
2
|
import {
|
|
3
|
+
BadRequestException,
|
|
3
4
|
ConflictException,
|
|
4
5
|
Injectable,
|
|
5
6
|
NotFoundException,
|
|
6
7
|
} from '@nestjs/common';
|
|
8
|
+
import { CreateCurrentBitcodeWalletTransactionDto } from './dto/create-current-bitcode-wallet-transaction.dto';
|
|
7
9
|
import { CreateBitcodeWalletTransactionDto } from './dto/create-bitcode-wallet-transaction.dto';
|
|
8
10
|
import { CreateBitcodeWalletDto } from './dto/create-bitcode-wallet.dto';
|
|
9
11
|
import { UpdateBitcodeWalletDto } from './dto/update-bitcode-wallet.dto';
|
|
@@ -220,6 +222,46 @@ export class BitcodeWalletService {
|
|
|
220
222
|
return this.getById(created.id);
|
|
221
223
|
}
|
|
222
224
|
|
|
225
|
+
async getCurrentUserWallet(userId: number) {
|
|
226
|
+
const personId = await this.resolveOrCreatePersonForUser(userId);
|
|
227
|
+
return this.getOrCreateWalletByPersonId(personId);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async creditCurrentUserWallet(
|
|
231
|
+
userId: number,
|
|
232
|
+
dto: CreateCurrentBitcodeWalletTransactionDto
|
|
233
|
+
) {
|
|
234
|
+
return this.createCurrentUserTransaction(userId, {
|
|
235
|
+
...dto,
|
|
236
|
+
type: 'credit',
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async createCurrentUserTransaction(
|
|
241
|
+
userId: number,
|
|
242
|
+
dto: CreateCurrentBitcodeWalletTransactionDto
|
|
243
|
+
) {
|
|
244
|
+
const amount = Math.trunc(Number(dto.amount));
|
|
245
|
+
const type = dto.type ?? 'credit';
|
|
246
|
+
|
|
247
|
+
if (!Number.isFinite(amount) || amount < 1) {
|
|
248
|
+
throw new BadRequestException('BitCode transaction amount must be positive');
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const personId = await this.resolvePersonIdFromUser(userId);
|
|
252
|
+
const wallet = await this.getOrCreateWalletByPersonId(personId);
|
|
253
|
+
|
|
254
|
+
if (type === 'debit' && Number(wallet.currentBalance ?? 0) < amount) {
|
|
255
|
+
throw new BadRequestException('Insufficient BitCode balance');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return this.createTransaction(wallet.id, {
|
|
259
|
+
type,
|
|
260
|
+
amount,
|
|
261
|
+
description: this.buildCurrentTransactionDescription(dto, type),
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
223
265
|
async update(id: number, dto: UpdateBitcodeWalletDto) {
|
|
224
266
|
await this.ensureWalletExists(id);
|
|
225
267
|
|
|
@@ -287,6 +329,96 @@ export class BitcodeWalletService {
|
|
|
287
329
|
}
|
|
288
330
|
}
|
|
289
331
|
|
|
332
|
+
private async resolvePersonIdFromUser(userId: number) {
|
|
333
|
+
const row = await this.querySingle<{ personId: number }>(
|
|
334
|
+
`SELECT person_id AS "personId" FROM person_user WHERE user_id = $1 LIMIT 1`,
|
|
335
|
+
[userId]
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
if (!row) {
|
|
339
|
+
throw new NotFoundException('No person profile found for this user');
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return Number(row.personId);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
private async resolveOrCreatePersonForUser(userId: number): Promise<number> {
|
|
346
|
+
const existing = await this.querySingle<{ personId: number }>(
|
|
347
|
+
`SELECT person_id AS "personId" FROM person_user WHERE user_id = $1 LIMIT 1`,
|
|
348
|
+
[userId]
|
|
349
|
+
);
|
|
350
|
+
if (existing) return Number(existing.personId);
|
|
351
|
+
|
|
352
|
+
// Gather name: prefer commerce_customer (richer), fall back to user record
|
|
353
|
+
const customerRow = await this.querySingle<{ name: string }>(
|
|
354
|
+
`SELECT name FROM commerce_customer
|
|
355
|
+
WHERE user_id = $1 AND deleted_at IS NULL
|
|
356
|
+
ORDER BY id DESC LIMIT 1`,
|
|
357
|
+
[userId]
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
const userRow = await this.querySingle<{ name: string }>(
|
|
361
|
+
`SELECT name FROM "user" WHERE id = $1`,
|
|
362
|
+
[userId]
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
const personName = customerRow?.name || userRow?.name || `Usuário #${userId}`;
|
|
366
|
+
|
|
367
|
+
const person = await this.querySingle<{ id: number }>(
|
|
368
|
+
`INSERT INTO person (name, type, status, created_at, updated_at)
|
|
369
|
+
VALUES ($1, 'individual'::person_type_6dfa750c4d_enum, 'active'::person_status_7efb97d61c_enum, NOW(), NOW())
|
|
370
|
+
RETURNING id`,
|
|
371
|
+
[personName]
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
if (!person) throw new Error('Failed to create person profile');
|
|
375
|
+
|
|
376
|
+
await this.querySingle(
|
|
377
|
+
`INSERT INTO person_user (person_id, user_id, created_at, updated_at)
|
|
378
|
+
VALUES ($1, $2, NOW(), NOW())
|
|
379
|
+
ON CONFLICT DO NOTHING`,
|
|
380
|
+
[person.id, userId]
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
return person.id;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
private async findWalletByPersonId(personId: number) {
|
|
387
|
+
return this.querySingle<{ id: number }>(
|
|
388
|
+
`SELECT id FROM bitcode_wallet WHERE person_id = $1`,
|
|
389
|
+
[personId]
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
private async getOrCreateWalletByPersonId(personId: number) {
|
|
394
|
+
await this.ensurePersonExists(personId);
|
|
395
|
+
|
|
396
|
+
const created = await this.querySingle<{ id: number }>(
|
|
397
|
+
`INSERT INTO bitcode_wallet (
|
|
398
|
+
person_id,
|
|
399
|
+
current_balance,
|
|
400
|
+
created_at,
|
|
401
|
+
updated_at
|
|
402
|
+
) VALUES (
|
|
403
|
+
$1,
|
|
404
|
+
0,
|
|
405
|
+
NOW(),
|
|
406
|
+
NOW()
|
|
407
|
+
)
|
|
408
|
+
ON CONFLICT (person_id) DO NOTHING
|
|
409
|
+
RETURNING id`,
|
|
410
|
+
[personId]
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
const wallet = created ?? (await this.findWalletByPersonId(personId));
|
|
414
|
+
|
|
415
|
+
if (!wallet) {
|
|
416
|
+
throw new NotFoundException('BitCode wallet not found');
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return this.getById(wallet.id);
|
|
420
|
+
}
|
|
421
|
+
|
|
290
422
|
private async ensureWalletExists(id: number) {
|
|
291
423
|
const row = await this.querySingle<{ id: number }>(
|
|
292
424
|
`SELECT id FROM bitcode_wallet WHERE id = $1`,
|
|
@@ -345,6 +477,26 @@ export class BitcodeWalletService {
|
|
|
345
477
|
return normalized ? normalized : null;
|
|
346
478
|
}
|
|
347
479
|
|
|
480
|
+
private buildCurrentTransactionDescription(
|
|
481
|
+
dto: CreateCurrentBitcodeWalletTransactionDto,
|
|
482
|
+
type: 'credit' | 'debit'
|
|
483
|
+
) {
|
|
484
|
+
const description = this.normalizeOptionalText(dto.description);
|
|
485
|
+
const source = this.normalizeOptionalText(dto.source);
|
|
486
|
+
const fallback = type === 'debit' ? 'Class debit' : 'Class reward';
|
|
487
|
+
|
|
488
|
+
if (description && source) {
|
|
489
|
+
return description.toLowerCase().includes(source.toLowerCase())
|
|
490
|
+
? description
|
|
491
|
+
: `${description} - ${source}`;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (description) return description;
|
|
495
|
+
if (source) return `${fallback}: ${source}`;
|
|
496
|
+
|
|
497
|
+
return fallback;
|
|
498
|
+
}
|
|
499
|
+
|
|
348
500
|
private param(values: unknown[], value: unknown) {
|
|
349
501
|
values.push(value);
|
|
350
502
|
return `$${values.length}`;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IsEnum,
|
|
3
|
+
IsInt,
|
|
4
|
+
IsOptional,
|
|
5
|
+
IsString,
|
|
6
|
+
MaxLength,
|
|
7
|
+
Min,
|
|
8
|
+
} from 'class-validator';
|
|
9
|
+
import {
|
|
10
|
+
BITCODE_TRANSACTION_TYPE_VALUES,
|
|
11
|
+
type BitcodeTransactionType,
|
|
12
|
+
} from './create-bitcode-wallet-transaction.dto';
|
|
13
|
+
|
|
14
|
+
export class CreateCurrentBitcodeWalletTransactionDto {
|
|
15
|
+
@IsOptional()
|
|
16
|
+
@IsEnum(BITCODE_TRANSACTION_TYPE_VALUES)
|
|
17
|
+
type?: BitcodeTransactionType;
|
|
18
|
+
|
|
19
|
+
@IsInt()
|
|
20
|
+
@Min(1)
|
|
21
|
+
amount: number;
|
|
22
|
+
|
|
23
|
+
@IsOptional()
|
|
24
|
+
@IsString()
|
|
25
|
+
@MaxLength(2000)
|
|
26
|
+
description?: string | null;
|
|
27
|
+
|
|
28
|
+
@IsOptional()
|
|
29
|
+
@IsString()
|
|
30
|
+
@MaxLength(200)
|
|
31
|
+
source?: string | null;
|
|
32
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PrismaService } from '@hed-hog/api-prisma';
|
|
2
2
|
import { buildAiConfigFromIntegration, FileService, NotificationService, SettingService } from '@hed-hog/core';
|
|
3
|
-
import { IJobHandler, QueueHandlerRegistry } from '@hed-hog/queue';
|
|
3
|
+
import { DatabaseQueueProvider, IJobHandler, NonRetryableError, QueueHandlerRegistry } from '@hed-hog/queue';
|
|
4
4
|
import {
|
|
5
5
|
Inject,
|
|
6
6
|
Injectable,
|
|
@@ -102,6 +102,8 @@ export class CourseAudioTranscriptionService implements OnModuleInit, IJobHandle
|
|
|
102
102
|
private readonly notificationService: NotificationService,
|
|
103
103
|
@Inject(forwardRef(() => QueueHandlerRegistry))
|
|
104
104
|
private readonly registry: QueueHandlerRegistry,
|
|
105
|
+
@Inject(forwardRef(() => DatabaseQueueProvider))
|
|
106
|
+
private readonly dbQueue: DatabaseQueueProvider,
|
|
105
107
|
) {}
|
|
106
108
|
|
|
107
109
|
onModuleInit() {
|
|
@@ -159,18 +161,11 @@ export class CourseAudioTranscriptionService implements OnModuleInit, IJobHandle
|
|
|
159
161
|
const transcriptionEnabled = settings['lms-audio-transcription-enabled'] !== false;
|
|
160
162
|
|
|
161
163
|
if (!transcriptionEnabled) {
|
|
162
|
-
|
|
163
|
-
`Transcription skipped for lesson ${lessonId}: disabled by lms-audio-transcription-enabled setting`,
|
|
164
|
-
);
|
|
164
|
+
const msg = `Transcrição desabilitada nas configurações do LMS (lms-audio-transcription-enabled=false).`;
|
|
165
165
|
if (notificationContext) {
|
|
166
|
-
await this.updateAsyncNotification(
|
|
167
|
-
notificationContext,
|
|
168
|
-
100,
|
|
169
|
-
'Transcrição desabilitada nas configurações do LMS.',
|
|
170
|
-
false,
|
|
171
|
-
);
|
|
166
|
+
await this.updateAsyncNotification(notificationContext, 100, msg, false);
|
|
172
167
|
}
|
|
173
|
-
|
|
168
|
+
throw new NonRetryableError(msg);
|
|
174
169
|
}
|
|
175
170
|
|
|
176
171
|
const profileId = Number(settings['ai-openai-profile-id']);
|
|
@@ -190,18 +185,14 @@ export class CourseAudioTranscriptionService implements OnModuleInit, IJobHandle
|
|
|
190
185
|
}
|
|
191
186
|
|
|
192
187
|
if (!apiKey) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
188
|
+
const profileIdValue = settings['ai-openai-profile-id'];
|
|
189
|
+
const msg = profileIdValue
|
|
190
|
+
? `Perfil de IA (id=${profileIdValue}) não encontrado ou não possui chave de API OpenAI configurada. Verifique em Settings → Integrações → Profiles.`
|
|
191
|
+
: `Transcrição de áudio requer um perfil OpenAI configurado.\n\nComo configurar:\n1. Acesse Settings → Integrações → Profiles\n2. Crie um perfil do tipo OpenAI com sua API Key\n3. Copie o ID do perfil criado\n4. Acesse Settings → LMS e defina o campo \'ai-openai-profile-id\' com esse ID`;
|
|
196
192
|
if (notificationContext) {
|
|
197
|
-
await this.updateAsyncNotification(
|
|
198
|
-
notificationContext,
|
|
199
|
-
100,
|
|
200
|
-
'Transcrição não iniciada: perfil de IA não configurado em Settings → AI.',
|
|
201
|
-
false,
|
|
202
|
-
);
|
|
193
|
+
await this.updateAsyncNotification(notificationContext, 100, msg, false);
|
|
203
194
|
}
|
|
204
|
-
|
|
195
|
+
throw new NonRetryableError(msg);
|
|
205
196
|
}
|
|
206
197
|
|
|
207
198
|
const course = await (this.prismaService as any).course.findUnique({
|
|
@@ -369,6 +360,52 @@ export class CourseAudioTranscriptionService implements OnModuleInit, IJobHandle
|
|
|
369
360
|
this.logger.log(
|
|
370
361
|
`Transcription saved for lesson ${lessonId}: ${allSegments.length} segments`,
|
|
371
362
|
);
|
|
363
|
+
|
|
364
|
+
// Automatically trigger XP calculation after transcription completes.
|
|
365
|
+
try {
|
|
366
|
+
const existingMap = await (this.prismaService as any).lesson_xp_map.findUnique({
|
|
367
|
+
where: { course_lesson_id: lessonId },
|
|
368
|
+
select: { id: true },
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
let mapId: number;
|
|
372
|
+
if (existingMap) {
|
|
373
|
+
mapId = existingMap.id;
|
|
374
|
+
await this.prismaService.$executeRawUnsafe(
|
|
375
|
+
`UPDATE lesson_xp_map
|
|
376
|
+
SET status = 'processing'::lesson_xp_map_status_d4e5f6a7b8_enum,
|
|
377
|
+
processing_error = NULL,
|
|
378
|
+
updated_at = NOW()
|
|
379
|
+
WHERE id = $1`,
|
|
380
|
+
mapId,
|
|
381
|
+
);
|
|
382
|
+
} else {
|
|
383
|
+
const rows = await this.prismaService.$queryRawUnsafe<{ id: number }[]>(
|
|
384
|
+
`INSERT INTO lesson_xp_map (course_lesson_id, version, total_xp, status, created_at, updated_at)
|
|
385
|
+
VALUES ($1, 1, 0, 'processing'::lesson_xp_map_status_d4e5f6a7b8_enum, NOW(), NOW())
|
|
386
|
+
RETURNING id`,
|
|
387
|
+
lessonId,
|
|
388
|
+
);
|
|
389
|
+
mapId = rows[0].id;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
await this.dbQueue.enqueue({
|
|
393
|
+
type: 'lms.lesson.xp.calculate',
|
|
394
|
+
queueName: 'lms.lesson.xp.calculate',
|
|
395
|
+
payload: { lessonId, mapId, userId: notificationUserId ?? 0 },
|
|
396
|
+
maxAttempts: 3,
|
|
397
|
+
sourceModule: 'lms',
|
|
398
|
+
sourceEntity: 'course_lesson',
|
|
399
|
+
sourceEntityId: String(lessonId),
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
this.logger.log(`XP calculation job enqueued for lesson ${lessonId} (map ${mapId})`);
|
|
403
|
+
} catch (xpErr) {
|
|
404
|
+
this.logger.warn(
|
|
405
|
+
`Failed to enqueue XP calculation for lesson ${lessonId}: ${xpErr instanceof Error ? xpErr.message : String(xpErr)}`,
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
|
|
372
409
|
await emitProgress(
|
|
373
410
|
`Transcrição concluída com ${allSegments.length} segmento(s).`,
|
|
374
411
|
{
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { FileService, NotificationService } from '@hed-hog/core';
|
|
2
|
+
import { IJobHandler, QueueHandlerRegistry } from '@hed-hog/queue';
|
|
3
|
+
import {
|
|
4
|
+
Inject,
|
|
5
|
+
Injectable,
|
|
6
|
+
Logger,
|
|
7
|
+
OnModuleInit,
|
|
8
|
+
forwardRef,
|
|
9
|
+
} from '@nestjs/common';
|
|
10
|
+
import { promises as fs } from 'fs';
|
|
11
|
+
import { tmpdir } from 'os';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { CourseExportScorm12Service } from './course-export-scorm12.service';
|
|
14
|
+
import { CourseExportService, LMS_COURSE_EXPORT_SCORM12_JOB } from './course-export.service';
|
|
15
|
+
|
|
16
|
+
@Injectable()
|
|
17
|
+
export class CourseExportScorm12WorkerService implements OnModuleInit, IJobHandler {
|
|
18
|
+
private readonly logger = new Logger(CourseExportScorm12WorkerService.name);
|
|
19
|
+
|
|
20
|
+
constructor(
|
|
21
|
+
@Inject(forwardRef(() => FileService))
|
|
22
|
+
private readonly fileService: FileService,
|
|
23
|
+
@Inject(forwardRef(() => NotificationService))
|
|
24
|
+
private readonly notificationService: NotificationService,
|
|
25
|
+
@Inject(forwardRef(() => QueueHandlerRegistry))
|
|
26
|
+
private readonly registry: QueueHandlerRegistry,
|
|
27
|
+
private readonly courseExportService: CourseExportService,
|
|
28
|
+
private readonly scorm12Builder: CourseExportScorm12Service,
|
|
29
|
+
) {}
|
|
30
|
+
|
|
31
|
+
onModuleInit() {
|
|
32
|
+
this.registry.register(LMS_COURSE_EXPORT_SCORM12_JOB, this);
|
|
33
|
+
this.logger.log(`Registered handler for job type: ${LMS_COURSE_EXPORT_SCORM12_JOB}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async handle(job: {
|
|
37
|
+
id: number;
|
|
38
|
+
type: string;
|
|
39
|
+
payload: Record<string, any>;
|
|
40
|
+
}): Promise<void> {
|
|
41
|
+
const { exportId, courseId, userId, notificationId, settings } =
|
|
42
|
+
job.payload as {
|
|
43
|
+
exportId: number;
|
|
44
|
+
courseId: number;
|
|
45
|
+
userId: number;
|
|
46
|
+
notificationId: number;
|
|
47
|
+
settings: Record<string, any>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const startedAt = Date.now();
|
|
51
|
+
const workDir = await fs.mkdtemp(join(tmpdir(), `scorm-${job.id}-`));
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
this.logger.log(`Starting SCORM 1.2 export ${exportId} for course ${courseId}`);
|
|
55
|
+
await this.courseExportService.markStarted(exportId);
|
|
56
|
+
await this.notificationService.updateProgress(userId, notificationId, {
|
|
57
|
+
progress: 5,
|
|
58
|
+
body: 'Iniciando exportação SCORM 1.2...',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const { zipPath, filename } = await this.scorm12Builder.buildPackage({
|
|
62
|
+
courseId,
|
|
63
|
+
settings,
|
|
64
|
+
workDir,
|
|
65
|
+
onProgress: async (pct, msg) => {
|
|
66
|
+
await this.notificationService.updateProgress(userId, notificationId, {
|
|
67
|
+
progress: pct,
|
|
68
|
+
body: msg,
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
await this.notificationService.updateProgress(userId, notificationId, {
|
|
74
|
+
progress: 90,
|
|
75
|
+
body: 'Fazendo upload do pacote SCORM...',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const stat = await fs.stat(zipPath);
|
|
79
|
+
const uploadedFile = await this.fileService.uploadFromPath(
|
|
80
|
+
'course-exports',
|
|
81
|
+
zipPath,
|
|
82
|
+
{
|
|
83
|
+
originalname: filename,
|
|
84
|
+
mimetype: 'application/zip',
|
|
85
|
+
size: stat.size,
|
|
86
|
+
},
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const durationSeconds = Math.round((Date.now() - startedAt) / 1000);
|
|
90
|
+
await this.courseExportService.markCompleted(
|
|
91
|
+
exportId,
|
|
92
|
+
uploadedFile.id,
|
|
93
|
+
durationSeconds,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
await this.notificationService.updateProgress(userId, notificationId, {
|
|
97
|
+
progress: 100,
|
|
98
|
+
body: `Exportação SCORM 1.2 concluída em ${durationSeconds}s!`,
|
|
99
|
+
success: true,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
this.logger.log(
|
|
103
|
+
`SCORM 1.2 export ${exportId} completed in ${durationSeconds}s, file id=${uploadedFile.id}`,
|
|
104
|
+
);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
const msg =
|
|
107
|
+
err instanceof Error ? err.message : 'Erro desconhecido na exportação.';
|
|
108
|
+
this.logger.error(`SCORM 1.2 export ${exportId} failed: ${msg}`, err instanceof Error ? err.stack : undefined);
|
|
109
|
+
|
|
110
|
+
await this.courseExportService.markFailed(exportId, msg).catch(() => undefined);
|
|
111
|
+
await this.notificationService
|
|
112
|
+
.updateProgress(userId, notificationId, {
|
|
113
|
+
progress: 100,
|
|
114
|
+
body: `Falha na exportação: ${msg}`,
|
|
115
|
+
success: false,
|
|
116
|
+
})
|
|
117
|
+
.catch(() => undefined);
|
|
118
|
+
|
|
119
|
+
throw err;
|
|
120
|
+
} finally {
|
|
121
|
+
await fs.rm(workDir, { recursive: true, force: true }).catch(() => undefined);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|