@hed-hog/lms 0.0.365 → 0.0.370
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/certificate/certificate.controller.d.ts +1 -1
- package/dist/certificate/certificate.controller.d.ts.map +1 -1
- package/dist/certificate/certificate.controller.js +4 -2
- package/dist/certificate/certificate.controller.js.map +1 -1
- package/dist/certificate/certificate.service.d.ts +50 -0
- package/dist/certificate/certificate.service.d.ts.map +1 -1
- package/dist/certificate/certificate.service.js +73 -0
- package/dist/certificate/certificate.service.js.map +1 -1
- package/dist/class-group/class-group.controller.d.ts +1 -0
- package/dist/class-group/class-group.controller.d.ts.map +1 -1
- package/dist/class-group/class-group.service.d.ts +1 -0
- package/dist/class-group/class-group.service.d.ts.map +1 -1
- package/dist/course/course-ai-usage.service.d.ts +58 -0
- package/dist/course/course-ai-usage.service.d.ts.map +1 -0
- package/dist/course/course-ai-usage.service.js +176 -0
- package/dist/course/course-ai-usage.service.js.map +1 -0
- package/dist/course/course-audio-transcription.service.d.ts +65 -1
- package/dist/course/course-audio-transcription.service.d.ts.map +1 -1
- package/dist/course/course-audio-transcription.service.js +381 -29
- package/dist/course/course-audio-transcription.service.js.map +1 -1
- package/dist/course/course-export-scorm12.service.d.ts +3 -0
- package/dist/course/course-export-scorm12.service.d.ts.map +1 -1
- package/dist/course/course-export-scorm12.service.js +141 -6
- package/dist/course/course-export-scorm12.service.js.map +1 -1
- package/dist/course/course-export.service.d.ts.map +1 -1
- package/dist/course/course-export.service.js +2 -1
- package/dist/course/course-export.service.js.map +1 -1
- package/dist/course/course-lesson.controller.d.ts +25 -3
- package/dist/course/course-lesson.controller.d.ts.map +1 -1
- package/dist/course/course-lesson.controller.js +71 -8
- package/dist/course/course-lesson.controller.js.map +1 -1
- package/dist/course/course-structure.controller.d.ts +30 -7
- package/dist/course/course-structure.controller.d.ts.map +1 -1
- package/dist/course/course-structure.controller.js +37 -4
- package/dist/course/course-structure.controller.js.map +1 -1
- package/dist/course/course-structure.service.d.ts +37 -5
- package/dist/course/course-structure.service.d.ts.map +1 -1
- package/dist/course/course-structure.service.js +165 -20
- package/dist/course/course-structure.service.js.map +1 -1
- package/dist/course/course-transcription-translation.service.d.ts +31 -0
- package/dist/course/course-transcription-translation.service.d.ts.map +1 -0
- package/dist/course/course-transcription-translation.service.js +227 -0
- package/dist/course/course-transcription-translation.service.js.map +1 -0
- package/dist/course/course-video-agent-pipeline.service.d.ts +70 -0
- package/dist/course/course-video-agent-pipeline.service.d.ts.map +1 -0
- package/dist/course/course-video-agent-pipeline.service.js +398 -0
- package/dist/course/course-video-agent-pipeline.service.js.map +1 -0
- package/dist/course/course-video-hls.service.d.ts +14 -0
- package/dist/course/course-video-hls.service.d.ts.map +1 -1
- package/dist/course/course-video-hls.service.js +25 -8
- package/dist/course/course-video-hls.service.js.map +1 -1
- package/dist/course/course.controller.d.ts +2 -0
- package/dist/course/course.controller.d.ts.map +1 -1
- package/dist/course/course.module.d.ts.map +1 -1
- package/dist/course/course.module.js +9 -0
- package/dist/course/course.module.js.map +1 -1
- package/dist/course/course.service.d.ts +2 -0
- package/dist/course/course.service.d.ts.map +1 -1
- package/dist/course/course.service.js +36 -2
- package/dist/course/course.service.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 +1 -0
- package/dist/course/dto/create-course-export.dto.d.ts.map +1 -1
- package/dist/course/dto/create-course-export.dto.js +6 -0
- package/dist/course/dto/create-course-export.dto.js.map +1 -1
- package/dist/course/ffmpeg.util.d.ts +10 -0
- package/dist/course/ffmpeg.util.d.ts.map +1 -0
- package/dist/course/ffmpeg.util.js +79 -0
- package/dist/course/ffmpeg.util.js.map +1 -0
- package/dist/course/lms-bulk-upload-automation.service.d.ts +3 -1
- package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload-automation.service.js +33 -16
- package/dist/course/lms-bulk-upload-automation.service.js.map +1 -1
- package/dist/course/lms-bulk-upload.controller.d.ts +3 -0
- package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.service.d.ts +3 -0
- package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
- package/dist/course/lms-bulk-upload.service.js +48 -29
- package/dist/course/lms-bulk-upload.service.js.map +1 -1
- package/dist/course/subtitle.util.d.ts +46 -0
- package/dist/course/subtitle.util.d.ts.map +1 -0
- package/dist/course/subtitle.util.js +206 -0
- package/dist/course/subtitle.util.js.map +1 -0
- package/dist/enterprise/training/training-admin.controller.d.ts +2 -0
- package/dist/enterprise/training/training-admin.controller.d.ts.map +1 -1
- package/dist/enterprise/training/training-admin.service.d.ts +2 -0
- package/dist/enterprise/training/training-admin.service.d.ts.map +1 -1
- package/dist/enterprise/training/training-student.service.d.ts +27 -0
- package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
- package/dist/enterprise/training/training-student.service.js +197 -10
- package/dist/enterprise/training/training-student.service.js.map +1 -1
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts +3 -1
- 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 +19 -5
- package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -1
- package/dist/lesson-xp-map/lesson-xp-map.module.d.ts.map +1 -1
- package/dist/lesson-xp-map/lesson-xp-map.module.js +2 -1
- package/dist/lesson-xp-map/lesson-xp-map.module.js.map +1 -1
- package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -1
- package/dist/lms.module.d.ts.map +1 -1
- package/dist/lms.module.js +14 -0
- package/dist/lms.module.js.map +1 -1
- package/dist/platforma/dto/heartbeat.dto.d.ts +9 -0
- package/dist/platforma/dto/heartbeat.dto.d.ts.map +1 -0
- package/dist/platforma/dto/heartbeat.dto.js +50 -0
- package/dist/platforma/dto/heartbeat.dto.js.map +1 -0
- package/dist/platforma/handlers/emit-certificate.handler.d.ts +27 -0
- package/dist/platforma/handlers/emit-certificate.handler.d.ts.map +1 -0
- package/dist/platforma/handlers/emit-certificate.handler.js +117 -0
- package/dist/platforma/handlers/emit-certificate.handler.js.map +1 -0
- package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts +31 -0
- package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts.map +1 -0
- package/dist/platforma/handlers/lesson-heartbeat.handler.js +281 -0
- package/dist/platforma/handlers/lesson-heartbeat.handler.js.map +1 -0
- package/dist/platforma/platforma-heartbeat.service.d.ts +10 -0
- package/dist/platforma/platforma-heartbeat.service.d.ts.map +1 -0
- package/dist/platforma/platforma-heartbeat.service.js +50 -0
- package/dist/platforma/platforma-heartbeat.service.js.map +1 -0
- package/dist/platforma/platforma-performance.service.d.ts +121 -0
- package/dist/platforma/platforma-performance.service.d.ts.map +1 -0
- package/dist/platforma/platforma-performance.service.js +500 -0
- package/dist/platforma/platforma-performance.service.js.map +1 -0
- package/dist/platforma/platforma-search.service.d.ts +21 -0
- package/dist/platforma/platforma-search.service.d.ts.map +1 -0
- package/dist/platforma/platforma-search.service.js +64 -0
- package/dist/platforma/platforma-search.service.js.map +1 -0
- package/dist/platforma/platforma-video.service.d.ts +8 -0
- package/dist/platforma/platforma-video.service.d.ts.map +1 -1
- package/dist/platforma/platforma-video.service.js +45 -2
- package/dist/platforma/platforma-video.service.js.map +1 -1
- package/dist/platforma/platforma.controller.d.ts +213 -1
- package/dist/platforma/platforma.controller.d.ts.map +1 -1
- package/dist/platforma/platforma.controller.js +159 -2
- package/dist/platforma/platforma.controller.js.map +1 -1
- package/dist/realtime/lms-realtime.controller.d.ts +2 -0
- package/dist/realtime/lms-realtime.controller.d.ts.map +1 -1
- package/dist/realtime/lms-realtime.controller.js +31 -0
- package/dist/realtime/lms-realtime.controller.js.map +1 -1
- package/dist/realtime/lms-realtime.service.d.ts +1 -1
- package/dist/realtime/lms-realtime.service.d.ts.map +1 -1
- package/dist/realtime/lms-realtime.service.js.map +1 -1
- package/dist/training/dto/create-training.dto.d.ts +9 -0
- package/dist/training/dto/create-training.dto.d.ts.map +1 -1
- package/dist/training/dto/create-training.dto.js +45 -1
- package/dist/training/dto/create-training.dto.js.map +1 -1
- package/dist/training/training.controller.d.ts +144 -0
- package/dist/training/training.controller.d.ts.map +1 -1
- package/dist/training/training.service.d.ts +149 -0
- package/dist/training/training.service.d.ts.map +1 -1
- package/dist/training/training.service.js +332 -167
- package/dist/training/training.service.js.map +1 -1
- package/hedhog/data/image_type.yaml +10 -0
- package/hedhog/data/route.yaml +251 -0
- package/hedhog/data/setting_group.yaml +97 -0
- package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +139 -27
- package/hedhog/frontend/app/certificates/models/page.tsx.ejs +182 -29
- package/hedhog/frontend/app/classes/_components/classes-calendar-view.tsx.ejs +277 -0
- package/hedhog/frontend/app/classes/page.tsx.ejs +127 -20
- package/hedhog/frontend/app/courses/[id]/_components/CourseFlagsCard.tsx.ejs +69 -57
- package/hedhog/frontend/app/courses/[id]/_components/CourseIssuedCertificatesCard.tsx.ejs +168 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-ai-costs-tab.tsx.ejs +191 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-export-sheet.tsx.ejs +81 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-exports-tab.tsx.ejs +12 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-overview-tab.tsx.ejs +141 -30
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-xp-overview-tab.tsx.ejs +13 -13
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +69 -1
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson-xp-tab.tsx.ejs +11 -23
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +267 -19
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +114 -86
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +239 -31
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +344 -59
- package/hedhog/frontend/app/courses/[id]/structure/_components/lesson-video-preview.tsx.ejs +200 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +1 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +3 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/xp-premium-pills.tsx.ejs +1 -8
- package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +19 -7
- package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +4 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-ai-costs.ts.ejs +40 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-content-overview.ts.ejs +2 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-exports.ts.ejs +25 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +148 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-transcription-segments.ts.ejs +157 -8
- package/hedhog/frontend/app/courses/_components/CourseRowActions.tsx.ejs +1 -22
- package/hedhog/frontend/app/courses/page.tsx.ejs +66 -13
- package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +6 -0
- package/hedhog/frontend/app/enterprise/_components/enterprise-classes-calendar-tab.tsx.ejs +264 -0
- package/hedhog/frontend/app/enterprise/page.tsx.ejs +104 -47
- package/hedhog/frontend/app/exams/page.tsx.ejs +38 -4
- package/hedhog/frontend/app/instructors/page.tsx.ejs +87 -46
- package/hedhog/frontend/app/paths/page.tsx.ejs +650 -168
- package/hedhog/frontend/app/training/page.tsx.ejs +38 -4
- package/hedhog/frontend/messages/en.json +41 -12
- package/hedhog/frontend/messages/pt.json +44 -13
- package/hedhog/query/triggers.sql +33 -0
- package/hedhog/table/course_ai_usage.yaml +46 -0
- package/hedhog/table/course_enrollment.yaml +3 -0
- package/hedhog/table/course_lesson.yaml +3 -0
- package/hedhog/table/course_lesson_answer.yaml +37 -0
- package/hedhog/table/course_lesson_transcription_segment.yaml +8 -0
- package/hedhog/table/learning_path.yaml +6 -0
- package/hedhog/table/learning_path_module.yaml +22 -0
- package/hedhog/table/learning_path_step.yaml +9 -6
- package/hedhog/table/lesson_view_event.yaml +66 -0
- package/package.json +8 -7
- package/src/certificate/certificate.controller.ts +2 -0
- package/src/certificate/certificate.service.ts +99 -0
- package/src/course/course-ai-usage.service.ts +221 -0
- package/src/course/course-audio-transcription.service.ts +471 -43
- package/src/course/course-export-scorm12.service.ts +149 -5
- package/src/course/course-export.service.ts +1 -0
- package/src/course/course-lesson.controller.ts +59 -6
- package/src/course/course-structure.controller.ts +19 -1
- package/src/course/course-structure.service.ts +184 -10
- package/src/course/course-transcription-translation.service.ts +293 -0
- package/src/course/course-video-agent-pipeline.service.ts +471 -0
- package/src/course/course-video-hls.service.ts +30 -10
- package/src/course/course.module.ts +9 -0
- package/src/course/course.service.ts +46 -1
- package/src/course/dto/create-course-bulk-job.dto.ts +7 -3
- package/src/course/dto/create-course-export.dto.ts +6 -0
- package/src/course/ffmpeg.util.ts +65 -0
- package/src/course/lms-bulk-upload-automation.service.ts +33 -8
- package/src/course/lms-bulk-upload.service.ts +20 -1
- package/src/course/subtitle.util.ts +220 -0
- package/src/enterprise/training/training-student.service.ts +224 -4
- package/src/lesson-xp-map/lesson-xp-ai-calculation.service.ts +14 -0
- package/src/lesson-xp-map/lesson-xp-map.module.ts +2 -1
- package/src/lms.module.ts +14 -0
- package/src/platforma/dto/heartbeat.dto.ts +30 -0
- package/src/platforma/handlers/emit-certificate.handler.ts +117 -0
- package/src/platforma/handlers/lesson-heartbeat.handler.ts +343 -0
- package/src/platforma/platforma-heartbeat.service.ts +33 -0
- package/src/platforma/platforma-performance.service.ts +606 -0
- package/src/platforma/platforma-search.service.ts +48 -0
- package/src/platforma/platforma-video.service.ts +59 -3
- package/src/platforma/platforma.controller.ts +130 -0
- package/src/realtime/lms-realtime.controller.ts +27 -1
- package/src/realtime/lms-realtime.service.ts +2 -1
- package/src/training/dto/create-training.dto.ts +36 -0
- package/src/training/training.service.ts +360 -163
|
@@ -6,17 +6,19 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
6
6
|
import {
|
|
7
7
|
AlertTriangle,
|
|
8
8
|
BookOpen,
|
|
9
|
-
Briefcase,
|
|
10
9
|
CheckCircle2,
|
|
11
10
|
CircleDot,
|
|
12
11
|
Clock,
|
|
13
12
|
Download,
|
|
13
|
+
Languages,
|
|
14
14
|
Layers,
|
|
15
15
|
Loader2,
|
|
16
16
|
Mic,
|
|
17
|
+
MoreVertical,
|
|
17
18
|
Pencil,
|
|
18
19
|
Plus,
|
|
19
20
|
Save,
|
|
21
|
+
Trash2,
|
|
20
22
|
Undo2,
|
|
21
23
|
UploadCloud,
|
|
22
24
|
Video,
|
|
@@ -28,6 +30,7 @@ import { useRouter } from 'next/navigation';
|
|
|
28
30
|
import { type ChangeEvent, useEffect, useMemo, useRef, useState } from 'react';
|
|
29
31
|
import { useForm } from 'react-hook-form';
|
|
30
32
|
import { toast } from 'sonner';
|
|
33
|
+
import { useDeleteCourseTranscriptionsMutation } from '../_data/use-transcription-segments';
|
|
31
34
|
import { z } from 'zod';
|
|
32
35
|
|
|
33
36
|
import { createDefaultTemplate } from '@/app/(app)/(libraries)/lms/_lib/editor/types';
|
|
@@ -105,6 +108,7 @@ import { CourseClassificationCard } from '../../_components/CourseClassification
|
|
|
105
108
|
import { CourseContentCard } from '../../_components/CourseContentCard';
|
|
106
109
|
import { CourseDangerZoneCard } from '../../_components/CourseDangerZoneCard';
|
|
107
110
|
import { CourseFlagsCard } from '../../_components/CourseFlagsCard';
|
|
111
|
+
import { CourseIssuedCertificatesCard } from '../../_components/CourseIssuedCertificatesCard';
|
|
108
112
|
import { CourseMediaCard } from '../../_components/CourseMediaCard';
|
|
109
113
|
import { CourseRelationsCard } from '../../_components/CourseRelationsCard';
|
|
110
114
|
import {
|
|
@@ -120,6 +124,7 @@ import { CourseExportSheet } from './course-export-sheet';
|
|
|
120
124
|
import { CourseExportsTab } from './course-exports-tab';
|
|
121
125
|
import { CourseOperationsTab } from './course-operations-tab';
|
|
122
126
|
import { CourseOverviewTab } from './course-overview-tab';
|
|
127
|
+
import { CourseAiCostsTab } from './course-ai-costs-tab';
|
|
123
128
|
import { CourseXpOverviewTab } from './course-xp-overview-tab';
|
|
124
129
|
import { CourseInstructorsSummaryCard } from './CourseInstructorsSummaryCard';
|
|
125
130
|
import { IconActionTooltip } from './icon-action-tooltip';
|
|
@@ -511,6 +516,7 @@ const COURSE_TABS = [
|
|
|
511
516
|
'publicacao',
|
|
512
517
|
'extra',
|
|
513
518
|
'exportacoes',
|
|
519
|
+
'custos-ia',
|
|
514
520
|
] as const;
|
|
515
521
|
type CourseTab = (typeof COURSE_TABS)[number];
|
|
516
522
|
|
|
@@ -521,6 +527,7 @@ interface EditorCourseProps {
|
|
|
521
527
|
|
|
522
528
|
export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
523
529
|
const courseId = useStructureStore((s) => s.courseId);
|
|
530
|
+
const showConfirm = useStructureStore((s) => s.showConfirm);
|
|
524
531
|
const course = useStructureStore((s) => s.course);
|
|
525
532
|
const sessions = useStructureStore((s) => s.sessions);
|
|
526
533
|
const lessons = useStructureStore((s) => s.lessons);
|
|
@@ -535,6 +542,39 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
535
542
|
const router = useRouter();
|
|
536
543
|
const isMobile = useIsMobile();
|
|
537
544
|
const queryClient = useQueryClient();
|
|
545
|
+
const { mutate: deleteCourseTranscriptions, isPending: isDeletingTranscriptions } =
|
|
546
|
+
useDeleteCourseTranscriptionsMutation(courseId);
|
|
547
|
+
|
|
548
|
+
const handleDeleteAllTranscriptions = () => {
|
|
549
|
+
showConfirm({
|
|
550
|
+
title: 'Excluir todas as transcrições e traduções',
|
|
551
|
+
description:
|
|
552
|
+
'Isso remove permanentemente todas as transcrições e traduções de todas as aulas deste curso. Esta ação não pode ser desfeita.',
|
|
553
|
+
confirmText: 'Excluir tudo',
|
|
554
|
+
destructive: true,
|
|
555
|
+
onConfirm: () => {
|
|
556
|
+
deleteCourseTranscriptions({
|
|
557
|
+
onSuccess: (result) => {
|
|
558
|
+
toast.success(
|
|
559
|
+
`Transcrições removidas (${result.deleted} segmento(s) excluído(s)).`,
|
|
560
|
+
);
|
|
561
|
+
queryClient.invalidateQueries({
|
|
562
|
+
queryKey: ['course-content-overview', courseId],
|
|
563
|
+
});
|
|
564
|
+
queryClient.invalidateQueries({
|
|
565
|
+
queryKey: ['lesson-transcription-locales'],
|
|
566
|
+
});
|
|
567
|
+
queryClient.invalidateQueries({
|
|
568
|
+
queryKey: ['lesson-transcription-segments'],
|
|
569
|
+
});
|
|
570
|
+
},
|
|
571
|
+
onError: (err) => {
|
|
572
|
+
toast.error(err.message || 'Erro ao excluir as transcrições.');
|
|
573
|
+
},
|
|
574
|
+
});
|
|
575
|
+
},
|
|
576
|
+
});
|
|
577
|
+
};
|
|
538
578
|
const createSessionMutation = useCreateSessionMutation();
|
|
539
579
|
const lmsSettings = useLmsSettingsQuery();
|
|
540
580
|
|
|
@@ -547,6 +587,9 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
547
587
|
const [exportSheetOpen, setExportSheetOpen] = useState(false);
|
|
548
588
|
const [pendingBulkJob, setPendingBulkJob] = useState<'transcription' | 'xp_recalculation' | 'video_processing' | null>(null);
|
|
549
589
|
const [isBulkJobPending, setIsBulkJobPending] = useState(false);
|
|
590
|
+
const [translateTranscriptionSheetOpen, setTranslateTranscriptionSheetOpen] = useState(false);
|
|
591
|
+
const [bulkTranslateLocaleId, setBulkTranslateLocaleId] = useState<number | null>(null);
|
|
592
|
+
const [isBulkTranslating, setIsBulkTranslating] = useState(false);
|
|
550
593
|
const [videoProcessingStats, setVideoProcessingStats] = useState<{
|
|
551
594
|
withOriginal: number;
|
|
552
595
|
withoutOriginal: number;
|
|
@@ -951,6 +994,12 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
951
994
|
String(formValues.modeloCertificado ?? '').trim().length > 0,
|
|
952
995
|
required: formValues.certificado,
|
|
953
996
|
},
|
|
997
|
+
{
|
|
998
|
+
id: 'listed',
|
|
999
|
+
label: t('structureEditor.publishChecklist.items.listed'),
|
|
1000
|
+
done: formValues.listado,
|
|
1001
|
+
required: false,
|
|
1002
|
+
},
|
|
954
1003
|
];
|
|
955
1004
|
const requiredChecklist = checklistItems.filter((item) => item.required);
|
|
956
1005
|
const completedRequired = requiredChecklist.filter(
|
|
@@ -1589,6 +1638,26 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
1589
1638
|
}
|
|
1590
1639
|
|
|
1591
1640
|
// ── Bulk jobs ─────────────────────────────────────────────────────────────────
|
|
1641
|
+
const handleBulkTranslateTranscription = async () => {
|
|
1642
|
+
if (!bulkTranslateLocaleId) return;
|
|
1643
|
+
setIsBulkTranslating(true);
|
|
1644
|
+
try {
|
|
1645
|
+
const res = await request<{ queued: number; skipped: number }>({
|
|
1646
|
+
url: `/lms/courses/${courseId}/structure/bulk-jobs`,
|
|
1647
|
+
method: 'POST',
|
|
1648
|
+
data: { jobType: 'translate_transcription', targetLocaleId: bulkTranslateLocaleId },
|
|
1649
|
+
});
|
|
1650
|
+
const { queued = 0, skipped = 0 } = res.data ?? {};
|
|
1651
|
+
toast.success(`${queued} job(s) de tradução enfileirado(s). ${skipped} aula(s) ignoradas.`);
|
|
1652
|
+
setTranslateTranscriptionSheetOpen(false);
|
|
1653
|
+
setBulkTranslateLocaleId(null);
|
|
1654
|
+
} catch (err) {
|
|
1655
|
+
toast.error(err instanceof Error ? err.message : 'Erro ao enfileirar traduções em massa.');
|
|
1656
|
+
} finally {
|
|
1657
|
+
setIsBulkTranslating(false);
|
|
1658
|
+
}
|
|
1659
|
+
};
|
|
1660
|
+
|
|
1592
1661
|
const handleBulkJob = async (
|
|
1593
1662
|
jobType: 'transcription' | 'xp_recalculation' | 'video_processing',
|
|
1594
1663
|
opts?: { reprocessAlreadyProcessed?: boolean },
|
|
@@ -1771,7 +1840,7 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
1771
1840
|
{isBulkJobPending || isFetchingVideoStats ? (
|
|
1772
1841
|
<Loader2 className="size-3.5 animate-spin" />
|
|
1773
1842
|
) : (
|
|
1774
|
-
<
|
|
1843
|
+
<MoreVertical className="size-3.5" />
|
|
1775
1844
|
)}
|
|
1776
1845
|
</Button>
|
|
1777
1846
|
</DropdownMenuTrigger>
|
|
@@ -1779,37 +1848,90 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
1779
1848
|
<DropdownMenuLabel className="text-xs">Jobs em massa</DropdownMenuLabel>
|
|
1780
1849
|
<DropdownMenuSeparator />
|
|
1781
1850
|
{lmsSettings.transcriptionEnabled && (
|
|
1851
|
+
<IconActionTooltip
|
|
1852
|
+
side="right"
|
|
1853
|
+
label="Reprocessa a transcrição de áudio de todas as aulas do curso"
|
|
1854
|
+
>
|
|
1855
|
+
<DropdownMenuItem
|
|
1856
|
+
onSelect={() => setPendingBulkJob('transcription')}
|
|
1857
|
+
className="gap-2"
|
|
1858
|
+
>
|
|
1859
|
+
<Mic className="size-4 text-muted-foreground" />
|
|
1860
|
+
Refazer transcrições
|
|
1861
|
+
</DropdownMenuItem>
|
|
1862
|
+
</IconActionTooltip>
|
|
1863
|
+
)}
|
|
1864
|
+
{lmsSettings.transcriptionEnabled && (
|
|
1865
|
+
<IconActionTooltip
|
|
1866
|
+
side="right"
|
|
1867
|
+
label="Gera traduções das transcrições das aulas para outro idioma"
|
|
1868
|
+
>
|
|
1869
|
+
<DropdownMenuItem
|
|
1870
|
+
onSelect={() => setTranslateTranscriptionSheetOpen(true)}
|
|
1871
|
+
className="gap-2"
|
|
1872
|
+
>
|
|
1873
|
+
<Languages className="size-4 text-muted-foreground" />
|
|
1874
|
+
Traduzir transcrições
|
|
1875
|
+
</DropdownMenuItem>
|
|
1876
|
+
</IconActionTooltip>
|
|
1877
|
+
)}
|
|
1878
|
+
<IconActionTooltip
|
|
1879
|
+
side="right"
|
|
1880
|
+
label="Recalcula a pontuação de XP de todas as aulas do curso"
|
|
1881
|
+
>
|
|
1782
1882
|
<DropdownMenuItem
|
|
1783
|
-
onSelect={() => setPendingBulkJob('
|
|
1883
|
+
onSelect={() => setPendingBulkJob('xp_recalculation')}
|
|
1784
1884
|
className="gap-2"
|
|
1785
1885
|
>
|
|
1786
|
-
<
|
|
1787
|
-
|
|
1886
|
+
<Zap className="size-4 text-muted-foreground" />
|
|
1887
|
+
Recalcular XP
|
|
1788
1888
|
</DropdownMenuItem>
|
|
1789
|
-
|
|
1790
|
-
<
|
|
1791
|
-
|
|
1792
|
-
|
|
1889
|
+
</IconActionTooltip>
|
|
1890
|
+
<IconActionTooltip
|
|
1891
|
+
side="right"
|
|
1892
|
+
label="Inicia o processamento de todos os vídeos do curso"
|
|
1793
1893
|
>
|
|
1794
|
-
<
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
Processar todos os vídeos
|
|
1803
|
-
</DropdownMenuItem>
|
|
1894
|
+
<DropdownMenuItem
|
|
1895
|
+
onSelect={handleOpenVideoProcessingDialog}
|
|
1896
|
+
className="gap-2"
|
|
1897
|
+
>
|
|
1898
|
+
<Video className="size-4 text-muted-foreground" />
|
|
1899
|
+
Processar vídeos
|
|
1900
|
+
</DropdownMenuItem>
|
|
1901
|
+
</IconActionTooltip>
|
|
1804
1902
|
<DropdownMenuSeparator />
|
|
1805
1903
|
<DropdownMenuLabel className="text-xs">Exportar</DropdownMenuLabel>
|
|
1806
|
-
<
|
|
1807
|
-
|
|
1808
|
-
|
|
1904
|
+
<IconActionTooltip
|
|
1905
|
+
side="right"
|
|
1906
|
+
label="Exporta o curso no formato SCORM 1.2"
|
|
1809
1907
|
>
|
|
1810
|
-
<
|
|
1811
|
-
|
|
1812
|
-
|
|
1908
|
+
<DropdownMenuItem
|
|
1909
|
+
onSelect={() => setExportSheetOpen(true)}
|
|
1910
|
+
className="gap-2"
|
|
1911
|
+
>
|
|
1912
|
+
<Download className="size-4 text-muted-foreground" />
|
|
1913
|
+
SCORM 1.2
|
|
1914
|
+
</DropdownMenuItem>
|
|
1915
|
+
</IconActionTooltip>
|
|
1916
|
+
{lmsSettings.transcriptionEnabled && (
|
|
1917
|
+
<>
|
|
1918
|
+
<DropdownMenuSeparator />
|
|
1919
|
+
<DropdownMenuLabel className="text-xs">Exclusão</DropdownMenuLabel>
|
|
1920
|
+
<IconActionTooltip
|
|
1921
|
+
side="right"
|
|
1922
|
+
label="Remove todas as transcrições e traduções de todas as aulas do curso"
|
|
1923
|
+
>
|
|
1924
|
+
<DropdownMenuItem
|
|
1925
|
+
onSelect={handleDeleteAllTranscriptions}
|
|
1926
|
+
disabled={isDeletingTranscriptions}
|
|
1927
|
+
className="gap-2 text-destructive focus:text-destructive"
|
|
1928
|
+
>
|
|
1929
|
+
<Trash2 className="size-4" />
|
|
1930
|
+
Excluir transcrições
|
|
1931
|
+
</DropdownMenuItem>
|
|
1932
|
+
</IconActionTooltip>
|
|
1933
|
+
</>
|
|
1934
|
+
)}
|
|
1813
1935
|
</DropdownMenuContent>
|
|
1814
1936
|
</DropdownMenu>
|
|
1815
1937
|
|
|
@@ -1897,6 +2019,71 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
1897
2019
|
</DialogFooter>
|
|
1898
2020
|
</DialogContent>
|
|
1899
2021
|
</Dialog>
|
|
2022
|
+
|
|
2023
|
+
{/* ── Sheet: Traduzir transcrições em massa ──────────────────── */}
|
|
2024
|
+
<Sheet
|
|
2025
|
+
open={translateTranscriptionSheetOpen}
|
|
2026
|
+
onOpenChange={(open) => {
|
|
2027
|
+
setTranslateTranscriptionSheetOpen(open);
|
|
2028
|
+
if (!open) setBulkTranslateLocaleId(null);
|
|
2029
|
+
}}
|
|
2030
|
+
>
|
|
2031
|
+
<ResizableSheetContent sheetId="bulk-translate-transcription" side="right">
|
|
2032
|
+
<SheetHeader className="px-4 pt-4">
|
|
2033
|
+
<SheetTitle>Traduzir transcrições — todas as aulas</SheetTitle>
|
|
2034
|
+
<SheetDescription>
|
|
2035
|
+
Selecione o idioma-alvo. Um job de tradução será criado para cada
|
|
2036
|
+
aula que já tiver transcrição neste curso. Aulas sem transcrição
|
|
2037
|
+
serão ignoradas.
|
|
2038
|
+
</SheetDescription>
|
|
2039
|
+
</SheetHeader>
|
|
2040
|
+
<div className="flex flex-col gap-4 px-4 pt-4">
|
|
2041
|
+
<EntityPicker
|
|
2042
|
+
placeholder="Selecione o idioma"
|
|
2043
|
+
value={bulkTranslateLocaleId ?? undefined}
|
|
2044
|
+
onChange={(val) => setBulkTranslateLocaleId(val ? Number(val) : null)}
|
|
2045
|
+
showCreateButton
|
|
2046
|
+
loadOptions={async ({ page, search }) => {
|
|
2047
|
+
const res = await request<{
|
|
2048
|
+
data: Array<{ id: number; name: string; code: string; region?: string }>;
|
|
2049
|
+
}>({
|
|
2050
|
+
url: `/core/locales?page=${page}&search=${encodeURIComponent(search)}`,
|
|
2051
|
+
method: 'GET',
|
|
2052
|
+
});
|
|
2053
|
+
return res.data?.data ?? [];
|
|
2054
|
+
}}
|
|
2055
|
+
getOptionValue={(l) => l.id}
|
|
2056
|
+
getOptionLabel={(l) => l.name}
|
|
2057
|
+
createTitle="Adicionar idioma"
|
|
2058
|
+
createFields={[
|
|
2059
|
+
{ name: 'name', label: 'Nome', placeholder: 'Ex: Français (France)' },
|
|
2060
|
+
{ name: 'code', label: 'Código', placeholder: 'fr' },
|
|
2061
|
+
{ name: 'region', label: 'Região', placeholder: 'FR' },
|
|
2062
|
+
]}
|
|
2063
|
+
onCreate={async (values) => {
|
|
2064
|
+
const res = await request<{
|
|
2065
|
+
id: number;
|
|
2066
|
+
name: string;
|
|
2067
|
+
code: string;
|
|
2068
|
+
region?: string;
|
|
2069
|
+
}>({
|
|
2070
|
+
url: '/core/locales',
|
|
2071
|
+
method: 'POST',
|
|
2072
|
+
data: { ...values, enabled: false },
|
|
2073
|
+
});
|
|
2074
|
+
return res.data ?? null;
|
|
2075
|
+
}}
|
|
2076
|
+
/>
|
|
2077
|
+
<Button
|
|
2078
|
+
onClick={handleBulkTranslateTranscription}
|
|
2079
|
+
disabled={!bulkTranslateLocaleId || isBulkTranslating}
|
|
2080
|
+
>
|
|
2081
|
+
{isBulkTranslating && <Loader2 className="size-4 mr-2 animate-spin" />}
|
|
2082
|
+
Enfileirar traduções
|
|
2083
|
+
</Button>
|
|
2084
|
+
</div>
|
|
2085
|
+
</ResizableSheetContent>
|
|
2086
|
+
</Sheet>
|
|
1900
2087
|
</div>
|
|
1901
2088
|
</div>
|
|
1902
2089
|
|
|
@@ -1930,6 +2117,7 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
1930
2117
|
'publicacao',
|
|
1931
2118
|
'extra',
|
|
1932
2119
|
'exportacoes',
|
|
2120
|
+
'custos-ia',
|
|
1933
2121
|
] as const
|
|
1934
2122
|
).map((tab) => (
|
|
1935
2123
|
<TabsTrigger
|
|
@@ -1958,7 +2146,9 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
1958
2146
|
? 'Operações'
|
|
1959
2147
|
: tab === 'exportacoes'
|
|
1960
2148
|
? 'Exportações'
|
|
1961
|
-
:
|
|
2149
|
+
: tab === 'custos-ia'
|
|
2150
|
+
? 'Custos de IA'
|
|
2151
|
+
: t('structureEditor.tabs.publish')}
|
|
1962
2152
|
</TabsTrigger>
|
|
1963
2153
|
))}
|
|
1964
2154
|
</TabsList>
|
|
@@ -2111,7 +2301,7 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
2111
2301
|
region?: string;
|
|
2112
2302
|
}>
|
|
2113
2303
|
>({
|
|
2114
|
-
url: `/core/locales?page=${page}&search=${encodeURIComponent(search ?? '')}`,
|
|
2304
|
+
url: `/core/locales?page=${page}&search=${encodeURIComponent(search ?? '')}&enabled=true`,
|
|
2115
2305
|
method: 'GET',
|
|
2116
2306
|
});
|
|
2117
2307
|
|
|
@@ -2209,6 +2399,11 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
2209
2399
|
compact
|
|
2210
2400
|
/>
|
|
2211
2401
|
<CourseContentCard form={form} compact />
|
|
2402
|
+
<CourseDangerZoneCard
|
|
2403
|
+
t={t}
|
|
2404
|
+
onDelete={openDeleteDialog}
|
|
2405
|
+
compact
|
|
2406
|
+
/>
|
|
2212
2407
|
</TabsContent>
|
|
2213
2408
|
|
|
2214
2409
|
<TabsContent value="xp" className="mt-0 min-w-0">
|
|
@@ -2218,6 +2413,11 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
2218
2413
|
/>
|
|
2219
2414
|
</TabsContent>
|
|
2220
2415
|
|
|
2416
|
+
{/* ── Tab: Custos de IA ───────────────────────────────────── */}
|
|
2417
|
+
<TabsContent value="custos-ia" className="mt-0 min-w-0">
|
|
2418
|
+
<CourseAiCostsTab courseId={courseId} />
|
|
2419
|
+
</TabsContent>
|
|
2420
|
+
|
|
2221
2421
|
{/* ── Tab: Mídia ──────────────────────────────────────────── */}
|
|
2222
2422
|
<TabsContent value="midia" className="mt-0 min-w-0">
|
|
2223
2423
|
<CourseMediaCard
|
|
@@ -2469,7 +2669,7 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
2469
2669
|
</Card>
|
|
2470
2670
|
</TabsContent>
|
|
2471
2671
|
|
|
2472
|
-
{/* ── Tab:
|
|
2672
|
+
{/* ── Tab: Certificado ────────────────────────────────────── */}
|
|
2473
2673
|
<TabsContent
|
|
2474
2674
|
value="extra"
|
|
2475
2675
|
className="mt-0 flex min-w-0 flex-col gap-3"
|
|
@@ -2481,12 +2681,13 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
2481
2681
|
onCreateTemplate={handleCreateCertificateTemplate}
|
|
2482
2682
|
compact
|
|
2483
2683
|
/>
|
|
2484
|
-
<CourseFlagsCard
|
|
2485
|
-
|
|
2684
|
+
<CourseFlagsCard
|
|
2685
|
+
form={form}
|
|
2486
2686
|
t={t}
|
|
2487
|
-
|
|
2687
|
+
flags={['certificado']}
|
|
2488
2688
|
compact
|
|
2489
2689
|
/>
|
|
2690
|
+
<CourseIssuedCertificatesCard courseId={courseId} compact />
|
|
2490
2691
|
</TabsContent>
|
|
2491
2692
|
|
|
2492
2693
|
{/* ── Tab: Operações ──────────────────────────────────────── */}
|
|
@@ -2578,6 +2779,13 @@ export function EditorCourse({ defaultTab, onTabChange }: EditorCourseProps) {
|
|
|
2578
2779
|
</Button>
|
|
2579
2780
|
</CardContent>
|
|
2580
2781
|
</Card>
|
|
2782
|
+
|
|
2783
|
+
<CourseFlagsCard
|
|
2784
|
+
form={form}
|
|
2785
|
+
t={t}
|
|
2786
|
+
flags={['destaque', 'listado']}
|
|
2787
|
+
compact
|
|
2788
|
+
/>
|
|
2581
2789
|
</TabsContent>
|
|
2582
2790
|
|
|
2583
2791
|
{/* ── Tab: Exportações ────────────────────────────────────────── */}
|