@nualang/nualang-ui-components 0.1.1386 → 0.1.1388
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 +4 -39
- package/dist/Editors/Phrases/Phrases.js +15 -5
- package/dist/Forms/CreateClassroom/Steps/ClassroomSettings/ClassroomSettings.js +2 -2
- package/dist/Forms/CreateCourse/Steps/CourseSettings/CourseSettings.js +2 -2
- package/dist/Live/Misc/StudentAnswerDrawer/StudentAnswerDrawer.js +8 -2
- package/dist/Misc/ExerciseBottomBar/ExerciseBottomBar.js +6 -2
- package/dist/Screens/Courses/ViewCourse/ViewCourse.js +8 -3
- package/dist/Screens/Courses/ViewCourse/ViewTopic/ViewTopic.js +1 -1
- package/dist/utils/index.js +10 -0
- package/package.json +2 -2
|
@@ -45,7 +45,6 @@ export default function CreateAssignmentDialog({
|
|
|
45
45
|
createAssignment,
|
|
46
46
|
username,
|
|
47
47
|
getMemberDetails,
|
|
48
|
-
getClassroom,
|
|
49
48
|
getCourses,
|
|
50
49
|
initialData = {},
|
|
51
50
|
dialogTitle,
|
|
@@ -74,45 +73,11 @@ export default function CreateAssignmentDialog({
|
|
|
74
73
|
});
|
|
75
74
|
const [isTitleEdited, setIsTitleEdited] = useState(Boolean(initialData.title));
|
|
76
75
|
const [isCreating, setIsCreating] = useState(false);
|
|
77
|
-
const classroomQuery = useQueries({
|
|
78
|
-
queries: (Array.isArray(assignment.classroomId) ? assignment.classroomId : [assignment.classroomId]).map(cId => ({
|
|
79
|
-
queryKey: classroomQuerys.classroomKeys.item(cId, username),
|
|
80
|
-
queryFn: () => getClassroom(cId, filters),
|
|
81
|
-
queryOptions: {
|
|
82
|
-
enabled: !!(Array.isArray(assignment.classroomId) ? assignment.classroomId.length > 0 : assignment.classroomId)
|
|
83
|
-
}
|
|
84
|
-
})),
|
|
85
|
-
combine: results => {
|
|
86
|
-
const normalizedData = results.map(result => {
|
|
87
|
-
const data = result.data;
|
|
88
|
-
if (data?.classroomId) {
|
|
89
|
-
return data;
|
|
90
|
-
}
|
|
91
|
-
if (data?.Item?.classroomId) {
|
|
92
|
-
return data.Item;
|
|
93
|
-
}
|
|
94
|
-
return null;
|
|
95
|
-
}).filter(Boolean);
|
|
96
|
-
return {
|
|
97
|
-
data: normalizedData,
|
|
98
|
-
pending: results.some(result => result.isPending)
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
76
|
const selectedClassroomCourses = useMemo(() => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (seen.has(courseId)) return false;
|
|
108
|
-
seen.add(courseId);
|
|
109
|
-
return true;
|
|
110
|
-
});
|
|
111
|
-
return uniqueCourses;
|
|
112
|
-
} else {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
}, [classroomQuery.data, classroomQuery.pending]);
|
|
77
|
+
const selectedIds = Array.isArray(assignment.classroomId) ? assignment.classroomId : [assignment.classroomId];
|
|
78
|
+
const allCourses = (classrooms || []).filter(c => selectedIds.includes(c.classroomId)).flatMap(c => c.courses || []);
|
|
79
|
+
return [...new Set(allCourses)];
|
|
80
|
+
}, [classrooms, assignment.classroomId]);
|
|
116
81
|
const coursesQuery = courseQuerys.useCourses(async filters => {
|
|
117
82
|
const response = await getCourses(filters);
|
|
118
83
|
return response;
|
|
@@ -296,6 +296,7 @@ function PhrasesEditor(props) {
|
|
|
296
296
|
type: "include",
|
|
297
297
|
ids: new Set()
|
|
298
298
|
});
|
|
299
|
+
const selectedRows = Array.from(selectionModel.ids);
|
|
299
300
|
const [spreadsheetPhrases, setSpreadsheetPhrases] = useState(Object.keys(phrases).length > 0 ? phrases : [rowTemplate]);
|
|
300
301
|
const isRowEmpty = row => {
|
|
301
302
|
let rowEmpty = true;
|
|
@@ -366,8 +367,6 @@ function PhrasesEditor(props) {
|
|
|
366
367
|
addRow,
|
|
367
368
|
isDirty,
|
|
368
369
|
hasTrailingEmptyRow,
|
|
369
|
-
selectedRow,
|
|
370
|
-
deleteSelectedRow,
|
|
371
370
|
processRowUpdate
|
|
372
371
|
} = useSpreadsheetState({
|
|
373
372
|
rowTemplate,
|
|
@@ -439,6 +438,15 @@ function PhrasesEditor(props) {
|
|
|
439
438
|
console.error(error);
|
|
440
439
|
}
|
|
441
440
|
};
|
|
441
|
+
const deleteSelectedRows = () => {
|
|
442
|
+
if (selectedRows.length === 0) return;
|
|
443
|
+
const updatedRows = rows.filter(r => !selectionModel.ids.has(r.id));
|
|
444
|
+
handleSpreadsheetSaveChanges(phrases, formatRowsToPhrases(updatedRows));
|
|
445
|
+
setSelectionModel({
|
|
446
|
+
type: "include",
|
|
447
|
+
ids: new Set()
|
|
448
|
+
});
|
|
449
|
+
};
|
|
442
450
|
return /*#__PURE__*/_jsxs(Box, {
|
|
443
451
|
className: classes.centeredContainer,
|
|
444
452
|
children: [isCreator && mode === Modes.SPREADSHEET && /*#__PURE__*/_jsx(Box, {
|
|
@@ -449,9 +457,9 @@ function PhrasesEditor(props) {
|
|
|
449
457
|
children: /*#__PURE__*/_jsx(DefaultButton, {
|
|
450
458
|
variant: "contained",
|
|
451
459
|
size: "small",
|
|
452
|
-
onClick:
|
|
460
|
+
onClick: deleteSelectedRows,
|
|
453
461
|
endIcon: /*#__PURE__*/_jsx(DeleteIcon, {}),
|
|
454
|
-
disabled:
|
|
462
|
+
disabled: selectedRows.length === 0,
|
|
455
463
|
children: t("delete_selected_row")
|
|
456
464
|
})
|
|
457
465
|
}), isMember && !isCreator && /*#__PURE__*/_jsx(NormalModeComponent, {
|
|
@@ -521,7 +529,9 @@ function PhrasesEditor(props) {
|
|
|
521
529
|
isDirty: isDirty,
|
|
522
530
|
hasTrailingEmptyRow: hasTrailingEmptyRow,
|
|
523
531
|
hasNonEmptyRows: hasNonEmptyRows,
|
|
524
|
-
processRowUpdate: processRowUpdate
|
|
532
|
+
processRowUpdate: processRowUpdate,
|
|
533
|
+
selectionModel: selectionModel,
|
|
534
|
+
onRowSelectionModelChange: setSelectionModel
|
|
525
535
|
}) : /*#__PURE__*/_jsx(EmptyPhraseList, {
|
|
526
536
|
t: t,
|
|
527
537
|
siteLanguage: siteLanguage,
|
|
@@ -4,7 +4,7 @@ import * as Yup from "yup";
|
|
|
4
4
|
import Tooltip from "@mui/material/Tooltip";
|
|
5
5
|
import ChipInput from "../../../../Forms/ChipInput/ChipInput";
|
|
6
6
|
import { domainPattern } from "../../../../utils/index";
|
|
7
|
-
import { containsInvalidSymbols } from "../../../../utils/index";
|
|
7
|
+
import { containsInvalidSymbols, containsInvalidCollaboratorSymbols } from "../../../../utils/index";
|
|
8
8
|
import HelpIcon from "@mui/icons-material/Help";
|
|
9
9
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
10
10
|
function ClassroomSettings({
|
|
@@ -396,6 +396,6 @@ ClassroomSettings.validationSchema = Yup.object().shape({
|
|
|
396
396
|
otherwise: () => Yup.string().nullable()
|
|
397
397
|
}),
|
|
398
398
|
allowedDomains: Yup.array(Yup.string().test("noSpecialChars", "no_special_characters", value => !containsInvalidSymbols(value)).matches(domainPattern, "Must be a valid domain e.g 'schooldomain.com'")).nullable(),
|
|
399
|
-
collaborators: Yup.array(Yup.string().test("noSpecialChars", "no_special_characters", value => !
|
|
399
|
+
collaborators: Yup.array(Yup.string().test("noSpecialChars", "no_special_characters", value => !containsInvalidCollaboratorSymbols(value))).nullable()
|
|
400
400
|
});
|
|
401
401
|
export default ClassroomSettings;
|
|
@@ -4,7 +4,7 @@ import * as Yup from "yup";
|
|
|
4
4
|
import Tooltip from "@mui/material/Tooltip";
|
|
5
5
|
import ChipInput from "../../../../Forms/ChipInput/ChipInput";
|
|
6
6
|
import { domainPattern } from "../../../../utils/index";
|
|
7
|
-
import { containsInvalidSymbols } from "../../../../utils/index";
|
|
7
|
+
import { containsInvalidSymbols, containsInvalidCollaboratorSymbols } from "../../../../utils/index";
|
|
8
8
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
9
9
|
function CourseSettings({
|
|
10
10
|
t,
|
|
@@ -250,7 +250,7 @@ CourseSettings.validationSchema = Yup.object().shape({
|
|
|
250
250
|
otherwise: () => Yup.string().nullable()
|
|
251
251
|
}),
|
|
252
252
|
allowedDomains: Yup.array(Yup.string().test("noSpecialChars", "no_special_characters", value => !containsInvalidSymbols(value)).matches(domainPattern, "Must be a valid domain e.g 'schooldomain.com'")).nullable(),
|
|
253
|
-
collaborators: Yup.array(Yup.string().test("noSpecialChars", "no_special_characters", value => !
|
|
253
|
+
collaborators: Yup.array(Yup.string().test("noSpecialChars", "no_special_characters", value => !containsInvalidCollaboratorSymbols(value))).nullable(),
|
|
254
254
|
isShareable: Yup.string().required("required"),
|
|
255
255
|
duplicated: Yup.bool()
|
|
256
256
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect } from "react";
|
|
1
|
+
import { useState, useEffect, useRef } from "react";
|
|
2
2
|
import { Drawer, List, ListSubheader, ListItemText, ListItemButton, ListItemIcon, IconButton, Tooltip } from "@mui/material";
|
|
3
3
|
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
|
|
4
4
|
import { useTheme } from "@mui/material/styles";
|
|
@@ -25,10 +25,15 @@ function StudentAnswerDrawer({
|
|
|
25
25
|
const theme = useTheme();
|
|
26
26
|
const [selectedIndex, setSelectedIndex] = useState();
|
|
27
27
|
const isSmallScreen = useMediaQuery("(max-width:959px)");
|
|
28
|
+
const committedAnswerRef = useRef(null);
|
|
29
|
+
const handleContinueRef = useRef(handleContinue);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
handleContinueRef.current = handleContinue;
|
|
32
|
+
});
|
|
28
33
|
useEffect(() => {
|
|
29
34
|
if (isTimeUp) {
|
|
30
35
|
setIsAnswered(true);
|
|
31
|
-
|
|
36
|
+
handleContinueRef.current(committedAnswerRef.current);
|
|
32
37
|
}
|
|
33
38
|
}, [isTimeUp]);
|
|
34
39
|
useEffect(() => {
|
|
@@ -41,6 +46,7 @@ function StudentAnswerDrawer({
|
|
|
41
46
|
setSelectedIndex(i);
|
|
42
47
|
setCurrentAnswer(value);
|
|
43
48
|
setIsAnswered(true);
|
|
49
|
+
committedAnswerRef.current = value;
|
|
44
50
|
}
|
|
45
51
|
};
|
|
46
52
|
const listItemIconStyle = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
2
|
import Button from "@mui/material/Button";
|
|
3
3
|
import Grid from "@mui/material/Grid";
|
|
4
4
|
import { makeStyles } from "tss-react/mui";
|
|
@@ -33,9 +33,13 @@ function ExerciseBottomBar({
|
|
|
33
33
|
const {
|
|
34
34
|
classes
|
|
35
35
|
} = useStyles();
|
|
36
|
+
const handleSubmitRef = useRef(handleSubmit);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
handleSubmitRef.current = handleSubmit;
|
|
39
|
+
});
|
|
36
40
|
useEffect(() => {
|
|
37
41
|
if (isTimeUp) {
|
|
38
|
-
|
|
42
|
+
handleSubmitRef.current();
|
|
39
43
|
setIsAnswered(true);
|
|
40
44
|
}
|
|
41
45
|
}, [isTimeUp]);
|
|
@@ -120,7 +120,8 @@ function OverflowMenu({
|
|
|
120
120
|
handleUploadVideo,
|
|
121
121
|
isTeacher,
|
|
122
122
|
video,
|
|
123
|
-
setVideo
|
|
123
|
+
setVideo,
|
|
124
|
+
handleCloseMenu
|
|
124
125
|
}) {
|
|
125
126
|
const [isShareDrawerOpen, setIsShareDrawerOpen] = useState(false);
|
|
126
127
|
const [isUploadVideoOpen, setIsUploadVideoOpen] = useState(false);
|
|
@@ -245,7 +246,10 @@ function OverflowMenu({
|
|
|
245
246
|
title: courseName,
|
|
246
247
|
url: window.location.href,
|
|
247
248
|
open: isShareDrawerOpen,
|
|
248
|
-
handleClose: () =>
|
|
249
|
+
handleClose: () => {
|
|
250
|
+
setIsShareDrawerOpen(false);
|
|
251
|
+
handleCloseMenu();
|
|
252
|
+
},
|
|
249
253
|
subscription: subscription,
|
|
250
254
|
trackRecommendedEvent: trackRecommendedEvent,
|
|
251
255
|
itemId: courseId,
|
|
@@ -933,7 +937,8 @@ function Course({
|
|
|
933
937
|
handleUploadVideo: handleUploadVideo,
|
|
934
938
|
isTeacher: !isStudent,
|
|
935
939
|
video: video,
|
|
936
|
-
setVideo: setVideo
|
|
940
|
+
setVideo: setVideo,
|
|
941
|
+
handleCloseMenu: handleCloseMenu
|
|
937
942
|
}), /*#__PURE__*/_jsx(UpgradeSubscription, {
|
|
938
943
|
t: t,
|
|
939
944
|
open: isUpgradeSubscriptionOpen,
|
|
@@ -515,7 +515,7 @@ function Topic({
|
|
|
515
515
|
total: 0,
|
|
516
516
|
percentage: 0
|
|
517
517
|
};
|
|
518
|
-
}, [isMember, topic?.topicId, topic?.completions?.length, isChallengeModeStudent, isReadWriteModeStudent]);
|
|
518
|
+
}, [isMember, topic?.topicId, topic?.completions?.length, topic?.roleplays?.length, topic?.bots?.length, isChallengeModeStudent, isReadWriteModeStudent]);
|
|
519
519
|
const {
|
|
520
520
|
percentage,
|
|
521
521
|
completed,
|
package/dist/utils/index.js
CHANGED
|
@@ -24,6 +24,16 @@ export const containsInvalidSymbols = input => {
|
|
|
24
24
|
}
|
|
25
25
|
return false;
|
|
26
26
|
};
|
|
27
|
+
|
|
28
|
+
// Same as containsInvalidSymbols but allows underscores
|
|
29
|
+
export const containsInvalidCollaboratorSymbols = input => {
|
|
30
|
+
const invalidChars = /[`#^*\[\];\\|<>\/~]/; // !()@,.'$%&+={}?:"_ allowed
|
|
31
|
+
|
|
32
|
+
if (invalidChars.test(input)) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
};
|
|
27
37
|
export const removeExtraWhiteSpaces = (str = "") => str.replace(/\s+/g, " ").trim();
|
|
28
38
|
export const removeAllSymbols = (str = "") => {
|
|
29
39
|
const removedEmojis = removeEmojis(str);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nualang/nualang-ui-components",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1388",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"@mui/system": "^7.0.2",
|
|
102
102
|
"@mui/x-date-pickers": "^8.27.2",
|
|
103
103
|
"@nualang/eslint-config-nualang": "0.2.0-alpha-5",
|
|
104
|
-
"@nualang/nualang-api-and-queries": "^1.1.
|
|
104
|
+
"@nualang/nualang-api-and-queries": "^1.1.51",
|
|
105
105
|
"@react-theming/storybook-addon": "^1.1.10",
|
|
106
106
|
"@storybook/addon-docs": "^10.0.2",
|
|
107
107
|
"@storybook/addon-links": "^10.0.2",
|