@hed-hog/lms 0.0.364 → 0.0.366

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.
Files changed (290) hide show
  1. package/dist/bitcode-wallet/bitcode-wallet.service.d.ts +1 -0
  2. package/dist/bitcode-wallet/bitcode-wallet.service.d.ts.map +1 -1
  3. package/dist/bitcode-wallet/bitcode-wallet.service.js +22 -3
  4. package/dist/bitcode-wallet/bitcode-wallet.service.js.map +1 -1
  5. package/dist/class-group/class-group.controller.d.ts +1 -0
  6. package/dist/class-group/class-group.controller.d.ts.map +1 -1
  7. package/dist/class-group/class-group.service.d.ts +1 -0
  8. package/dist/class-group/class-group.service.d.ts.map +1 -1
  9. package/dist/course/course-export-scorm12-worker.service.d.ts +21 -0
  10. package/dist/course/course-export-scorm12-worker.service.d.ts.map +1 -0
  11. package/dist/course/course-export-scorm12-worker.service.js +109 -0
  12. package/dist/course/course-export-scorm12-worker.service.js.map +1 -0
  13. package/dist/course/course-export-scorm12.service.d.ts +42 -0
  14. package/dist/course/course-export-scorm12.service.d.ts.map +1 -0
  15. package/dist/course/course-export-scorm12.service.js +628 -0
  16. package/dist/course/course-export-scorm12.service.js.map +1 -0
  17. package/dist/course/course-export.service.d.ts +84 -0
  18. package/dist/course/course-export.service.d.ts.map +1 -0
  19. package/dist/course/course-export.service.js +237 -0
  20. package/dist/course/course-export.service.js.map +1 -0
  21. package/dist/course/course-structure.controller.d.ts +20 -10
  22. package/dist/course/course-structure.controller.d.ts.map +1 -1
  23. package/dist/course/course-structure.controller.js +20 -4
  24. package/dist/course/course-structure.controller.js.map +1 -1
  25. package/dist/course/course-structure.service.d.ts +12 -4
  26. package/dist/course/course-structure.service.d.ts.map +1 -1
  27. package/dist/course/course-structure.service.js +98 -23
  28. package/dist/course/course-structure.service.js.map +1 -1
  29. package/dist/course/course-video-agent-pipeline.service.d.ts +70 -0
  30. package/dist/course/course-video-agent-pipeline.service.d.ts.map +1 -0
  31. package/dist/course/course-video-agent-pipeline.service.js +398 -0
  32. package/dist/course/course-video-agent-pipeline.service.js.map +1 -0
  33. package/dist/course/course-video-hls.service.d.ts +71 -0
  34. package/dist/course/course-video-hls.service.d.ts.map +1 -0
  35. package/dist/course/course-video-hls.service.js +784 -0
  36. package/dist/course/course-video-hls.service.js.map +1 -0
  37. package/dist/course/course.controller.d.ts +47 -13
  38. package/dist/course/course.controller.d.ts.map +1 -1
  39. package/dist/course/course.controller.js +40 -26
  40. package/dist/course/course.controller.js.map +1 -1
  41. package/dist/course/course.mcp-tools.js +1 -1
  42. package/dist/course/course.mcp-tools.js.map +1 -1
  43. package/dist/course/course.module.d.ts.map +1 -1
  44. package/dist/course/course.module.js +16 -0
  45. package/dist/course/course.module.js.map +1 -1
  46. package/dist/course/course.service.d.ts +8 -9
  47. package/dist/course/course.service.d.ts.map +1 -1
  48. package/dist/course/course.service.js +93 -50
  49. package/dist/course/course.service.js.map +1 -1
  50. package/dist/course/dto/cleanup-course-storage.dto.d.ts +1 -1
  51. package/dist/course/dto/cleanup-course-storage.dto.d.ts.map +1 -1
  52. package/dist/course/dto/cleanup-course-storage.dto.js +1 -0
  53. package/dist/course/dto/cleanup-course-storage.dto.js.map +1 -1
  54. package/dist/course/dto/cleanup-upload-history.dto.d.ts +1 -1
  55. package/dist/course/dto/cleanup-upload-history.dto.d.ts.map +1 -1
  56. package/dist/course/dto/cleanup-upload-history.dto.js +1 -1
  57. package/dist/course/dto/cleanup-upload-history.dto.js.map +1 -1
  58. package/dist/course/dto/create-course-bulk-job.dto.d.ts +2 -1
  59. package/dist/course/dto/create-course-bulk-job.dto.d.ts.map +1 -1
  60. package/dist/course/dto/create-course-bulk-job.dto.js +6 -1
  61. package/dist/course/dto/create-course-bulk-job.dto.js.map +1 -1
  62. package/dist/course/dto/create-course-export.dto.d.ts +14 -0
  63. package/dist/course/dto/create-course-export.dto.d.ts.map +1 -0
  64. package/dist/course/dto/create-course-export.dto.js +71 -0
  65. package/dist/course/dto/create-course-export.dto.js.map +1 -0
  66. package/dist/course/dto/create-course-structure-lesson.dto.d.ts +2 -2
  67. package/dist/course/dto/create-course-structure-lesson.dto.d.ts.map +1 -1
  68. package/dist/course/dto/create-course-structure-lesson.dto.js +3 -2
  69. package/dist/course/dto/create-course-structure-lesson.dto.js.map +1 -1
  70. package/dist/course/ffmpeg.util.d.ts +10 -0
  71. package/dist/course/ffmpeg.util.d.ts.map +1 -0
  72. package/dist/course/ffmpeg.util.js +79 -0
  73. package/dist/course/ffmpeg.util.js.map +1 -0
  74. package/dist/course/lms-bulk-upload-automation.service.d.ts +18 -1
  75. package/dist/course/lms-bulk-upload-automation.service.d.ts.map +1 -1
  76. package/dist/course/lms-bulk-upload-automation.service.js +106 -8
  77. package/dist/course/lms-bulk-upload-automation.service.js.map +1 -1
  78. package/dist/course/lms-bulk-upload-infra.service.d.ts +1 -0
  79. package/dist/course/lms-bulk-upload-infra.service.d.ts.map +1 -1
  80. package/dist/course/lms-bulk-upload-infra.service.js +32 -8
  81. package/dist/course/lms-bulk-upload-infra.service.js.map +1 -1
  82. package/dist/course/lms-bulk-upload.controller.d.ts +30 -3
  83. package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -1
  84. package/dist/course/lms-bulk-upload.controller.js +43 -2
  85. package/dist/course/lms-bulk-upload.controller.js.map +1 -1
  86. package/dist/course/lms-bulk-upload.service.d.ts +11 -0
  87. package/dist/course/lms-bulk-upload.service.d.ts.map +1 -1
  88. package/dist/course/lms-bulk-upload.service.js +59 -6
  89. package/dist/course/lms-bulk-upload.service.js.map +1 -1
  90. package/dist/course/lms-setting.controller.d.ts +2 -1
  91. package/dist/course/lms-setting.controller.d.ts.map +1 -1
  92. package/dist/course/lms-setting.controller.js +4 -2
  93. package/dist/course/lms-setting.controller.js.map +1 -1
  94. package/dist/course/scorm12-schemas.d.ts +4 -0
  95. package/dist/course/scorm12-schemas.d.ts.map +1 -0
  96. package/dist/course/scorm12-schemas.js +9 -0
  97. package/dist/course/scorm12-schemas.js.map +1 -0
  98. package/dist/enterprise/training/training-admin.controller.d.ts +2 -0
  99. package/dist/enterprise/training/training-admin.controller.d.ts.map +1 -1
  100. package/dist/enterprise/training/training-admin.service.d.ts +2 -0
  101. package/dist/enterprise/training/training-admin.service.d.ts.map +1 -1
  102. package/dist/enterprise/training/training-student.service.d.ts +51 -0
  103. package/dist/enterprise/training/training-student.service.d.ts.map +1 -1
  104. package/dist/enterprise/training/training-student.service.js +217 -4
  105. package/dist/enterprise/training/training-student.service.js.map +1 -1
  106. package/dist/evaluation/evaluation.service.d.ts +18 -0
  107. package/dist/evaluation/evaluation.service.d.ts.map +1 -1
  108. package/dist/evaluation/evaluation.service.js +125 -0
  109. package/dist/evaluation/evaluation.service.js.map +1 -1
  110. package/dist/exam/dto/create-standalone-question.dto.d.ts +12 -0
  111. package/dist/exam/dto/create-standalone-question.dto.d.ts.map +1 -0
  112. package/dist/exam/dto/create-standalone-question.dto.js +70 -0
  113. package/dist/exam/dto/create-standalone-question.dto.js.map +1 -0
  114. package/dist/exam/exam.module.d.ts.map +1 -1
  115. package/dist/exam/exam.module.js +2 -1
  116. package/dist/exam/exam.module.js.map +1 -1
  117. package/dist/exam/exam.service.d.ts +21 -0
  118. package/dist/exam/exam.service.d.ts.map +1 -1
  119. package/dist/exam/exam.service.js +80 -0
  120. package/dist/exam/exam.service.js.map +1 -1
  121. package/dist/exam/question.controller.d.ts +27 -0
  122. package/dist/exam/question.controller.d.ts.map +1 -0
  123. package/dist/exam/question.controller.js +53 -0
  124. package/dist/exam/question.controller.js.map +1 -0
  125. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts +4 -0
  126. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.d.ts.map +1 -1
  127. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js +161 -25
  128. package/dist/lesson-xp-map/lesson-xp-ai-calculation.service.js.map +1 -1
  129. package/dist/libraries/lms/tsconfig.tsbuildinfo +1 -1
  130. package/dist/lms-commerce-access.subscriber.d.ts +11 -0
  131. package/dist/lms-commerce-access.subscriber.d.ts.map +1 -0
  132. package/dist/lms-commerce-access.subscriber.js +74 -0
  133. package/dist/lms-commerce-access.subscriber.js.map +1 -0
  134. package/dist/lms.module.d.ts.map +1 -1
  135. package/dist/lms.module.js +16 -5
  136. package/dist/lms.module.js.map +1 -1
  137. package/dist/platforma/dto/heartbeat.dto.d.ts +9 -0
  138. package/dist/platforma/dto/heartbeat.dto.d.ts.map +1 -0
  139. package/dist/platforma/dto/heartbeat.dto.js +50 -0
  140. package/dist/platforma/dto/heartbeat.dto.js.map +1 -0
  141. package/dist/platforma/handlers/emit-certificate.handler.d.ts +27 -0
  142. package/dist/platforma/handlers/emit-certificate.handler.d.ts.map +1 -0
  143. package/dist/platforma/handlers/emit-certificate.handler.js +117 -0
  144. package/dist/platforma/handlers/emit-certificate.handler.js.map +1 -0
  145. package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts +31 -0
  146. package/dist/platforma/handlers/lesson-heartbeat.handler.d.ts.map +1 -0
  147. package/dist/platforma/handlers/lesson-heartbeat.handler.js +281 -0
  148. package/dist/platforma/handlers/lesson-heartbeat.handler.js.map +1 -0
  149. package/dist/platforma/platforma-heartbeat.service.d.ts +10 -0
  150. package/dist/platforma/platforma-heartbeat.service.d.ts.map +1 -0
  151. package/dist/platforma/platforma-heartbeat.service.js +50 -0
  152. package/dist/platforma/platforma-heartbeat.service.js.map +1 -0
  153. package/dist/platforma/platforma-performance.service.d.ts +121 -0
  154. package/dist/platforma/platforma-performance.service.d.ts.map +1 -0
  155. package/dist/platforma/platforma-performance.service.js +500 -0
  156. package/dist/platforma/platforma-performance.service.js.map +1 -0
  157. package/dist/platforma/platforma-search.service.d.ts +21 -0
  158. package/dist/platforma/platforma-search.service.d.ts.map +1 -0
  159. package/dist/platforma/platforma-search.service.js +64 -0
  160. package/dist/platforma/platforma-search.service.js.map +1 -0
  161. package/dist/platforma/platforma-video.service.d.ts +39 -0
  162. package/dist/platforma/platforma-video.service.d.ts.map +1 -0
  163. package/dist/platforma/platforma-video.service.js +301 -0
  164. package/dist/platforma/platforma-video.service.js.map +1 -0
  165. package/dist/platforma/platforma.controller.d.ts +209 -1
  166. package/dist/platforma/platforma.controller.d.ts.map +1 -1
  167. package/dist/platforma/platforma.controller.js +208 -2
  168. package/dist/platforma/platforma.controller.js.map +1 -1
  169. package/dist/realtime/lms-realtime.controller.d.ts +2 -0
  170. package/dist/realtime/lms-realtime.controller.d.ts.map +1 -1
  171. package/dist/realtime/lms-realtime.controller.js +31 -0
  172. package/dist/realtime/lms-realtime.controller.js.map +1 -1
  173. package/dist/realtime/lms-realtime.service.d.ts +1 -1
  174. package/dist/realtime/lms-realtime.service.d.ts.map +1 -1
  175. package/dist/realtime/lms-realtime.service.js.map +1 -1
  176. package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts +5 -0
  177. package/dist/student-xp/dto/grant-skill-card-xp.dto.d.ts.map +1 -0
  178. package/dist/student-xp/dto/grant-skill-card-xp.dto.js +26 -0
  179. package/dist/student-xp/dto/grant-skill-card-xp.dto.js.map +1 -0
  180. package/dist/student-xp/student-xp.controller.d.ts +15 -0
  181. package/dist/student-xp/student-xp.controller.d.ts.map +1 -1
  182. package/dist/student-xp/student-xp.controller.js +24 -0
  183. package/dist/student-xp/student-xp.controller.js.map +1 -1
  184. package/dist/student-xp/student-xp.service.d.ts +16 -0
  185. package/dist/student-xp/student-xp.service.d.ts.map +1 -1
  186. package/dist/student-xp/student-xp.service.js +51 -1
  187. package/dist/student-xp/student-xp.service.js.map +1 -1
  188. package/hedhog/data/evaluation_topic.yaml +17 -0
  189. package/hedhog/data/menu.yaml +0 -17
  190. package/hedhog/data/queue_definition.yaml +48 -0
  191. package/hedhog/data/route.yaml +94 -124
  192. package/hedhog/data/setting_group.yaml +19 -19
  193. package/hedhog/frontend/app/bulk-upload-sessions/page.tsx.ejs +337 -41
  194. package/hedhog/frontend/app/certificates/models/page.tsx.ejs +182 -29
  195. package/hedhog/frontend/app/classes/_components/classes-calendar-view.tsx.ejs +277 -0
  196. package/hedhog/frontend/app/classes/page.tsx.ejs +127 -20
  197. package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +69 -4
  198. package/hedhog/frontend/app/courses/[id]/structure/_components/course-export-sheet.tsx.ejs +420 -0
  199. package/hedhog/frontend/app/courses/[id]/structure/_components/course-exports-tab.tsx.ejs +308 -0
  200. package/hedhog/frontend/app/courses/[id]/structure/_components/course-overview-tab.tsx.ejs +158 -45
  201. package/hedhog/frontend/app/courses/[id]/structure/_components/course-xp-overview-tab.tsx.ejs +13 -13
  202. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson-xp-tab.tsx.ejs +11 -23
  203. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +51 -63
  204. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-panel.tsx.ejs +8 -3
  205. package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +31 -8
  206. package/hedhog/frontend/app/courses/[id]/structure/_components/drag-overlay.tsx.ejs +16 -9
  207. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +201 -401
  208. package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +378 -690
  209. package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -2
  210. package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +3 -9
  211. package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +1 -1
  212. package/hedhog/frontend/app/courses/[id]/structure/_components/xp-premium-pills.tsx.ejs +1 -8
  213. package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +6 -10
  214. package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +49 -0
  215. package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +4 -3
  216. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-content-overview.ts.ejs +2 -1
  217. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-exports.ts.ejs +106 -0
  218. package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +28 -1
  219. package/hedhog/frontend/app/courses/[id]/structure/_data/use-lms-settings-query.ts.ejs +0 -2
  220. package/hedhog/frontend/app/courses/page.tsx.ejs +85 -9
  221. package/hedhog/frontend/app/enterprise/[id]/page.tsx.ejs +6 -0
  222. package/hedhog/frontend/app/enterprise/_components/enterprise-classes-calendar-tab.tsx.ejs +264 -0
  223. package/hedhog/frontend/app/enterprise/page.tsx.ejs +104 -47
  224. package/hedhog/frontend/app/exams/page.tsx.ejs +38 -4
  225. package/hedhog/frontend/app/instructors/page.tsx.ejs +87 -46
  226. package/hedhog/frontend/app/paths/page.tsx.ejs +38 -4
  227. package/hedhog/frontend/app/training/page.tsx.ejs +38 -4
  228. package/hedhog/frontend/messages/en.json +44 -28
  229. package/hedhog/frontend/messages/pt.json +47 -29
  230. package/hedhog/table/course_enrollment.yaml +3 -0
  231. package/hedhog/table/course_export.yaml +62 -0
  232. package/hedhog/table/lesson_view_event.yaml +66 -0
  233. package/package.json +14 -9
  234. package/src/bitcode-wallet/bitcode-wallet.service.ts +43 -4
  235. package/src/course/course-export-scorm12-worker.service.ts +124 -0
  236. package/src/course/course-export-scorm12.service.ts +668 -0
  237. package/src/course/course-export.service.ts +280 -0
  238. package/src/course/course-structure.controller.ts +16 -2
  239. package/src/course/course-structure.service.ts +100 -7
  240. package/src/course/course-video-agent-pipeline.service.ts +471 -0
  241. package/src/course/course-video-hls.service.ts +966 -0
  242. package/src/course/course.controller.ts +33 -19
  243. package/src/course/course.mcp-tools.ts +1 -1
  244. package/src/course/course.module.ts +16 -0
  245. package/src/course/course.service.ts +119 -61
  246. package/src/course/dto/cleanup-course-storage.dto.ts +1 -0
  247. package/src/course/dto/cleanup-upload-history.dto.ts +1 -1
  248. package/src/course/dto/create-course-bulk-job.dto.ts +7 -3
  249. package/src/course/dto/create-course-export.dto.ts +56 -0
  250. package/src/course/dto/create-course-structure-lesson.dto.ts +4 -3
  251. package/src/course/ffmpeg.util.ts +65 -0
  252. package/src/course/lms-bulk-upload-automation.service.ts +156 -6
  253. package/src/course/lms-bulk-upload-infra.service.ts +39 -6
  254. package/src/course/lms-bulk-upload.controller.ts +32 -2
  255. package/src/course/lms-bulk-upload.service.ts +70 -7
  256. package/src/course/lms-setting.controller.ts +4 -2
  257. package/src/course/scorm12-schemas.ts +9 -0
  258. package/src/enterprise/training/training-student.service.ts +221 -2
  259. package/src/evaluation/evaluation.service.ts +123 -0
  260. package/src/exam/dto/create-standalone-question.dto.ts +66 -0
  261. package/src/exam/exam.module.ts +2 -1
  262. package/src/exam/exam.service.ts +86 -0
  263. package/src/exam/question.controller.ts +28 -0
  264. package/src/lesson-xp-map/lesson-xp-ai-calculation.service.ts +205 -31
  265. package/src/lms-commerce-access.subscriber.ts +88 -0
  266. package/src/lms.module.ts +16 -5
  267. package/src/platforma/dto/heartbeat.dto.ts +30 -0
  268. package/src/platforma/handlers/emit-certificate.handler.ts +117 -0
  269. package/src/platforma/handlers/lesson-heartbeat.handler.ts +343 -0
  270. package/src/platforma/platforma-heartbeat.service.ts +33 -0
  271. package/src/platforma/platforma-performance.service.ts +606 -0
  272. package/src/platforma/platforma-search.service.ts +48 -0
  273. package/src/platforma/platforma-video.service.ts +346 -0
  274. package/src/platforma/platforma.controller.ts +137 -1
  275. package/src/platforma/platforma.service.ts +268 -268
  276. package/src/realtime/lms-realtime.controller.ts +27 -1
  277. package/src/realtime/lms-realtime.service.ts +2 -1
  278. package/src/student-xp/dto/grant-skill-card-xp.dto.ts +10 -0
  279. package/src/student-xp/student-xp.controller.ts +18 -2
  280. package/src/student-xp/student-xp.service.ts +84 -2
  281. package/hedhog/data/video_resolution_profile.yaml +0 -7
  282. package/hedhog/frontend/app/video-resolution-profiles/page.tsx.ejs +0 -607
  283. package/hedhog/table/course_video_resolution_profile.yaml +0 -22
  284. package/hedhog/table/video_resolution_profile.yaml +0 -18
  285. package/src/video-resolution-profile/dto/create-video-resolution-profile.dto.ts +0 -16
  286. package/src/video-resolution-profile/dto/update-video-resolution-profile.dto.ts +0 -16
  287. package/src/video-resolution-profile/video-resolution-profile.controller.ts +0 -62
  288. package/src/video-resolution-profile/video-resolution-profile.mcp-tools.ts +0 -128
  289. package/src/video-resolution-profile/video-resolution-profile.module.ts +0 -13
  290. package/src/video-resolution-profile/video-resolution-profile.service.ts +0 -117
