@hed-hog/lms 0.0.309 → 0.0.311
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/hedhog/frontend/app/_components/class-form-sheet.tsx.ejs +1 -2
- package/hedhog/frontend/app/certificates/models/CanvasStage.tsx.ejs +10 -1
- package/hedhog/frontend/app/certificates/models/TopBar.tsx.ejs +44 -3
- package/hedhog/frontend/app/certificates/models/page.tsx.ejs +32 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/editor-lesson.tsx.ejs +8 -11
- package/hedhog/frontend/app/courses/[id]/structure/_components/mock-data.ts.ejs +1 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/store.ts.ejs +1 -0
- package/hedhog/frontend/app/courses/[id]/structure/_components/types.ts.ejs +1 -0
- package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs +1 -0
- package/hedhog/frontend/messages/en.json +3 -1
- package/hedhog/frontend/messages/pt.json +3 -1
- package/package.json +8 -8
|
@@ -944,7 +944,7 @@ export function ClassFormSheet({
|
|
|
944
944
|
setCustomRecurrenceDialogOpen(false);
|
|
945
945
|
}
|
|
946
946
|
|
|
947
|
-
const handleProfessorCreated =
|
|
947
|
+
const handleProfessorCreated = (instructor: {
|
|
948
948
|
id: number;
|
|
949
949
|
personId: number;
|
|
950
950
|
name: string;
|
|
@@ -960,7 +960,6 @@ export function ClassFormSheet({
|
|
|
960
960
|
shouldTouch: true,
|
|
961
961
|
shouldValidate: true,
|
|
962
962
|
});
|
|
963
|
-
await refetchProfessorOptions();
|
|
964
963
|
};
|
|
965
964
|
|
|
966
965
|
async function onSubmitCourse(data: CourseSheetFormValues) {
|
|
@@ -658,7 +658,16 @@ async function applyBg(canvas: any, fabricMod: any, src: string) {
|
|
|
658
658
|
});
|
|
659
659
|
const scaleX = CANVAS_W / (img.width || 1);
|
|
660
660
|
const scaleY = CANVAS_H / (img.height || 1);
|
|
661
|
-
img.set({
|
|
661
|
+
img.set({
|
|
662
|
+
left: 0,
|
|
663
|
+
top: 0,
|
|
664
|
+
originX: 'left',
|
|
665
|
+
originY: 'top',
|
|
666
|
+
scaleX,
|
|
667
|
+
scaleY,
|
|
668
|
+
selectable: false,
|
|
669
|
+
evented: false,
|
|
670
|
+
});
|
|
662
671
|
canvas.backgroundImage = img;
|
|
663
672
|
canvas.requestRenderAll();
|
|
664
673
|
} catch {
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
ZoomIn,
|
|
22
22
|
ZoomOut,
|
|
23
23
|
} from 'lucide-react';
|
|
24
|
-
import { useCallback, useRef } from 'react';
|
|
24
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
25
25
|
import { toast } from 'sonner';
|
|
26
26
|
import { getCanvasAPI } from '../../_lib/editor/canvasInstance';
|
|
27
27
|
import {
|
|
@@ -63,6 +63,49 @@ export default function Topbar({ templateContext }: TopbarProps) {
|
|
|
63
63
|
|
|
64
64
|
const importRef = useRef<HTMLInputElement>(null);
|
|
65
65
|
|
|
66
|
+
const isFirstRender = useRef(true);
|
|
67
|
+
const autoSaveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
68
|
+
const templateContextRef = useRef(templateContext);
|
|
69
|
+
templateContextRef.current = templateContext;
|
|
70
|
+
const requestRef = useRef(request);
|
|
71
|
+
requestRef.current = request;
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (isFirstRender.current) {
|
|
75
|
+
isFirstRender.current = false;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
localStorage.setItem(LS_KEY, JSON.stringify(templateState));
|
|
80
|
+
|
|
81
|
+
const ctx = templateContextRef.current;
|
|
82
|
+
if (!ctx) return;
|
|
83
|
+
|
|
84
|
+
if (autoSaveTimerRef.current) clearTimeout(autoSaveTimerRef.current);
|
|
85
|
+
|
|
86
|
+
autoSaveTimerRef.current = setTimeout(() => {
|
|
87
|
+
requestRef
|
|
88
|
+
.current({
|
|
89
|
+
url: `/lms/certificates/templates/${ctx.id}`,
|
|
90
|
+
method: 'PATCH',
|
|
91
|
+
data: {
|
|
92
|
+
name: templateState.name,
|
|
93
|
+
slug: ctx.slug,
|
|
94
|
+
status: ctx.status,
|
|
95
|
+
templateContent: JSON.stringify(templateState),
|
|
96
|
+
},
|
|
97
|
+
})
|
|
98
|
+
.catch(() => {
|
|
99
|
+
toast.error('Falha ao salvar automaticamente');
|
|
100
|
+
});
|
|
101
|
+
}, 1500);
|
|
102
|
+
|
|
103
|
+
return () => {
|
|
104
|
+
if (autoSaveTimerRef.current) clearTimeout(autoSaveTimerRef.current);
|
|
105
|
+
};
|
|
106
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
107
|
+
}, [templateState]);
|
|
108
|
+
|
|
66
109
|
const handleNew = useCallback(() => {
|
|
67
110
|
resetTemplate();
|
|
68
111
|
getCanvasAPI()?.loadTemplate(useTemplateStore.getState().template);
|
|
@@ -72,7 +115,6 @@ export default function Topbar({ templateContext }: TopbarProps) {
|
|
|
72
115
|
const handleSave = useCallback(() => {
|
|
73
116
|
const run = async () => {
|
|
74
117
|
if (!templateContext) {
|
|
75
|
-
localStorage.setItem(LS_KEY, JSON.stringify(templateState));
|
|
76
118
|
toast.success('Template salvo no localStorage');
|
|
77
119
|
return;
|
|
78
120
|
}
|
|
@@ -88,7 +130,6 @@ export default function Topbar({ templateContext }: TopbarProps) {
|
|
|
88
130
|
},
|
|
89
131
|
});
|
|
90
132
|
|
|
91
|
-
localStorage.setItem(LS_KEY, JSON.stringify(templateState));
|
|
92
133
|
toast.success('Template salvo');
|
|
93
134
|
};
|
|
94
135
|
|
|
@@ -99,6 +99,7 @@ type CreateCertificateTemplatePayload = {
|
|
|
99
99
|
type UpdateCertificateTemplatePayload = {
|
|
100
100
|
name: string;
|
|
101
101
|
description?: string;
|
|
102
|
+
status: TemplateStatus;
|
|
102
103
|
};
|
|
103
104
|
|
|
104
105
|
const PAGE_SIZES = [6, 12, 24];
|
|
@@ -114,6 +115,7 @@ const updateTemplateSchema = (t: (key: string) => string) =>
|
|
|
114
115
|
z.object({
|
|
115
116
|
name: z.string().trim().min(1, t('editSheet.validation.required')),
|
|
116
117
|
description: z.string().trim().optional(),
|
|
118
|
+
status: z.enum(['draft', 'active', 'inactive']),
|
|
117
119
|
});
|
|
118
120
|
|
|
119
121
|
type CreateTemplateFormValues = z.infer<
|
|
@@ -173,6 +175,7 @@ export default function ModelsPage() {
|
|
|
173
175
|
defaultValues: {
|
|
174
176
|
name: '',
|
|
175
177
|
description: '',
|
|
178
|
+
status: 'draft',
|
|
176
179
|
},
|
|
177
180
|
});
|
|
178
181
|
|
|
@@ -304,6 +307,7 @@ export default function ModelsPage() {
|
|
|
304
307
|
editForm.reset({
|
|
305
308
|
name: '',
|
|
306
309
|
description: '',
|
|
310
|
+
status: 'draft',
|
|
307
311
|
});
|
|
308
312
|
setEditingTemplateId(null);
|
|
309
313
|
}
|
|
@@ -325,6 +329,7 @@ export default function ModelsPage() {
|
|
|
325
329
|
editForm.reset({
|
|
326
330
|
name: template.name,
|
|
327
331
|
description: template.description ?? '',
|
|
332
|
+
status: template.status,
|
|
328
333
|
});
|
|
329
334
|
setIsEditSheetOpen(true);
|
|
330
335
|
}
|
|
@@ -410,6 +415,7 @@ export default function ModelsPage() {
|
|
|
410
415
|
const payload: UpdateCertificateTemplatePayload = {
|
|
411
416
|
name,
|
|
412
417
|
description: values.description?.trim() || undefined,
|
|
418
|
+
status: values.status,
|
|
413
419
|
};
|
|
414
420
|
|
|
415
421
|
try {
|
|
@@ -825,6 +831,32 @@ export default function ModelsPage() {
|
|
|
825
831
|
/>
|
|
826
832
|
</div>
|
|
827
833
|
|
|
834
|
+
<div className="space-y-2">
|
|
835
|
+
<p className="text-sm font-medium">
|
|
836
|
+
{t('editSheet.fields.status')}
|
|
837
|
+
</p>
|
|
838
|
+
<Controller
|
|
839
|
+
name="status"
|
|
840
|
+
control={editForm.control}
|
|
841
|
+
render={({ field }) => (
|
|
842
|
+
<Select value={field.value} onValueChange={field.onChange}>
|
|
843
|
+
<SelectTrigger className="w-full">
|
|
844
|
+
<SelectValue placeholder={t('editSheet.fields.status')} />
|
|
845
|
+
</SelectTrigger>
|
|
846
|
+
<SelectContent>
|
|
847
|
+
<SelectItem value="draft">{t('status.draft')}</SelectItem>
|
|
848
|
+
<SelectItem value="active">
|
|
849
|
+
{t('status.active')}
|
|
850
|
+
</SelectItem>
|
|
851
|
+
<SelectItem value="inactive">
|
|
852
|
+
{t('status.inactive')}
|
|
853
|
+
</SelectItem>
|
|
854
|
+
</SelectContent>
|
|
855
|
+
</Select>
|
|
856
|
+
)}
|
|
857
|
+
/>
|
|
858
|
+
</div>
|
|
859
|
+
|
|
828
860
|
{editForm.formState.errors.name?.message ? (
|
|
829
861
|
<p className="text-sm text-destructive">
|
|
830
862
|
{editForm.formState.errors.name.message}
|
|
@@ -475,17 +475,14 @@ export function EditorLesson({ lessonId }: EditorLessonProps) {
|
|
|
475
475
|
try {
|
|
476
476
|
const results = await Promise.allSettled(
|
|
477
477
|
files.map((f) =>
|
|
478
|
-
uploadFile(request, f).then(
|
|
479
|
-
(res)
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
url: undefined,
|
|
487
|
-
}) satisfies Resource
|
|
488
|
-
)
|
|
478
|
+
uploadFile(request, f).then<Resource>((res) => ({
|
|
479
|
+
id: String(res.id),
|
|
480
|
+
name: f.name,
|
|
481
|
+
size: formatFileSize(f.size),
|
|
482
|
+
type: f.type || f.name.split('.').pop() || 'file',
|
|
483
|
+
public: false,
|
|
484
|
+
url: undefined,
|
|
485
|
+
}))
|
|
489
486
|
)
|
|
490
487
|
);
|
|
491
488
|
const succeeded = results
|
|
@@ -25,6 +25,7 @@ import type {
|
|
|
25
25
|
export const MOCK_COURSE: Course = {
|
|
26
26
|
id: 'course-1',
|
|
27
27
|
code: 'REACT-ADV',
|
|
28
|
+
name: 'React Avancado',
|
|
28
29
|
title: 'React Avancado',
|
|
29
30
|
description:
|
|
30
31
|
'Domine os conceitos avancados do React: hooks, patterns, performance e gerenciamento de estado moderno.',
|
package/hedhog/frontend/app/courses/[id]/structure/_data/adapters/course-structure.adapter.ts.ejs
CHANGED
|
@@ -91,6 +91,7 @@ function normalizeResource(raw: ApiLessonResource): Resource {
|
|
|
91
91
|
export function normalizeCourse(raw: ApiCourse): Course {
|
|
92
92
|
return {
|
|
93
93
|
id: raw.id,
|
|
94
|
+
code: raw.slug || raw.id,
|
|
94
95
|
name: raw.name ?? raw.slug,
|
|
95
96
|
title: raw.titulo,
|
|
96
97
|
description: raw.descricao,
|
|
@@ -2171,6 +2171,7 @@
|
|
|
2171
2171
|
"cards": {
|
|
2172
2172
|
"status": "Status",
|
|
2173
2173
|
"updatedAt": "Updated",
|
|
2174
|
+
"noDescription": "No description",
|
|
2174
2175
|
"actions": {
|
|
2175
2176
|
"menuLabel": "More actions",
|
|
2176
2177
|
"editTemplate": "Edit template",
|
|
@@ -2205,7 +2206,8 @@
|
|
|
2205
2206
|
"description": "Update the template basic information.",
|
|
2206
2207
|
"fields": {
|
|
2207
2208
|
"name": "Name",
|
|
2208
|
-
"description": "Description"
|
|
2209
|
+
"description": "Description",
|
|
2210
|
+
"status": "Status"
|
|
2209
2211
|
},
|
|
2210
2212
|
"placeholders": {
|
|
2211
2213
|
"name": "e.g. Corporate Certificate",
|
|
@@ -2178,6 +2178,7 @@
|
|
|
2178
2178
|
"cards": {
|
|
2179
2179
|
"status": "Status",
|
|
2180
2180
|
"updatedAt": "Atualizado",
|
|
2181
|
+
"noDescription": "Sem descrição",
|
|
2181
2182
|
"actions": {
|
|
2182
2183
|
"menuLabel": "Mais ações",
|
|
2183
2184
|
"editTemplate": "Editar template",
|
|
@@ -2212,7 +2213,8 @@
|
|
|
2212
2213
|
"description": "Atualize os dados básicos do template.",
|
|
2213
2214
|
"fields": {
|
|
2214
2215
|
"name": "Nome",
|
|
2215
|
-
"description": "Descrição"
|
|
2216
|
+
"description": "Descrição",
|
|
2217
|
+
"status": "Status"
|
|
2216
2218
|
},
|
|
2217
2219
|
"placeholders": {
|
|
2218
2220
|
"name": "Ex.: Certificado Corporativo",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/lms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.311",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
"@nestjs/core": "^11",
|
|
10
10
|
"@nestjs/jwt": "^11",
|
|
11
11
|
"@nestjs/mapped-types": "*",
|
|
12
|
-
"@hed-hog/
|
|
13
|
-
"@hed-hog/api-types": "0.0.1",
|
|
14
|
-
"@hed-hog/contact": "0.0.309",
|
|
12
|
+
"@hed-hog/contact": "0.0.311",
|
|
15
13
|
"@hed-hog/api-pagination": "0.0.7",
|
|
16
|
-
"@hed-hog/
|
|
17
|
-
"@hed-hog/api-locale": "0.0.14",
|
|
14
|
+
"@hed-hog/api-types": "0.0.1",
|
|
18
15
|
"@hed-hog/api": "0.0.6",
|
|
19
|
-
"@hed-hog/
|
|
20
|
-
"@hed-hog/
|
|
16
|
+
"@hed-hog/api-locale": "0.0.14",
|
|
17
|
+
"@hed-hog/finance": "0.0.311",
|
|
18
|
+
"@hed-hog/category": "0.0.311",
|
|
19
|
+
"@hed-hog/core": "0.0.311",
|
|
20
|
+
"@hed-hog/api-prisma": "0.0.6"
|
|
21
21
|
},
|
|
22
22
|
"exports": {
|
|
23
23
|
".": {
|