@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
|
@@ -7,25 +7,44 @@ import type { TranscriptionSegment } from '../_components/types';
|
|
|
7
7
|
|
|
8
8
|
type ApiTranscriptionSegment = {
|
|
9
9
|
id?: number;
|
|
10
|
+
locale_id?: number | null;
|
|
10
11
|
start_seconds?: number | string;
|
|
11
12
|
end_seconds?: number | string;
|
|
12
13
|
text?: string;
|
|
13
14
|
};
|
|
14
15
|
|
|
15
|
-
export
|
|
16
|
+
export type TranscriptionLocale = {
|
|
17
|
+
id: number | null;
|
|
18
|
+
code: string | null;
|
|
19
|
+
name: string | null;
|
|
20
|
+
region: string | null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export function useTranscriptionSegmentsQuery(
|
|
24
|
+
lessonId: string | null,
|
|
25
|
+
localeId?: number | null,
|
|
26
|
+
) {
|
|
16
27
|
const { request } = useApp();
|
|
17
28
|
|
|
29
|
+
const localeParam =
|
|
30
|
+
localeId === undefined
|
|
31
|
+
? ''
|
|
32
|
+
: localeId === null
|
|
33
|
+
? '?locale_id=null'
|
|
34
|
+
: `?locale_id=${localeId}`;
|
|
35
|
+
|
|
18
36
|
return useQuery<TranscriptionSegment[]>({
|
|
19
|
-
queryKey: ['lesson-transcription-segments', lessonId],
|
|
37
|
+
queryKey: ['lesson-transcription-segments', lessonId, localeId ?? 'all'],
|
|
20
38
|
enabled: Boolean(lessonId),
|
|
21
39
|
queryFn: async () => {
|
|
22
40
|
const res = await request<ApiTranscriptionSegment[]>({
|
|
23
|
-
url: `/lms/lessons/${lessonId}/transcription-segments`,
|
|
41
|
+
url: `/lms/lessons/${lessonId}/transcription-segments${localeParam}`,
|
|
24
42
|
method: 'GET',
|
|
25
43
|
});
|
|
26
44
|
|
|
27
45
|
return (res.data ?? []).map((segment) => ({
|
|
28
46
|
id: Number(segment.id ?? 0),
|
|
47
|
+
localeId: segment.locale_id ?? null,
|
|
29
48
|
startSeconds: Number(segment.start_seconds ?? 0),
|
|
30
49
|
endSeconds: Number(segment.end_seconds ?? 0),
|
|
31
50
|
text: String(segment.text ?? ''),
|
|
@@ -35,13 +54,38 @@ export function useTranscriptionSegmentsQuery(lessonId: string | null) {
|
|
|
35
54
|
});
|
|
36
55
|
}
|
|
37
56
|
|
|
57
|
+
export function useTranscriptionLocalesQuery(lessonId: string | null) {
|
|
58
|
+
const { request } = useApp();
|
|
59
|
+
|
|
60
|
+
return useQuery<TranscriptionLocale[]>({
|
|
61
|
+
queryKey: ['lesson-transcription-locales', lessonId],
|
|
62
|
+
enabled: Boolean(lessonId),
|
|
63
|
+
queryFn: async () => {
|
|
64
|
+
const res = await request<TranscriptionLocale[]>({
|
|
65
|
+
url: `/lms/lessons/${lessonId}/transcription-locales`,
|
|
66
|
+
method: 'GET',
|
|
67
|
+
});
|
|
68
|
+
return res.data ?? [];
|
|
69
|
+
},
|
|
70
|
+
initialData: [],
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
38
74
|
export function useUpdateTranscriptionSegmentsMutation(
|
|
39
|
-
lessonId: string | null
|
|
75
|
+
lessonId: string | null,
|
|
76
|
+
localeId?: number | null,
|
|
40
77
|
) {
|
|
41
78
|
const { request } = useApp();
|
|
42
79
|
const [isPending, setIsPending] = useState(false);
|
|
43
80
|
const [error, setError] = useState<Error | null>(null);
|
|
44
81
|
|
|
82
|
+
const localeParam =
|
|
83
|
+
localeId === undefined
|
|
84
|
+
? ''
|
|
85
|
+
: localeId === null
|
|
86
|
+
? '?locale_id=null'
|
|
87
|
+
: `?locale_id=${localeId}`;
|
|
88
|
+
|
|
45
89
|
const mutate = useCallback(
|
|
46
90
|
async (
|
|
47
91
|
segments: Array<{
|
|
@@ -49,13 +93,13 @@ export function useUpdateTranscriptionSegmentsMutation(
|
|
|
49
93
|
endSeconds: number;
|
|
50
94
|
text: string;
|
|
51
95
|
}>,
|
|
52
|
-
options?: { onSuccess?: () => void; onError?: (err: Error) => void }
|
|
96
|
+
options?: { onSuccess?: () => void; onError?: (err: Error) => void },
|
|
53
97
|
) => {
|
|
54
98
|
setIsPending(true);
|
|
55
99
|
setError(null);
|
|
56
100
|
try {
|
|
57
101
|
await request({
|
|
58
|
-
url: `/lms/lessons/${lessonId}/transcription-segments`,
|
|
102
|
+
url: `/lms/lessons/${lessonId}/transcription-segments${localeParam}`,
|
|
59
103
|
method: 'PUT',
|
|
60
104
|
data: { segments },
|
|
61
105
|
});
|
|
@@ -69,7 +113,7 @@ export function useUpdateTranscriptionSegmentsMutation(
|
|
|
69
113
|
setIsPending(false);
|
|
70
114
|
}
|
|
71
115
|
},
|
|
72
|
-
[lessonId, request]
|
|
116
|
+
[lessonId, localeParam, request],
|
|
73
117
|
);
|
|
74
118
|
|
|
75
119
|
return { mutate, isPending, error };
|
|
@@ -99,7 +143,112 @@ export function useStartTranscriptionMutation(lessonId: string | null) {
|
|
|
99
143
|
setIsPending(false);
|
|
100
144
|
}
|
|
101
145
|
},
|
|
102
|
-
[lessonId, request]
|
|
146
|
+
[lessonId, request],
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return { mutate, isPending, error };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function useDeleteTranscriptionLocaleMutation(lessonId: string | null) {
|
|
153
|
+
const { request } = useApp();
|
|
154
|
+
const [isPending, setIsPending] = useState(false);
|
|
155
|
+
const [error, setError] = useState<Error | null>(null);
|
|
156
|
+
|
|
157
|
+
const mutate = useCallback(
|
|
158
|
+
async (
|
|
159
|
+
localeId: number | null,
|
|
160
|
+
options?: { onSuccess?: () => void; onError?: (err: Error) => void },
|
|
161
|
+
) => {
|
|
162
|
+
const localeParam = localeId === null ? '?locale_id=null' : `?locale_id=${localeId}`;
|
|
163
|
+
setIsPending(true);
|
|
164
|
+
setError(null);
|
|
165
|
+
try {
|
|
166
|
+
await request({
|
|
167
|
+
url: `/lms/lessons/${lessonId}/transcription-segments${localeParam}`,
|
|
168
|
+
method: 'DELETE',
|
|
169
|
+
});
|
|
170
|
+
options?.onSuccess?.();
|
|
171
|
+
} catch (err) {
|
|
172
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
173
|
+
setError(e);
|
|
174
|
+
options?.onError?.(e);
|
|
175
|
+
throw e;
|
|
176
|
+
} finally {
|
|
177
|
+
setIsPending(false);
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
[lessonId, request],
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
return { mutate, isPending, error };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function useDeleteCourseTranscriptionsMutation(courseId: string | null) {
|
|
187
|
+
const { request } = useApp();
|
|
188
|
+
const [isPending, setIsPending] = useState(false);
|
|
189
|
+
const [error, setError] = useState<Error | null>(null);
|
|
190
|
+
|
|
191
|
+
const mutate = useCallback(
|
|
192
|
+
async (options?: {
|
|
193
|
+
onSuccess?: (result: { deleted: number }) => void;
|
|
194
|
+
onError?: (err: Error) => void;
|
|
195
|
+
}) => {
|
|
196
|
+
setIsPending(true);
|
|
197
|
+
setError(null);
|
|
198
|
+
try {
|
|
199
|
+
const res = await request<{ success: boolean; deleted: number }>({
|
|
200
|
+
url: `/lms/courses/${courseId}/structure/transcription-segments`,
|
|
201
|
+
method: 'DELETE',
|
|
202
|
+
});
|
|
203
|
+
options?.onSuccess?.(res.data ?? { deleted: 0 });
|
|
204
|
+
} catch (err) {
|
|
205
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
206
|
+
setError(e);
|
|
207
|
+
options?.onError?.(e);
|
|
208
|
+
throw e;
|
|
209
|
+
} finally {
|
|
210
|
+
setIsPending(false);
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
[courseId, request],
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
return { mutate, isPending, error };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function useTranslateTranscriptionMutation(lessonId: string | null) {
|
|
220
|
+
const { request } = useApp();
|
|
221
|
+
const [isPending, setIsPending] = useState(false);
|
|
222
|
+
const [error, setError] = useState<Error | null>(null);
|
|
223
|
+
|
|
224
|
+
const mutate = useCallback(
|
|
225
|
+
async (
|
|
226
|
+
targetLocaleId: number,
|
|
227
|
+
sourceLocaleId?: number | null,
|
|
228
|
+
options?: {
|
|
229
|
+
onSuccess?: (result: { queueJobId: number; status: string }) => void;
|
|
230
|
+
onError?: (err: Error) => void;
|
|
231
|
+
},
|
|
232
|
+
) => {
|
|
233
|
+
setIsPending(true);
|
|
234
|
+
setError(null);
|
|
235
|
+
try {
|
|
236
|
+
const res = await request<{ queueJobId: number; status: string }>({
|
|
237
|
+
url: `/lms/lessons/${lessonId}/transcription/translate`,
|
|
238
|
+
method: 'POST',
|
|
239
|
+
data: { targetLocaleId, sourceLocaleId: sourceLocaleId ?? null },
|
|
240
|
+
});
|
|
241
|
+
options?.onSuccess?.(res.data ?? { queueJobId: 0, status: 'pending' });
|
|
242
|
+
} catch (err) {
|
|
243
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
244
|
+
setError(e);
|
|
245
|
+
options?.onError?.(e);
|
|
246
|
+
throw e;
|
|
247
|
+
} finally {
|
|
248
|
+
setIsPending(false);
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
[lessonId, request],
|
|
103
252
|
);
|
|
104
253
|
|
|
105
254
|
return { mutate, isPending, error };
|
|
@@ -8,26 +8,22 @@ import {
|
|
|
8
8
|
TooltipTrigger,
|
|
9
9
|
} from '@/components/ui/tooltip';
|
|
10
10
|
import { cn } from '@/lib/utils';
|
|
11
|
-
import { Eye,
|
|
11
|
+
import { Eye, Trash2 } from 'lucide-react';
|
|
12
12
|
import type { MouseEvent } from 'react';
|
|
13
13
|
|
|
14
14
|
type CourseRowActionsProps = {
|
|
15
15
|
className?: string;
|
|
16
16
|
onView: () => void;
|
|
17
|
-
onEdit: () => void;
|
|
18
17
|
onDelete: (event: MouseEvent<HTMLButtonElement>) => void;
|
|
19
18
|
viewLabel: string;
|
|
20
|
-
editLabel: string;
|
|
21
19
|
deleteLabel: string;
|
|
22
20
|
};
|
|
23
21
|
|
|
24
22
|
export function CourseRowActions({
|
|
25
23
|
className,
|
|
26
24
|
onView,
|
|
27
|
-
onEdit,
|
|
28
25
|
onDelete,
|
|
29
26
|
viewLabel,
|
|
30
|
-
editLabel,
|
|
31
27
|
deleteLabel,
|
|
32
28
|
}: CourseRowActionsProps) {
|
|
33
29
|
return (
|
|
@@ -50,23 +46,6 @@ export function CourseRowActions({
|
|
|
50
46
|
<TooltipContent>{viewLabel}</TooltipContent>
|
|
51
47
|
</Tooltip>
|
|
52
48
|
|
|
53
|
-
<Tooltip>
|
|
54
|
-
<TooltipTrigger asChild>
|
|
55
|
-
<Button
|
|
56
|
-
type="button"
|
|
57
|
-
variant="ghost"
|
|
58
|
-
size="icon"
|
|
59
|
-
className="h-8 w-8"
|
|
60
|
-
onClick={onEdit}
|
|
61
|
-
aria-label={editLabel}
|
|
62
|
-
>
|
|
63
|
-
<Pencil className="size-4" />
|
|
64
|
-
<span className="sr-only">{editLabel}</span>
|
|
65
|
-
</Button>
|
|
66
|
-
</TooltipTrigger>
|
|
67
|
-
<TooltipContent>{editLabel}</TooltipContent>
|
|
68
|
-
</Tooltip>
|
|
69
|
-
|
|
70
49
|
<Tooltip>
|
|
71
50
|
<TooltipTrigger asChild>
|
|
72
51
|
<Button
|
|
@@ -318,7 +318,7 @@ const OFFERING_TYPE_COLOR: Record<string, string> = {
|
|
|
318
318
|
hibrido: 'bg-teal-50 text-teal-700 border-teal-200',
|
|
319
319
|
};
|
|
320
320
|
|
|
321
|
-
const
|
|
321
|
+
const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
|
|
322
322
|
|
|
323
323
|
// ── Seed Data ─────────────────────────────────────────────────────────────────
|
|
324
324
|
|
|
@@ -388,10 +388,44 @@ export default function CursosPage() {
|
|
|
388
388
|
|
|
389
389
|
// Pagination
|
|
390
390
|
const [currentPage, setCurrentPage] = useState(1);
|
|
391
|
+
|
|
392
|
+
const { data: generalSettings } = useQuery<{
|
|
393
|
+
data: Array<{ slug: string; value: string }>;
|
|
394
|
+
}>({
|
|
395
|
+
queryKey: ['setting-group-general'],
|
|
396
|
+
queryFn: async () => {
|
|
397
|
+
const response = await request<{
|
|
398
|
+
data: Array<{ slug: string; value: string }>;
|
|
399
|
+
}>({
|
|
400
|
+
url: '/setting/group/general',
|
|
401
|
+
method: 'GET',
|
|
402
|
+
});
|
|
403
|
+
return response.data;
|
|
404
|
+
},
|
|
405
|
+
staleTime: 5 * 60 * 1000,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
const pageSizeOptions = useMemo(() => {
|
|
409
|
+
const setting = generalSettings?.data?.find(
|
|
410
|
+
(s) => s.slug === 'pagination-page-sizes'
|
|
411
|
+
);
|
|
412
|
+
if (!setting?.value) return DEFAULT_PAGE_SIZES;
|
|
413
|
+
try {
|
|
414
|
+
const parsed = JSON.parse(setting.value) as string[];
|
|
415
|
+
const sizes = parsed
|
|
416
|
+
.map(Number)
|
|
417
|
+
.filter((n) => !isNaN(n) && n > 0)
|
|
418
|
+
.sort((a, b) => a - b);
|
|
419
|
+
return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
|
|
420
|
+
} catch {
|
|
421
|
+
return DEFAULT_PAGE_SIZES;
|
|
422
|
+
}
|
|
423
|
+
}, [generalSettings]);
|
|
424
|
+
|
|
391
425
|
const [pageSize, setPageSize] = usePersistedPageSize({
|
|
392
426
|
storageKey: 'pagination:global:pageSize',
|
|
393
427
|
defaultValue: 12,
|
|
394
|
-
allowedValues:
|
|
428
|
+
allowedValues: pageSizeOptions,
|
|
395
429
|
});
|
|
396
430
|
|
|
397
431
|
const form = useForm<CourseSheetFormValues>({
|
|
@@ -1091,7 +1125,7 @@ export default function CursosPage() {
|
|
|
1091
1125
|
],
|
|
1092
1126
|
},
|
|
1093
1127
|
]}
|
|
1094
|
-
|
|
1128
|
+
actions={
|
|
1095
1129
|
<ViewModeToggle
|
|
1096
1130
|
viewMode={viewMode}
|
|
1097
1131
|
onViewModeChange={setViewMode}
|
|
@@ -1292,12 +1326,9 @@ export default function CursosPage() {
|
|
|
1292
1326
|
/>
|
|
1293
1327
|
) : (
|
|
1294
1328
|
<div className="relative">
|
|
1295
|
-
{cardsRefreshing && (
|
|
1296
|
-
<div className="absolute inset-0 z-10 rounded-2xl bg-background/55 backdrop-blur-[1px]" />
|
|
1297
|
-
)}
|
|
1298
1329
|
{viewMode === 'cards' ? (
|
|
1299
1330
|
<motion.div
|
|
1300
|
-
className=
|
|
1331
|
+
className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3"
|
|
1301
1332
|
variants={stagger}
|
|
1302
1333
|
initial="hidden"
|
|
1303
1334
|
animate="show"
|
|
@@ -1366,12 +1397,10 @@ export default function CursosPage() {
|
|
|
1366
1397
|
<CourseRowActions
|
|
1367
1398
|
className="ml-auto -mr-1"
|
|
1368
1399
|
onView={() => goToCourseDetails(curso)}
|
|
1369
|
-
onEdit={() => goToCourseDetails(curso)}
|
|
1370
1400
|
onDelete={(event) =>
|
|
1371
1401
|
void openDeleteDialog(curso, event)
|
|
1372
1402
|
}
|
|
1373
1403
|
viewLabel={t('table.actions.viewDetails')}
|
|
1374
|
-
editLabel={t('table.actions.edit')}
|
|
1375
1404
|
deleteLabel={t('table.actions.delete')}
|
|
1376
1405
|
/>
|
|
1377
1406
|
</div>
|
|
@@ -1388,6 +1417,19 @@ export default function CursosPage() {
|
|
|
1388
1417
|
>
|
|
1389
1418
|
{getStatusLabel(curso)}
|
|
1390
1419
|
</Badge>
|
|
1420
|
+
{curso.status === 'publicado' && (
|
|
1421
|
+
<span
|
|
1422
|
+
className={`inline-flex items-center rounded-full border px-2 py-0.5 text-[10px] font-medium ${
|
|
1423
|
+
curso.listado
|
|
1424
|
+
? 'border-emerald-200 bg-emerald-50 text-emerald-700'
|
|
1425
|
+
: 'border-amber-200 bg-amber-50 text-amber-700'
|
|
1426
|
+
}`}
|
|
1427
|
+
>
|
|
1428
|
+
{curso.listado
|
|
1429
|
+
? t('status.listed')
|
|
1430
|
+
: t('status.unlisted')}
|
|
1431
|
+
</span>
|
|
1432
|
+
)}
|
|
1391
1433
|
{deletingCourseIds.has(curso.id) && (
|
|
1392
1434
|
<motion.div
|
|
1393
1435
|
initial={{ opacity: 0, scale: 0.8 }}
|
|
@@ -1464,7 +1506,7 @@ export default function CursosPage() {
|
|
|
1464
1506
|
</motion.div>
|
|
1465
1507
|
) : (
|
|
1466
1508
|
<div
|
|
1467
|
-
className=
|
|
1509
|
+
className="overflow-hidden rounded-xl border border-border/70"
|
|
1468
1510
|
>
|
|
1469
1511
|
<Table>
|
|
1470
1512
|
<TableHeader>
|
|
@@ -1558,6 +1600,19 @@ export default function CursosPage() {
|
|
|
1558
1600
|
>
|
|
1559
1601
|
{getStatusLabel(curso)}
|
|
1560
1602
|
</Badge>
|
|
1603
|
+
{curso.status === 'publicado' && (
|
|
1604
|
+
<span
|
|
1605
|
+
className={`inline-flex items-center rounded-full border px-2 py-0.5 text-[11px] font-medium ${
|
|
1606
|
+
curso.listado
|
|
1607
|
+
? 'border-emerald-200 bg-emerald-50 text-emerald-700'
|
|
1608
|
+
: 'border-amber-200 bg-amber-50 text-amber-700'
|
|
1609
|
+
}`}
|
|
1610
|
+
>
|
|
1611
|
+
{curso.listado
|
|
1612
|
+
? t('status.listed')
|
|
1613
|
+
: t('status.unlisted')}
|
|
1614
|
+
</span>
|
|
1615
|
+
)}
|
|
1561
1616
|
{deletingCourseIds.has(curso.id) && (
|
|
1562
1617
|
<motion.div
|
|
1563
1618
|
initial={{ opacity: 0, scale: 0.8 }}
|
|
@@ -1641,12 +1696,10 @@ export default function CursosPage() {
|
|
|
1641
1696
|
<CourseRowActions
|
|
1642
1697
|
className="ml-auto"
|
|
1643
1698
|
onView={() => goToCourseDetails(curso)}
|
|
1644
|
-
onEdit={() => goToCourseDetails(curso)}
|
|
1645
1699
|
onDelete={(event) =>
|
|
1646
1700
|
void openDeleteDialog(curso, event)
|
|
1647
1701
|
}
|
|
1648
1702
|
viewLabel={t('table.actions.viewDetails')}
|
|
1649
|
-
editLabel={t('table.actions.edit')}
|
|
1650
1703
|
deleteLabel={t('table.actions.delete')}
|
|
1651
1704
|
/>
|
|
1652
1705
|
</TableCell>
|
|
@@ -1672,7 +1725,7 @@ export default function CursosPage() {
|
|
|
1672
1725
|
setPageSize(nextPageSize);
|
|
1673
1726
|
setCurrentPage(1);
|
|
1674
1727
|
}}
|
|
1675
|
-
pageSizeOptions={
|
|
1728
|
+
pageSizeOptions={pageSizeOptions}
|
|
1676
1729
|
selectedCount={selectedIds.size}
|
|
1677
1730
|
/>
|
|
1678
1731
|
</div>
|
|
@@ -25,6 +25,7 @@ import { notFound, useParams, useRouter } from 'next/navigation';
|
|
|
25
25
|
import { useState } from 'react';
|
|
26
26
|
import { AdministratorsTab } from '../_components/enterprise-administrators-tab';
|
|
27
27
|
import { ClassesTab } from '../_components/enterprise-classes-tab';
|
|
28
|
+
import { ClassesCalendarTab } from '../_components/enterprise-classes-calendar-tab';
|
|
28
29
|
import { CoursesTab } from '../_components/enterprise-courses-tab';
|
|
29
30
|
import { EnterpriseSheet } from '../_components/enterprise-sheet';
|
|
30
31
|
import { StudentsTab } from '../_components/enterprise-students-tab';
|
|
@@ -265,6 +266,7 @@ export default function EnterpriseDetailPage() {
|
|
|
265
266
|
<TabsTrigger value="overview">{t('tabs.overview')}</TabsTrigger>
|
|
266
267
|
<TabsTrigger value="crm">{t('tabs.crm')}</TabsTrigger>
|
|
267
268
|
<TabsTrigger value="classes">{t('tabs.classes')}</TabsTrigger>
|
|
269
|
+
<TabsTrigger value="classesCalendar">{t('tabs.classesCalendar')}</TabsTrigger>
|
|
268
270
|
<TabsTrigger value="courses">{t('tabs.courses')}</TabsTrigger>
|
|
269
271
|
<TabsTrigger value="students">{t('tabs.students')}</TabsTrigger>
|
|
270
272
|
<TabsTrigger value="administrators">
|
|
@@ -288,6 +290,10 @@ export default function EnterpriseDetailPage() {
|
|
|
288
290
|
<ClassesTab enterpriseId={account.id} />
|
|
289
291
|
</TabsContent>
|
|
290
292
|
|
|
293
|
+
<TabsContent value="classesCalendar" className="mt-4 px-1">
|
|
294
|
+
<ClassesCalendarTab enterpriseId={account.id} />
|
|
295
|
+
</TabsContent>
|
|
296
|
+
|
|
291
297
|
<TabsContent value="courses" className="mt-4">
|
|
292
298
|
<CoursesTab enterpriseId={account.id} />
|
|
293
299
|
</TabsContent>
|