@nualang/nualang-ui-components 0.1.1326 → 0.1.1329
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/Assignments/CreateAssignmentDialog/CreateAssignmentDialog.js +5 -1
- package/dist/Cards/FeedbackCard/FeedbackCard.js +130 -34
- package/dist/Dialogs/GenerateBot/GenerateBot.js +2 -1
- package/dist/Dialogs/GroupedFeedbackDialog/GroupedFeedbackDialog.js +340 -256
- package/dist/Exercises/Listener/Listener.js +2 -1
- package/dist/Exercises/Translator/Translator.js +2 -1
- package/dist/Forms/AppContact/AppContact.js +19 -1
- package/dist/Forms/Contact/Contact.js +20 -1
- package/dist/Forms/InputHelper/InputHelper.js +3 -3
- package/dist/Live/LiveListener/LiveListener.js +1 -1
- package/dist/Live/LiveTranslator/LiveTranslator.js +2 -1
- package/dist/Misc/NualaCreating/NualaCreating.js +8 -6
- package/dist/Screens/Classrooms/ViewClassroom/ViewClassroom.js +10 -1
- package/dist/Tables/Progress/Progress.js +16 -12
- package/package.json +1 -1
|
@@ -73,6 +73,7 @@ export default function CreateAssignmentDialog({
|
|
|
73
73
|
exercises: submittedExercises
|
|
74
74
|
});
|
|
75
75
|
const [isTitleEdited, setIsTitleEdited] = useState(Boolean(initialData.title));
|
|
76
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
76
77
|
const classroomQuery = useQueries({
|
|
77
78
|
queries: (Array.isArray(assignment.classroomId) ? assignment.classroomId : [assignment.classroomId]).map(cId => ({
|
|
78
79
|
queryKey: classroomQuerys.classroomKeys.item(cId, username),
|
|
@@ -262,6 +263,7 @@ export default function CreateAssignmentDialog({
|
|
|
262
263
|
}));
|
|
263
264
|
};
|
|
264
265
|
const handleCreateAssignment = async () => {
|
|
266
|
+
setIsCreating(true);
|
|
265
267
|
try {
|
|
266
268
|
await Promise.all(assignment.classroomId.map(async cId => {
|
|
267
269
|
const selectedClassroomMembers = uniqueClassroomMembers.filter(member => member.classroomId === cId).map(student => student.memberId).filter(studentId => assignment?.assignedStudents.includes(studentId));
|
|
@@ -275,6 +277,8 @@ export default function CreateAssignmentDialog({
|
|
|
275
277
|
handleClose();
|
|
276
278
|
} catch (error) {
|
|
277
279
|
console.error("Error creating assignments:", error);
|
|
280
|
+
} finally {
|
|
281
|
+
setIsCreating(false);
|
|
278
282
|
}
|
|
279
283
|
};
|
|
280
284
|
const handleRemoveExercise = toRemove => {
|
|
@@ -647,7 +651,7 @@ export default function CreateAssignmentDialog({
|
|
|
647
651
|
},
|
|
648
652
|
children: /*#__PURE__*/_jsx(Button, {
|
|
649
653
|
"data-cy": "assignment-assign-button",
|
|
650
|
-
disabled: !assignment.assignedStudents?.length || !assignment.scheduleDate || !assignment.dueDate || !assignment.title || !assignment.classroomId || !assignment.exercises?.length,
|
|
654
|
+
disabled: isCreating || !assignment.assignedStudents?.length || !assignment.scheduleDate || !assignment.dueDate || !assignment.title || !assignment.classroomId || !assignment.exercises?.length,
|
|
651
655
|
onClick: async () => await handleCreateAssignment(),
|
|
652
656
|
children: t("assign")
|
|
653
657
|
})
|
|
@@ -4,6 +4,8 @@ import { grey, green } from "@mui/material/colors";
|
|
|
4
4
|
import AutoFixHighIcon from "@mui/icons-material/AutoFixHigh";
|
|
5
5
|
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
|
|
6
6
|
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
|
7
|
+
import TrendingUpIcon from "@mui/icons-material/TrendingUp";
|
|
8
|
+
import TrendingDownIcon from "@mui/icons-material/TrendingDown";
|
|
7
9
|
import { Formik } from "formik";
|
|
8
10
|
import * as Yup from "yup";
|
|
9
11
|
import RecordingDialog from "../../Dialogs/RecordingDialog/RecordingDialog";
|
|
@@ -13,8 +15,39 @@ import level2Rubric from "../../Dialogs/PDFViewer/rubrics/level2Rubric.pdf";
|
|
|
13
15
|
import level3Rubric from "../../Dialogs/PDFViewer/rubrics/level3Rubric.pdf";
|
|
14
16
|
import level4Rubric from "../../Dialogs/PDFViewer/rubrics/level4Rubric.pdf";
|
|
15
17
|
import HelpOutlineIcon from "@mui/icons-material/HelpOutline";
|
|
16
|
-
import NualaCreating from "../../Misc/NualaCreating/NualaCreating";
|
|
17
18
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
19
|
+
const getPerformanceLevel = (student, aiGrade) => {
|
|
20
|
+
if (!aiGrade || Object.keys(aiGrade).length === 0) return null;
|
|
21
|
+
const keyVariants = [student.username, `${student.username}Student`, student.username?.replace(/\s+/g, "")];
|
|
22
|
+
const aiData = keyVariants.map(k => aiGrade?.[k]).find(v => v && typeof v === "object") || null;
|
|
23
|
+
return aiData?.LevelPerformance || null;
|
|
24
|
+
};
|
|
25
|
+
const getPerformanceChipProps = (level, t) => {
|
|
26
|
+
switch (level?.toLowerCase()) {
|
|
27
|
+
case 'above':
|
|
28
|
+
return {
|
|
29
|
+
label: t('above_level'),
|
|
30
|
+
color: 'success',
|
|
31
|
+
icon: /*#__PURE__*/_jsx(TrendingUpIcon, {
|
|
32
|
+
sx: {
|
|
33
|
+
fontSize: 16
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
};
|
|
37
|
+
case 'below':
|
|
38
|
+
return {
|
|
39
|
+
label: t('below_level'),
|
|
40
|
+
color: 'warning',
|
|
41
|
+
icon: /*#__PURE__*/_jsx(TrendingDownIcon, {
|
|
42
|
+
sx: {
|
|
43
|
+
fontSize: 16
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
};
|
|
47
|
+
default:
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
18
51
|
export default function FeedbackCard({
|
|
19
52
|
t = x => x,
|
|
20
53
|
discussionData = {},
|
|
@@ -39,7 +72,8 @@ export default function FeedbackCard({
|
|
|
39
72
|
goToTimestamp = () => {},
|
|
40
73
|
startTimes = {},
|
|
41
74
|
canSubmitAll = {},
|
|
42
|
-
setCanSubmit = () => {}
|
|
75
|
+
setCanSubmit = () => {},
|
|
76
|
+
setIsGeneratingIndividual = () => {}
|
|
43
77
|
}) {
|
|
44
78
|
const [isRecordingDialogOpen, setIsRecordingDialogOpen] = useState(false);
|
|
45
79
|
const [hasBeenEdited, setHasBeenEdited] = useState(false);
|
|
@@ -50,6 +84,7 @@ export default function FeedbackCard({
|
|
|
50
84
|
const [openPDF, setOpenPDF] = useState(false);
|
|
51
85
|
const [pageNumber, setPageNumber] = useState(1);
|
|
52
86
|
const [scale, setScale] = useState(1);
|
|
87
|
+
const [isGeneratingFeedback, setIsGeneratingFeedback] = useState(false);
|
|
53
88
|
const handleChangeCheckbox = event => {
|
|
54
89
|
setCheckedSubmissions({
|
|
55
90
|
...checkedSubmissions,
|
|
@@ -81,18 +116,21 @@ export default function FeedbackCard({
|
|
|
81
116
|
attendedMembers.forEach(student => {
|
|
82
117
|
const existingStudentFeedback = existingFeedback[student.memberId];
|
|
83
118
|
feedbackData[student.memberId] = {
|
|
84
|
-
feedbackText: existingStudentFeedback?.feedbackText || ""
|
|
119
|
+
feedbackText: existingStudentFeedback?.feedbackText || "",
|
|
120
|
+
levelPerformance: existingStudentFeedback?.levelPerformance || null
|
|
85
121
|
};
|
|
86
122
|
});
|
|
87
123
|
notAttendedMembers.forEach(student => {
|
|
88
124
|
feedbackData[student.memberId] = {
|
|
89
|
-
feedbackText: existingFeedback[student.memberId]?.feedbackText || t("not_present")
|
|
125
|
+
feedbackText: existingFeedback[student.memberId]?.feedbackText || t("not_present"),
|
|
126
|
+
levelPerformance: existingFeedback[student.memberId]?.levelPerformance || null
|
|
90
127
|
};
|
|
91
128
|
});
|
|
92
129
|
} else {
|
|
93
130
|
selectedMembers.forEach(student => {
|
|
94
131
|
feedbackData[student.memberId] = {
|
|
95
|
-
feedbackText: existingFeedback[student.memberId]?.feedbackText || ""
|
|
132
|
+
feedbackText: existingFeedback[student.memberId]?.feedbackText || "",
|
|
133
|
+
levelPerformance: existingFeedback[student.memberId]?.levelPerformance || null
|
|
96
134
|
};
|
|
97
135
|
});
|
|
98
136
|
}
|
|
@@ -132,6 +170,9 @@ export default function FeedbackCard({
|
|
|
132
170
|
if (aiData?.Feedback) {
|
|
133
171
|
formik.setFieldValue(`feedbackData.${student.memberId}.feedbackText`, aiData.Feedback);
|
|
134
172
|
}
|
|
173
|
+
if (aiData?.LevelPerformance) {
|
|
174
|
+
formik.setFieldValue(`feedbackData.${student.memberId}.levelPerformance`, aiData.LevelPerformance);
|
|
175
|
+
}
|
|
135
176
|
});
|
|
136
177
|
setHasBeenEdited(true);
|
|
137
178
|
setIsSubmitted(false);
|
|
@@ -159,7 +200,14 @@ export default function FeedbackCard({
|
|
|
159
200
|
}, [submitTrigger]);
|
|
160
201
|
const handleGenerateAI = async () => {
|
|
161
202
|
setAiJustGenerated(true);
|
|
162
|
-
|
|
203
|
+
setIsGeneratingFeedback(true);
|
|
204
|
+
setIsGeneratingIndividual(true);
|
|
205
|
+
try {
|
|
206
|
+
await onGenerateFeedback(discussionData);
|
|
207
|
+
} finally {
|
|
208
|
+
setIsGeneratingFeedback(false);
|
|
209
|
+
setIsGeneratingIndividual(false);
|
|
210
|
+
}
|
|
163
211
|
};
|
|
164
212
|
const handleOpenPDF = () => {
|
|
165
213
|
setOpenPDF(true);
|
|
@@ -182,9 +230,18 @@ export default function FeedbackCard({
|
|
|
182
230
|
const feedbackDataWithAbsent = {
|
|
183
231
|
...values.feedbackData
|
|
184
232
|
};
|
|
233
|
+
selectedMembers.forEach(student => {
|
|
234
|
+
const existingLevel = feedbackDataWithAbsent[student.memberId]?.levelPerformance;
|
|
235
|
+
const aiLevel = getPerformanceLevel(student, aiGrade);
|
|
236
|
+
feedbackDataWithAbsent[student.memberId] = {
|
|
237
|
+
...feedbackDataWithAbsent[student.memberId],
|
|
238
|
+
levelPerformance: existingLevel ?? aiLevel ?? null
|
|
239
|
+
};
|
|
240
|
+
});
|
|
185
241
|
notAttendedMembers.forEach(student => {
|
|
186
242
|
feedbackDataWithAbsent[student.memberId] = {
|
|
187
|
-
feedbackText: t("not_present")
|
|
243
|
+
feedbackText: t("not_present"),
|
|
244
|
+
levelPerformance: feedbackDataWithAbsent[student.memberId]?.levelPerformance ?? null
|
|
188
245
|
};
|
|
189
246
|
});
|
|
190
247
|
await onSubmitFeedback({
|
|
@@ -241,23 +298,7 @@ export default function FeedbackCard({
|
|
|
241
298
|
overflow: "hidden",
|
|
242
299
|
backgroundColor: "background.paper"
|
|
243
300
|
},
|
|
244
|
-
children: [
|
|
245
|
-
sx: {
|
|
246
|
-
...(!aiJustGenerated && {
|
|
247
|
-
display: "none"
|
|
248
|
-
})
|
|
249
|
-
},
|
|
250
|
-
mx: 2,
|
|
251
|
-
size: 12,
|
|
252
|
-
children: [/*#__PURE__*/_jsx(Typography, {
|
|
253
|
-
variant: "h6",
|
|
254
|
-
sx: {
|
|
255
|
-
mt: 2,
|
|
256
|
-
mb: 2
|
|
257
|
-
},
|
|
258
|
-
children: t("generating_feedback")
|
|
259
|
-
}), /*#__PURE__*/_jsx(NualaCreating, {})]
|
|
260
|
-
}) : /*#__PURE__*/_jsxs(_Fragment, {
|
|
301
|
+
children: [/*#__PURE__*/_jsxs(_Fragment, {
|
|
261
302
|
children: [/*#__PURE__*/_jsxs(Box, {
|
|
262
303
|
sx: {
|
|
263
304
|
px: 3,
|
|
@@ -322,6 +363,8 @@ export default function FeedbackCard({
|
|
|
322
363
|
const isAbsent = hasSubmission && !joinedMembers.includes(student.memberId);
|
|
323
364
|
const disabled = !hasSubmission || isAbsent;
|
|
324
365
|
const studentFeedback = values.feedbackData[student.memberId] || {};
|
|
366
|
+
const perfLevel = studentFeedback.levelPerformance || getPerformanceLevel(student, aiGrade);
|
|
367
|
+
const chipProps = getPerformanceChipProps(perfLevel, t);
|
|
325
368
|
return /*#__PURE__*/_jsx(Box, {
|
|
326
369
|
sx: {
|
|
327
370
|
py: 2
|
|
@@ -338,7 +381,7 @@ export default function FeedbackCard({
|
|
|
338
381
|
children: /*#__PURE__*/_jsxs(Box, {
|
|
339
382
|
display: "flex",
|
|
340
383
|
alignItems: "center",
|
|
341
|
-
gap:
|
|
384
|
+
gap: 1.5,
|
|
342
385
|
children: [/*#__PURE__*/_jsx(Avatar, {
|
|
343
386
|
alt: student.username,
|
|
344
387
|
src: student.userImage,
|
|
@@ -347,12 +390,65 @@ export default function FeedbackCard({
|
|
|
347
390
|
height: 48,
|
|
348
391
|
filter: isAbsent ? "grayscale(100%)" : "none"
|
|
349
392
|
}
|
|
350
|
-
}), /*#__PURE__*/
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
393
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
394
|
+
display: "flex",
|
|
395
|
+
flexDirection: "column",
|
|
396
|
+
gap: 0.5,
|
|
397
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
398
|
+
fontWeight: 600,
|
|
399
|
+
sx: {
|
|
400
|
+
color: isAbsent ? grey[500] : "text.primary"
|
|
401
|
+
},
|
|
402
|
+
children: student.username
|
|
403
|
+
}), chipProps && hasSubmission && !isAbsent && /*#__PURE__*/_jsx(Tooltip, {
|
|
404
|
+
title: /*#__PURE__*/_jsxs(Box, {
|
|
405
|
+
sx: {
|
|
406
|
+
p: 0.5
|
|
407
|
+
},
|
|
408
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
409
|
+
variant: "body2",
|
|
410
|
+
fontWeight: "bold",
|
|
411
|
+
sx: {
|
|
412
|
+
mb: 0.5
|
|
413
|
+
},
|
|
414
|
+
children: t('ai_performance_assessment')
|
|
415
|
+
}), /*#__PURE__*/_jsx(Typography, {
|
|
416
|
+
variant: "caption",
|
|
417
|
+
sx: {
|
|
418
|
+
display: 'block',
|
|
419
|
+
mb: 0.5
|
|
420
|
+
},
|
|
421
|
+
children: t('performance_chip_tooltip')
|
|
422
|
+
}), /*#__PURE__*/_jsx(Typography, {
|
|
423
|
+
variant: "caption",
|
|
424
|
+
sx: {
|
|
425
|
+
fontStyle: 'italic',
|
|
426
|
+
opacity: 0.9
|
|
427
|
+
},
|
|
428
|
+
children: t('performance_chip_note')
|
|
429
|
+
})]
|
|
430
|
+
}),
|
|
431
|
+
placement: "top",
|
|
432
|
+
children: /*#__PURE__*/_jsx(Chip, {
|
|
433
|
+
label: chipProps.label,
|
|
434
|
+
color: chipProps.color,
|
|
435
|
+
size: "small",
|
|
436
|
+
icon: chipProps.icon,
|
|
437
|
+
sx: {
|
|
438
|
+
width: 'fit-content',
|
|
439
|
+
fontWeight: 600,
|
|
440
|
+
fontSize: '0.7rem',
|
|
441
|
+
height: '22px',
|
|
442
|
+
'& .MuiChip-label': {
|
|
443
|
+
paddingLeft: '8px',
|
|
444
|
+
paddingRight: '8px'
|
|
445
|
+
},
|
|
446
|
+
'&:hover': {
|
|
447
|
+
opacity: 0.9
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
})
|
|
451
|
+
})]
|
|
356
452
|
})]
|
|
357
453
|
})
|
|
358
454
|
}), /*#__PURE__*/_jsx(Grid, {
|
|
@@ -420,16 +516,16 @@ export default function FeedbackCard({
|
|
|
420
516
|
},
|
|
421
517
|
children: [/*#__PURE__*/_jsx(Button, {
|
|
422
518
|
variant: "outlined",
|
|
423
|
-
disabled: !hasSubmission ||
|
|
519
|
+
disabled: !hasSubmission || isGeneratingFeedback,
|
|
424
520
|
onClick: handleOpenRecordingDialog,
|
|
425
521
|
children: t("view_recording")
|
|
426
522
|
}), /*#__PURE__*/_jsx(Button, {
|
|
427
523
|
variant: "contained",
|
|
428
524
|
color: "secondary",
|
|
429
|
-
disabled: !hasSubmission ||
|
|
525
|
+
disabled: !hasSubmission || isGeneratingFeedback,
|
|
430
526
|
onClick: handleGenerateAI,
|
|
431
527
|
endIcon: /*#__PURE__*/_jsx(AutoFixHighIcon, {}),
|
|
432
|
-
children: t("generate_feedback")
|
|
528
|
+
children: isGeneratingFeedback ? t("generating") : t("generate_feedback")
|
|
433
529
|
}), /*#__PURE__*/_jsx(Button, {
|
|
434
530
|
type: "submit",
|
|
435
531
|
variant: "contained",
|