@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
|
@@ -5,23 +5,26 @@ import {
|
|
|
5
5
|
Controller,
|
|
6
6
|
Delete,
|
|
7
7
|
Get,
|
|
8
|
-
HttpCode,
|
|
9
|
-
HttpStatus,
|
|
10
8
|
Param,
|
|
11
9
|
ParseIntPipe,
|
|
12
10
|
Patch,
|
|
13
11
|
Post,
|
|
14
12
|
Query,
|
|
15
13
|
} from '@nestjs/common';
|
|
14
|
+
import { CourseExportService } from './course-export.service';
|
|
16
15
|
import { CourseService } from './course.service';
|
|
17
|
-
import { CreateCourseDto } from './dto/create-course.dto';
|
|
18
16
|
import { CleanupCourseStorageDto } from './dto/cleanup-course-storage.dto';
|
|
17
|
+
import { CreateCourseDto } from './dto/create-course.dto';
|
|
18
|
+
import { CreateCourseExportDto } from './dto/create-course-export.dto';
|
|
19
19
|
import { UpdateCourseDto } from './dto/update-course.dto';
|
|
20
20
|
|
|
21
21
|
@Role()
|
|
22
22
|
@Controller('lms/courses')
|
|
23
23
|
export class CourseController {
|
|
24
|
-
constructor(
|
|
24
|
+
constructor(
|
|
25
|
+
private readonly courseService: CourseService,
|
|
26
|
+
private readonly courseExportService: CourseExportService,
|
|
27
|
+
) {}
|
|
25
28
|
|
|
26
29
|
@Get()
|
|
27
30
|
list(
|
|
@@ -83,6 +86,32 @@ export class CourseController {
|
|
|
83
86
|
);
|
|
84
87
|
}
|
|
85
88
|
|
|
89
|
+
@Get(':id/exports')
|
|
90
|
+
listExports(@Param('id', ParseIntPipe) id: number) {
|
|
91
|
+
return this.courseExportService.listExports(id);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@Post(':id/exports')
|
|
95
|
+
createExport(
|
|
96
|
+
@Param('id', ParseIntPipe) id: number,
|
|
97
|
+
@Body() dto: CreateCourseExportDto,
|
|
98
|
+
@User() user: any,
|
|
99
|
+
) {
|
|
100
|
+
return this.courseExportService.enqueueScorm12Export(
|
|
101
|
+
id,
|
|
102
|
+
Number(user?.id || 0),
|
|
103
|
+
dto,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Delete(':id/exports/:exportId')
|
|
108
|
+
deleteExport(
|
|
109
|
+
@Param('id', ParseIntPipe) id: number,
|
|
110
|
+
@Param('exportId', ParseIntPipe) exportId: number,
|
|
111
|
+
) {
|
|
112
|
+
return this.courseExportService.deleteExport(id, exportId);
|
|
113
|
+
}
|
|
114
|
+
|
|
86
115
|
@Get(':id')
|
|
87
116
|
getById(@Param('id', ParseIntPipe) id: number) {
|
|
88
117
|
return this.courseService.getById(id);
|
|
@@ -106,19 +135,4 @@ export class CourseController {
|
|
|
106
135
|
return this.courseService.remove(id, Number(user?.id || 0) || null);
|
|
107
136
|
}
|
|
108
137
|
|
|
109
|
-
@Get(':courseId/video-resolution-profiles')
|
|
110
|
-
getCourseVideoProfiles(
|
|
111
|
-
@Param('courseId', ParseIntPipe) courseId: number,
|
|
112
|
-
) {
|
|
113
|
-
return this.courseService.getCourseVideoProfiles(courseId);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
@Post(':courseId/video-resolution-profiles/sync')
|
|
117
|
-
@HttpCode(HttpStatus.OK)
|
|
118
|
-
syncCourseVideoProfiles(
|
|
119
|
-
@Param('courseId', ParseIntPipe) courseId: number,
|
|
120
|
-
@Body() body: { profileIds: number[] },
|
|
121
|
-
) {
|
|
122
|
-
return this.courseService.syncCourseVideoProfiles(courseId, body.profileIds ?? []);
|
|
123
|
-
}
|
|
124
138
|
}
|
|
@@ -244,7 +244,7 @@ export class LmsCoursesMcpTools {
|
|
|
244
244
|
courseId: { type: 'number', description: 'Course ID' },
|
|
245
245
|
sessionId: { type: 'number', description: 'Session ID' },
|
|
246
246
|
titulo: { type: 'string', description: 'Lesson title (required, max 255)' },
|
|
247
|
-
tipo: { type: 'string', description: 'Lesson type (required): video|questao|post
|
|
247
|
+
tipo: { type: 'string', description: 'Lesson type (required): video|questao|post' },
|
|
248
248
|
descricaoPublica: { type: 'string', description: 'Public description' },
|
|
249
249
|
descricaoPrivada: { type: 'string', description: 'Private description' },
|
|
250
250
|
duracao: { type: 'number', description: 'Duration in seconds' },
|
|
@@ -9,10 +9,15 @@ import { CourseOperationsController } from './course-operations.controller';
|
|
|
9
9
|
import { CourseStructureController } from './course-structure.controller';
|
|
10
10
|
import { CourseStructureService } from './course-structure.service';
|
|
11
11
|
import { CourseVideoConversionService } from './course-video-conversion.service';
|
|
12
|
+
import { CourseVideoHlsService } from './course-video-hls.service';
|
|
13
|
+
import { CourseExportScorm12Service } from './course-export-scorm12.service';
|
|
14
|
+
import { CourseExportScorm12WorkerService } from './course-export-scorm12-worker.service';
|
|
15
|
+
import { CourseExportService } from './course-export.service';
|
|
12
16
|
import { CourseController } from './course.controller';
|
|
13
17
|
import { LmsCoursesMcpTools } from './course.mcp-tools';
|
|
14
18
|
import { LmsBulkUploadInfraService } from './lms-bulk-upload-infra.service';
|
|
15
19
|
import { CourseService } from './course.service';
|
|
20
|
+
import { LmsBulkUploadAutomationService } from './lms-bulk-upload-automation.service';
|
|
16
21
|
import { LmsBulkUploadController } from './lms-bulk-upload.controller';
|
|
17
22
|
import { LmsBulkUploadService } from './lms-bulk-upload.service';
|
|
18
23
|
import { LmsOperationsTaskSubscriber } from './lms-operations-task.subscriber';
|
|
@@ -34,10 +39,15 @@ import { LmsSettingController } from './lms-setting.controller';
|
|
|
34
39
|
LmsBulkUploadController,
|
|
35
40
|
],
|
|
36
41
|
providers: [
|
|
42
|
+
CourseExportService,
|
|
43
|
+
CourseExportScorm12Service,
|
|
44
|
+
CourseExportScorm12WorkerService,
|
|
37
45
|
CourseOperationsIntegrationService,
|
|
38
46
|
CourseService,
|
|
39
47
|
CourseStructureService,
|
|
40
48
|
CourseVideoConversionService,
|
|
49
|
+
CourseVideoHlsService,
|
|
50
|
+
LmsBulkUploadAutomationService,
|
|
41
51
|
LmsBulkUploadInfraService,
|
|
42
52
|
LmsBulkUploadService,
|
|
43
53
|
LmsCoursesMcpTools,
|
|
@@ -47,6 +57,7 @@ import { LmsSettingController } from './lms-setting.controller';
|
|
|
47
57
|
forwardRef(() => CourseService),
|
|
48
58
|
forwardRef(() => CourseStructureService),
|
|
49
59
|
forwardRef(() => CourseVideoConversionService),
|
|
60
|
+
forwardRef(() => CourseVideoHlsService),
|
|
50
61
|
],
|
|
51
62
|
})
|
|
52
63
|
export class CourseModule {}
|
|
@@ -16,8 +16,8 @@ import {
|
|
|
16
16
|
} from '@nestjs/common';
|
|
17
17
|
import { CourseOperationsIntegrationService } from './course-operations-integration.service';
|
|
18
18
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
COURSE_STORAGE_CLEANUP_CATEGORIES,
|
|
20
|
+
type CourseStorageCleanupCategory,
|
|
21
21
|
} from './dto/cleanup-course-storage.dto';
|
|
22
22
|
import { CreateCourseDto } from './dto/create-course.dto';
|
|
23
23
|
import { UpdateCourseDto } from './dto/update-course.dto';
|
|
@@ -480,10 +480,12 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
480
480
|
]);
|
|
481
481
|
|
|
482
482
|
const courseIds = courses.map((course) => course.id);
|
|
483
|
-
const [extrasById, projectLinksById] =
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
483
|
+
const [extrasById, projectLinksById, coursesWithRunningJobs] =
|
|
484
|
+
await Promise.all([
|
|
485
|
+
this.getCourseExtras(courseIds),
|
|
486
|
+
this.operationsIntegration.getCourseProjectLinks(courseIds),
|
|
487
|
+
this.getCoursesWithRunningJobs(courseIds),
|
|
488
|
+
]);
|
|
487
489
|
|
|
488
490
|
return {
|
|
489
491
|
total,
|
|
@@ -496,6 +498,8 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
496
498
|
undefined,
|
|
497
499
|
extrasById.get(c.id),
|
|
498
500
|
projectLinksById.get(c.id),
|
|
501
|
+
undefined,
|
|
502
|
+
coursesWithRunningJobs.has(c.id),
|
|
499
503
|
),
|
|
500
504
|
),
|
|
501
505
|
};
|
|
@@ -1169,6 +1173,7 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1169
1173
|
course_image: 'Imagens do curso',
|
|
1170
1174
|
course_file: 'Arquivos do curso',
|
|
1171
1175
|
other_lesson_file: 'Outros arquivos',
|
|
1176
|
+
course_export: 'Arquivos de exportação',
|
|
1172
1177
|
};
|
|
1173
1178
|
|
|
1174
1179
|
return labels[category];
|
|
@@ -1265,6 +1270,30 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1265
1270
|
return;
|
|
1266
1271
|
}
|
|
1267
1272
|
|
|
1273
|
+
if (category === 'course_export') {
|
|
1274
|
+
const exports = await this.prisma.course_export.findMany({
|
|
1275
|
+
where: {
|
|
1276
|
+
course_id: courseId,
|
|
1277
|
+
file_id: { not: null },
|
|
1278
|
+
status: { in: ['completed', 'failed'] },
|
|
1279
|
+
},
|
|
1280
|
+
select: { id: true, file_id: true },
|
|
1281
|
+
});
|
|
1282
|
+
|
|
1283
|
+
const fileIds = exports
|
|
1284
|
+
.map((e) => e.file_id)
|
|
1285
|
+
.filter((id): id is number => id != null);
|
|
1286
|
+
|
|
1287
|
+
await this.prisma.course_export.deleteMany({
|
|
1288
|
+
where: { id: { in: exports.map((e) => e.id) } },
|
|
1289
|
+
});
|
|
1290
|
+
|
|
1291
|
+
if (fileIds.length > 0) {
|
|
1292
|
+
await this.fileService.delete('pt', { ids: fileIds }).catch(() => undefined);
|
|
1293
|
+
}
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1268
1297
|
await this.prisma.course_lesson_file.deleteMany({
|
|
1269
1298
|
where: {
|
|
1270
1299
|
course_lesson: { course_module: { course_id: courseId } },
|
|
@@ -1315,6 +1344,15 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1315
1344
|
INNER JOIN course_lesson cl ON cl.id = clvf.course_lesson_id
|
|
1316
1345
|
INNER JOIN course_module cm ON cm.id = cl.course_module_id
|
|
1317
1346
|
WHERE cm.course_id = ${courseId}
|
|
1347
|
+
|
|
1348
|
+
UNION ALL
|
|
1349
|
+
|
|
1350
|
+
SELECT ce.file_id, f.size AS file_size, 'course_export' AS storage_category
|
|
1351
|
+
FROM course_export ce
|
|
1352
|
+
INNER JOIN file f ON f.id = ce.file_id
|
|
1353
|
+
WHERE ce.course_id = ${courseId}
|
|
1354
|
+
AND ce.status = 'completed'
|
|
1355
|
+
AND ce.file_id IS NOT NULL
|
|
1318
1356
|
) AS files
|
|
1319
1357
|
WHERE files.file_id IS NOT NULL
|
|
1320
1358
|
`;
|
|
@@ -1463,6 +1501,7 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1463
1501
|
} | null;
|
|
1464
1502
|
} | null;
|
|
1465
1503
|
}>,
|
|
1504
|
+
hasRunningJobs = false,
|
|
1466
1505
|
) {
|
|
1467
1506
|
const resolvedName = extras?.name ?? c.name ?? null;
|
|
1468
1507
|
const resolvedTitle = this.normalizeOptionalText(c.title) ?? c.slug;
|
|
@@ -1549,6 +1588,7 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1549
1588
|
(c.certificate_template_id
|
|
1550
1589
|
? String(c.certificate_template_id)
|
|
1551
1590
|
: null),
|
|
1591
|
+
hasRunningJobs,
|
|
1552
1592
|
progressByModule: metrics?.progressByModule ?? [],
|
|
1553
1593
|
instructors: Array.from(
|
|
1554
1594
|
new Map(
|
|
@@ -1624,6 +1664,25 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1624
1664
|
return extrasById;
|
|
1625
1665
|
}
|
|
1626
1666
|
|
|
1667
|
+
private async getCoursesWithRunningJobs(
|
|
1668
|
+
courseIds: number[],
|
|
1669
|
+
): Promise<Set<number>> {
|
|
1670
|
+
if (courseIds.length === 0) return new Set();
|
|
1671
|
+
|
|
1672
|
+
const rows = (await this.prisma.$queryRawUnsafe(`
|
|
1673
|
+
SELECT DISTINCT cm.course_id
|
|
1674
|
+
FROM queue_job qj
|
|
1675
|
+
INNER JOIN course_lesson cl ON cl.id = CAST(qj.source_entity_id AS INTEGER)
|
|
1676
|
+
INNER JOIN course_module cm ON cm.id = cl.course_module_id
|
|
1677
|
+
WHERE qj.source_entity = 'course_lesson'
|
|
1678
|
+
AND qj.source_module = 'lms'
|
|
1679
|
+
AND qj.status IN ('pending', 'scheduled', 'processing', 'retrying')
|
|
1680
|
+
AND cm.course_id IN (${courseIds.join(',')})
|
|
1681
|
+
`)) as Array<{ course_id: number }>;
|
|
1682
|
+
|
|
1683
|
+
return new Set(rows.map((r) => Number(r.course_id)));
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1627
1686
|
private async persistCourseExtras(
|
|
1628
1687
|
id: number,
|
|
1629
1688
|
data: PersistCourseExtrasInput,
|
|
@@ -1653,7 +1712,8 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1653
1712
|
}
|
|
1654
1713
|
|
|
1655
1714
|
if (data.offeringType !== undefined) {
|
|
1656
|
-
|
|
1715
|
+
values.push(data.offeringType);
|
|
1716
|
+
setClauses.push(`offering_type = $${values.length}::course_offering_type_8af4d2739d_enum`);
|
|
1657
1717
|
}
|
|
1658
1718
|
|
|
1659
1719
|
if (setClauses.length === 0) {
|
|
@@ -1670,8 +1730,8 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1670
1730
|
`,
|
|
1671
1731
|
...values,
|
|
1672
1732
|
);
|
|
1673
|
-
} catch {
|
|
1674
|
-
|
|
1733
|
+
} catch (err) {
|
|
1734
|
+
console.error('[persistCourseExtras] failed:', err);
|
|
1675
1735
|
}
|
|
1676
1736
|
}
|
|
1677
1737
|
|
|
@@ -1836,53 +1896,6 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1836
1896
|
});
|
|
1837
1897
|
}
|
|
1838
1898
|
|
|
1839
|
-
async getCourseVideoProfiles(courseId: number) {
|
|
1840
|
-
const rows = await (this.prisma as any).course_video_resolution_profile.findMany({
|
|
1841
|
-
where: { course_id: courseId },
|
|
1842
|
-
include: { video_resolution_profile: true },
|
|
1843
|
-
orderBy: { video_resolution_profile: { name: 'asc' } },
|
|
1844
|
-
});
|
|
1845
|
-
|
|
1846
|
-
return (rows as any[]).map((row) => ({
|
|
1847
|
-
id: row.video_resolution_profile.id,
|
|
1848
|
-
name: row.video_resolution_profile.name,
|
|
1849
|
-
ffmpeg_params: row.video_resolution_profile.ffmpeg_params,
|
|
1850
|
-
status: row.video_resolution_profile.status,
|
|
1851
|
-
}));
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
async syncCourseVideoProfiles(courseId: number, profileIds: number[]) {
|
|
1855
|
-
const linkClient = (this.prisma as any).course_video_resolution_profile;
|
|
1856
|
-
|
|
1857
|
-
await this.prisma.$transaction(async (tx: any) => {
|
|
1858
|
-
await tx.course_video_resolution_profile.deleteMany({
|
|
1859
|
-
where: { course_id: courseId },
|
|
1860
|
-
});
|
|
1861
|
-
|
|
1862
|
-
if (profileIds.length > 0) {
|
|
1863
|
-
await tx.course_video_resolution_profile.createMany({
|
|
1864
|
-
data: profileIds.map((id) => ({
|
|
1865
|
-
course_id: courseId,
|
|
1866
|
-
video_resolution_profile_id: id,
|
|
1867
|
-
})),
|
|
1868
|
-
});
|
|
1869
|
-
}
|
|
1870
|
-
});
|
|
1871
|
-
|
|
1872
|
-
return linkClient.findMany({
|
|
1873
|
-
where: { course_id: courseId },
|
|
1874
|
-
include: { video_resolution_profile: true },
|
|
1875
|
-
orderBy: { video_resolution_profile: { name: 'asc' } },
|
|
1876
|
-
}).then((rows: any[]) =>
|
|
1877
|
-
rows.map((row: any) => ({
|
|
1878
|
-
id: row.video_resolution_profile.id,
|
|
1879
|
-
name: row.video_resolution_profile.name,
|
|
1880
|
-
ffmpeg_params: row.video_resolution_profile.ffmpeg_params,
|
|
1881
|
-
status: row.video_resolution_profile.status,
|
|
1882
|
-
})),
|
|
1883
|
-
);
|
|
1884
|
-
}
|
|
1885
|
-
|
|
1886
1899
|
async getCourseContentOverview(courseId: number) {
|
|
1887
1900
|
const [
|
|
1888
1901
|
moduleCount,
|
|
@@ -1924,7 +1937,7 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1924
1937
|
);
|
|
1925
1938
|
const xpLessonIds = new Set(xpMapRows.map((r) => r.course_lesson_id));
|
|
1926
1939
|
|
|
1927
|
-
const lessonsByType = { video: 0, questao: 0, post: 0
|
|
1940
|
+
const lessonsByType = { video: 0, questao: 0, post: 0 };
|
|
1928
1941
|
let publishedLessonCount = 0;
|
|
1929
1942
|
let videoWithTranscription = 0;
|
|
1930
1943
|
let videoWithXp = 0;
|
|
@@ -1939,6 +1952,7 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
1939
1952
|
'course_image',
|
|
1940
1953
|
'course_file',
|
|
1941
1954
|
'other_lesson_file',
|
|
1955
|
+
'course_export',
|
|
1942
1956
|
];
|
|
1943
1957
|
|
|
1944
1958
|
const uniqueStorageFiles = new Map<number, number>();
|
|
@@ -2007,12 +2021,11 @@ export class CourseService implements OnModuleInit, IJobHandler {
|
|
|
2007
2021
|
// ignore malformed content
|
|
2008
2022
|
}
|
|
2009
2023
|
|
|
2010
|
-
let uiType: 'video' | 'questao' | 'post'
|
|
2024
|
+
let uiType: 'video' | 'questao' | 'post';
|
|
2011
2025
|
if (
|
|
2012
2026
|
sourceType === 'video' ||
|
|
2013
2027
|
sourceType === 'questao' ||
|
|
2014
|
-
sourceType === 'post'
|
|
2015
|
-
sourceType === 'exercicio'
|
|
2028
|
+
sourceType === 'post'
|
|
2016
2029
|
) {
|
|
2017
2030
|
uiType = sourceType;
|
|
2018
2031
|
} else if (lesson.type === 'video') {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ArrayNotEmpty, IsArray, IsIn, IsOptional } from 'class-validator';
|
|
2
2
|
|
|
3
|
-
export const BULK_UPLOAD_CLEANUP_STATUSES = ['done', 'error', 'cancelled'] as const;
|
|
3
|
+
export const BULK_UPLOAD_CLEANUP_STATUSES = ['received', 'done', 'error', 'cancelled'] as const;
|
|
4
4
|
export const BULK_UPLOAD_CLEANUP_WINDOWS = [
|
|
5
5
|
'last_hour',
|
|
6
6
|
'last_day',
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { IsIn } from 'class-validator';
|
|
1
|
+
import { IsBoolean, IsIn, IsOptional } from 'class-validator';
|
|
2
2
|
|
|
3
3
|
export class CreateCourseBulkJobDto {
|
|
4
|
-
@IsIn(['transcription', 'xp_recalculation'])
|
|
5
|
-
jobType: 'transcription' | 'xp_recalculation';
|
|
4
|
+
@IsIn(['transcription', 'xp_recalculation', 'video_processing'])
|
|
5
|
+
jobType: 'transcription' | 'xp_recalculation' | 'video_processing';
|
|
6
|
+
|
|
7
|
+
@IsBoolean()
|
|
8
|
+
@IsOptional()
|
|
9
|
+
reprocessAlreadyProcessed?: boolean;
|
|
6
10
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Type } from 'class-transformer';
|
|
2
|
+
import {
|
|
3
|
+
IsIn,
|
|
4
|
+
IsInt,
|
|
5
|
+
IsOptional,
|
|
6
|
+
IsString,
|
|
7
|
+
Matches,
|
|
8
|
+
Max,
|
|
9
|
+
Min,
|
|
10
|
+
ValidateNested,
|
|
11
|
+
} from 'class-validator';
|
|
12
|
+
|
|
13
|
+
export class ScormVisualSettingsDto {
|
|
14
|
+
@IsOptional()
|
|
15
|
+
@IsString()
|
|
16
|
+
@Matches(/^#[0-9a-fA-F]{6}$/, {
|
|
17
|
+
message: 'primaryColor deve ser uma cor hex válida (ex: #2563eb)',
|
|
18
|
+
})
|
|
19
|
+
primaryColor?: string;
|
|
20
|
+
|
|
21
|
+
@IsOptional()
|
|
22
|
+
@IsIn(['system', 'humanist', 'serif', 'mono'])
|
|
23
|
+
fontFamily?: string;
|
|
24
|
+
|
|
25
|
+
@IsOptional()
|
|
26
|
+
@IsIn(['sm', 'md', 'lg'])
|
|
27
|
+
fontSize?: string;
|
|
28
|
+
|
|
29
|
+
@IsOptional()
|
|
30
|
+
@IsInt()
|
|
31
|
+
@Min(200)
|
|
32
|
+
@Max(420)
|
|
33
|
+
sidebarWidth?: number;
|
|
34
|
+
|
|
35
|
+
@IsOptional()
|
|
36
|
+
@IsIn(['left', 'right'])
|
|
37
|
+
sidebarPosition?: string;
|
|
38
|
+
|
|
39
|
+
@IsOptional()
|
|
40
|
+
@IsIn(['bar', 'pie'])
|
|
41
|
+
progressStyle?: string;
|
|
42
|
+
|
|
43
|
+
@IsOptional()
|
|
44
|
+
@IsIn(['light', 'dark'])
|
|
45
|
+
sidebarTheme?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class CreateCourseExportDto {
|
|
49
|
+
@IsIn(['scorm_1_2'])
|
|
50
|
+
format: 'scorm_1_2';
|
|
51
|
+
|
|
52
|
+
@IsOptional()
|
|
53
|
+
@ValidateNested()
|
|
54
|
+
@Type(() => ScormVisualSettingsDto)
|
|
55
|
+
visualSettings?: ScormVisualSettingsDto;
|
|
56
|
+
}
|
|
@@ -18,10 +18,11 @@ const COURSE_LESSON_FILE_TYPES = [
|
|
|
18
18
|
'student_download',
|
|
19
19
|
'supplementary_material',
|
|
20
20
|
'video_original',
|
|
21
|
+
'video_hls',
|
|
21
22
|
] as const;
|
|
22
23
|
|
|
23
24
|
const COURSE_LESSON_FILE_TYPE_REGEX =
|
|
24
|
-
/^(lesson_audio|student_download|supplementary_material|video_original|video_profile:\d+)$/;
|
|
25
|
+
/^(lesson_audio|student_download|supplementary_material|video_original|video_hls|video_profile:\d+)$/;
|
|
25
26
|
|
|
26
27
|
export type CourseLessonFileType =
|
|
27
28
|
| (typeof COURSE_LESSON_FILE_TYPES)[number]
|
|
@@ -74,8 +75,8 @@ export class CreateCourseStructureLessonDto {
|
|
|
74
75
|
@IsOptional()
|
|
75
76
|
descricaoPrivada?: string;
|
|
76
77
|
|
|
77
|
-
@IsEnum(['video', 'questao', 'post'
|
|
78
|
-
tipo: 'video' | 'questao' | 'post'
|
|
78
|
+
@IsEnum(['video', 'questao', 'post'])
|
|
79
|
+
tipo: 'video' | 'questao' | 'post';
|
|
79
80
|
|
|
80
81
|
@IsInt()
|
|
81
82
|
@Min(0)
|