@nualang/nualang-ui-components 0.1.1377 → 0.1.1379
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/AssignmentBotSelection/AssignmentBotSelection.js +41 -18
- package/dist/Assignments/AssignmentCard/AssignmentCard.js +4 -2
- package/dist/Assignments/AssignmentCardsList/AssignmentCardsList.js +3 -1
- package/dist/Assignments/AssignmentCourseSelection/AssignmentCourseSelection.js +12 -7
- package/dist/Assignments/AssignmentExerciseSelection/AssignmentExerciseSelection.js +6 -2
- package/dist/Assignments/AssignmentExerciseSelector/AssignmentExerciseSelector.js +4 -2
- package/dist/Assignments/AssignmentPhraseListSelection/AssignmentPhraseListSelection.js +42 -19
- package/dist/Assignments/AssignmentRoleplaySelection/AssignmentRoleplaySelection.js +43 -20
- package/dist/Assignments/AssignmentSelectExercise/AssignmentSelectExercise.js +4 -2
- package/dist/Exercises/Translator/Translator.js +2 -2
- package/dist/Forms/CreateTopic/CreateTopic.js +0 -4
- package/dist/Forms/UpdateTopic/UpdateTopic.js +2 -27
- package/dist/Screens/Courses/ViewCourse/ViewTopic/ViewTopic.js +0 -4
- package/dist/Tables/Progress/ProgressTableRow.js +16 -7
- package/dist/Tables/Progress/cells/index.js +41 -13
- package/dist/Tables/Progress/cells/index.test.js +19 -30
- package/dist/Tables/Progress/sorting.js +4 -4
- package/dist/Tables/Progress/utils.js +18 -7
- package/dist/hooks/useExerciseState.js +1 -1
- package/package.json +1 -1
|
@@ -227,23 +227,46 @@ function AssignmentBotSelection({
|
|
|
227
227
|
return true;
|
|
228
228
|
});
|
|
229
229
|
const filteredBots = useCase === "assignment-view" || useCase === "assignment-start" ? visibleBots.filter(bot => selectedExercises.some(ex => ex.botId === bot.botId && ex.courseSectionTopicId === courseSectionTopicId)) : visibleBots;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
230
|
+
const existingBotIds = new Set(visibleBots.map(b => b.botId));
|
|
231
|
+
const orphanedBotIds = useCase === "assignment-view" || useCase === "assignment-start" ? [...new Set(selectedExercises.filter(ex => ex.botId && ex.courseSectionTopicId === courseSectionTopicId && !existingBotIds.has(ex.botId)).map(ex => ex.botId))] : [];
|
|
232
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
233
|
+
children: [filteredBots.map((bot, index) => /*#__PURE__*/_jsx(Bot, {
|
|
234
|
+
bot: bot,
|
|
235
|
+
courseSectionTopicId: courseSectionTopicId,
|
|
236
|
+
t: t,
|
|
237
|
+
isExerciseSelected: isExerciseSelected,
|
|
238
|
+
handleSelectExercise: handleSelectExercise,
|
|
239
|
+
selectedExercises: selectedExercises,
|
|
240
|
+
useCase: useCase,
|
|
241
|
+
assignment: assignment,
|
|
242
|
+
lastClickedExerciseId: lastClickedExerciseId,
|
|
243
|
+
memberCourseCompletions: memberCourseCompletions,
|
|
244
|
+
topicProgress: topicProgress,
|
|
245
|
+
handleRemoveExercise: handleRemoveExercise,
|
|
246
|
+
isPreview: isPreview,
|
|
247
|
+
isChallengeModeStudent: isChallengeModeStudent,
|
|
248
|
+
isCreator: isCreator,
|
|
249
|
+
isCreateMode: isCreateMode
|
|
250
|
+
}, index)), orphanedBotIds.map(id => /*#__PURE__*/_jsx(Box, {
|
|
251
|
+
sx: {
|
|
252
|
+
display: "flex",
|
|
253
|
+
alignItems: "center",
|
|
254
|
+
pl: 2,
|
|
255
|
+
py: 1.5,
|
|
256
|
+
ml: {
|
|
257
|
+
xs: "16px",
|
|
258
|
+
sm: "72px",
|
|
259
|
+
md: "76px"
|
|
260
|
+
},
|
|
261
|
+
borderLeft: "3px solid",
|
|
262
|
+
borderColor: "warning.main"
|
|
263
|
+
},
|
|
264
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
265
|
+
variant: "body2",
|
|
266
|
+
color: "text.secondary",
|
|
267
|
+
children: t("exercise_no_longer_available")
|
|
268
|
+
})
|
|
269
|
+
}, id))]
|
|
270
|
+
});
|
|
248
271
|
}
|
|
249
272
|
export default AssignmentBotSelection;
|
|
@@ -29,7 +29,8 @@ export default function AssignmentCard({
|
|
|
29
29
|
handleViewProgress,
|
|
30
30
|
lastAssignmentFetch,
|
|
31
31
|
assignedStudents = [],
|
|
32
|
-
isChallengeModeStudent
|
|
32
|
+
isChallengeModeStudent,
|
|
33
|
+
isReadWriteModeStudent
|
|
33
34
|
}) {
|
|
34
35
|
const [confirm] = useConfirm(t);
|
|
35
36
|
const {
|
|
@@ -223,7 +224,8 @@ export default function AssignmentCard({
|
|
|
223
224
|
completionHelpers: completionHelpers,
|
|
224
225
|
memberCourseCompletions: memberCourseCompletions,
|
|
225
226
|
lastClickedExerciseId: lastClickedExerciseId,
|
|
226
|
-
isChallengeModeStudent: isChallengeModeStudent
|
|
227
|
+
isChallengeModeStudent: isChallengeModeStudent,
|
|
228
|
+
isReadWriteModeStudent: isReadWriteModeStudent
|
|
227
229
|
})
|
|
228
230
|
})]
|
|
229
231
|
}), /*#__PURE__*/_jsx(Grid, {
|
|
@@ -29,6 +29,7 @@ const AssignmentCardsList = ({
|
|
|
29
29
|
assignmentMembersById = {},
|
|
30
30
|
isLoadingAssignments,
|
|
31
31
|
isChallengeModeStudent,
|
|
32
|
+
isReadWriteModeStudent,
|
|
32
33
|
scrollableTarget = null
|
|
33
34
|
}) => {
|
|
34
35
|
const [lastClickedExerciseId, setLastClickedExerciseId] = useState(null);
|
|
@@ -345,7 +346,8 @@ const AssignmentCardsList = ({
|
|
|
345
346
|
memberId: memberId,
|
|
346
347
|
handleViewProgress: handleViewProgress,
|
|
347
348
|
assignedStudents: assignmentMembersById[assignment.assignmentId] || [],
|
|
348
|
-
isChallengeModeStudent: isChallengeModeStudent
|
|
349
|
+
isChallengeModeStudent: isChallengeModeStudent,
|
|
350
|
+
isReadWriteModeStudent: isReadWriteModeStudent
|
|
349
351
|
}, assignment.assignmentId))
|
|
350
352
|
})]
|
|
351
353
|
});
|
|
@@ -32,7 +32,8 @@ function Course({
|
|
|
32
32
|
lastClickedExerciseId,
|
|
33
33
|
handleRemoveExercise,
|
|
34
34
|
isPreview,
|
|
35
|
-
isChallengeModeStudent
|
|
35
|
+
isChallengeModeStudent,
|
|
36
|
+
isReadWriteModeStudent
|
|
36
37
|
}) {
|
|
37
38
|
const numOfIds = lastClickedExerciseId ? lastClickedExerciseId.split("|") : [];
|
|
38
39
|
const [open, setOpen] = useState(false);
|
|
@@ -88,11 +89,11 @@ function Course({
|
|
|
88
89
|
}
|
|
89
90
|
});
|
|
90
91
|
if (courseSections && memberCourseCompletions && selectedExercises) {
|
|
91
|
-
const sectionsWithProgress = calcCompletions(courseSections.filter(section => assignedSectionIds.has(section.sectionId)), memberCourseCompletions, selectedExercises, isChallengeModeStudent);
|
|
92
|
+
const sectionsWithProgress = calcCompletions(courseSections.filter(section => assignedSectionIds.has(section.sectionId)), memberCourseCompletions, selectedExercises, isChallengeModeStudent, isReadWriteModeStudent);
|
|
92
93
|
const percentCompletion = calcPercentageCompletion(sectionsWithProgress);
|
|
93
94
|
setCourseSectionCompletion(percentCompletion);
|
|
94
95
|
}
|
|
95
|
-
}, [courseSections, memberCourseCompletions, selectedExercises]);
|
|
96
|
+
}, [courseSections, memberCourseCompletions, selectedExercises, isChallengeModeStudent, isReadWriteModeStudent]);
|
|
96
97
|
return /*#__PURE__*/_jsx(_Fragment, {
|
|
97
98
|
children: useCase === "assignment-select" ? /*#__PURE__*/_jsxs(List, {
|
|
98
99
|
disablePadding: true,
|
|
@@ -178,7 +179,8 @@ function Course({
|
|
|
178
179
|
completionHelpers: completionHelpers,
|
|
179
180
|
memberCourseCompletions: memberCourseCompletions,
|
|
180
181
|
lastClickedExerciseId: lastClickedExerciseId,
|
|
181
|
-
isChallengeModeStudent: isChallengeModeStudent
|
|
182
|
+
isChallengeModeStudent: isChallengeModeStudent,
|
|
183
|
+
isReadWriteModeStudent: isReadWriteModeStudent
|
|
182
184
|
})
|
|
183
185
|
})
|
|
184
186
|
})]
|
|
@@ -209,7 +211,8 @@ function Course({
|
|
|
209
211
|
course: course,
|
|
210
212
|
handleRemoveExercise: handleRemoveExercise,
|
|
211
213
|
isPreview: isPreview,
|
|
212
|
-
isChallengeModeStudent: isChallengeModeStudent
|
|
214
|
+
isChallengeModeStudent: isChallengeModeStudent,
|
|
215
|
+
isReadWriteModeStudent: isReadWriteModeStudent
|
|
213
216
|
})
|
|
214
217
|
})
|
|
215
218
|
});
|
|
@@ -237,7 +240,8 @@ function AssignmentCourseSelection({
|
|
|
237
240
|
lastClickedExerciseId,
|
|
238
241
|
handleRemoveExercise,
|
|
239
242
|
isPreview,
|
|
240
|
-
isChallengeModeStudent
|
|
243
|
+
isChallengeModeStudent,
|
|
244
|
+
isReadWriteModeStudent
|
|
241
245
|
}) {
|
|
242
246
|
return /*#__PURE__*/_jsx("div", {
|
|
243
247
|
children: courses.map((course, index) => /*#__PURE__*/_jsx(Course, {
|
|
@@ -264,7 +268,8 @@ function AssignmentCourseSelection({
|
|
|
264
268
|
lastClickedExerciseId: lastClickedExerciseId,
|
|
265
269
|
handleRemoveExercise: handleRemoveExercise,
|
|
266
270
|
isPreview: isPreview,
|
|
267
|
-
isChallengeModeStudent: isChallengeModeStudent
|
|
271
|
+
isChallengeModeStudent: isChallengeModeStudent,
|
|
272
|
+
isReadWriteModeStudent: isReadWriteModeStudent
|
|
268
273
|
}, course.courseId || index))
|
|
269
274
|
});
|
|
270
275
|
}
|
|
@@ -888,15 +888,16 @@ function SectionList({
|
|
|
888
888
|
handleRemoveExercise,
|
|
889
889
|
isPreview,
|
|
890
890
|
isChallengeModeStudent,
|
|
891
|
+
isReadWriteModeStudent,
|
|
891
892
|
...otherProps
|
|
892
893
|
}) {
|
|
893
894
|
const [courseSectionWithProgress, setCourseSectionWithProgress] = useState([]);
|
|
894
895
|
useEffect(() => {
|
|
895
896
|
if (sections && memberCourseCompletions && selectedExercises) {
|
|
896
|
-
const sectionsWithProgress = calcCompletions(sections, memberCourseCompletions, selectedExercises, isChallengeModeStudent);
|
|
897
|
+
const sectionsWithProgress = calcCompletions(sections, memberCourseCompletions, selectedExercises, isChallengeModeStudent, isReadWriteModeStudent);
|
|
897
898
|
setCourseSectionWithProgress(sectionsWithProgress);
|
|
898
899
|
}
|
|
899
|
-
}, [sections, memberCourseCompletions, selectedExercises, isChallengeModeStudent]);
|
|
900
|
+
}, [sections, memberCourseCompletions, selectedExercises, isChallengeModeStudent, isReadWriteModeStudent]);
|
|
900
901
|
const courseSections = courseSectionWithProgress && courseSectionWithProgress.length ? courseSectionWithProgress : sections;
|
|
901
902
|
return /*#__PURE__*/_jsx(_Fragment, {
|
|
902
903
|
children: courseSections.length > 0 ? courseSections.map((section, index) => {
|
|
@@ -967,6 +968,7 @@ function AssignmentExerciseSelection({
|
|
|
967
968
|
handleRemoveExercise,
|
|
968
969
|
isPreview,
|
|
969
970
|
isChallengeModeStudent,
|
|
971
|
+
isReadWriteModeStudent,
|
|
970
972
|
...otherProps
|
|
971
973
|
}) {
|
|
972
974
|
if (isLoading) {
|
|
@@ -998,6 +1000,7 @@ function AssignmentExerciseSelection({
|
|
|
998
1000
|
handleRemoveExercise: handleRemoveExercise,
|
|
999
1001
|
isPreview: isPreview,
|
|
1000
1002
|
isChallengeModeStudent: isChallengeModeStudent,
|
|
1003
|
+
isReadWriteModeStudent: isReadWriteModeStudent,
|
|
1001
1004
|
...otherProps
|
|
1002
1005
|
})
|
|
1003
1006
|
});
|
|
@@ -1030,6 +1033,7 @@ function AssignmentExerciseSelection({
|
|
|
1030
1033
|
handleRemoveExercise: handleRemoveExercise,
|
|
1031
1034
|
isPreview: isPreview,
|
|
1032
1035
|
isChallengeModeStudent: isChallengeModeStudent,
|
|
1036
|
+
isReadWriteModeStudent: isReadWriteModeStudent,
|
|
1033
1037
|
...otherProps
|
|
1034
1038
|
})
|
|
1035
1039
|
});
|
|
@@ -21,7 +21,8 @@ function AssignmentExerciseSelector({
|
|
|
21
21
|
lastClickedExerciseId,
|
|
22
22
|
handleRemoveExercise,
|
|
23
23
|
isPreview,
|
|
24
|
-
isChallengeModeStudent
|
|
24
|
+
isChallengeModeStudent,
|
|
25
|
+
isReadWriteModeStudent
|
|
25
26
|
}) {
|
|
26
27
|
return /*#__PURE__*/_jsx(Box, {
|
|
27
28
|
children: /*#__PURE__*/_jsx(AssignmentCourseSelection, {
|
|
@@ -44,7 +45,8 @@ function AssignmentExerciseSelector({
|
|
|
44
45
|
lastClickedExerciseId: lastClickedExerciseId,
|
|
45
46
|
handleRemoveExercise: handleRemoveExercise,
|
|
46
47
|
isPreview: isPreview,
|
|
47
|
-
isChallengeModeStudent: isChallengeModeStudent
|
|
48
|
+
isChallengeModeStudent: isChallengeModeStudent,
|
|
49
|
+
isReadWriteModeStudent: isReadWriteModeStudent
|
|
48
50
|
})
|
|
49
51
|
});
|
|
50
52
|
}
|
|
@@ -418,23 +418,46 @@ export default function AssignmentPhraseListSelection({
|
|
|
418
418
|
preferred_username,
|
|
419
419
|
isCreator
|
|
420
420
|
}) {
|
|
421
|
-
const
|
|
422
|
-
const filteredPhraseLists = !viewOnly ? phraseLists : phraseLists.filter(phraseList =>
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
421
|
+
const selectedPhraseListIds = new Set(selectedExercises?.map(exercise => exercise.phraseListId) || []);
|
|
422
|
+
const filteredPhraseLists = !viewOnly ? phraseLists : phraseLists.filter(phraseList => selectedPhraseListIds.has(phraseList.phraseListId));
|
|
423
|
+
const existingPhraseListIds = new Set(phraseLists.map(pl => pl.phraseListId));
|
|
424
|
+
const orphanedPhraseListIds = useCase === "assignment-view" || useCase === "assignment-start" ? [...new Set((selectedExercises || []).filter(e => e.phraseListId && e.courseSectionTopicId === courseSectionTopicId && !existingPhraseListIds.has(e.phraseListId)).map(e => e.phraseListId))] : [];
|
|
425
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
426
|
+
children: [filteredPhraseLists.map((phraseList, index) => /*#__PURE__*/_jsx(PhraseList, {
|
|
427
|
+
t: t,
|
|
428
|
+
phraseList: phraseList,
|
|
429
|
+
courseSectionTopicId: courseSectionTopicId,
|
|
430
|
+
assignment: assignment,
|
|
431
|
+
useCase: useCase,
|
|
432
|
+
selectedExercises: selectedExercises,
|
|
433
|
+
handleSelectExercise: handleSelectExercise,
|
|
434
|
+
handleRemoveExercise: handleRemoveExercise,
|
|
435
|
+
isPreview: isPreview,
|
|
436
|
+
viewOnly: viewOnly,
|
|
437
|
+
progressHelpers: progressHelpers,
|
|
438
|
+
completionHelpers: completionHelpers,
|
|
439
|
+
username: username,
|
|
440
|
+
preferred_username: preferred_username,
|
|
441
|
+
isCreator: isCreator
|
|
442
|
+
}, index)), orphanedPhraseListIds.map(id => /*#__PURE__*/_jsx(Box, {
|
|
443
|
+
sx: {
|
|
444
|
+
display: "flex",
|
|
445
|
+
alignItems: "center",
|
|
446
|
+
pl: 2,
|
|
447
|
+
py: 1.5,
|
|
448
|
+
ml: {
|
|
449
|
+
xs: "16px",
|
|
450
|
+
sm: "72px",
|
|
451
|
+
md: "76px"
|
|
452
|
+
},
|
|
453
|
+
borderLeft: "3px solid",
|
|
454
|
+
borderColor: "warning.main"
|
|
455
|
+
},
|
|
456
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
457
|
+
variant: "body2",
|
|
458
|
+
color: "text.secondary",
|
|
459
|
+
children: t("exercise_no_longer_available")
|
|
460
|
+
})
|
|
461
|
+
}, id))]
|
|
462
|
+
});
|
|
440
463
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useEffect } from "react";
|
|
2
|
-
import { Box, ListItemText, ListItemButton, Avatar, ListItemIcon, Tooltip, Collapse, Checkbox, Badge, IconButton } from "@mui/material";
|
|
2
|
+
import { Box, ListItemText, ListItemButton, Avatar, ListItemIcon, Tooltip, Collapse, Checkbox, Badge, IconButton, Typography } from "@mui/material";
|
|
3
3
|
import ClearIcon from "@mui/icons-material/Clear";
|
|
4
4
|
import MessageIcon from "@mui/icons-material/Message";
|
|
5
5
|
import RateReviewIcon from "@mui/icons-material/RateReview";
|
|
@@ -440,24 +440,47 @@ function AssignmentRoleplaySelection({
|
|
|
440
440
|
const filteredCompletions = Array.isArray(memberCourseCompletions) && memberCourseCompletions.length > 0 ? memberCourseCompletions.filter(completion => completion.courseSectionTopicId === courseSectionTopicId) : [];
|
|
441
441
|
const selectedRoleplayIds = new Set(selectedExercises.map(sE => sE.roleplayId));
|
|
442
442
|
const filteredRoleplays = !viewOnly ? roleplays : roleplays.filter(e => selectedRoleplayIds.has(e.roleplayId));
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
443
|
+
const existingRoleplayIds = new Set(roleplays.map(r => r.roleplayId));
|
|
444
|
+
const orphanedRoleplayIds = useCase === "assignment-view" || useCase === "assignment-start" ? [...new Set(selectedExercises.filter(e => e.roleplayId && e.courseSectionTopicId === courseSectionTopicId && !existingRoleplayIds.has(e.roleplayId)).map(e => e.roleplayId))] : [];
|
|
445
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
446
|
+
children: [filteredRoleplays.map(roleplay => /*#__PURE__*/_jsx(Roleplay, {
|
|
447
|
+
roleplay: roleplay,
|
|
448
|
+
isRoleplaySelected: isRoleplaySelected,
|
|
449
|
+
setIsRoleplaySelected: setIsRoleplaySelected,
|
|
450
|
+
courseSectionTopicId: courseSectionTopicId,
|
|
451
|
+
t: t,
|
|
452
|
+
isExerciseSelected: isExerciseSelected,
|
|
453
|
+
handleSelectExercise: handleSelectExercise,
|
|
454
|
+
selectedExercises: selectedExercises,
|
|
455
|
+
useCase: useCase,
|
|
456
|
+
assignment: assignment,
|
|
457
|
+
memberCourseCompletions: filteredCompletions,
|
|
458
|
+
topicProgress: topicProgress,
|
|
459
|
+
topics: topics,
|
|
460
|
+
isCreator: isCreator,
|
|
461
|
+
lastClickedExerciseId: lastClickedExerciseId,
|
|
462
|
+
handleRemoveExercise: handleRemoveExercise,
|
|
463
|
+
isPreview: isPreview
|
|
464
|
+
}, roleplay.roleplayId)), orphanedRoleplayIds.map(id => /*#__PURE__*/_jsx(Box, {
|
|
465
|
+
sx: {
|
|
466
|
+
display: "flex",
|
|
467
|
+
alignItems: "center",
|
|
468
|
+
pl: 2,
|
|
469
|
+
py: 1.5,
|
|
470
|
+
ml: {
|
|
471
|
+
xs: "16px",
|
|
472
|
+
sm: "72px",
|
|
473
|
+
md: "76px"
|
|
474
|
+
},
|
|
475
|
+
borderLeft: "3px solid",
|
|
476
|
+
borderColor: "warning.main"
|
|
477
|
+
},
|
|
478
|
+
children: /*#__PURE__*/_jsx(Typography, {
|
|
479
|
+
variant: "body2",
|
|
480
|
+
color: "text.secondary",
|
|
481
|
+
children: t("exercise_no_longer_available")
|
|
482
|
+
})
|
|
483
|
+
}, id))]
|
|
484
|
+
});
|
|
462
485
|
}
|
|
463
486
|
export default AssignmentRoleplaySelection;
|
|
@@ -22,7 +22,8 @@ function AssignmentSelectExercise({
|
|
|
22
22
|
completionHelpers,
|
|
23
23
|
isCreator,
|
|
24
24
|
memberCourseCompletions,
|
|
25
|
-
isChallengeModeStudent
|
|
25
|
+
isChallengeModeStudent,
|
|
26
|
+
isReadWriteModeStudent
|
|
26
27
|
}) {
|
|
27
28
|
const [isExerciseSelected, setIsExerciseSelected] = useState(false);
|
|
28
29
|
const handleSelectExercise = (exercises = []) => {
|
|
@@ -101,7 +102,8 @@ function AssignmentSelectExercise({
|
|
|
101
102
|
completionHelpers: completionHelpers,
|
|
102
103
|
isCreator: isCreator,
|
|
103
104
|
memberCourseCompletions: memberCourseCompletions,
|
|
104
|
-
isChallengeModeStudent: isChallengeModeStudent
|
|
105
|
+
isChallengeModeStudent: isChallengeModeStudent,
|
|
106
|
+
isReadWriteModeStudent: isReadWriteModeStudent
|
|
105
107
|
})
|
|
106
108
|
})]
|
|
107
109
|
});
|
|
@@ -743,10 +743,10 @@ function Translator({
|
|
|
743
743
|
wordList: currentPhrase ? removeExtraWhiteSpaces(currentPhrase.phrase).split(" ") : [],
|
|
744
744
|
disableTranslation: false,
|
|
745
745
|
isMessage: false,
|
|
746
|
-
muteSound:
|
|
746
|
+
muteSound: muteSound,
|
|
747
747
|
t: t,
|
|
748
748
|
languageTag: languageTag
|
|
749
|
-
}), learnLang !== "irish" &&
|
|
749
|
+
}), learnLang !== "irish" && /*#__PURE__*/_jsx(Box, {
|
|
750
750
|
children: /*#__PURE__*/_jsx(WaveFormLite, {
|
|
751
751
|
src: pollyResult ? pollyResult : "",
|
|
752
752
|
controls: false,
|
|
@@ -18,9 +18,6 @@ const useStyles = makeStyles()(theme => ({
|
|
|
18
18
|
},
|
|
19
19
|
formContent: {
|
|
20
20
|
padding: theme.spacing(3)
|
|
21
|
-
},
|
|
22
|
-
group: {
|
|
23
|
-
flexDirection: "row"
|
|
24
21
|
}
|
|
25
22
|
}));
|
|
26
23
|
export default function UpdateTopic({
|
|
@@ -31,10 +28,6 @@ export default function UpdateTopic({
|
|
|
31
28
|
description: "",
|
|
32
29
|
difficulty: "",
|
|
33
30
|
visibility: "",
|
|
34
|
-
shuffleEnabled: "enabled",
|
|
35
|
-
voice: "",
|
|
36
|
-
voiceLanguageCode: "",
|
|
37
|
-
voicePitch: "",
|
|
38
31
|
notes: "",
|
|
39
32
|
topicGoal: "",
|
|
40
33
|
tags: []
|
|
@@ -45,10 +38,6 @@ export default function UpdateTopic({
|
|
|
45
38
|
subscription = {
|
|
46
39
|
isUpgradePossible: true
|
|
47
40
|
},
|
|
48
|
-
voices = {},
|
|
49
|
-
handleSpeak,
|
|
50
|
-
learnLang,
|
|
51
|
-
isUserInternal,
|
|
52
41
|
verificationStatus
|
|
53
42
|
}) {
|
|
54
43
|
const {
|
|
@@ -59,10 +48,6 @@ export default function UpdateTopic({
|
|
|
59
48
|
description,
|
|
60
49
|
difficulty,
|
|
61
50
|
visibility,
|
|
62
|
-
shuffleEnabled,
|
|
63
|
-
voice,
|
|
64
|
-
voicePitch,
|
|
65
|
-
voiceLanguageCode,
|
|
66
51
|
picture,
|
|
67
52
|
banner,
|
|
68
53
|
tags,
|
|
@@ -81,7 +66,6 @@ export default function UpdateTopic({
|
|
|
81
66
|
description,
|
|
82
67
|
difficulty,
|
|
83
68
|
visibility,
|
|
84
|
-
shuffleEnabled,
|
|
85
69
|
picture,
|
|
86
70
|
topicGoal,
|
|
87
71
|
tags
|
|
@@ -142,11 +126,7 @@ export default function UpdateTopic({
|
|
|
142
126
|
})
|
|
143
127
|
}), /*#__PURE__*/_jsx("br", {}), /*#__PURE__*/_jsx(Formik, {
|
|
144
128
|
initialValues: {
|
|
145
|
-
visibility
|
|
146
|
-
shuffleEnabled,
|
|
147
|
-
voice,
|
|
148
|
-
voiceLanguageCode,
|
|
149
|
-
voicePitch
|
|
129
|
+
visibility
|
|
150
130
|
},
|
|
151
131
|
enableReinitialize: enableReinitialize,
|
|
152
132
|
validationSchema: TopicSettings.validationSchema,
|
|
@@ -186,12 +166,7 @@ export default function UpdateTopic({
|
|
|
186
166
|
dirty: dirty,
|
|
187
167
|
values: values,
|
|
188
168
|
...otherProps,
|
|
189
|
-
|
|
190
|
-
subscription: subscription,
|
|
191
|
-
voiceOptions: voices,
|
|
192
|
-
handleSpeak: handleSpeak,
|
|
193
|
-
learnLang: learnLang,
|
|
194
|
-
isUserInternal: isUserInternal
|
|
169
|
+
subscription: subscription
|
|
195
170
|
})
|
|
196
171
|
}), /*#__PURE__*/_jsx(Divider, {}), /*#__PURE__*/_jsx(CardActions, {
|
|
197
172
|
className: classes.padding,
|
|
@@ -1019,10 +1019,6 @@ function Topic({
|
|
|
1019
1019
|
onSubmit: handleUpdateTopic,
|
|
1020
1020
|
fileSizeLimit: fileSizeLimit,
|
|
1021
1021
|
subscription: subscription,
|
|
1022
|
-
voices: voices,
|
|
1023
|
-
handleSpeak: handleSpeak,
|
|
1024
|
-
learnLang: learnLang,
|
|
1025
|
-
isUserInternal: isUserInternal,
|
|
1026
1022
|
verificationStatus: verificationStatus
|
|
1027
1023
|
})
|
|
1028
1024
|
})]
|
|
@@ -48,6 +48,8 @@ export default function ProgressTableRow(props) {
|
|
|
48
48
|
assignedLabels
|
|
49
49
|
} = member;
|
|
50
50
|
const isChallengeModeStudent = assignedLabels?.isChallengeModeStudent;
|
|
51
|
+
const isReadWriteModeStudent = assignedLabels?.isReadWriteModeStudent;
|
|
52
|
+
const assignmentDueDateMs = selectedAssignment?.dueDate ? new Date(selectedAssignment.dueDate).getTime() : null;
|
|
51
53
|
const memberCourseCompletionsQuery = useQuery({
|
|
52
54
|
queryKey: ["memberCourseProgress", memberId, courseIds],
|
|
53
55
|
queryFn: async () => {
|
|
@@ -61,8 +63,8 @@ export default function ProgressTableRow(props) {
|
|
|
61
63
|
error,
|
|
62
64
|
isLoading
|
|
63
65
|
} = memberCourseCompletionsQuery;
|
|
64
|
-
const data = useMemo(() => memberCourseCompletionsQuery.isSuccess && Array.isArray(memberCourseCompletionsQuery.data.Items) && memberCourseCompletionsQuery.data.Items.length ? formatMemberCourseCompletions(courses, memberCourseCompletionsQuery.data.Items, reportType === "assignments" && selectedAssignment ? selectedAssignment?.exercises : null, isChallengeModeStudent, selectedAssignment, reportType) : {}, [memberCourseCompletionsQuery.data, memberCourseCompletionsQuery.isSuccess, courses, reportType, selectedAssignment, isChallengeModeStudent]);
|
|
65
|
-
const assignmentsTableData = useMemo(() => memberCourseCompletionsQuery.isSuccess && Array.isArray(memberCourseCompletionsQuery.data.Items) && memberCourseCompletionsQuery.data.Items.length && assignments && assignments.length ? formatMemberAssignmentCompletions(assignments, courses, memberCourseCompletionsQuery.data.Items, isChallengeModeStudent) : {}, [memberCourseCompletionsQuery.data, memberCourseCompletionsQuery.isSuccess, courses, assignments, isChallengeModeStudent]);
|
|
66
|
+
const data = useMemo(() => memberCourseCompletionsQuery.isSuccess && Array.isArray(memberCourseCompletionsQuery.data.Items) && memberCourseCompletionsQuery.data.Items.length ? formatMemberCourseCompletions(courses, memberCourseCompletionsQuery.data.Items, reportType === "assignments" && selectedAssignment ? selectedAssignment?.exercises : null, isChallengeModeStudent, selectedAssignment, reportType, isReadWriteModeStudent) : {}, [memberCourseCompletionsQuery.data, memberCourseCompletionsQuery.isSuccess, courses, reportType, selectedAssignment, isChallengeModeStudent, isReadWriteModeStudent]);
|
|
67
|
+
const assignmentsTableData = useMemo(() => memberCourseCompletionsQuery.isSuccess && Array.isArray(memberCourseCompletionsQuery.data.Items) && memberCourseCompletionsQuery.data.Items.length && assignments && assignments.length ? formatMemberAssignmentCompletions(assignments, courses, memberCourseCompletionsQuery.data.Items, isChallengeModeStudent, isReadWriteModeStudent) : {}, [memberCourseCompletionsQuery.data, memberCourseCompletionsQuery.isSuccess, courses, assignments, isChallengeModeStudent, isReadWriteModeStudent]);
|
|
66
68
|
let memberActivityLink = `/classrooms/${classroomId}/activity/member/${member.memberId}`;
|
|
67
69
|
if (currentView === "course") {
|
|
68
70
|
memberActivityLink = `${memberActivityLink}/${selectedCourse.courseId}`;
|
|
@@ -205,7 +207,8 @@ export default function ProgressTableRow(props) {
|
|
|
205
207
|
phraseListId: phraseList.phraseListId,
|
|
206
208
|
isLoading: isLoading,
|
|
207
209
|
error: error,
|
|
208
|
-
index: i
|
|
210
|
+
index: i,
|
|
211
|
+
assignmentDueDateMs: assignmentDueDateMs
|
|
209
212
|
}, `phrase-list-cell-${i}`);
|
|
210
213
|
}), (currentView === "phrase-list" || currentView === "assignment-phrase-list") && ["translation", "listening", "pronunciation"].map((exercise, i) => {
|
|
211
214
|
const topicData = getTopicData(data, selectedTopic, selectedCourse, selectedSection);
|
|
@@ -220,7 +223,8 @@ export default function ProgressTableRow(props) {
|
|
|
220
223
|
sectionId: selectedSection?.sectionId || selectedTopic?.courseSectionId?.split("|")[1],
|
|
221
224
|
topicId: selectedTopic?.topicId,
|
|
222
225
|
memberId: member.memberId,
|
|
223
|
-
index: i
|
|
226
|
+
index: i,
|
|
227
|
+
assignmentDueDateMs: assignmentDueDateMs
|
|
224
228
|
}, `phrase-list-exercise-cell-${i}`);
|
|
225
229
|
}), (currentView === "topic" || currentView === "assignment-topic") && tableRoleplays.map((roleplay, i) => {
|
|
226
230
|
const topicData = getTopicData(data, selectedTopic, selectedCourse, selectedSection);
|
|
@@ -235,7 +239,9 @@ export default function ProgressTableRow(props) {
|
|
|
235
239
|
sectionId: selectedSection?.sectionId || selectedTopic?.courseSectionId?.split("|")[1],
|
|
236
240
|
topicId: selectedTopic?.topicId,
|
|
237
241
|
memberId: member.memberId,
|
|
238
|
-
index: i
|
|
242
|
+
index: i,
|
|
243
|
+
assignmentDueDateMs: assignmentDueDateMs,
|
|
244
|
+
showDaysLate: false
|
|
239
245
|
}, `roleplay-cell-${i}`);
|
|
240
246
|
}), (currentView === "topic" || currentView === "assignment-topic") && tableBots.map((bot, i) => {
|
|
241
247
|
const topicData = getTopicData(data, selectedTopic, selectedCourse, selectedSection);
|
|
@@ -252,7 +258,9 @@ export default function ProgressTableRow(props) {
|
|
|
252
258
|
sectionId: selectedSection?.sectionId || selectedTopic?.courseSectionId?.split("|")[1],
|
|
253
259
|
topicId: selectedTopic?.topicId,
|
|
254
260
|
memberId: member.memberId,
|
|
255
|
-
index: i
|
|
261
|
+
index: i,
|
|
262
|
+
assignmentDueDateMs: assignmentDueDateMs,
|
|
263
|
+
showDaysLate: false
|
|
256
264
|
}, `bot-cell-${i}`);
|
|
257
265
|
}), (currentView === "roleplay" || currentView === "assignment-roleplay") && tableRoleplayGames?.length > 0 && tableRoleplayGames.map((game, i) => {
|
|
258
266
|
const topicData = getTopicData(data, selectedTopic, selectedCourse, selectedSection);
|
|
@@ -267,7 +275,8 @@ export default function ProgressTableRow(props) {
|
|
|
267
275
|
sectionId: selectedSection?.sectionId || selectedTopic?.courseSectionId?.split("|")[1],
|
|
268
276
|
topicId: selectedTopic?.topicId,
|
|
269
277
|
memberId: member.memberId,
|
|
270
|
-
index: i
|
|
278
|
+
index: i,
|
|
279
|
+
assignmentDueDateMs: assignmentDueDateMs
|
|
271
280
|
}, `roleplay-game-cell-${i}`);
|
|
272
281
|
}), currentView === "assignments" && assignments.map((assignment, i) => /*#__PURE__*/_jsx(AssignmentCellData, {
|
|
273
282
|
t: t,
|
|
@@ -18,6 +18,7 @@ export function ExerciseCell({
|
|
|
18
18
|
backgroundColor,
|
|
19
19
|
submittedLate = false,
|
|
20
20
|
daysLate = 0,
|
|
21
|
+
showDaysLate = true,
|
|
21
22
|
t
|
|
22
23
|
}) {
|
|
23
24
|
return /*#__PURE__*/_jsx(Box, {
|
|
@@ -41,9 +42,9 @@ export function ExerciseCell({
|
|
|
41
42
|
fontWeight: "bold"
|
|
42
43
|
}),
|
|
43
44
|
size: "small",
|
|
44
|
-
label: t("days_late", {
|
|
45
|
+
label: showDaysLate ? t("days_late", {
|
|
45
46
|
count: daysLate
|
|
46
|
-
})
|
|
47
|
+
}) : t("late_submission")
|
|
47
48
|
})
|
|
48
49
|
})]
|
|
49
50
|
})
|
|
@@ -219,6 +220,12 @@ export function AssignmentCellData(props) {
|
|
|
219
220
|
index
|
|
220
221
|
} = props;
|
|
221
222
|
const cellData = getCellDataForFilter(data, filter);
|
|
223
|
+
let submittedLate = false;
|
|
224
|
+
let daysLate = null;
|
|
225
|
+
if (data?.submittedLate?.isLate === true) {
|
|
226
|
+
submittedLate = true;
|
|
227
|
+
daysLate = data.submittedLate.daysLate;
|
|
228
|
+
}
|
|
222
229
|
return /*#__PURE__*/_jsx(DataCellContainer, {
|
|
223
230
|
t: t,
|
|
224
231
|
data: cellData,
|
|
@@ -226,7 +233,9 @@ export function AssignmentCellData(props) {
|
|
|
226
233
|
isNotAssigned: isNotAssigned,
|
|
227
234
|
error: error,
|
|
228
235
|
memberActivityLink: memberActivityLink,
|
|
229
|
-
index: index
|
|
236
|
+
index: index,
|
|
237
|
+
submittedLate: submittedLate,
|
|
238
|
+
daysLate: daysLate
|
|
230
239
|
});
|
|
231
240
|
}
|
|
232
241
|
export function CourseCellData(props) {
|
|
@@ -268,13 +277,21 @@ export function SectionCellData(props) {
|
|
|
268
277
|
index
|
|
269
278
|
} = props;
|
|
270
279
|
const cellData = getCellDataForFilter(data, filter);
|
|
280
|
+
let submittedLate = false;
|
|
281
|
+
let daysLate = null;
|
|
282
|
+
if (data?.submittedLate?.isLate === true) {
|
|
283
|
+
submittedLate = true;
|
|
284
|
+
daysLate = data.submittedLate.daysLate;
|
|
285
|
+
}
|
|
271
286
|
return /*#__PURE__*/_jsx(DataCellContainer, {
|
|
272
287
|
t: t,
|
|
273
288
|
data: cellData,
|
|
274
289
|
isLoading: isLoading,
|
|
275
290
|
error: error,
|
|
276
291
|
memberActivityLink: memberActivityLink,
|
|
277
|
-
index: index
|
|
292
|
+
index: index,
|
|
293
|
+
submittedLate: submittedLate,
|
|
294
|
+
daysLate: daysLate
|
|
278
295
|
});
|
|
279
296
|
}
|
|
280
297
|
export function TopicCellData(props) {
|
|
@@ -321,7 +338,9 @@ export function ExerciseCellData(props) {
|
|
|
321
338
|
phraseListId,
|
|
322
339
|
index,
|
|
323
340
|
isChallengeModeStudent = false,
|
|
324
|
-
botIsChallengeModeOnly = false
|
|
341
|
+
botIsChallengeModeOnly = false,
|
|
342
|
+
assignmentDueDateMs = null,
|
|
343
|
+
showDaysLate = true
|
|
325
344
|
} = props;
|
|
326
345
|
let icon = null;
|
|
327
346
|
let type = null;
|
|
@@ -329,10 +348,6 @@ export function ExerciseCellData(props) {
|
|
|
329
348
|
let memberActivityLink = null;
|
|
330
349
|
let submittedLate = false;
|
|
331
350
|
let daysLate = null;
|
|
332
|
-
if (data?.submittedLate?.isLate === true) {
|
|
333
|
-
submittedLate = true;
|
|
334
|
-
daysLate = data.submittedLate.daysLate;
|
|
335
|
-
}
|
|
336
351
|
if (isLoading) return /*#__PURE__*/_jsx(DataCell, {
|
|
337
352
|
t: t,
|
|
338
353
|
data: "",
|
|
@@ -360,6 +375,13 @@ export function ExerciseCellData(props) {
|
|
|
360
375
|
} else {
|
|
361
376
|
completions = data?.completions.filter(completion => completion.exercise === exercise);
|
|
362
377
|
}
|
|
378
|
+
if (assignmentDueDateMs && completions?.length > 0) {
|
|
379
|
+
const earliestCompletion = [...completions].sort((a, b) => a.createdAt - b.createdAt)[0];
|
|
380
|
+
if (earliestCompletion.createdAt > assignmentDueDateMs) {
|
|
381
|
+
submittedLate = true;
|
|
382
|
+
daysLate = Math.max(1, Math.ceil((earliestCompletion.createdAt - assignmentDueDateMs) / (1000 * 60 * 60 * 24)));
|
|
383
|
+
}
|
|
384
|
+
}
|
|
363
385
|
if (exercise === "roleplays" && roleplayId && completions?.length > 0) {
|
|
364
386
|
const roleplayCompletionData = data?.percentComplete["roleplays"].completedCounts.find(c => c.roleplayId === roleplayId);
|
|
365
387
|
icon = /*#__PURE__*/_jsx(Typography, {
|
|
@@ -418,7 +440,8 @@ export function ExerciseCellData(props) {
|
|
|
418
440
|
memberActivityLink: memberActivityLink,
|
|
419
441
|
index: index,
|
|
420
442
|
submittedLate: submittedLate,
|
|
421
|
-
daysLate: daysLate
|
|
443
|
+
daysLate: daysLate,
|
|
444
|
+
showDaysLate: showDaysLate
|
|
422
445
|
});
|
|
423
446
|
}
|
|
424
447
|
export function RoleplayCellData({
|
|
@@ -461,7 +484,8 @@ export function PhraseListCellData({
|
|
|
461
484
|
phraseListId,
|
|
462
485
|
isLoading,
|
|
463
486
|
error,
|
|
464
|
-
index
|
|
487
|
+
index,
|
|
488
|
+
assignmentDueDateMs = null
|
|
465
489
|
}) {
|
|
466
490
|
if (isLoading) return /*#__PURE__*/_jsx(DataCell, {
|
|
467
491
|
t: t,
|
|
@@ -474,8 +498,10 @@ export function PhraseListCellData({
|
|
|
474
498
|
index: index
|
|
475
499
|
});
|
|
476
500
|
const phraseListExercises = ["translation", "listening", "pronunciation"];
|
|
477
|
-
const
|
|
501
|
+
const phraseListCompletions = data?.completions?.filter(c => phraseListExercises.includes(c.exercise) && (c.phraseListId === phraseListId || !c.phraseListId && phraseListId?.startsWith('leg-'))) ?? [];
|
|
502
|
+
const completedCount = phraseListExercises.filter(exercise => phraseListCompletions.some(c => c.exercise === exercise)).length;
|
|
478
503
|
const total = phraseListExercises.length;
|
|
504
|
+
const submittedLate = assignmentDueDateMs != null && phraseListCompletions.some(c => c.createdAt > assignmentDueDateMs);
|
|
479
505
|
let color;
|
|
480
506
|
if (completedCount === total) color = green[400];else if (completedCount > 0) color = yellow[400];else color = red[400];
|
|
481
507
|
return /*#__PURE__*/_jsx(ExerciseCell, {
|
|
@@ -485,6 +511,8 @@ export function PhraseListCellData({
|
|
|
485
511
|
children: `${completedCount} / ${total}`
|
|
486
512
|
}),
|
|
487
513
|
backgroundColor: color,
|
|
488
|
-
index: index
|
|
514
|
+
index: index,
|
|
515
|
+
submittedLate: submittedLate,
|
|
516
|
+
showDaysLate: false
|
|
489
517
|
});
|
|
490
518
|
}
|
|
@@ -268,71 +268,60 @@ describe("TopicCellData", () => {
|
|
|
268
268
|
});
|
|
269
269
|
|
|
270
270
|
// ---------------------------------------------------------------------------
|
|
271
|
-
// ExerciseCellData —
|
|
272
|
-
// the daysLate count chip inside ExerciseCell
|
|
271
|
+
// ExerciseCellData — computes submittedLate from assignmentDueDateMs vs
|
|
272
|
+
// completion timestamps; shows the daysLate count chip inside ExerciseCell
|
|
273
273
|
// ---------------------------------------------------------------------------
|
|
274
274
|
describe("ExerciseCellData", () => {
|
|
275
275
|
const baseCourseId = "1";
|
|
276
276
|
const baseSectionId = "54321";
|
|
277
277
|
const baseTopicId = "154321";
|
|
278
|
-
const
|
|
278
|
+
const completionAt = 1578268085029;
|
|
279
|
+
const dueDateBefore = completionAt - 5 * 24 * 60 * 60 * 1000; // 5 days before completion
|
|
280
|
+
const dueDateAfter = completionAt + 1 * 24 * 60 * 60 * 1000; // 1 day after completion
|
|
281
|
+
|
|
282
|
+
const makeData = () => ({
|
|
279
283
|
completions: [{
|
|
280
284
|
exercise: "translation",
|
|
281
|
-
createdAt:
|
|
285
|
+
createdAt: completionAt
|
|
282
286
|
}],
|
|
283
287
|
percentComplete: {
|
|
284
288
|
translation: {
|
|
285
289
|
completedCount: 1
|
|
286
290
|
}
|
|
287
|
-
}
|
|
288
|
-
submittedLate
|
|
291
|
+
}
|
|
289
292
|
});
|
|
290
|
-
it("shows days_late chip when
|
|
293
|
+
it("shows days_late chip when completion is after assignmentDueDateMs", () => {
|
|
291
294
|
wrap(/*#__PURE__*/_jsx(ExerciseCellData, {
|
|
292
295
|
t: t,
|
|
293
|
-
data: makeData(
|
|
294
|
-
isLate: true,
|
|
295
|
-
daysLate: 5
|
|
296
|
-
}),
|
|
296
|
+
data: makeData(),
|
|
297
297
|
exercise: "translation",
|
|
298
298
|
courseId: baseCourseId,
|
|
299
299
|
sectionId: baseSectionId,
|
|
300
300
|
topicId: baseTopicId,
|
|
301
301
|
memberId: "490230",
|
|
302
|
-
index: 0
|
|
302
|
+
index: 0,
|
|
303
|
+
assignmentDueDateMs: dueDateBefore
|
|
303
304
|
}));
|
|
304
305
|
expect(screen.getByText("5 days_late")).toBeTruthy();
|
|
305
306
|
});
|
|
306
|
-
it("does not show days_late chip when
|
|
307
|
+
it("does not show days_late chip when completion is before assignmentDueDateMs", () => {
|
|
307
308
|
wrap(/*#__PURE__*/_jsx(ExerciseCellData, {
|
|
308
309
|
t: t,
|
|
309
|
-
data: makeData(
|
|
310
|
-
isLate: false
|
|
311
|
-
}),
|
|
310
|
+
data: makeData(),
|
|
312
311
|
exercise: "translation",
|
|
313
312
|
courseId: baseCourseId,
|
|
314
313
|
sectionId: baseSectionId,
|
|
315
314
|
topicId: baseTopicId,
|
|
316
315
|
memberId: "490230",
|
|
317
|
-
index: 0
|
|
316
|
+
index: 0,
|
|
317
|
+
assignmentDueDateMs: dueDateAfter
|
|
318
318
|
}));
|
|
319
319
|
expect(screen.queryByText(/days_late/i)).toBeNull();
|
|
320
320
|
});
|
|
321
|
-
it("does not show days_late chip when
|
|
322
|
-
const data = {
|
|
323
|
-
completions: [{
|
|
324
|
-
exercise: "translation",
|
|
325
|
-
createdAt: 1578268085029
|
|
326
|
-
}],
|
|
327
|
-
percentComplete: {
|
|
328
|
-
translation: {
|
|
329
|
-
completedCount: 1
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
};
|
|
321
|
+
it("does not show days_late chip when assignmentDueDateMs is not provided", () => {
|
|
333
322
|
wrap(/*#__PURE__*/_jsx(ExerciseCellData, {
|
|
334
323
|
t: t,
|
|
335
|
-
data:
|
|
324
|
+
data: makeData(),
|
|
336
325
|
exercise: "translation",
|
|
337
326
|
courseId: baseCourseId,
|
|
338
327
|
sectionId: baseSectionId,
|
|
@@ -30,12 +30,12 @@ export function descendingComparator(a, b, property, opts = {}) {
|
|
|
30
30
|
const aCompletions = queryClient.getQueryData(["memberCourseProgress", a.memberId, currentCourseIds])?.Items ?? [];
|
|
31
31
|
const bCompletions = queryClient.getQueryData(["memberCourseProgress", b.memberId, currentCourseIds])?.Items ?? [];
|
|
32
32
|
if (currentView === "assignments") {
|
|
33
|
-
a.completions = opts.formatMemberAssignmentCompletions(assignments, courses, aCompletions, a?.assignedLabels?.isChallengeModeStudent);
|
|
34
|
-
b.completions = opts.formatMemberAssignmentCompletions(assignments, courses, bCompletions, b?.assignedLabels?.isChallengeModeStudent);
|
|
33
|
+
a.completions = opts.formatMemberAssignmentCompletions(assignments, courses, aCompletions, a?.assignedLabels?.isChallengeModeStudent, a?.assignedLabels?.isReadWriteModeStudent);
|
|
34
|
+
b.completions = opts.formatMemberAssignmentCompletions(assignments, courses, bCompletions, b?.assignedLabels?.isChallengeModeStudent, b?.assignedLabels?.isReadWriteModeStudent);
|
|
35
35
|
} else {
|
|
36
36
|
const assignmentEx = reportType === "assignments" && selectedAssignment ? selectedAssignment?.exercises : null;
|
|
37
|
-
a.completions = opts.formatMemberCourseCompletions(courses, aCompletions, assignmentEx, a?.assignedLabels?.isChallengeModeStudent);
|
|
38
|
-
b.completions = opts.formatMemberCourseCompletions(courses, bCompletions, assignmentEx, b?.assignedLabels?.isChallengeModeStudent);
|
|
37
|
+
a.completions = opts.formatMemberCourseCompletions(courses, aCompletions, assignmentEx, a?.assignedLabels?.isChallengeModeStudent, null, "course", a?.assignedLabels?.isReadWriteModeStudent);
|
|
38
|
+
b.completions = opts.formatMemberCourseCompletions(courses, bCompletions, assignmentEx, b?.assignedLabels?.isChallengeModeStudent, null, "course", b?.assignedLabels?.isReadWriteModeStudent);
|
|
39
39
|
}
|
|
40
40
|
if (currentView === "all_courses" || currentView === "assignments") {
|
|
41
41
|
a1 = a.completions[property][percentageAccessor].percentage;
|
|
@@ -6,7 +6,7 @@ function calculateDaysLate(submissionTimestamp, dueDateMs) {
|
|
|
6
6
|
if (daysDifference <= 0) return 0; // Not actually late
|
|
7
7
|
return Math.max(1, Math.ceil(daysDifference)); // Round up, minimum 1 day
|
|
8
8
|
}
|
|
9
|
-
export const formatMemberCourseCompletions = (courses = [], completions = [], assignmentExercises, isChallengeModeStudent = false, selectedAssignment = null, reportType = "course") => {
|
|
9
|
+
export const formatMemberCourseCompletions = (courses = [], completions = [], assignmentExercises, isChallengeModeStudent = false, selectedAssignment = null, reportType = "course", isReadWriteModeStudent = false) => {
|
|
10
10
|
const dueDateMs = selectedAssignment?.dueDate ? new Date(selectedAssignment.dueDate).getTime() : null;
|
|
11
11
|
const initialStatsObject = courses.reduce((obj, v) => {
|
|
12
12
|
const scoreValues = getScoreValues("course", v.courseId, completions);
|
|
@@ -25,7 +25,7 @@ export const formatMemberCourseCompletions = (courses = [], completions = [], as
|
|
|
25
25
|
return obj;
|
|
26
26
|
}, {});
|
|
27
27
|
const stats = courses.reduce((previousValue, currentValue) => {
|
|
28
|
-
const sectionsWithProgress = calcCompletions(currentValue.sections, completions, assignmentExercises, isChallengeModeStudent);
|
|
28
|
+
const sectionsWithProgress = calcCompletions(currentValue.sections, completions, assignmentExercises, isChallengeModeStudent, isReadWriteModeStudent);
|
|
29
29
|
const percentCompletion = calcPercentageCompletion(sectionsWithProgress);
|
|
30
30
|
previousValue[currentValue.courseId].percentComplete = percentCompletion;
|
|
31
31
|
const initialSectionsObject = sectionsWithProgress.reduce((sectionObj, sectionVal) => {
|
|
@@ -79,10 +79,21 @@ export const formatMemberCourseCompletions = (courses = [], completions = [], as
|
|
|
79
79
|
if (!dueDateMs) return {
|
|
80
80
|
isLate: false
|
|
81
81
|
};
|
|
82
|
-
const
|
|
83
|
-
|
|
82
|
+
const courseSectionTopicId = `${topicVal.courseSectionId}|${topicVal.topicId}`;
|
|
83
|
+
const topicAssignmentExercises = assignmentExercises?.filter(e => e.courseSectionTopicId === courseSectionTopicId);
|
|
84
|
+
if (!topicAssignmentExercises?.length) return {
|
|
85
|
+
isLate: false
|
|
86
|
+
};
|
|
87
|
+
const relevantCompletions = topicCompletions.filter(c => topicAssignmentExercises.some(e => {
|
|
88
|
+
if (e.name && c.exercise !== e.name) return false;
|
|
89
|
+
if (e.roleplayId && c.roleplayId !== e.roleplayId) return false;
|
|
90
|
+
if (e.botId && c.botId !== e.botId) return false;
|
|
91
|
+
return true;
|
|
92
|
+
}));
|
|
93
|
+
const lateCompletion = relevantCompletions.find(c => c.createdAt > dueDateMs);
|
|
94
|
+
return lateCompletion ? {
|
|
84
95
|
isLate: true,
|
|
85
|
-
daysLate: calculateDaysLate(
|
|
96
|
+
daysLate: calculateDaysLate(lateCompletion.createdAt, dueDateMs)
|
|
86
97
|
} : {
|
|
87
98
|
isLate: false
|
|
88
99
|
};
|
|
@@ -131,7 +142,7 @@ export const formatMemberCourseCompletions = (courses = [], completions = [], as
|
|
|
131
142
|
}, initialStatsObject);
|
|
132
143
|
return stats;
|
|
133
144
|
};
|
|
134
|
-
export const formatMemberAssignmentCompletions = (assignments = [], courses = [], completions = [], isChallengeModeStudent = false) => {
|
|
145
|
+
export const formatMemberAssignmentCompletions = (assignments = [], courses = [], completions = [], isChallengeModeStudent = false, isReadWriteModeStudent = false) => {
|
|
135
146
|
const stats = assignments.reduce((obj, assignment) => {
|
|
136
147
|
const assignmentCompletions = completions.filter(completion => assignment.exercises?.some(e => {
|
|
137
148
|
if (!e.name && !e.roleplayId && !e.botId && !e.courseSectionTopicId) return false;
|
|
@@ -141,7 +152,7 @@ export const formatMemberAssignmentCompletions = (assignments = [], courses = []
|
|
|
141
152
|
if (e.courseSectionTopicId && `${completion.courseSectionId}|${completion.topicId}` !== e.courseSectionTopicId) return false;
|
|
142
153
|
return true;
|
|
143
154
|
}));
|
|
144
|
-
const assignmentCourseCompletions = formatMemberCourseCompletions(courses, assignmentCompletions, assignment?.exercises, isChallengeModeStudent);
|
|
155
|
+
const assignmentCourseCompletions = formatMemberCourseCompletions(courses, assignmentCompletions, assignment?.exercises, isChallengeModeStudent, null, "course", isReadWriteModeStudent);
|
|
145
156
|
const accumulator = {
|
|
146
157
|
percentComplete: {
|
|
147
158
|
completed: 0,
|
|
@@ -275,7 +275,7 @@ export default function useExerciseState({
|
|
|
275
275
|
}
|
|
276
276
|
}, [exerciseName, questions]);
|
|
277
277
|
useEffect(() => {
|
|
278
|
-
if (open && currentPhrase && currentPhrase.phrase !== "" && !isCompletionModalOpen && learnLang && learnLang !== "irish" && isTourFinished &&
|
|
278
|
+
if (open && currentPhrase && currentPhrase.phrase !== "" && !isCompletionModalOpen && learnLang && learnLang !== "irish" && isTourFinished && exerciseName !== "meaning") {
|
|
279
279
|
const {
|
|
280
280
|
voice,
|
|
281
281
|
voiceLanguageCode,
|