@hed-hog/lms 0.0.306 → 0.0.309
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/course/course-structure.controller.d.ts +60 -0
- package/dist/course/course-structure.controller.d.ts.map +1 -1
- package/dist/course/course-structure.controller.js +79 -0
- package/dist/course/course-structure.controller.js.map +1 -1
- package/dist/course/course-structure.service.d.ts +61 -1
- package/dist/course/course-structure.service.d.ts.map +1 -1
- package/dist/course/course-structure.service.js +326 -1
- package/dist/course/course-structure.service.js.map +1 -1
- package/dist/course/course.controller.d.ts +52 -4
- package/dist/course/course.controller.d.ts.map +1 -1
- package/dist/course/course.service.d.ts +52 -5
- package/dist/course/course.service.d.ts.map +1 -1
- package/dist/course/course.service.js +78 -57
- package/dist/course/course.service.js.map +1 -1
- package/dist/course/dto/create-course-structure-lesson.dto.d.ts.map +1 -1
- package/dist/course/dto/create-course-structure-lesson.dto.js +5 -1
- package/dist/course/dto/create-course-structure-lesson.dto.js.map +1 -1
- package/dist/course/dto/create-course.dto.d.ts +1 -1
- package/dist/course/dto/create-course.dto.d.ts.map +1 -1
- package/dist/course/dto/create-course.dto.js +4 -1
- package/dist/course/dto/create-course.dto.js.map +1 -1
- package/dist/course/dto/move-lesson.dto.d.ts +10 -0
- package/dist/course/dto/move-lesson.dto.d.ts.map +1 -0
- package/dist/course/dto/move-lesson.dto.js +28 -0
- package/dist/course/dto/move-lesson.dto.js.map +1 -0
- package/dist/course/dto/paste-lessons.dto.d.ts +4 -0
- package/dist/course/dto/paste-lessons.dto.d.ts.map +1 -0
- package/dist/course/dto/paste-lessons.dto.js +24 -0
- package/dist/course/dto/paste-lessons.dto.js.map +1 -0
- package/dist/course/dto/reorder-lessons.dto.d.ts +5 -0
- package/dist/course/dto/reorder-lessons.dto.d.ts.map +1 -0
- package/dist/course/dto/reorder-lessons.dto.js +24 -0
- package/dist/course/dto/reorder-lessons.dto.js.map +1 -0
- package/dist/course/dto/reorder-sessions.dto.d.ts +5 -0
- package/dist/course/dto/reorder-sessions.dto.d.ts.map +1 -0
- package/dist/course/dto/reorder-sessions.dto.js +24 -0
- package/dist/course/dto/reorder-sessions.dto.js.map +1 -0
- package/dist/training/training.controller.js +1 -1
- package/dist/training/training.controller.js.map +1 -1
- package/hedhog/data/image_type.yaml +20 -0
- package/hedhog/data/menu.yaml +2 -2
- package/hedhog/data/route.yaml +60 -6
- package/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +146 -165
- package/hedhog/frontend/app/_components/course-avatar.tsx.ejs +70 -0
- package/hedhog/frontend/app/_components/course-form-sheet.tsx.ejs +372 -22
- package/hedhog/frontend/app/classes/[id]/page.tsx.ejs +437 -77
- package/hedhog/frontend/app/classes/page.tsx.ejs +311 -289
- package/hedhog/frontend/app/courses/[id]/_components/CourseCertificateCard.tsx.ejs +10 -7
- package/hedhog/frontend/app/courses/[id]/_components/CourseClassificationCard.tsx.ejs +23 -32
- package/hedhog/frontend/app/courses/[id]/_components/CourseContentCard.tsx.ejs +3 -9
- package/hedhog/frontend/app/courses/[id]/_components/CourseDangerZoneCard.tsx.ejs +26 -16
- package/hedhog/frontend/app/courses/[id]/_components/CourseFlagsCard.tsx.ejs +19 -5
- package/hedhog/frontend/app/courses/[id]/_components/CourseMainInfoCard.tsx.ejs +10 -14
- package/hedhog/frontend/app/courses/[id]/_components/CourseMediaCard.tsx.ejs +131 -107
- package/hedhog/frontend/app/courses/[id]/_components/CourseRelationsCard.tsx.ejs +10 -7
- package/hedhog/frontend/app/courses/[id]/_components/CourseSectionCard.tsx.ejs +38 -19
- package/hedhog/frontend/app/courses/[id]/_components/CourseSummaryCard.tsx.ejs +1 -1
- package/hedhog/frontend/app/courses/[id]/_components/course-edit-types.ts.ejs +1 -1
- package/hedhog/frontend/app/courses/[id]/page.tsx.ejs +336 -1057
- package/hedhog/frontend/app/courses/[id]/structure/_components/confirm-dialog.tsx.ejs +45 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-dnd.tsx.ejs +362 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-panel.tsx.ejs +111 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree-skeleton.tsx.ejs +64 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/course-tree.tsx.ejs +134 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-course.tsx.ejs +113 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-lesson.tsx.ejs +314 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-panel.tsx.ejs +62 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/detail-session.tsx.ejs +174 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/drag-handle.tsx.ejs +58 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/drag-overlay.tsx.ejs +52 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-bulk.tsx.ejs +276 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-course.tsx.ejs +1216 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +1827 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-session.tsx.ejs +443 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/highlighted-text.tsx.ejs +41 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +184 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/multi-select-bar.tsx.ejs +264 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/search-filter.tsx.ejs +96 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/session-picker-dialog.tsx.ejs +74 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/shortcuts-help.tsx.ejs +136 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/sortable-tree-row.tsx.ejs +80 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/store.ts.ejs +948 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-context-menu.tsx.ejs +525 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-display-settings-popover.tsx.ejs +150 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-helpers.ts.ejs +182 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-course.tsx.ejs +52 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-lesson.tsx.ejs +271 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row-session.tsx.ejs +167 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/tree-row.tsx.ejs +108 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +122 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/use-course-structure-shortcuts.ts.ejs +318 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/use-tree-display-settings.ts.ejs +97 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +347 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/course-structure-contract.ts.ejs +195 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/services/course-structure.service.ts.ejs +420 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/types/api-course.types.ts.ejs +254 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-mutations.ts.ejs +987 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure-query.ts.ejs +86 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/use-course-structure.ts.ejs +160 -0
- package/hedhog/frontend/app/courses/[id]/structure/page.tsx.ejs +10 -3212
- package/hedhog/frontend/app/courses/page.tsx.ejs +45 -26
- package/hedhog/frontend/app/{training → paths}/page.tsx.ejs +29 -7
- package/hedhog/frontend/messages/en.json +88 -10
- package/hedhog/frontend/messages/pt.json +88 -10
- package/hedhog/table/course.yaml +1 -1
- package/hedhog/table/image_type.yaml +14 -0
- package/package.json +7 -7
- package/src/course/course-structure.controller.ts +63 -0
- package/src/course/course-structure.service.ts +390 -3
- package/src/course/course.service.ts +59 -27
- package/src/course/dto/create-course-structure-lesson.dto.ts +3 -2
- package/src/course/dto/create-course.dto.ts +4 -1
- package/src/course/dto/move-lesson.dto.ts +17 -0
- package/src/course/dto/paste-lessons.dto.ts +9 -0
- package/src/course/dto/reorder-lessons.dto.ts +10 -0
- package/src/course/dto/reorder-sessions.dto.ts +10 -0
- package/src/training/training.controller.ts +1 -1
|
@@ -62,6 +62,7 @@ import { useRouter } from 'next/navigation';
|
|
|
62
62
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
63
63
|
import { useForm, useWatch } from 'react-hook-form';
|
|
64
64
|
import { toast } from 'sonner';
|
|
65
|
+
import { CourseAvatar } from '../_components/course-avatar';
|
|
65
66
|
import {
|
|
66
67
|
CourseCategoryOption,
|
|
67
68
|
CourseFormSheet,
|
|
@@ -76,7 +77,7 @@ const API_COURSES_CACHE_KEY = 'lms:courses:api-cache';
|
|
|
76
77
|
|
|
77
78
|
interface Curso {
|
|
78
79
|
id: number;
|
|
79
|
-
|
|
80
|
+
slug: string;
|
|
80
81
|
nomeInterno: string;
|
|
81
82
|
tituloComercial: string;
|
|
82
83
|
descricao: string;
|
|
@@ -90,11 +91,12 @@ interface Curso {
|
|
|
90
91
|
listado: boolean;
|
|
91
92
|
alunosInscritos: number;
|
|
92
93
|
criadoEm: string;
|
|
94
|
+
logoFileId?: number | null;
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
type ApiCourse = {
|
|
96
98
|
id: number;
|
|
97
|
-
|
|
99
|
+
name: string;
|
|
98
100
|
slug: string;
|
|
99
101
|
title: string;
|
|
100
102
|
description: string;
|
|
@@ -110,6 +112,7 @@ type ApiCourse = {
|
|
|
110
112
|
isListed: boolean;
|
|
111
113
|
enrollmentCount: number;
|
|
112
114
|
createdAt: string;
|
|
115
|
+
logoFileId?: number | null;
|
|
113
116
|
};
|
|
114
117
|
|
|
115
118
|
type ApiCourseList = {
|
|
@@ -199,8 +202,8 @@ function toPtStatus(status?: string | null): CourseSheetFormValues['status'] {
|
|
|
199
202
|
function mapApiCourse(course: ApiCourse): Curso {
|
|
200
203
|
return {
|
|
201
204
|
id: course.id,
|
|
202
|
-
|
|
203
|
-
nomeInterno: course.
|
|
205
|
+
slug: course.slug,
|
|
206
|
+
nomeInterno: course.name ?? '',
|
|
204
207
|
tituloComercial: course.title,
|
|
205
208
|
descricao: course.description ?? '',
|
|
206
209
|
primaryColor: course.primaryColor ?? null,
|
|
@@ -213,6 +216,7 @@ function mapApiCourse(course: ApiCourse): Curso {
|
|
|
213
216
|
listado: course.isListed,
|
|
214
217
|
alunosInscritos: course.enrollmentCount ?? 0,
|
|
215
218
|
criadoEm: course.createdAt ?? '',
|
|
219
|
+
logoFileId: course.logoFileId ?? null,
|
|
216
220
|
};
|
|
217
221
|
}
|
|
218
222
|
|
|
@@ -592,6 +596,7 @@ export default function CursosPage() {
|
|
|
592
596
|
setEditingCurso(curso);
|
|
593
597
|
form.reset({
|
|
594
598
|
nomeInterno: curso.nomeInterno,
|
|
599
|
+
slug: curso.slug,
|
|
595
600
|
tituloComercial: curso.tituloComercial,
|
|
596
601
|
descricao: curso.descricao,
|
|
597
602
|
primaryColor: curso.primaryColor || '#1D4ED8',
|
|
@@ -599,6 +604,7 @@ export default function CursosPage() {
|
|
|
599
604
|
nivel: curso.nivel,
|
|
600
605
|
status: curso.status,
|
|
601
606
|
categorias: curso.categorias,
|
|
607
|
+
logoFileId: curso.logoFileId ?? null,
|
|
602
608
|
});
|
|
603
609
|
setSheetOpen(true);
|
|
604
610
|
}
|
|
@@ -607,7 +613,8 @@ export default function CursosPage() {
|
|
|
607
613
|
setSaving(true);
|
|
608
614
|
try {
|
|
609
615
|
const payload = {
|
|
610
|
-
|
|
616
|
+
name: data.nomeInterno.trim(),
|
|
617
|
+
slug: data.slug.trim().toLowerCase(),
|
|
611
618
|
title: data.tituloComercial,
|
|
612
619
|
description: data.descricao,
|
|
613
620
|
level: toApiLevel(data.nivel),
|
|
@@ -617,6 +624,7 @@ export default function CursosPage() {
|
|
|
617
624
|
primaryContrastColor: getContrastColor(data.primaryColor),
|
|
618
625
|
secondaryColor: data.secondaryColor,
|
|
619
626
|
secondaryContrastColor: getContrastColor(data.secondaryColor),
|
|
627
|
+
logoFileId: data.logoFileId ?? null,
|
|
620
628
|
};
|
|
621
629
|
|
|
622
630
|
if (editingCurso) {
|
|
@@ -1071,13 +1079,16 @@ export default function CursosPage() {
|
|
|
1071
1079
|
|
|
1072
1080
|
<CardContent className="flex h-full flex-col p-4">
|
|
1073
1081
|
<div className="mb-3 flex items-start gap-3">
|
|
1074
|
-
<
|
|
1075
|
-
|
|
1076
|
-
|
|
1082
|
+
<CourseAvatar
|
|
1083
|
+
fileId={curso.logoFileId}
|
|
1084
|
+
title={curso.nomeInterno}
|
|
1085
|
+
className="size-12 rounded-xl"
|
|
1086
|
+
iconSize="size-6"
|
|
1087
|
+
/>
|
|
1077
1088
|
<div className="min-w-0 flex-1">
|
|
1078
1089
|
<div className="mb-1.5 flex items-start justify-between gap-2">
|
|
1079
1090
|
<h3 className="line-clamp-2 font-semibold leading-snug text-foreground">
|
|
1080
|
-
{curso.
|
|
1091
|
+
{curso.nomeInterno}
|
|
1081
1092
|
</h3>
|
|
1082
1093
|
<DropdownMenu>
|
|
1083
1094
|
<DropdownMenuTrigger asChild>
|
|
@@ -1123,12 +1134,12 @@ export default function CursosPage() {
|
|
|
1123
1134
|
</div>
|
|
1124
1135
|
<p className="text-xs text-muted-foreground">
|
|
1125
1136
|
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-[10px]">
|
|
1126
|
-
{curso.
|
|
1137
|
+
{curso.slug}
|
|
1127
1138
|
</code>
|
|
1128
1139
|
<span className="mx-1.5 text-muted-foreground/50">
|
|
1129
1140
|
|
|
|
1130
1141
|
</span>
|
|
1131
|
-
<span>{curso.
|
|
1142
|
+
<span>{curso.tituloComercial}</span>
|
|
1132
1143
|
</p>
|
|
1133
1144
|
</div>
|
|
1134
1145
|
</div>
|
|
@@ -1236,25 +1247,33 @@ export default function CursosPage() {
|
|
|
1236
1247
|
onCheckedChange={() => {}}
|
|
1237
1248
|
onClick={(e) => toggleSelect(curso.id, e)}
|
|
1238
1249
|
aria-label={t('table.selectCourse', {
|
|
1239
|
-
title: curso.
|
|
1250
|
+
title: curso.nomeInterno,
|
|
1240
1251
|
})}
|
|
1241
1252
|
className="border-2 bg-background shadow-sm"
|
|
1242
1253
|
/>
|
|
1243
1254
|
</TableCell>
|
|
1244
1255
|
<TableCell>
|
|
1245
|
-
<div className="min-w-0">
|
|
1246
|
-
<
|
|
1247
|
-
{curso.
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
<
|
|
1254
|
-
|
|
1255
|
-
</
|
|
1256
|
-
<
|
|
1257
|
-
|
|
1256
|
+
<div className="flex min-w-0 items-center gap-3">
|
|
1257
|
+
<CourseAvatar
|
|
1258
|
+
fileId={curso.logoFileId}
|
|
1259
|
+
title={curso.nomeInterno}
|
|
1260
|
+
className="size-8 shrink-0 rounded-lg"
|
|
1261
|
+
iconSize="size-4"
|
|
1262
|
+
/>
|
|
1263
|
+
<div className="min-w-0">
|
|
1264
|
+
<p className="truncate font-semibold text-foreground">
|
|
1265
|
+
{curso.nomeInterno}
|
|
1266
|
+
</p>
|
|
1267
|
+
<p className="mt-1 truncate text-xs text-muted-foreground">
|
|
1268
|
+
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-[10px]">
|
|
1269
|
+
{curso.slug}
|
|
1270
|
+
</code>
|
|
1271
|
+
<span className="mx-1.5 text-muted-foreground/50">
|
|
1272
|
+
|
|
|
1273
|
+
</span>
|
|
1274
|
+
<span>{curso.tituloComercial}</span>
|
|
1275
|
+
</p>
|
|
1276
|
+
</div>
|
|
1258
1277
|
</div>
|
|
1259
1278
|
</TableCell>
|
|
1260
1279
|
<TableCell>
|
|
@@ -1383,8 +1402,8 @@ export default function CursosPage() {
|
|
|
1383
1402
|
form={form}
|
|
1384
1403
|
onSubmit={onSubmit}
|
|
1385
1404
|
categories={categoryOptions}
|
|
1386
|
-
courseCode={editingCurso?.codigo}
|
|
1387
1405
|
onCreateCategory={() => router.push('/category?new=1')}
|
|
1406
|
+
initialLogoFileId={editingCurso?.logoFileId ?? null}
|
|
1388
1407
|
t={t}
|
|
1389
1408
|
/>
|
|
1390
1409
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { CourseAvatar } from '@/app/(app)/(libraries)/lms/_components/course-avatar';
|
|
3
4
|
import {
|
|
4
5
|
CourseCategoryOption,
|
|
5
6
|
CourseFormSheet,
|
|
@@ -141,6 +142,8 @@ interface CursoOption {
|
|
|
141
142
|
cargaHoraria: number;
|
|
142
143
|
categories: string[];
|
|
143
144
|
area: string;
|
|
145
|
+
name?: string;
|
|
146
|
+
logoFileId?: number | null;
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
interface ExameOption {
|
|
@@ -188,6 +191,8 @@ type ApiCourseListResponse = {
|
|
|
188
191
|
title: string;
|
|
189
192
|
durationHours: number;
|
|
190
193
|
categories?: string[];
|
|
194
|
+
name?: string;
|
|
195
|
+
logoFileId?: number | null;
|
|
191
196
|
}>;
|
|
192
197
|
};
|
|
193
198
|
|
|
@@ -590,7 +595,7 @@ export default function TrainingPage() {
|
|
|
590
595
|
],
|
|
591
596
|
queryFn: async () => {
|
|
592
597
|
const response = await request<ApiTrainingListResponse>({
|
|
593
|
-
url: '/lms/
|
|
598
|
+
url: '/lms/paths',
|
|
594
599
|
method: 'GET',
|
|
595
600
|
params: {
|
|
596
601
|
page: currentPage,
|
|
@@ -613,7 +618,7 @@ export default function TrainingPage() {
|
|
|
613
618
|
queryKey: ['lms-training-stats'],
|
|
614
619
|
queryFn: async () => {
|
|
615
620
|
const response = await request<ApiTrainingStatsResponse>({
|
|
616
|
-
url: '/lms/
|
|
621
|
+
url: '/lms/paths/stats',
|
|
617
622
|
method: 'GET',
|
|
618
623
|
});
|
|
619
624
|
|
|
@@ -708,6 +713,8 @@ export default function TrainingPage() {
|
|
|
708
713
|
cargaHoraria: course.durationHours ?? 0,
|
|
709
714
|
categories: course.categories ?? [],
|
|
710
715
|
area: categorySlugToArea(course.categories ?? []),
|
|
716
|
+
name: course.name,
|
|
717
|
+
logoFileId: course.logoFileId ?? null,
|
|
711
718
|
})
|
|
712
719
|
);
|
|
713
720
|
|
|
@@ -975,7 +982,7 @@ export default function TrainingPage() {
|
|
|
975
982
|
try {
|
|
976
983
|
const [response] = await Promise.all([
|
|
977
984
|
request<Formacao>({
|
|
978
|
-
url: `/lms/
|
|
985
|
+
url: `/lms/paths/${formacao.id}`,
|
|
979
986
|
method: 'GET',
|
|
980
987
|
}),
|
|
981
988
|
refetchCourses(),
|
|
@@ -1220,7 +1227,7 @@ export default function TrainingPage() {
|
|
|
1220
1227
|
}
|
|
1221
1228
|
|
|
1222
1229
|
await request({
|
|
1223
|
-
url: `/lms/
|
|
1230
|
+
url: `/lms/paths/${editingFormacao.id}`,
|
|
1224
1231
|
method: 'PATCH',
|
|
1225
1232
|
data: payload,
|
|
1226
1233
|
});
|
|
@@ -1243,7 +1250,7 @@ export default function TrainingPage() {
|
|
|
1243
1250
|
};
|
|
1244
1251
|
|
|
1245
1252
|
await request({
|
|
1246
|
-
url: '/lms/
|
|
1253
|
+
url: '/lms/paths',
|
|
1247
1254
|
method: 'POST',
|
|
1248
1255
|
data: payload,
|
|
1249
1256
|
});
|
|
@@ -1334,7 +1341,7 @@ export default function TrainingPage() {
|
|
|
1334
1341
|
if (!formacaoToDelete) return;
|
|
1335
1342
|
|
|
1336
1343
|
await request({
|
|
1337
|
-
url: `/lms/
|
|
1344
|
+
url: `/lms/paths/${formacaoToDelete.id}`,
|
|
1338
1345
|
method: 'DELETE',
|
|
1339
1346
|
});
|
|
1340
1347
|
|
|
@@ -2054,7 +2061,22 @@ export default function TrainingPage() {
|
|
|
2054
2061
|
key={course.id}
|
|
2055
2062
|
value={String(course.id)}
|
|
2056
2063
|
>
|
|
2057
|
-
|
|
2064
|
+
<div className="flex items-center gap-2">
|
|
2065
|
+
<CourseAvatar
|
|
2066
|
+
fileId={course.logoFileId}
|
|
2067
|
+
title={course.nome}
|
|
2068
|
+
className="size-5 shrink-0 rounded"
|
|
2069
|
+
iconSize="size-3"
|
|
2070
|
+
/>
|
|
2071
|
+
<div className="min-w-0">
|
|
2072
|
+
<span className="truncate">
|
|
2073
|
+
{course.nome}
|
|
2074
|
+
</span>
|
|
2075
|
+
<span className="ml-1.5 text-xs text-muted-foreground">
|
|
2076
|
+
{course.name ?? '—'} · #{course.id}
|
|
2077
|
+
</span>
|
|
2078
|
+
</div>
|
|
2079
|
+
</div>
|
|
2058
2080
|
</SelectItem>
|
|
2059
2081
|
))}
|
|
2060
2082
|
</SelectContent>
|
|
@@ -526,15 +526,15 @@
|
|
|
526
526
|
"edit": "Update the course information below."
|
|
527
527
|
},
|
|
528
528
|
"fields": {
|
|
529
|
-
"code": {
|
|
530
|
-
"label": "Course Code",
|
|
531
|
-
"placeholder": "Ex: REACT-ADV",
|
|
532
|
-
"description": "Unique course identifier (e.g.: REACT-ADV)"
|
|
533
|
-
},
|
|
534
529
|
"internalName": {
|
|
535
530
|
"label": "Internal Name",
|
|
536
|
-
"placeholder": "Ex:
|
|
537
|
-
"description": "Internal
|
|
531
|
+
"placeholder": "Ex: Advanced React",
|
|
532
|
+
"description": "Internal course name for administrative use"
|
|
533
|
+
},
|
|
534
|
+
"slug": {
|
|
535
|
+
"label": "Slug",
|
|
536
|
+
"placeholder": "Ex: advanced-react",
|
|
537
|
+
"description": "Unique URL identifier (lowercase letters, numbers and hyphens)"
|
|
538
538
|
},
|
|
539
539
|
"commercialTitle": {
|
|
540
540
|
"label": "Commercial Title",
|
|
@@ -596,6 +596,7 @@
|
|
|
596
596
|
"codeMaxLength": "Code must have at most 16 characters",
|
|
597
597
|
"codePattern": "Only letters, numbers, and hyphens",
|
|
598
598
|
"internalNameMinLength": "Internal name must have at least 3 characters",
|
|
599
|
+
"slugPattern": "Slug must contain only lowercase letters, numbers and hyphens",
|
|
599
600
|
"commercialTitleMinLength": "Commercial title must have at least 3 characters",
|
|
600
601
|
"descriptionMinLength": "Description must have at least 10 characters",
|
|
601
602
|
"levelRequired": "Select a level",
|
|
@@ -666,7 +667,8 @@
|
|
|
666
667
|
"autoSaveSaved": "Session saved automatically",
|
|
667
668
|
"autoSaveError": "Automatic session save failed",
|
|
668
669
|
"create": "Create Session",
|
|
669
|
-
"update": "Update"
|
|
670
|
+
"update": "Update",
|
|
671
|
+
"save": "Save session"
|
|
670
672
|
},
|
|
671
673
|
"lessonForm": {
|
|
672
674
|
"titleCreate": "New Lesson",
|
|
@@ -736,7 +738,25 @@
|
|
|
736
738
|
"autoSaveError": "Automatic save failed",
|
|
737
739
|
"cancel": "Cancel",
|
|
738
740
|
"create": "Create Lesson",
|
|
739
|
-
"update": "Update"
|
|
741
|
+
"update": "Update",
|
|
742
|
+
"save": "Save lesson",
|
|
743
|
+
"tabData": "Data",
|
|
744
|
+
"tabTranscription": "Transcription",
|
|
745
|
+
"tabResources": "Resources",
|
|
746
|
+
"videoProvider": "Video provider",
|
|
747
|
+
"videoUrl": "Video URL",
|
|
748
|
+
"autoDuration": "Auto duration",
|
|
749
|
+
"postContent": "Content",
|
|
750
|
+
"linkedExam": "Linked exam",
|
|
751
|
+
"linkedExamPlaceholder": "Exam ID...",
|
|
752
|
+
"transcriptionHint": "Full video transcription.",
|
|
753
|
+
"transcriptionVideoOnly": "Transcription is only available for video lessons.",
|
|
754
|
+
"transcriptionPlaceholder": "Write or paste the transcription here...",
|
|
755
|
+
"resourcesCount": "{count} resource(s)",
|
|
756
|
+
"addResource": "Add resource",
|
|
757
|
+
"noResources": "No resources added",
|
|
758
|
+
"public": "Public",
|
|
759
|
+
"private": "Private"
|
|
740
760
|
},
|
|
741
761
|
"deleteSession": {
|
|
742
762
|
"title": "Delete Session",
|
|
@@ -799,9 +819,13 @@
|
|
|
799
819
|
"sessionUpdated": "Session updated!",
|
|
800
820
|
"sessionCreated": "Session created!",
|
|
801
821
|
"sessionDeleted": "Session removed!",
|
|
822
|
+
"sessionDuplicated": "Session duplicated!",
|
|
802
823
|
"lessonUpdated": "Lesson updated!",
|
|
803
824
|
"lessonCreated": "Lesson created!",
|
|
804
825
|
"lessonDeleted": "Lesson removed!",
|
|
826
|
+
"lessonDuplicated": "Lesson duplicated!",
|
|
827
|
+
"lessonMoved": "Lesson moved!",
|
|
828
|
+
"courseUpdated": "Course updated!",
|
|
805
829
|
"resourceAdded": "Resource added!",
|
|
806
830
|
"resourceRemoved": "Resource removed!",
|
|
807
831
|
"lessonsDeleted": "{count} lesson(s) removed!",
|
|
@@ -828,6 +852,56 @@
|
|
|
828
852
|
"titleMin": "Title must be at least 3 characters",
|
|
829
853
|
"durationMin": "Minimum duration of 1 minute",
|
|
830
854
|
"typeRequired": "Select a type"
|
|
855
|
+
},
|
|
856
|
+
"pageDescription": "{sessions} sessions · {lessons} lessons · {hours}h {minutes}min",
|
|
857
|
+
"mobileTabs": {
|
|
858
|
+
"tree": "Tree",
|
|
859
|
+
"detail": "Details"
|
|
860
|
+
},
|
|
861
|
+
"breadcrumbs": {
|
|
862
|
+
"lms": "LMS",
|
|
863
|
+
"courses": "Courses",
|
|
864
|
+
"structure": "Structure"
|
|
865
|
+
},
|
|
866
|
+
"search": {
|
|
867
|
+
"placeholder": "Search..."
|
|
868
|
+
},
|
|
869
|
+
"tree": {
|
|
870
|
+
"collapseAll": "Collapse all",
|
|
871
|
+
"expandAll": "Expand all",
|
|
872
|
+
"addItem": "Add item",
|
|
873
|
+
"addSession": "New session"
|
|
874
|
+
},
|
|
875
|
+
"contextMenu": {
|
|
876
|
+
"edit": "Edit",
|
|
877
|
+
"addLesson": "Add lesson",
|
|
878
|
+
"addSession": "New session",
|
|
879
|
+
"duplicate": "Duplicate",
|
|
880
|
+
"mergeWith": "Merge with...",
|
|
881
|
+
"moveTo": "Move to...",
|
|
882
|
+
"delete": "Delete"
|
|
883
|
+
},
|
|
884
|
+
"deleteDialog": {
|
|
885
|
+
"title": "Confirm deletion",
|
|
886
|
+
"sessionMessage": "Are you sure? All lessons in this session will be removed.",
|
|
887
|
+
"lessonMessage": "Are you sure? This lesson will be permanently removed.",
|
|
888
|
+
"cancel": "Cancel",
|
|
889
|
+
"confirm": "Delete"
|
|
890
|
+
},
|
|
891
|
+
"detailPanel": {
|
|
892
|
+
"emptyHint": "Select an item in the tree to view details"
|
|
893
|
+
},
|
|
894
|
+
"detailCourse": {
|
|
895
|
+
"subtitle": "General course data",
|
|
896
|
+
"title": "Title",
|
|
897
|
+
"code": "Code",
|
|
898
|
+
"slug": "Slug",
|
|
899
|
+
"description": "Description",
|
|
900
|
+
"published": "Published",
|
|
901
|
+
"save": "Save course"
|
|
902
|
+
},
|
|
903
|
+
"detailSession": {
|
|
904
|
+
"subtitle": "{lessons} lessons · {minutes}min"
|
|
831
905
|
}
|
|
832
906
|
}
|
|
833
907
|
},
|
|
@@ -2434,7 +2508,11 @@
|
|
|
2434
2508
|
"helper": "Click a lesson to edit it or create new lessons.",
|
|
2435
2509
|
"viewSingle": "Month",
|
|
2436
2510
|
"viewQuarter": "Quarter",
|
|
2437
|
-
"viewYear": "Year"
|
|
2511
|
+
"viewYear": "Year",
|
|
2512
|
+
"empty": {
|
|
2513
|
+
"title": "No lessons registered",
|
|
2514
|
+
"description": "Add the first lesson to get started."
|
|
2515
|
+
}
|
|
2438
2516
|
},
|
|
2439
2517
|
"info": {
|
|
2440
2518
|
"period": "Period",
|
|
@@ -253,7 +253,7 @@
|
|
|
253
253
|
"internalName": {
|
|
254
254
|
"label": "Nome Interno *",
|
|
255
255
|
"placeholder": "Ex: react-avancado",
|
|
256
|
-
"description": "
|
|
256
|
+
"description": "Nome Interno para uso do sistema"
|
|
257
257
|
},
|
|
258
258
|
"title": {
|
|
259
259
|
"label": "Título Comercial *",
|
|
@@ -535,15 +535,15 @@
|
|
|
535
535
|
"edit": "Atualize as informações do curso abaixo."
|
|
536
536
|
},
|
|
537
537
|
"fields": {
|
|
538
|
-
"code": {
|
|
539
|
-
"label": "Código do Curso",
|
|
540
|
-
"placeholder": "Ex: REACT-ADV",
|
|
541
|
-
"description": "Identificador único do curso (ex: REACT-ADV)"
|
|
542
|
-
},
|
|
543
538
|
"internalName": {
|
|
544
539
|
"label": "Nome Interno",
|
|
540
|
+
"placeholder": "Ex: React Avançado",
|
|
541
|
+
"description": "Nome interno do curso para uso administrativo"
|
|
542
|
+
},
|
|
543
|
+
"slug": {
|
|
544
|
+
"label": "Slug",
|
|
545
545
|
"placeholder": "Ex: react-avancado",
|
|
546
|
-
"description": "
|
|
546
|
+
"description": "Identificador único na URL (letras minúsculas, números e hífens)"
|
|
547
547
|
},
|
|
548
548
|
"commercialTitle": {
|
|
549
549
|
"label": "Título Comercial",
|
|
@@ -605,6 +605,7 @@
|
|
|
605
605
|
"codeMaxLength": "Código deve ter no máximo 16 caracteres",
|
|
606
606
|
"codePattern": "Apenas letras, números e hífens",
|
|
607
607
|
"internalNameMinLength": "Nome interno deve ter pelo menos 3 caracteres",
|
|
608
|
+
"slugPattern": "Slug deve conter apenas letras minúsculas, números e hífens",
|
|
608
609
|
"commercialTitleMinLength": "Título comercial deve ter pelo menos 3 caracteres",
|
|
609
610
|
"descriptionMinLength": "Descrição deve ter pelo menos 10 caracteres",
|
|
610
611
|
"levelRequired": "Selecione um nível",
|
|
@@ -675,7 +676,8 @@
|
|
|
675
676
|
"autoSaveSaved": "Sessão salva automaticamente",
|
|
676
677
|
"autoSaveError": "Falha no salvamento automático da sessão",
|
|
677
678
|
"create": "Criar Sessão",
|
|
678
|
-
"update": "Atualizar"
|
|
679
|
+
"update": "Atualizar",
|
|
680
|
+
"save": "Salvar sessão"
|
|
679
681
|
},
|
|
680
682
|
"lessonForm": {
|
|
681
683
|
"titleCreate": "Nova Aula",
|
|
@@ -745,7 +747,25 @@
|
|
|
745
747
|
"autoSaveError": "Falha no salvamento automático",
|
|
746
748
|
"cancel": "Cancelar",
|
|
747
749
|
"create": "Criar Aula",
|
|
748
|
-
"update": "Atualizar"
|
|
750
|
+
"update": "Atualizar",
|
|
751
|
+
"save": "Salvar aula",
|
|
752
|
+
"tabData": "Dados",
|
|
753
|
+
"tabTranscription": "Transcrição",
|
|
754
|
+
"tabResources": "Recursos",
|
|
755
|
+
"videoProvider": "Provedor de vídeo",
|
|
756
|
+
"videoUrl": "URL do vídeo",
|
|
757
|
+
"autoDuration": "Duração automática",
|
|
758
|
+
"postContent": "Conteúdo",
|
|
759
|
+
"linkedExam": "Exame vinculado",
|
|
760
|
+
"linkedExamPlaceholder": "ID do exame...",
|
|
761
|
+
"transcriptionHint": "Transcrição completa do vídeo.",
|
|
762
|
+
"transcriptionVideoOnly": "A transcrição está disponível somente para aulas do tipo vídeo.",
|
|
763
|
+
"transcriptionPlaceholder": "Escreva ou cole a transcrição aqui...",
|
|
764
|
+
"resourcesCount": "{count} recurso(s)",
|
|
765
|
+
"addResource": "Adicionar recurso",
|
|
766
|
+
"noResources": "Nenhum recurso adicionado",
|
|
767
|
+
"public": "Público",
|
|
768
|
+
"private": "Privado"
|
|
749
769
|
},
|
|
750
770
|
"deleteSession": {
|
|
751
771
|
"title": "Excluir Sessão",
|
|
@@ -808,9 +828,13 @@
|
|
|
808
828
|
"sessionUpdated": "Sessão atualizada!",
|
|
809
829
|
"sessionCreated": "Sessão criada!",
|
|
810
830
|
"sessionDeleted": "Sessão removida!",
|
|
831
|
+
"sessionDuplicated": "Sessão duplicada!",
|
|
811
832
|
"lessonUpdated": "Aula atualizada!",
|
|
812
833
|
"lessonCreated": "Aula criada!",
|
|
813
834
|
"lessonDeleted": "Aula removida!",
|
|
835
|
+
"lessonDuplicated": "Aula duplicada!",
|
|
836
|
+
"lessonMoved": "Aula movida!",
|
|
837
|
+
"courseUpdated": "Curso atualizado!",
|
|
814
838
|
"resourceAdded": "Recurso adicionado!",
|
|
815
839
|
"resourceRemoved": "Recurso removido!",
|
|
816
840
|
"lessonsDeleted": "{count} aula(s) removida(s)!",
|
|
@@ -837,6 +861,56 @@
|
|
|
837
861
|
"titleMin": "Título deve ter pelo menos 3 caracteres",
|
|
838
862
|
"durationMin": "Duração mínima de 1 minuto",
|
|
839
863
|
"typeRequired": "Selecione um tipo"
|
|
864
|
+
},
|
|
865
|
+
"pageDescription": "{sessions} sessões · {lessons} aulas · {hours}h {minutes}min",
|
|
866
|
+
"mobileTabs": {
|
|
867
|
+
"tree": "Árvore",
|
|
868
|
+
"detail": "Detalhes"
|
|
869
|
+
},
|
|
870
|
+
"breadcrumbs": {
|
|
871
|
+
"lms": "LMS",
|
|
872
|
+
"courses": "Cursos",
|
|
873
|
+
"structure": "Estrutura"
|
|
874
|
+
},
|
|
875
|
+
"search": {
|
|
876
|
+
"placeholder": "Buscar..."
|
|
877
|
+
},
|
|
878
|
+
"tree": {
|
|
879
|
+
"collapseAll": "Recolher tudo",
|
|
880
|
+
"expandAll": "Expandir tudo",
|
|
881
|
+
"addItem": "Adicionar item",
|
|
882
|
+
"addSession": "Nova sessão"
|
|
883
|
+
},
|
|
884
|
+
"contextMenu": {
|
|
885
|
+
"edit": "Editar",
|
|
886
|
+
"addLesson": "Adicionar aula",
|
|
887
|
+
"addSession": "Nova sessão",
|
|
888
|
+
"duplicate": "Duplicar",
|
|
889
|
+
"mergeWith": "Mesclar com...",
|
|
890
|
+
"moveTo": "Mover para...",
|
|
891
|
+
"delete": "Excluir"
|
|
892
|
+
},
|
|
893
|
+
"deleteDialog": {
|
|
894
|
+
"title": "Confirmar exclusão",
|
|
895
|
+
"sessionMessage": "Tem certeza? Todas as aulas desta sessão serão removidas.",
|
|
896
|
+
"lessonMessage": "Tem certeza? Esta aula será removida permanentemente.",
|
|
897
|
+
"cancel": "Cancelar",
|
|
898
|
+
"confirm": "Excluir"
|
|
899
|
+
},
|
|
900
|
+
"detailPanel": {
|
|
901
|
+
"emptyHint": "Selecione um item na árvore para ver os detalhes"
|
|
902
|
+
},
|
|
903
|
+
"detailCourse": {
|
|
904
|
+
"subtitle": "Dados gerais do curso",
|
|
905
|
+
"title": "Título",
|
|
906
|
+
"code": "Código",
|
|
907
|
+
"slug": "Slug",
|
|
908
|
+
"description": "Descrição",
|
|
909
|
+
"published": "Publicado",
|
|
910
|
+
"save": "Salvar curso"
|
|
911
|
+
},
|
|
912
|
+
"detailSession": {
|
|
913
|
+
"subtitle": "{lessons} aulas · {minutes}min"
|
|
840
914
|
}
|
|
841
915
|
}
|
|
842
916
|
},
|
|
@@ -2441,7 +2515,11 @@
|
|
|
2441
2515
|
"helper": "Clique em uma aula para editar ou criar novas aulas.",
|
|
2442
2516
|
"viewSingle": "Mês",
|
|
2443
2517
|
"viewQuarter": "Trimestre",
|
|
2444
|
-
"viewYear": "Ano"
|
|
2518
|
+
"viewYear": "Ano",
|
|
2519
|
+
"empty": {
|
|
2520
|
+
"title": "Nenhuma aula cadastrada",
|
|
2521
|
+
"description": "Cadastre a primeira aula para começar."
|
|
2522
|
+
}
|
|
2445
2523
|
},
|
|
2446
2524
|
"info": {
|
|
2447
2525
|
"period": "Período",
|
package/hedhog/table/course.yaml
CHANGED
|
@@ -15,6 +15,20 @@ columns:
|
|
|
15
15
|
- name: applies_to_learning_path
|
|
16
16
|
type: boolean
|
|
17
17
|
default: false
|
|
18
|
+
- name: suggested_width
|
|
19
|
+
type: int
|
|
20
|
+
isNullable: true
|
|
21
|
+
- name: suggested_height
|
|
22
|
+
type: int
|
|
23
|
+
isNullable: true
|
|
24
|
+
- name: allowed_extensions
|
|
25
|
+
type: varchar
|
|
26
|
+
length: 100
|
|
27
|
+
isNullable: true
|
|
28
|
+
- name: aspect_ratio
|
|
29
|
+
type: varchar
|
|
30
|
+
length: 20
|
|
31
|
+
isNullable: true
|
|
18
32
|
- name: status
|
|
19
33
|
type: enum
|
|
20
34
|
values: [active, inactive]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/lms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.309",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
"@nestjs/jwt": "^11",
|
|
11
11
|
"@nestjs/mapped-types": "*",
|
|
12
12
|
"@hed-hog/api-prisma": "0.0.6",
|
|
13
|
-
"@hed-hog/
|
|
13
|
+
"@hed-hog/api-types": "0.0.1",
|
|
14
|
+
"@hed-hog/contact": "0.0.309",
|
|
14
15
|
"@hed-hog/api-pagination": "0.0.7",
|
|
15
|
-
"@hed-hog/core": "0.0.
|
|
16
|
+
"@hed-hog/core": "0.0.309",
|
|
16
17
|
"@hed-hog/api-locale": "0.0.14",
|
|
17
|
-
"@hed-hog/api
|
|
18
|
-
"@hed-hog/finance": "0.0.
|
|
19
|
-
"@hed-hog/category": "0.0.
|
|
20
|
-
"@hed-hog/api": "0.0.6"
|
|
18
|
+
"@hed-hog/api": "0.0.6",
|
|
19
|
+
"@hed-hog/finance": "0.0.309",
|
|
20
|
+
"@hed-hog/category": "0.0.309"
|
|
21
21
|
},
|
|
22
22
|
"exports": {
|
|
23
23
|
".": {
|