@@ -33,6 +33,12 @@ import {
33
33
  TableRow,
34
34
  } from '@/components/ui/table';
35
35
  import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';
36
+ import {
37
+ Tooltip,
38
+ TooltipContent,
39
+ TooltipProvider,
40
+ TooltipTrigger,
41
+ } from '@/components/ui/tooltip';
36
42
  import { usePersistedPageSize } from '@/hooks/use-persisted-page-size';
37
43
  import { cn } from '@/lib/utils';
38
44
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
@@ -48,7 +54,7 @@ import {
48
54
  Users,
49
55
  } from 'lucide-react';
50
56
  import { useTranslations } from 'next-intl';
51
- import { useEffect, useState } from 'react';
57
+ import { useEffect, useMemo, useState } from 'react';
52
58
  import { toast } from 'sonner';
53
59
  import { InstructorFormSheet } from './_components/instructor-form-sheet';
54
60
  import type {
@@ -95,10 +101,43 @@ export default function InstructorsPage() {
95
101
  const t = useTranslations('lms.InstructorsPage');
96
102
 
97
103
  const [page, setPage] = useState(1);
104
+ const { data: generalSettings } = useQuery<{
105
+ data: Array<{ slug: string; value: string }>;
106
+ }>({
107
+ queryKey: ['setting-group-general'],
108
+ queryFn: async () => {
109
+ const response = await request<{
110
+ data: Array<{ slug: string; value: string }>;
111
+ }>({
112
+ url: '/setting/group/general',
113
+ method: 'GET',
114
+ });
115
+ return response.data;
116
+ },
117
+ staleTime: 5 * 60 * 1000,
118
+ });
119
+
120
+ const pageSizeOptions = useMemo(() => {
121
+ const setting = generalSettings?.data?.find(
122
+ (s) => s.slug === 'pagination-page-sizes'
123
+ );
124
+ if (!setting?.value) return [6, 12, 24, 48, 96];
125
+ try {
126
+ const parsed = JSON.parse(setting.value) as string[];
127
+ const sizes = parsed
128
+ .map(Number)
129
+ .filter((n) => !isNaN(n) && n > 0)
130
+ .sort((a, b) => a - b);
131
+ return sizes.length > 0 ? sizes : [6, 12, 24, 48, 96];
132
+ } catch {
133
+ return [6, 12, 24, 48, 96];
134
+ }
135
+ }, [generalSettings]);
136
+
98
137
  const [pageSize, setPageSize] = usePersistedPageSize({
99
138
  storageKey: 'pagination:global:pageSize',
100
139
  defaultValue: 12,
101
- allowedValues: [6, 12, 24, 48],
140
+ allowedValues: pageSizeOptions,
102
141
  });
103
142
  const [searchInput, setSearchInput] = useState('');
104
143
  const [debouncedSearch, setDebouncedSearch] = useState('');
@@ -329,50 +368,52 @@ export default function InstructorsPage() {
329
368
 
330
369
  <KpiCardsGrid items={statsCards} />
331
370
 
332
- <div className="flex flex-col gap-4 xl:flex-row xl:items-center">
333
- <div className="flex-1">
334
- <SearchBar
335
- searchQuery={searchInput}
336
- onSearchChange={(value) => {
337
- setSearchInput(value);
338
- }}
339
- onSearch={() => setPage(1)}
340
- placeholder={t('search.placeholder')}
341
- controls={searchControls}
342
- />{' '}
343
- </div>
344
-
345
- <div className="flex items-center justify-between gap-3 sm:justify-start xl:justify-end">
346
- <span className="text-xs font-medium text-muted-foreground">
347
- {t('viewMode.label')}
348
- </span>
349
- <ToggleGroup
350
- type="single"
351
- value={viewMode}
352
- onValueChange={handleViewModeChange}
353
- variant="outline"
354
- size="sm"
355
- aria-label={t('viewMode.ariaLabel')}
356
- >
357
- <ToggleGroupItem
358
- value="table"
359
- className="gap-1.5 px-2.5"
360
- aria-label={t('viewMode.tableAriaLabel')}
361
- >
362
- <List className="h-4 w-4" />
363
- <span className="hidden sm:inline">{t('viewMode.table')}</span>
364
- </ToggleGroupItem>
365
- <ToggleGroupItem
366
- value="cards"
367
- className="gap-1.5 px-2.5"
368
- aria-label={t('viewMode.cardsAriaLabel')}
371
+ <SearchBar
372
+ searchQuery={searchInput}
373
+ onSearchChange={(value) => {
374
+ setSearchInput(value);
375
+ }}
376
+ onSearch={() => setPage(1)}
377
+ placeholder={t('search.placeholder')}
378
+ controls={searchControls}
379
+ actions={
380
+ <TooltipProvider>
381
+ <ToggleGroup
382
+ type="single"
383
+ value={viewMode}
384
+ onValueChange={handleViewModeChange}
385
+ variant="outline"
386
+ size="sm"
387
+ aria-label={t('viewMode.ariaLabel')}
369
388
  >
370
- <LayoutGrid className="h-4 w-4" />
371
- <span className="hidden sm:inline">{t('viewMode.cards')}</span>
372
- </ToggleGroupItem>
373
- </ToggleGroup>
374
- </div>
375
- </div>
389
+ <Tooltip>
390
+ <TooltipTrigger asChild>
391
+ <ToggleGroupItem
392
+ value="table"
393
+ className="cursor-pointer"
394
+ aria-label={t('viewMode.tableAriaLabel')}
395
+ >
396
+ <List className="h-4 w-4" />
397
+ </ToggleGroupItem>
398
+ </TooltipTrigger>
399
+ <TooltipContent>{t('viewMode.table')}</TooltipContent>
400
+ </Tooltip>
401
+ <Tooltip>
402
+ <TooltipTrigger asChild>
403
+ <ToggleGroupItem
404
+ value="cards"
405
+ className="cursor-pointer"
406
+ aria-label={t('viewMode.cardsAriaLabel')}
407
+ >
408
+ <LayoutGrid className="h-4 w-4" />
409
+ </ToggleGroupItem>
410
+ </TooltipTrigger>
411
+ <TooltipContent>{t('viewMode.cards')}</TooltipContent>
412
+ </Tooltip>
413
+ </ToggleGroup>
414
+ </TooltipProvider>
415
+ }
416
+ />
376
417
 
377
418
  {isLoading ? (
378
419
  viewMode === 'cards' ? (
@@ -726,7 +767,7 @@ export default function InstructorsPage() {
726
767
  setPageSize(nextPageSize);
727
768
  setPage(1);
728
769
  }}
729
- pageSizeOptions={[6, 12, 24]}
770
+ pageSizeOptions={pageSizeOptions}
730
771
  />
731
772
 
732
773
  <InstructorFormSheet
@@ -462,7 +462,7 @@ const STATUS_MAP: Record<
462
462
  encerrada: { label: 'Encerrada', variant: 'outline' },
463
463
  };
464
464
 
465
- const PAGE_SIZES = [6, 12, 24];
465
+ const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
466
466
  const API_TRAINING_CACHE_KEY = 'lms:training:api-cache';
467
467
 
468
468
  // ── Animations ────────────────────────────────────────────────────────────────
@@ -578,10 +578,44 @@ export default function TrainingPage() {
578
578
 
579
579
  // Pagination
580
580
  const [currentPage, setCurrentPage] = useState(1);
581
+
582
+ const { data: generalSettings } = useQuery<{
583
+ data: Array<{ slug: string; value: string }>;
584
+ }>({
585
+ queryKey: ['setting-group-general'],
586
+ queryFn: async () => {
587
+ const response = await request<{
588
+ data: Array<{ slug: string; value: string }>;
589
+ }>({
590
+ url: '/setting/group/general',
591
+ method: 'GET',
592
+ });
593
+ return response.data;
594
+ },
595
+ staleTime: 5 * 60 * 1000,
596
+ });
597
+
598
+ const pageSizeOptions = useMemo(() => {
599
+ const setting = generalSettings?.data?.find(
600
+ (s) => s.slug === 'pagination-page-sizes'
601
+ );
602
+ if (!setting?.value) return DEFAULT_PAGE_SIZES;
603
+ try {
604
+ const parsed = JSON.parse(setting.value) as string[];
605
+ const sizes = parsed
606
+ .map(Number)
607
+ .filter((n) => !isNaN(n) && n > 0)
608
+ .sort((a, b) => a - b);
609
+ return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
610
+ } catch {
611
+ return DEFAULT_PAGE_SIZES;
612
+ }
613
+ }, [generalSettings]);
614
+
581
615
  const [pageSize, setPageSize] = usePersistedPageSize({
582
616
  storageKey: 'pagination:global:pageSize',
583
617
  defaultValue: 12,
584
- allowedValues: PAGE_SIZES,
618
+ allowedValues: pageSizeOptions,
585
619
  });
586
620
 
587
621
  const sensors = useSensors(
@@ -1500,7 +1534,7 @@ export default function TrainingPage() {
1500
1534
  ],
1501
1535
  },
1502
1536
  ]}
1503
- afterSearchButton={
1537
+ actions={
1504
1538
  <ViewModeToggle
1505
1539
  viewMode={viewMode}
1506
1540
  onViewModeChange={setViewMode}
@@ -1848,7 +1882,7 @@ export default function TrainingPage() {
1848
1882
  setPageSize(nextPageSize);
1849
1883
  setCurrentPage(1);
1850
1884
  }}
1851
- pageSizeOptions={PAGE_SIZES}
1885
+ pageSizeOptions={pageSizeOptions}
1852
1886
  />
1853
1887
  </div>
1854
1888
  )}
@@ -448,7 +448,7 @@ const STATUS_MAP: Record<
448
448
  encerrada: { label: 'Encerrada', variant: 'outline' },
449
449
  };
450
450
 
451
- const PAGE_SIZES = [6, 12, 24];
451
+ const DEFAULT_PAGE_SIZES = [6, 12, 24, 48, 96] as const;
452
452
  const API_TRAINING_CACHE_KEY = 'lms:training:api-cache';
453
453
 
454
454
  // ── Animations ────────────────────────────────────────────────────────────────
@@ -564,10 +564,44 @@ export default function TrainingPage() {
564
564
 
565
565
  // Pagination
566
566
  const [currentPage, setCurrentPage] = useState(1);
567
+
568
+ const { data: generalSettings } = useQuery<{
569
+ data: Array<{ slug: string; value: string }>;
570
+ }>({
571
+ queryKey: ['setting-group-general'],
572
+ queryFn: async () => {
573
+ const response = await request<{
574
+ data: Array<{ slug: string; value: string }>;
575
+ }>({
576
+ url: '/setting/group/general',
577
+ method: 'GET',
578
+ });
579
+ return response.data;
580
+ },
581
+ staleTime: 5 * 60 * 1000,
582
+ });
583
+
584
+ const pageSizeOptions = useMemo(() => {
585
+ const setting = generalSettings?.data?.find(
586
+ (s) => s.slug === 'pagination-page-sizes'
587
+ );
588
+ if (!setting?.value) return DEFAULT_PAGE_SIZES;
589
+ try {
590
+ const parsed = JSON.parse(setting.value) as string[];
591
+ const sizes = parsed
592
+ .map(Number)
593
+ .filter((n) => !isNaN(n) && n > 0)
594
+ .sort((a, b) => a - b);
595
+ return sizes.length > 0 ? sizes : DEFAULT_PAGE_SIZES;
596
+ } catch {
597
+ return DEFAULT_PAGE_SIZES;
598
+ }
599
+ }, [generalSettings]);
600
+
567
601
  const [pageSize, setPageSize] = usePersistedPageSize({
568
602
  storageKey: 'pagination:global:pageSize',
569
603
  defaultValue: 12,
570
- allowedValues: PAGE_SIZES,
604
+ allowedValues: pageSizeOptions,
571
605
  });
572
606
 
573
607
  const sensors = useSensors(
@@ -1490,7 +1524,7 @@ export default function TrainingPage() {
1490
1524
  ],
1491
1525
  },
1492
1526
  ]}
