@hed-hog/lms 0.0.364 → 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 +1 -0
- package/dist/bitcode-wallet/bitcode-wallet.service.d.ts.map +1 -1
- package/dist/bitcode-wallet/bitcode-wallet.service.js +22 -3
- package/dist/bitcode-wallet/bitcode-wallet.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-structure.controller.d.ts +17 -9
- package/dist/course/course-structure.controller.d.ts.map +1 -1
- package/dist/course/course-structure.controller.js +17 -4
- package/dist/course/course-structure.controller.js.map +1 -1
- package/dist/course/course-structure.service.d.ts +12 -4
- package/dist/course/course-structure.service.d.ts.map +1 -1
- package/dist/course/course-structure.service.js +98 -23
- package/dist/course/course-structure.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 +45 -13
- package/dist/course/course.controller.d.ts.map +1 -1
- package/dist/course/course.controller.js +40 -26
- 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 +11 -0
- package/dist/course/course.module.js.map +1 -1
- package/dist/course/course.service.d.ts +6 -9
- package/dist/course/course.service.d.ts.map +1 -1
- package/dist/course/course.service.js +57 -48
- package/dist/course/course.service.js.map +1 -1
- package/dist/course/dto/cleanup-course-storage.dto.d.ts +1 -1
- package/dist/course/dto/cleanup-course-storage.dto.d.ts.map +1 -1
- package/dist/course/dto/cleanup-course-storage.dto.js +1 -0
- package/dist/course/dto/cleanup-course-storage.dto.js.map +1 -1
- package/dist/course/dto/cleanup-upload-history.dto.d.ts +1 -1
- package/dist/course/dto/cleanup-upload-history.dto.d.ts.map +1 -1
- package/dist/course/dto/cleanup-upload-history.dto.js +1 -1
- package/dist/course/dto/cleanup-upload-history.dto.js.map +1 -1
- package/dist/course/dto/create-course-bulk-job.dto.d.ts +2 -1
- package/dist/course/dto/create-course-bulk-job.dto.d.ts.map +1 -1
- package/dist/course/dto/create-course-bulk-job.dto.js +6 -1
- package/dist/course/dto/create-course-bulk-job.dto.js.map +1 -1
- 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 +16 -1
- package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload-automation.service.js +102 -8
- package/dist/course/lms-bulk-upload-automation.service.js.map +1 -1
- package/dist/course/lms-bulk-upload-infra.service.d.ts +1 -0
- package/dist/course/lms-bulk-upload-infra.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload-infra.service.js +32 -8
- package/dist/course/lms-bulk-upload-infra.service.js.map +1 -1
- package/dist/course/lms-bulk-upload.controller.d.ts +30 -3
- package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.controller.js +43 -2
- package/dist/course/lms-bulk-upload.controller.js.map +1 -1
- package/dist/course/lms-bulk-upload.service.d.ts +11 -0
- package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.service.js +59 -6
- package/dist/course/lms-bulk-upload.service.js.map +1 -1
- package/dist/course/lms-setting.controller.d.ts +2 -1
- package/dist/course/lms-setting.controller.d.ts.map +1 -1
- package/dist/course/lms-setting.controller.js +4 -2
- 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/training/training-student.service.d.ts +51 -0
- 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/evaluation/evaluation.service.d.ts +18 -0
- 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/lesson-xp-ai-calculation.service.d.ts +4 -0
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts.map +1 -1
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js +161 -25
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -1
- package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -1
- 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 +6 -5
- package/dist/lms.module.js.map +1 -1
- 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 +95 -1
- package/dist/platforma/platforma.controller.d.ts.map +1 -1
- package/dist/platforma/platforma.controller.js +160 -2
- package/dist/platforma/platforma.controller.js.map +1 -1
- 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 +15 -0
- package/dist/student-xp/student-xp.controller.d.ts.map +1 -1
- package/dist/student-xp/student-xp.controller.js +24 -0
- package/dist/student-xp/student-xp.controller.js.map +1 -1
- package/dist/student-xp/student-xp.service.d.ts +16 -0
- package/dist/student-xp/student-xp.service.d.ts.map +1 -1
- package/dist/student-xp/student-xp.service.js +51 -1
- package/dist/student-xp/student-xp.service.js.map +1 -1
- package/hedhog/data/evaluation_topic.yaml +17 -0
- package/hedhog/data/menu.yaml +0 -17
- package/hedhog/data/queue_definition.yaml +48 -0
- package/hedhog/data/route.yaml +94 -124
- package/hedhog/data/setting_group.yaml +19 -19
- package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +337 -41
- package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +69 -4
- 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-overview-tab.tsx.ejs +17 -15
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +51 -63
- 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 +201 -401
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +378 -690
- package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -2
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +3 -9
- package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +1 -1
- 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 +0 -1
- 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 +28 -1
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-lms-settings-query.ts.ejs +0 -2
- package/hedhog/frontend/app/courses/page.tsx.ejs +45 -0
- package/hedhog/frontend/messages/en.json +26 -28
- package/hedhog/frontend/messages/pt.json +26 -28
- package/hedhog/table/course_export.yaml +62 -0
- package/package.json +13 -9
- package/src/bitcode-wallet/bitcode-wallet.service.ts +43 -4
- 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-structure.controller.ts +14 -2
- package/src/course/course-structure.service.ts +100 -7
- package/src/course/course-video-hls.service.ts +946 -0
- package/src/course/course.controller.ts +33 -19
- package/src/course/course.mcp-tools.ts +1 -1
- package/src/course/course.module.ts +11 -0
- package/src/course/course.service.ts +73 -60
- package/src/course/dto/cleanup-course-storage.dto.ts +1 -0
- package/src/course/dto/cleanup-upload-history.dto.ts +1 -1
- package/src/course/dto/create-course-bulk-job.dto.ts +7 -3
- 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 +153 -6
- package/src/course/lms-bulk-upload-infra.service.ts +39 -6
- package/src/course/lms-bulk-upload.controller.ts +32 -2
- package/src/course/lms-bulk-upload.service.ts +70 -7
- package/src/course/lms-setting.controller.ts +4 -2
- 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/lesson-xp-ai-calculation.service.ts +205 -31
- package/src/lms-commerce-access.subscriber.ts +88 -0
- package/src/lms.module.ts +6 -5
- package/src/platforma/platforma-video.service.ts +346 -0
- package/src/platforma/platforma.controller.ts +95 -1
- package/src/platforma/platforma.service.ts +268 -268
- package/src/student-xp/dto/grant-skill-card-xp.dto.ts +10 -0
- package/src/student-xp/student-xp.controller.ts +18 -2
- package/src/student-xp/student-xp.service.ts +84 -2
- 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
|
@@ -588,6 +588,8 @@
|
|
|
588
588
|
"statusProgress": "{completed}/{total} itens obrigatórios concluídos",
|
|
589
589
|
"ready": "Pronto para publicar",
|
|
590
590
|
"notReady": "Ainda não pronto",
|
|
591
|
+
"publishButton": "Publicar curso",
|
|
592
|
+
"alreadyPublished": "Curso já publicado",
|
|
591
593
|
"items": {
|
|
592
594
|
"title": "Título comercial preenchido",
|
|
593
595
|
"description": "Descrição pública preenchida",
|
|
@@ -1206,36 +1208,32 @@
|
|
|
1206
1208
|
},
|
|
1207
1209
|
"addResource": "Adicionar recurso",
|
|
1208
1210
|
"noResources": "Nenhum recurso adicionado",
|
|
1209
|
-
"
|
|
1210
|
-
"
|
|
1211
|
-
"
|
|
1212
|
-
"
|
|
1213
|
-
"loadingVideoProfiles": "Carregando perfis de vídeo do curso...",
|
|
1214
|
-
"videoProfilesLoadError": "Não foi possível carregar os perfis de vídeo do curso.",
|
|
1215
|
-
"retryLoadVideoProfiles": "Tentar carregar novamente",
|
|
1216
|
-
"noVideoProfilesConfigured": "Configure os perfis de vídeo na aba Resoluções do curso antes de anexar vídeos File Storage.",
|
|
1211
|
+
"hlsStatusTitle": "Streaming HLS",
|
|
1212
|
+
"hlsStatusReady": "Streaming disponível para os alunos.",
|
|
1213
|
+
"hlsStatusProcessing": "Processando vídeo...",
|
|
1214
|
+
"hlsStatusPending": "Nenhum vídeo processado ainda.",
|
|
1217
1215
|
"originalVideoTitle": "Vídeo original em alta resolução",
|
|
1218
|
-
"originalVideoHint": "Envie um original para gerar automaticamente
|
|
1219
|
-
"originalVideoPurpose": "Este arquivo original é usado apenas para gerar
|
|
1220
|
-
"fileStorageVideoHint": "Use o vídeo original abaixo para gerar automaticamente
|
|
1221
|
-
"uploadOriginalForConversion": "Enviar
|
|
1216
|
+
"originalVideoHint": "Envie um original para gerar automaticamente o streaming HLS do curso.",
|
|
1217
|
+
"originalVideoPurpose": "Este arquivo original é usado apenas para gerar o streaming adaptativo do curso.",
|
|
1218
|
+
"fileStorageVideoHint": "Use o vídeo original abaixo para gerar automaticamente o streaming HLS do curso.",
|
|
1219
|
+
"uploadOriginalForConversion": "Enviar vídeo para processamento",
|
|
1222
1220
|
"replaceOriginalForConversion": "Substituir vídeo original",
|
|
1223
1221
|
"retryConversionWithSavedOriginal": "Iniciar novo job com o original salvo",
|
|
1224
|
-
"videoUploadBlockedWhileProcessing": "O upload de original fica bloqueado enquanto
|
|
1222
|
+
"videoUploadBlockedWhileProcessing": "O upload de original fica bloqueado enquanto o processamento atual estiver em andamento.",
|
|
1225
1223
|
"videoJobStateLoading": "Aguardando o status mais recente do job atual para liberar novas ações.",
|
|
1226
1224
|
"videoProviderSavePending": "Aguarde o provedor ser salvo antes de enviar o vídeo original.",
|
|
1227
1225
|
"videoUploadMaxSizeError": "O vídeo excede o limite de {size}.",
|
|
1228
|
-
"videoConversionQueued": "
|
|
1229
|
-
"videoConversionFailed": "Não foi possível enviar o vídeo para
|
|
1226
|
+
"videoConversionQueued": "Processamento de vídeo enviado para a fila #{id}.",
|
|
1227
|
+
"videoConversionFailed": "Não foi possível enviar o vídeo para processamento.",
|
|
1230
1228
|
"videoConversionRetryFailed": "Não foi possível iniciar um novo job com o vídeo original salvo.",
|
|
1231
|
-
"videoConversionJob": "
|
|
1232
|
-
"videoJobFeedbackTitle": "Acompanhamento
|
|
1233
|
-
"videoJobToggleDetails": "Alternar detalhes
|
|
1234
|
-
"videoJobCollapsedSummary": "
|
|
1235
|
-
"videoJobLoading": "Carregando andamento
|
|
1236
|
-
"videoJobPendingLoad": "Preparando acompanhamento do
|
|
1237
|
-
"awaitingConversion": "Aguardando
|
|
1238
|
-
"videoJobLoadError": "Não foi possível carregar o andamento
|
|
1229
|
+
"videoConversionJob": "Processamento na fila #{id}",
|
|
1230
|
+
"videoJobFeedbackTitle": "Acompanhamento do processamento",
|
|
1231
|
+
"videoJobToggleDetails": "Alternar detalhes do processamento",
|
|
1232
|
+
"videoJobCollapsedSummary": "Processamento concluído com sucesso. O streaming HLS está disponível para os alunos.",
|
|
1233
|
+
"videoJobLoading": "Carregando andamento do processamento...",
|
|
1234
|
+
"videoJobPendingLoad": "Preparando acompanhamento do processamento...",
|
|
1235
|
+
"awaitingConversion": "Aguardando processamento...",
|
|
1236
|
+
"videoJobLoadError": "Não foi possível carregar o andamento do processamento.",
|
|
1239
1237
|
"retryLoadVideoJob": "Tentar novamente",
|
|
1240
1238
|
"videoJobIdLabel": "Job",
|
|
1241
1239
|
"videoJobAttemptsLabel": "Tentativas",
|
|
@@ -1251,7 +1249,6 @@
|
|
|
1251
1249
|
"videoJobRecentEvents": "Eventos recentes",
|
|
1252
1250
|
"videoJobTranscriptionEvents": "Eventos recentes da transcrição",
|
|
1253
1251
|
"videoJobNoEvents": "Nenhum evento registrado ainda.",
|
|
1254
|
-
"videoProfilesLockedWhileProcessing": "Os vídeos por perfil ficam bloqueados enquanto a conversão do original está ativa.",
|
|
1255
1252
|
"videoJobStatuses": {
|
|
1256
1253
|
"pending": "Na fila",
|
|
1257
1254
|
"scheduled": "Agendado",
|
|
@@ -1283,8 +1280,9 @@
|
|
|
1283
1280
|
},
|
|
1284
1281
|
"videoJobProgress": {
|
|
1285
1282
|
"download_original": "Baixando vídeo original...",
|
|
1286
|
-
"probe_duration": "Lendo duração do vídeo...",
|
|
1287
|
-
"
|
|
1283
|
+
"probe_duration": "Lendo dimensões e duração do vídeo...",
|
|
1284
|
+
"hls_encode": "Gerando streaming HLS...",
|
|
1285
|
+
"hls_upload": "Enviando segmentos HLS para storage...",
|
|
1288
1286
|
"extract_frames": "Extraindo imagens do vídeo...",
|
|
1289
1287
|
"extract_frames_done": "Imagens extraídas: {count}.",
|
|
1290
1288
|
"extract_audio": "Extraindo áudio do vídeo...",
|
|
@@ -1351,8 +1349,7 @@
|
|
|
1351
1349
|
"types": {
|
|
1352
1350
|
"video": "Vídeo",
|
|
1353
1351
|
"post": "Post",
|
|
1354
|
-
"questao": "Questão"
|
|
1355
|
-
"exercicio": "Exercício"
|
|
1352
|
+
"questao": "Questão"
|
|
1356
1353
|
},
|
|
1357
1354
|
"statuses": {
|
|
1358
1355
|
"preparada": "Preparada",
|
|
@@ -1391,6 +1388,7 @@
|
|
|
1391
1388
|
"videoUploadFailed": "Falha ao enviar {count} arquivo(s) de vídeo.",
|
|
1392
1389
|
"newQuestion": "Nova questão",
|
|
1393
1390
|
"editQuestion": "Editar questão",
|
|
1391
|
+
"loadingQuestions": "Carregando questões...",
|
|
1394
1392
|
"selectQuestion": "Selecionar questão...",
|
|
1395
1393
|
"searchQuestion": "Buscar questão...",
|
|
1396
1394
|
"noQuestionsFound": "Nenhuma questão encontrada",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
columns:
|
|
2
|
+
- type: pk
|
|
3
|
+
- name: course_id
|
|
4
|
+
type: fk
|
|
5
|
+
references:
|
|
6
|
+
table: course
|
|
7
|
+
column: id
|
|
8
|
+
onDelete: CASCADE
|
|
9
|
+
- name: user_id
|
|
10
|
+
type: fk
|
|
11
|
+
references:
|
|
12
|
+
table: user
|
|
13
|
+
column: id
|
|
14
|
+
onDelete: CASCADE
|
|
15
|
+
- name: format
|
|
16
|
+
type: varchar
|
|
17
|
+
length: 32
|
|
18
|
+
- name: status
|
|
19
|
+
type: enum
|
|
20
|
+
values: [pending, processing, completed, failed]
|
|
21
|
+
default: pending
|
|
22
|
+
- name: queue_job_id
|
|
23
|
+
type: fk
|
|
24
|
+
isNullable: true
|
|
25
|
+
references:
|
|
26
|
+
table: queue_job
|
|
27
|
+
column: id
|
|
28
|
+
onDelete: SET NULL
|
|
29
|
+
- name: file_id
|
|
30
|
+
type: fk
|
|
31
|
+
isNullable: true
|
|
32
|
+
references:
|
|
33
|
+
table: file
|
|
34
|
+
column: id
|
|
35
|
+
onDelete: SET NULL
|
|
36
|
+
- name: settings
|
|
37
|
+
type: jsonb
|
|
38
|
+
isNullable: true
|
|
39
|
+
- name: duration_seconds
|
|
40
|
+
type: int
|
|
41
|
+
isNullable: true
|
|
42
|
+
- name: error_message
|
|
43
|
+
type: text
|
|
44
|
+
isNullable: true
|
|
45
|
+
- name: notification_id
|
|
46
|
+
type: int
|
|
47
|
+
isNullable: true
|
|
48
|
+
- name: started_at
|
|
49
|
+
type: datetime
|
|
50
|
+
isNullable: true
|
|
51
|
+
- name: finished_at
|
|
52
|
+
type: datetime
|
|
53
|
+
isNullable: true
|
|
54
|
+
- type: created_at
|
|
55
|
+
- type: updated_at
|
|
56
|
+
|
|
57
|
+
indices:
|
|
58
|
+
- columns: [course_id]
|
|
59
|
+
- columns: [user_id]
|
|
60
|
+
- columns: [course_id, status]
|
|
61
|
+
- columns: [queue_job_id]
|
|
62
|
+
- columns: [file_id]
|
package/package.json
CHANGED
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/lms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.365",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@aws-sdk/client-s3": "
|
|
7
|
+
"@aws-sdk/client-s3": "3.1014.0",
|
|
8
|
+
"archiver": "^5.3.2",
|
|
9
|
+
"@types/archiver": "^5.3.4",
|
|
10
|
+
"@aws-sdk/s3-request-presigner": "3.1014.0",
|
|
8
11
|
"@nestjs/common": "*",
|
|
9
12
|
"@nestjs/config": "^4.0.2",
|
|
10
13
|
"@nestjs/core": "^11",
|
|
11
14
|
"@nestjs/jwt": "^11",
|
|
12
15
|
"@nestjs/mapped-types": "*",
|
|
13
|
-
"@hed-hog/api-types": "0.0.1",
|
|
14
16
|
"@hed-hog/api-prisma": "0.0.6",
|
|
15
17
|
"@hed-hog/api-locale": "0.0.14",
|
|
16
|
-
"@hed-hog/api": "0.0.8",
|
|
17
18
|
"@hed-hog/api-pagination": "0.0.7",
|
|
18
|
-
"@hed-hog/
|
|
19
|
-
"@hed-hog/category": "0.0.
|
|
20
|
-
"@hed-hog/
|
|
21
|
-
"@hed-hog/
|
|
22
|
-
"@hed-hog/
|
|
19
|
+
"@hed-hog/api-types": "0.0.1",
|
|
20
|
+
"@hed-hog/category": "0.0.365",
|
|
21
|
+
"@hed-hog/crm": "0.0.365",
|
|
22
|
+
"@hed-hog/api": "0.0.8",
|
|
23
|
+
"@hed-hog/finance": "0.0.365",
|
|
24
|
+
"@hed-hog/commerce": "0.0.365",
|
|
25
|
+
"@hed-hog/queue": "0.0.365",
|
|
26
|
+
"@hed-hog/core": "0.0.365"
|
|
23
27
|
},
|
|
24
28
|
"exports": {
|
|
25
29
|
".": {
|
|
@@ -223,10 +223,8 @@ export class BitcodeWalletService {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
async getCurrentUserWallet(userId: number) {
|
|
226
|
-
const personId = await this.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
return existingWallet ? this.getById(existingWallet.id) : null;
|
|
226
|
+
const personId = await this.resolveOrCreatePersonForUser(userId);
|
|
227
|
+
return this.getOrCreateWalletByPersonId(personId);
|
|
230
228
|
}
|
|
231
229
|
|
|
232
230
|
async creditCurrentUserWallet(
|
|
@@ -344,6 +342,47 @@ export class BitcodeWalletService {
|
|
|
344
342
|
return Number(row.personId);
|
|
345
343
|
}
|
|
346
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
|
+
|
|
347
386
|
private async findWalletByPersonId(personId: number) {
|
|
348
387
|
return this.querySingle<{ id: number }>(
|
|
349
388
|
`SELECT id FROM bitcode_wallet WHERE person_id = $1`,
|
|
@@ -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
|
+
}
|