1493
- afterSearchButton={
1527
+ actions={
1494
1528
  <ViewModeToggle
1495
1529
  viewMode={viewMode}
1496
1530
  onViewModeChange={setViewMode}
@@ -1838,7 +1872,7 @@ export default function TrainingPage() {
1838
1872
  setPageSize(nextPageSize);
1839
1873
  setCurrentPage(1);
1840
1874
  }}
1841
- pageSizeOptions={PAGE_SIZES}
1875
+ pageSizeOptions={pageSizeOptions}
1842
1876
  />
1843
1877
  </div>
1844
1878
  )}
@@ -555,6 +555,13 @@
555
555
  "withTranscription": "With transcription",
556
556
  "withXp": "With XP"
557
557
  },
558
+ "videoPipeline": {
559
+ "title": "Video pipeline",
560
+ "description": "Video lessons by stage: total → has video → processed",
561
+ "total": "Video lessons",
562
+ "withVideo": "With video",
563
+ "withProcessedVideo": "Video processed"
564
+ },
558
565
  "areas": {
559
566
  "title": "Macro areas",
560
567
  "description": "Areas mapped across lessons, ordered by XP weight"
@@ -579,6 +586,8 @@
579
586
  "statusProgress": "{completed}/{total} required items completed",
580
587
  "ready": "Ready to publish",
581
588
  "notReady": "Not ready yet",
589
+ "publishButton": "Publish course",
590
+ "alreadyPublished": "Course already published",
582
591
  "items": {
583
592
  "title": "Commercial title filled",
584
593
  "description": "Public description filled",
@@ -1197,36 +1206,32 @@
1197
1206
  },
1198
1207
  "addResource": "Add resource",
1199
1208
  "noResources": "No resources added",
1200
- "fileStorageVideosByResolution": "Videos by resolution (File Storage)",
1201
- "videoResolutionPlaceholder": "Eg.: 1080p",
1202
- "uploadVideoForResolution": "Upload video for this resolution",
1203
- "noResolutionVideosYet": "No resolution-based videos uploaded yet.",
1204
- "loadingVideoProfiles": "Loading course video profiles...",
1205
- "videoProfilesLoadError": "Could not load the course video profiles.",
1206
- "retryLoadVideoProfiles": "Try loading again",
1207
- "noVideoProfilesConfigured": "Configure video profiles in the course Resolutions tab before attaching File Storage videos.",
1209
+ "hlsStatusTitle": "HLS Stream",
1210
+ "hlsStatusReady": "Stream available for students.",
1211
+ "hlsStatusProcessing": "Processing video...",
1212
+ "hlsStatusPending": "No video processed yet.",
1208
1213
  "originalVideoTitle": "Original high-resolution video",
1209
- "originalVideoHint": "Upload an original video to automatically generate the course profile videos.",
1210
- "originalVideoPurpose": "This original file is only used to generate the course video variants.",
1211
- "fileStorageVideoHint": "Use the original video below to automatically generate the course profile variants.",
1212
- "uploadOriginalForConversion": "Upload original for conversion",
1214
+ "originalVideoHint": "Upload an original video to automatically generate the HLS stream for this course.",
1215
+ "originalVideoPurpose": "This original file is only used to generate the adaptive streaming for this course.",
1216
+ "fileStorageVideoHint": "Use the original video below to automatically generate the HLS stream for this course.",
1217
+ "uploadOriginalForConversion": "Upload video for processing",
1213
1218
  "replaceOriginalForConversion": "Replace original video",
1214
1219
  "retryConversionWithSavedOriginal": "Start a new job with the saved original",
1215
- "videoUploadBlockedWhileProcessing": "Original uploads stay blocked while the current conversion is still running.",
1220
+ "videoUploadBlockedWhileProcessing": "Original uploads stay blocked while the current processing job is still running.",
1216
1221
  "videoJobStateLoading": "Waiting for the latest job status before allowing new actions.",
1217
1222
  "videoProviderSavePending": "Wait for the provider to be saved before uploading the original video.",
1218
1223
  "videoUploadMaxSizeError": "The video exceeds the {size} limit.",
1219
- "videoConversionQueued": "Video conversion queued as job #{id}.",
1220
- "videoConversionFailed": "Could not queue the video conversion.",
1224
+ "videoConversionQueued": "Video processing queued as job #{id}.",
1225
+ "videoConversionFailed": "Could not queue the video for processing.",
1221
1226
  "videoConversionRetryFailed": "Could not start a new job with the saved original video.",
1222
- "videoConversionJob": "Conversion queued as job #{id}",
1223
- "videoJobFeedbackTitle": "Conversion tracking",
1224
- "videoJobToggleDetails": "Toggle conversion details",
1225
- "videoJobCollapsedSummary": "Conversion completed successfully. Processed videos are listed in the resolution section above.",
1226
- "videoJobLoading": "Loading conversion progress...",
1227
- "videoJobPendingLoad": "Preparing conversion job tracking...",
1228
- "awaitingConversion": "Awaiting conversion...",
1229
- "videoJobLoadError": "Could not load the conversion progress.",
1227
+ "videoConversionJob": "Processing queued as job #{id}",
1228
+ "videoJobFeedbackTitle": "Processing status",
1229
+ "videoJobToggleDetails": "Toggle processing details",
1230
+ "videoJobCollapsedSummary": "Processing completed successfully. HLS streaming is now available for students.",
1231
+ "videoJobLoading": "Loading processing progress...",
1232
+ "videoJobPendingLoad": "Preparing processing job tracking...",
1233
+ "awaitingConversion": "Awaiting processing...",
1234
+ "videoJobLoadError": "Could not load the processing progress.",
1230
1235
  "retryLoadVideoJob": "Try again",
1231
1236
  "videoJobIdLabel": "Job",
1232
1237
  "videoJobAttemptsLabel": "Attempts",
@@ -1242,7 +1247,6 @@
1242
1247
  "videoJobRecentEvents": "Recent events",
1243
1248
  "videoJobTranscriptionEvents": "Recent transcription events",
1244
1249
  "videoJobNoEvents": "No events recorded yet.",
1245
- "videoProfilesLockedWhileProcessing": "Profile video uploads stay locked while the original conversion job is active.",
1246
1250
  "videoJobStatuses": {
1247
1251
  "pending": "Queued",
1248
1252
  "scheduled": "Scheduled",
@@ -1274,8 +1278,9 @@
1274
1278
  },
1275
1279
  "videoJobProgress": {
1276
1280
  "download_original": "Downloading original video...",
1277
- "probe_duration": "Reading video duration...",
1278
- "convert_profile": "Converting video for the {profileName} profile...",
1281
+ "probe_duration": "Reading video dimensions and duration...",
1282
+ "hls_encode": "Generating HLS stream...",
1283
+ "hls_upload": "Uploading HLS segments to storage...",
1279
1284
  "extract_frames": "Extracting video frames...",
1280
1285
  "extract_frames_done": "Frames extracted: {count}.",
1281
1286
  "extract_audio": "Extracting video audio...",
@@ -1342,8 +1347,7 @@
1342
1347
  "types": {
1343
1348
  "video": "Video",
1344
1349
  "post": "Post",
1345
- "questao": "Question",
1346
- "exercicio": "Exercise"
1350
+ "questao": "Question"
1347
1351
  },
1348
1352
  "statuses": {
1349
1353
  "preparada": "Prepared",
@@ -1382,6 +1386,7 @@
1382
1386
  "videoUploadFailed": "Failed to upload {count} video file(s).",
1383
1387
  "newQuestion": "New question",
1384
1388
  "editQuestion": "Edit question",
1389
+ "loadingQuestions": "Loading questions...",
1385
1390
  "selectQuestion": "Select question...",
1386
1391
  "searchQuestion": "Search question...",
1387
1392
  "noQuestionsFound": "No questions found",
@@ -3051,6 +3056,17 @@
3051
3056
  "cancel": "Cancel",
3052
3057
  "delete": "Remove"
3053
3058
  }
3059
+ },
3060
+ "viewMode": {
3061
+ "list": "Show as list",
3062
+ "cards": "Show as cards"
3063
+ },
3064
+ "table": {
3065
+ "name": "Name",
3066
+ "slug": "Slug",
3067
+ "status": "Status",
3068
+ "updatedAt": "Updated at",
3069
+ "actions": "Actions"
3054
3070
  }
3055
3071
  },
3056
3072
  "ClassesPage": {
@@ -564,6 +564,13 @@
564
564
  "withTranscription": "Com transcrição",
565
565
  "withXp": "Com XP"
566
566
  },
567
+ "videoPipeline": {
568
+ "title": "Pipeline de vídeo",
569
+ "description": "Aulas de vídeo por estágio: total → com vídeo → processado",
570
+ "total": "Aulas de vídeo",
571
+ "withVideo": "Com vídeo",
572
+ "withProcessedVideo": "Vídeo processado"
573
+ },
567
574
  "areas": {
568
575
  "title": "Áreas macro",
569
576
  "description": "Áreas mapeadas nas aulas, ordenadas por peso de XP"
@@ -588,6 +595,8 @@
588
595
  "statusProgress": "{completed}/{total} itens obrigatórios concluídos",
589
596
  "ready": "Pronto para publicar",
590
597
  "notReady": "Ainda não pronto",
598
+ "publishButton": "Publicar curso",
599
+ "alreadyPublished": "Curso já publicado",
591
600
  "items": {
592
601
  "title": "Título comercial preenchido",
593
602
  "description": "Descrição pública preenchida",
@@ -1206,36 +1215,32 @@
1206
1215
  },
1207
1216
  "addResource": "Adicionar recurso",
1208
1217
  "noResources": "Nenhum recurso adicionado",
1209
- "fileStorageVideosByResolution": "Vídeos por resolução (File Storage)",
1210
- "videoResolutionPlaceholder": "Ex.: 1080p",
1211
- "uploadVideoForResolution": "Enviar vídeo para esta resolução",
1212
- "noResolutionVideosYet": "Nenhum vídeo por resolução enviado ainda.",
1213
- "loadingVideoProfiles": "Carregando perfis de vídeo do curso...",
1214
- "videoProfilesLoadError": "Não foi possível carregar os perfis de vídeo do curso.",
1215
- "retryLoadVideoProfiles": "Tentar carregar novamente",
1216
- "noVideoProfilesConfigured": "Configure os perfis de vídeo na aba Resoluções do curso antes de anexar vídeos File Storage.",
1218
+ "hlsStatusTitle": "Streaming HLS",
1219
+ "hlsStatusReady": "Streaming disponível para os alunos.",
1220
+ "hlsStatusProcessing": "Processando vídeo...",
1221
+ "hlsStatusPending": "Nenhum vídeo processado ainda.",
1217
1222
  "originalVideoTitle": "Vídeo original em alta resolução",
1218
- "originalVideoHint": "Envie um original para gerar automaticamente os vídeos dos perfis do curso.",
1219
- "originalVideoPurpose": "Este arquivo original é usado apenas para gerar as versões de vídeo do curso.",
1220
- "fileStorageVideoHint": "Use o vídeo original abaixo para gerar automaticamente as versões por perfil do curso.",
1221
- "uploadOriginalForConversion": "Enviar original para conversão",
1223
+ "originalVideoHint": "Envie um original para gerar automaticamente o streaming HLS do curso.",
1224
+ "originalVideoPurpose": "Este arquivo original é usado apenas para gerar o streaming adaptativo do curso.",
1225
+ "fileStorageVideoHint": "Use o vídeo original abaixo para gerar automaticamente o streaming HLS do curso.",
1226
+ "uploadOriginalForConversion": "Enviar vídeo para processamento",
1222
1227
  "replaceOriginalForConversion": "Substituir vídeo original",
1223
1228
  "retryConversionWithSavedOriginal": "Iniciar novo job com o original salvo",
1224
- "videoUploadBlockedWhileProcessing": "O upload de original fica bloqueado enquanto a conversão atual estiver em andamento.",
1229
+ "videoUploadBlockedWhileProcessing": "O upload de original fica bloqueado enquanto o processamento atual estiver em andamento.",
1225
1230
  "videoJobStateLoading": "Aguardando o status mais recente do job atual para liberar novas ações.",
1226
1231
  "videoProviderSavePending": "Aguarde o provedor ser salvo antes de enviar o vídeo original.",
1227
1232
  "videoUploadMaxSizeError": "O vídeo excede o limite de {size}.",
1228
- "videoConversionQueued": "Conversão de vídeo enviada para a fila #{id}.",
1229
- "videoConversionFailed": "Não foi possível enviar o vídeo para conversão.",
1233
+ "videoConversionQueued": "Processamento de vídeo enviado para a fila #{id}.",
1234
+ "videoConversionFailed": "Não foi possível enviar o vídeo para processamento.",
1230
1235
  "videoConversionRetryFailed": "Não foi possível iniciar um novo job com o vídeo original salvo.",
1231
- "videoConversionJob": "Conversão na fila #{id}",
1232
- "videoJobFeedbackTitle": "Acompanhamento da conversão",
1233
- "videoJobToggleDetails": "Alternar detalhes da conversão",
1234
- "videoJobCollapsedSummary": "Conversão concluída com sucesso. Os vídeos processados aparecem na lista de resoluções acima.",
1235
- "videoJobLoading": "Carregando andamento da conversão...",
1236
- "videoJobPendingLoad": "Preparando acompanhamento do job de conversão...",
1237
- "awaitingConversion": "Aguardando conversão...",
1238
- "videoJobLoadError": "Não foi possível carregar o andamento da conversão.",
1236
+ "videoConversionJob": "Processamento na fila #{id}",
1237
+ "videoJobFeedbackTitle": "Acompanhamento do processamento",
1238
+ "videoJobToggleDetails": "Alternar detalhes do processamento",
1239
+ "videoJobCollapsedSummary": "Processamento concluído com sucesso. O streaming HLS está disponível para os alunos.",
1240
+ "videoJobLoading": "Carregando andamento do processamento...",
1241
+ "videoJobPendingLoad": "Preparando acompanhamento do processamento...",
1242
+ "awaitingConversion": "Aguardando processamento...",
1243
+ "videoJobLoadError": "Não foi possível carregar o andamento do processamento.",
1239
1244
  "retryLoadVideoJob": "Tentar novamente",
1240
1245
  "videoJobIdLabel": "Job",
1241
1246
  "videoJobAttemptsLabel": "Tentativas",
@@ -1251,7 +1256,6 @@
1251
1256
  "videoJobRecentEvents": "Eventos recentes",
1252
1257
  "videoJobTranscriptionEvents": "Eventos recentes da transcrição",
1253
1258
  "videoJobNoEvents": "Nenhum evento registrado ainda.",
1254
- "videoProfilesLockedWhileProcessing": "Os vídeos por perfil ficam bloqueados enquanto a conversão do original está ativa.",
1255
1259
  "videoJobStatuses": {
1256
1260
  "pending": "Na fila",
1257
1261
  "scheduled": "Agendado",
@@ -1283,8 +1287,9 @@
1283
1287
  },
1284
1288
  "videoJobProgress": {
1285
1289
  "download_original": "Baixando vídeo original...",
1286
- "probe_duration": "Lendo duração do vídeo...",
1287
- "convert_profile": "Convertendo vídeo para o perfil {profileName}...",
1290
+ "probe_duration": "Lendo dimensões e duração do vídeo...",
1291
+ "hls_encode": "Gerando streaming HLS...",
1292
+ "hls_upload": "Enviando segmentos HLS para storage...",
1288
1293
  "extract_frames": "Extraindo imagens do vídeo...",
1289
1294
  "extract_frames_done": "Imagens extraídas: {count}.",
1290
1295
  "extract_audio": "Extraindo áudio do vídeo...",
@@ -1351,8 +1356,7 @@
1351
1356
  "types": {
1352
1357
  "video": "Vídeo",
1353
1358
  "post": "Post",
1354
- "questao": "Questão",
1355
- "exercicio": "Exercício"
1359
+ "questao": "Questão"
1356
1360
  },
1357
1361
  "statuses": {
1358
1362
  "preparada": "Preparada",
@@ -1391,6 +1395,7 @@
1391
1395
  "videoUploadFailed": "Falha ao enviar {count} arquivo(s) de vídeo.",
1392
1396
  "newQuestion": "Nova questão",
1393
1397
  "editQuestion": "Editar questão",
1398
+ "loadingQuestions": "Carregando questões...",
1394
1399
  "selectQuestion": "Selecionar questão...",
1395
1400
  "searchQuestion": "Buscar questão...",
1396
1401
  "noQuestionsFound": "Nenhuma questão encontrada",
@@ -3073,6 +3078,17 @@
3073
3078
  "cancel": "Cancelar",
3074
3079
  "delete": "Remover"
3075
3080
  }
3081
+ },
3082
+ "viewMode": {
3083
+ "list": "Visualizar em lista",
3084
+ "cards": "Visualizar em cards"
3085
+ },
3086
+ "table": {
3087
+ "name": "Nome",
3088
+ "slug": "Slug",
3089
+ "status": "Status",
3090
+ "updatedAt": "Atualizado em",
3091
+ "actions": "Ações"
3076
3092
  }
3077
3093
  },
3078
3094
  "ClassesPage": {
@@ -3154,7 +3170,8 @@
3154
3170
  },
3155
3171
  "viewMode": {
3156
3172
  "list": "Visualizar em lista",
3157
- "cards": "Visualizar em cards"
3173
+ "cards": "Visualizar em cards",
3174
+ "calendar": "Visualizar em calendário"
3158
3175
  },
3159
3176
  "pagination": {
3160
3177
  "class": "turma",
@@ -4571,6 +4588,7 @@
4571
4588
  "users": "Usuários",
4572
4589
  "courses": "Cursos",
4573
4590
  "classes": "Turmas",
4591
+ "classesCalendar": "Calendário de Turmas",
4574
4592
  "billing": "Faturamento",
4575
4593
  "students": "Alunos",
4576
4594
  "administrators": "Administradores",
@@ -34,6 +34,9 @@ columns:
34
34
  - name: final_score
35
35
  type: int
36
36
  isNullable: true
37
+ - name: certificate_issued_at
38
+ type: datetime
39
+ isNullable: true
37
40
  - type: created_at
38
41
  - type: updated_at
39
42