@selfcommunity/react-ui 0.10.2-courses.172 → 0.10.2-courses.174

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.
Files changed (28) hide show
  1. package/lib/cjs/components/CourseDashboard/Student.js +10 -3
  2. package/lib/cjs/components/CourseParticipantsButton/CourseParticipantsButton.js +9 -7
  3. package/lib/cjs/components/EditCourse/Lessons/LessonRow.js +1 -1
  4. package/lib/cjs/components/EditCourse/Lessons/SectionRow.js +7 -6
  5. package/lib/cjs/components/EditCourse/Lessons.js +4 -2
  6. package/lib/cjs/components/EditCourse/Users.js +5 -2
  7. package/lib/cjs/components/LessonCommentObject/LessonCommentObject.js +1 -6
  8. package/lib/cjs/components/LessonCommentObjects/LessonCommentObjects.js +1 -2
  9. package/lib/cjs/shared/AccordionLessons/AccordionLessons.d.ts +2 -1
  10. package/lib/cjs/shared/AccordionLessons/AccordionLessons.js +16 -3
  11. package/lib/cjs/shared/AddUsersButton/AddUsersButton.d.ts +0 -5
  12. package/lib/cjs/shared/AddUsersButton/AddUsersButton.js +6 -7
  13. package/lib/cjs/shared/CourseUsersTable/SeeProgressButton.js +4 -1
  14. package/lib/esm/components/CourseDashboard/Student.js +11 -4
  15. package/lib/esm/components/CourseParticipantsButton/CourseParticipantsButton.js +9 -7
  16. package/lib/esm/components/EditCourse/Lessons/LessonRow.js +1 -1
  17. package/lib/esm/components/EditCourse/Lessons/SectionRow.js +7 -6
  18. package/lib/esm/components/EditCourse/Lessons.js +4 -2
  19. package/lib/esm/components/EditCourse/Users.js +5 -2
  20. package/lib/esm/components/LessonCommentObject/LessonCommentObject.js +1 -6
  21. package/lib/esm/components/LessonCommentObjects/LessonCommentObjects.js +1 -2
  22. package/lib/esm/shared/AccordionLessons/AccordionLessons.d.ts +2 -1
  23. package/lib/esm/shared/AccordionLessons/AccordionLessons.js +18 -5
  24. package/lib/esm/shared/AddUsersButton/AddUsersButton.d.ts +0 -5
  25. package/lib/esm/shared/AddUsersButton/AddUsersButton.js +6 -7
  26. package/lib/esm/shared/CourseUsersTable/SeeProgressButton.js +4 -1
  27. package/lib/umd/react-ui.js +1 -1
  28. package/package.json +8 -8
@@ -52,6 +52,7 @@ const classes = {
52
52
  contrastBgColor: `${constants_1.PREFIX}-contrast-bg-color`
53
53
  };
54
54
  function getUrlNextLesson(course) {
55
+ var _a;
55
56
  const data = {
56
57
  id: course.id,
57
58
  slug: course.slug
@@ -63,7 +64,7 @@ function getUrlNextLesson(course) {
63
64
  });
64
65
  return data;
65
66
  }
66
- course.sections.some((section) => {
67
+ (_a = course.sections) === null || _a === void 0 ? void 0 : _a.some((section) => {
67
68
  const isNextLessonInThisSection = section.num_lessons_completed < section.num_lessons;
68
69
  if (isNextLessonInThisSection) {
69
70
  Object.assign(data, {
@@ -76,7 +77,8 @@ function getUrlNextLesson(course) {
76
77
  return data;
77
78
  }
78
79
  function getIsNextLessonLocked(course) {
79
- return course.sections.every((section) => {
80
+ var _a;
81
+ return (_a = course.sections) === null || _a === void 0 ? void 0 : _a.every((section) => {
80
82
  var _a, _b;
81
83
  return (section.num_lessons_completed < section.num_lessons &&
82
84
  ((_b = (_a = section.lessons) === null || _a === void 0 ? void 0 : _a.find((lesson) => lesson.completion_status === types_1.SCCourseLessonCompletionStatusType.UNCOMPLETED)) === null || _b === void 0 ? void 0 : _b.locked));
@@ -99,6 +101,8 @@ function Student(inProps) {
99
101
  const [loadingRequest, setLoadingRequest] = (0, react_1.useState)(false);
100
102
  // CONTEXTS
101
103
  const scRoutingContext = (0, react_core_1.useSCRouting)();
104
+ const scContext = (0, react_core_1.useSCContext)();
105
+ const scUserContext = (0, react_core_1.useSCUser)();
102
106
  // HOOKS
103
107
  const { scCourse, setSCCourse } = (0, react_core_1.useSCFetchCourse)({ id: courseId, course });
104
108
  const intl = (0, react_intl_1.useIntl)();
@@ -140,6 +144,9 @@ function Student(inProps) {
140
144
  utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
141
145
  });
142
146
  }, [scCourse, sentRequest, setLoadingRequest]);
147
+ const handleAnonymousAction = (0, react_1.useCallback)(() => {
148
+ scContext.settings.handleAnonymousAction();
149
+ }, [scContext.settings.handleAnonymousAction]);
143
150
  // MEMOS
144
151
  const actionButton = (0, react_1.useMemo)(() => {
145
152
  if (!scCourse) {
@@ -153,7 +160,7 @@ function Student(inProps) {
153
160
  ? BUTTON_MESSAGES.start
154
161
  : scCourse.user_completion_rate === 100
155
162
  ? BUTTON_MESSAGES.review
156
- : BUTTON_MESSAGES.continue, to: scCourse.join_status !== null ? scRoutingContext.url(react_core_1.SCRoutes.COURSE_LESSON_ROUTE_NAME, getUrlNextLesson(scCourse)) : undefined, disabled: scCourse.join_status !== null ? getIsNextLessonLocked(scCourse) : undefined, color: scCourse.user_completion_rate === 100 ? 'inherit' : undefined, variant: scCourse.user_completion_rate === 100 ? 'outlined' : undefined, loading: scCourse.join_status === null ? loadingRequest : undefined, onClick: scCourse.join_status === null ? handleRequest : undefined })), scCourse.privacy === types_1.SCCoursePrivacyType.PRIVATE &&
163
+ : BUTTON_MESSAGES.continue, to: scCourse.join_status !== null ? scRoutingContext.url(react_core_1.SCRoutes.COURSE_LESSON_ROUTE_NAME, getUrlNextLesson(scCourse)) : undefined, disabled: scCourse.join_status !== null ? getIsNextLessonLocked(scCourse) : undefined, color: scCourse.user_completion_rate === 100 ? 'inherit' : undefined, variant: scCourse.user_completion_rate === 100 ? 'outlined' : undefined, loading: scCourse.join_status === null ? loadingRequest : undefined, onClick: !scUserContext.user ? handleAnonymousAction : scCourse.join_status === null ? handleRequest : undefined })), scCourse.privacy === types_1.SCCoursePrivacyType.PRIVATE &&
157
164
  (scCourse.join_status === null || scCourse.join_status === types_1.SCCourseJoinStatusType.REQUESTED) && ((0, jsx_runtime_1.jsx)(ActionButton_1.default, { labelId: sentRequest ? BUTTON_MESSAGES.cancel : BUTTON_MESSAGES.request, color: "inherit", variant: "outlined", loading: loadingRequest, onClick: handleRequest }))] })));
158
165
  }, [scCourse, sentRequest, loadingRequest, handleRequest]);
159
166
  if (!scCourse) {
@@ -71,6 +71,7 @@ function CourseParticipantsButton(inProps) {
71
71
  const { className, courseId, course, hideCaption = false, DialogProps = {} } = props, rest = tslib_1.__rest(props, ["className", "courseId", "course", "hideCaption", "DialogProps"]);
72
72
  // STATE
73
73
  const [loading, setLoading] = (0, react_1.useState)(true);
74
+ const [count, setCount] = (0, react_1.useState)(0);
74
75
  const [next, setNext] = (0, react_1.useState)(null);
75
76
  const [offset, setOffset] = (0, react_1.useState)(null);
76
77
  const [enrolled, setEnrolled] = (0, react_1.useState)([]);
@@ -87,17 +88,18 @@ function CourseParticipantsButton(inProps) {
87
88
  if (!scCourse) {
88
89
  return;
89
90
  }
90
- if (!enrolled.length && participantsAvailable) {
91
+ if (!count && participantsAvailable) {
91
92
  api_services_1.CourseService.getCourseJoinedUsers(scCourse.id, { limit: 3 }).then((res) => {
92
93
  setEnrolled([...res.results]);
93
94
  setOffset(4);
95
+ setCount(res.count);
94
96
  setLoading(false);
95
97
  });
96
98
  }
97
99
  else {
98
100
  setOffset(0);
99
101
  }
100
- }, [scCourse, participantsAvailable, enrolled]);
102
+ }, [scCourse, participantsAvailable, count, setEnrolled, setOffset, setLoading]);
101
103
  (0, react_1.useEffect)(() => {
102
104
  if (open && offset !== null) {
103
105
  setLoading(true);
@@ -108,7 +110,7 @@ function CourseParticipantsButton(inProps) {
108
110
  setOffset(null);
109
111
  });
110
112
  }
111
- }, [open, enrolled, offset]);
113
+ }, [open, enrolled, offset, setLoading, setNext]);
112
114
  /**
113
115
  * Memoized fetchEnrolledUsers
114
116
  */
@@ -127,8 +129,8 @@ function CourseParticipantsButton(inProps) {
127
129
  })
128
130
  .catch((error) => utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error))
129
131
  .then(() => setLoading(false));
130
- }, [enrolled, scCourse, next]);
131
- const renderSurplus = (0, react_1.useCallback)(() => (0, buttonCounters_1.numberFormatter)(enrolled.length), [enrolled]);
132
+ }, [enrolled, next, setLoading]);
133
+ const renderSurplus = (0, react_1.useCallback)(() => (0, buttonCounters_1.numberFormatter)(count), [count]);
132
134
  /**
133
135
  * Opens participants dialog
134
136
  */
@@ -141,8 +143,8 @@ function CourseParticipantsButton(inProps) {
141
143
  if (!participantsAvailable) {
142
144
  return (0, jsx_runtime_1.jsx)(HiddenPlaceholder_1.default, {});
143
145
  }
144
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className), onClick: handleToggleDialogOpen, disabled: loading || !scCourse || enrolled.length === 0,
146
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className), onClick: handleToggleDialogOpen, disabled: loading || !scCourse || count === 0,
145
147
  // @ts-expect-error this is needed to use enrolled into SCCourseParticipantsButton
146
- enrolled: enrolled }, rest, { children: [!hideCaption && ((0, jsx_runtime_1.jsxs)(material_1.Typography, Object.assign({ className: classes.participants }, { children: [(0, jsx_runtime_1.jsx)(material_1.Icon, { children: "people_alt" }), (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { defaultMessage: "ui.courseParticipantsButton.participants", id: "ui.courseParticipantsButton.participants", values: { total: enrolled.length } })] }))), !enrolled.length && (loading || !scCourse) ? ((0, jsx_runtime_1.jsx)(AvatarGroupSkeleton_1.default, Object.assign({}, rest, (!participantsAvailable && { skeletonsAnimation: false }), { count: 4 }))) : ((0, jsx_runtime_1.jsx)(material_1.AvatarGroup, Object.assign({ total: enrolled.length, renderSurplus: renderSurplus }, { children: enrolled.map((c) => ((0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: c.username, src: c.avatar }, c.id))) })))] })), open && ((0, jsx_runtime_1.jsx)(DialogRoot, Object.assign({ className: classes.dialogRoot, title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { defaultMessage: "ui.courseParticipantsButton.dialogTitle", id: "ui.courseParticipantsButton.dialogTitle", values: { total: enrolled.length } }), onClose: handleToggleDialogOpen, open: true }, DialogProps, { children: (0, jsx_runtime_1.jsx)(InfiniteScroll_1.default, Object.assign({ dataLength: enrolled.length, next: fetchEnrolledUsers, hasMoreNext: next !== null || loading, loaderNext: (0, jsx_runtime_1.jsx)(User_1.UserSkeleton, { elevation: 0 }), className: classes.infiniteScroll, endMessage: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ className: classes.endMessage }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseParticipantsButton.noOtherParticipants", defaultMessage: "ui.courseParticipantsButton.noOtherParticipants" }) })) }, { children: (0, jsx_runtime_1.jsx)(material_1.List, { children: enrolled.map((e) => ((0, jsx_runtime_1.jsx)(material_1.ListItem, { children: (0, jsx_runtime_1.jsx)(User_1.default, { elevation: 0, user: e }) }, e.id))) }) })) })))] }));
148
+ enrolled: enrolled }, rest, { children: [!hideCaption && ((0, jsx_runtime_1.jsxs)(material_1.Typography, Object.assign({ className: classes.participants }, { children: [(0, jsx_runtime_1.jsx)(material_1.Icon, { children: "people_alt" }), (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { defaultMessage: "ui.courseParticipantsButton.participants", id: "ui.courseParticipantsButton.participants", values: { total: count } })] }))), !count && (loading || !scCourse) ? ((0, jsx_runtime_1.jsx)(AvatarGroupSkeleton_1.default, Object.assign({}, rest, (!participantsAvailable && { skeletonsAnimation: false }), { count: 4 }))) : ((0, jsx_runtime_1.jsx)(material_1.AvatarGroup, Object.assign({ total: count, renderSurplus: renderSurplus }, { children: enrolled.map((c) => ((0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: c.username, src: c.avatar }, c.id))) })))] })), open && ((0, jsx_runtime_1.jsx)(DialogRoot, Object.assign({ className: classes.dialogRoot, title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { defaultMessage: "ui.courseParticipantsButton.dialogTitle", id: "ui.courseParticipantsButton.dialogTitle", values: { total: count } }), onClose: handleToggleDialogOpen, open: true }, DialogProps, { children: (0, jsx_runtime_1.jsx)(InfiniteScroll_1.default, Object.assign({ dataLength: count, next: fetchEnrolledUsers, hasMoreNext: next !== null || loading, loaderNext: (0, jsx_runtime_1.jsx)(User_1.UserSkeleton, { elevation: 0 }), className: classes.infiniteScroll, endMessage: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ className: classes.endMessage }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseParticipantsButton.noOtherParticipants", defaultMessage: "ui.courseParticipantsButton.noOtherParticipants" }) })) }, { children: (0, jsx_runtime_1.jsx)(material_1.List, { children: enrolled.map((e) => ((0, jsx_runtime_1.jsx)(material_1.ListItem, { children: (0, jsx_runtime_1.jsx)(User_1.default, { elevation: 0, user: e }) }, e.id))) }) })) })))] }));
147
149
  }
148
150
  exports.default = CourseParticipantsButton;
@@ -45,7 +45,7 @@ function LessonRow(props) {
45
45
  const { isDisabled } = (0, hooks_1.useDisabled)();
46
46
  const { enqueueSnackbar } = (0, notistack_1.useSnackbar)();
47
47
  // HANDLERS
48
- const handleAbleEditMode = (0, react_1.useCallback)(() => setTimeout(() => setEditMode(true), 100), [setEditMode]);
48
+ const handleAbleEditMode = (0, react_1.useCallback)(() => setTimeout(() => setEditMode(true)), [setEditMode]);
49
49
  const handleDisableEditMode = (0, react_1.useCallback)(() => setEditMode(false), [setEditMode]);
50
50
  const handleDeleteLesson = (0, react_1.useCallback)(() => {
51
51
  api_services_1.CourseService.deleteCourseLesson(course.id, section.id, lesson.id)
@@ -60,6 +60,9 @@ function SectionRow(props) {
60
60
  };
61
61
  }, []);
62
62
  // HANDLERS
63
+ const handleOpenDialog = (0, react_1.useCallback)(() => {
64
+ setOpen((prev) => !prev);
65
+ }, [setOpen]);
63
66
  const handleExpandAccordion = (0, react_1.useCallback)(() => setExpand((prev) => !prev), [setExpand]);
64
67
  const handleDragEnd = (0, react_1.useCallback)((e) => {
65
68
  if (!e.destination || e.destination.index === e.source.index) {
@@ -90,7 +93,7 @@ function SectionRow(props) {
90
93
  }, [course, section, handleManageSection]);
91
94
  const handleAddTempLesson = (0, react_1.useCallback)(() => {
92
95
  setLessons((prevLessons) => ((prevLessons === null || prevLessons === void 0 ? void 0 : prevLessons.length) > 0 ? [...prevLessons, getLesson(prevLessons.length + 1)] : [getLesson(1)]));
93
- }, [setLessons]);
96
+ }, [setLessons, getLesson]);
94
97
  const handleAbleEditMode = (0, react_1.useCallback)(() => setTimeout(() => setEditMode(true)), [setEditMode]);
95
98
  const handleDisableEditMode = (0, react_1.useCallback)(() => setEditMode(false), [setEditMode]);
96
99
  const handleDeleteSection = (0, react_1.useCallback)(() => {
@@ -99,6 +102,7 @@ function SectionRow(props) {
99
102
  var _a;
100
103
  const tempSection = Object.assign(Object.assign({}, section), { num_lessons: ((_a = section.lessons) === null || _a === void 0 ? void 0 : _a.length) || 0 });
101
104
  handleManageSection(tempSection, types_2.ActionLessonType.DELETE);
105
+ handleOpenDialog();
102
106
  enqueueSnackbar((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editCourse.tab.lessons.table.snackbar.delete", defaultMessage: "ui.editCourse.tab.lessons.table.snackbar.delete" }), {
103
107
  variant: 'success',
104
108
  autoHideDuration: 3000
@@ -111,7 +115,7 @@ function SectionRow(props) {
111
115
  autoHideDuration: 3000
112
116
  });
113
117
  });
114
- }, [course, section, handleManageSection]);
118
+ }, [course, section, handleManageSection, handleOpenDialog]);
115
119
  const handleManageLesson = (0, react_1.useCallback)((lesson, type, newRow) => {
116
120
  switch (type) {
117
121
  case types_2.ActionLessonType.ADD: {
@@ -135,14 +139,11 @@ function SectionRow(props) {
135
139
  }
136
140
  }
137
141
  }, [section, handleManageSection]);
138
- const handleOpenDialog = (0, react_1.useCallback)(() => {
139
- setOpen((prev) => !prev);
140
- }, [setOpen]);
141
142
  return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.TableRow, Object.assign({}, provider.draggableProps, { ref: provider.innerRef, className: classes.tableBodyAccordion }, { children: [(0, jsx_runtime_1.jsx)(material_1.TableCell, Object.assign({ component: "th", scope: "row" }, provider.dragHandleProps, { className: (0, classnames_1.default)(classes.cellWidth, classes.cellPadding) }, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.tableBodyIconWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ "aria-label": "expand row", size: "small", onClick: handleExpandAccordion }, { children: expand ? (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "expand_less" }) : (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "expand_more" }) })), (0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ color: "disabled" }, { children: "drag" }))] })) })), (0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(FieldName_1.default, { endpoint: {
142
143
  url: () => isNewRow
143
144
  ? api_services_1.Endpoints.CreateCourseSection.url({ id: course.id })
144
145
  : api_services_1.Endpoints.PatchCourseSection.url({ id: course.id, section_id: section.id }),
145
146
  method: isNewRow ? api_services_1.Endpoints.CreateCourseSection.method : api_services_1.Endpoints.PatchCourseSection.method
146
- }, row: section, isNewRow: isNewRow, handleManageRow: handleManageSection, editMode: editMode, handleDisableEditMode: handleDisableEditMode }) }), (0, jsx_runtime_1.jsx)(material_1.TableCell, Object.assign({ className: classes.cellAlignCenter }, { children: isDisabled ? ((0, jsx_runtime_1.jsx)(material_1.Skeleton, { animation: false, variant: "rectangular", width: "250px", height: "53px", sx: { margin: 'auto', borderRadius: '5px' } })) : ((0, jsx_runtime_1.jsx)(LessonReleaseMenu_1.default, { course: course, section: section })) })), (0, jsx_runtime_1.jsx)(material_1.TableCell, Object.assign({ className: classes.cellAlignRight }, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.actionsWrapper }, { children: [(0, jsx_runtime_1.jsx)(AddButton_1.default, { label: "ui.editCourse.tab.lessons.table.lesson", handleAddRow: handleAddTempLesson, color: "primary", variant: "outlined", disabled: isDisabled }), (0, jsx_runtime_1.jsxs)(MenuRow_1.default, Object.assign({ disabled: isDisabled }, { children: [(0, jsx_runtime_1.jsx)(material_1.MenuItem, Object.assign({ onClick: handleAbleEditMode }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editCourse.tab.lessons.table.menu.rename", defaultMessage: "ui.editCourse.tab.lessons.table.menu.rename" }) })) })), (0, jsx_runtime_1.jsx)(material_1.MenuItem, Object.assign({ onClick: handleOpenDialog }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editCourse.tab.lessons.table.menu.delete", defaultMessage: "ui.editCourse.tab.lessons.table.menu.delete" }) })) }))] }))] })) }))] })), (0, jsx_runtime_1.jsx)(material_1.TableRow, { children: (0, jsx_runtime_1.jsxs)(material_1.TableCell, Object.assign({ className: classes.tableBodyCollapseWrapper, colSpan: 4 }, { children: [(0, jsx_runtime_1.jsx)(material_1.Collapse, Object.assign({ in: expand, timeout: "auto", unmountOnExit: true }, { children: (0, jsx_runtime_1.jsx)(dnd_1.DragDropContext, Object.assign({ onDragEnd: handleDragEnd }, { children: (0, jsx_runtime_1.jsx)(material_1.Table, { children: (0, jsx_runtime_1.jsx)(dnd_1.Droppable, Object.assign({ droppableId: "droppable-2" }, { children: (outerProvider) => ((0, jsx_runtime_1.jsxs)(material_1.TableBody, Object.assign({ ref: outerProvider.innerRef }, outerProvider.droppableProps, { children: [lessons.map((lesson, i, array) => ((0, jsx_runtime_1.jsx)(dnd_1.Draggable, Object.assign({ draggableId: i.toString(), index: i, isDragDisabled: isDisabled }, { children: (innerProvider) => ((0, jsx_runtime_1.jsx)(LessonRow_1.default, { provider: innerProvider, course: course, section: section, lesson: lesson, isNewRow: isNewLocalRow && i + 1 === array.length, handleManageLesson: handleManageLesson }, i)) }), i))), outerProvider.placeholder] }))) })) }) })) })), open && (0, jsx_runtime_1.jsx)(ConfirmDialog_1.default, { open: true, onClose: handleOpenDialog, onConfirm: handleDeleteSection })] })) })] }));
147
+ }, row: section, isNewRow: isNewRow, handleManageRow: handleManageSection, editMode: editMode, handleDisableEditMode: handleDisableEditMode }) }), (0, jsx_runtime_1.jsx)(material_1.TableCell, Object.assign({ className: classes.cellAlignCenter }, { children: isDisabled ? ((0, jsx_runtime_1.jsx)(material_1.Skeleton, { animation: false, variant: "rectangular", width: "250px", height: "38px", sx: { margin: 'auto', borderRadius: '5px' } })) : ((0, jsx_runtime_1.jsx)(LessonReleaseMenu_1.default, { course: course, section: section })) })), (0, jsx_runtime_1.jsx)(material_1.TableCell, Object.assign({ className: classes.cellAlignRight }, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.actionsWrapper }, { children: [(0, jsx_runtime_1.jsx)(AddButton_1.default, { label: "ui.editCourse.tab.lessons.table.lesson", handleAddRow: handleAddTempLesson, color: "primary", variant: "outlined", disabled: isDisabled }), (0, jsx_runtime_1.jsxs)(MenuRow_1.default, Object.assign({ disabled: isDisabled }, { children: [(0, jsx_runtime_1.jsx)(material_1.MenuItem, Object.assign({ onClick: handleAbleEditMode }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editCourse.tab.lessons.table.menu.rename", defaultMessage: "ui.editCourse.tab.lessons.table.menu.rename" }) })) })), (0, jsx_runtime_1.jsx)(material_1.MenuItem, Object.assign({ onClick: handleOpenDialog }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editCourse.tab.lessons.table.menu.delete", defaultMessage: "ui.editCourse.tab.lessons.table.menu.delete" }) })) }))] }))] })) }))] })), (0, jsx_runtime_1.jsx)(material_1.TableRow, { children: (0, jsx_runtime_1.jsxs)(material_1.TableCell, Object.assign({ className: classes.tableBodyCollapseWrapper, colSpan: 4 }, { children: [(0, jsx_runtime_1.jsx)(material_1.Collapse, Object.assign({ in: expand, timeout: "auto", unmountOnExit: true }, { children: (0, jsx_runtime_1.jsx)(dnd_1.DragDropContext, Object.assign({ onDragEnd: handleDragEnd }, { children: (0, jsx_runtime_1.jsx)(material_1.Table, { children: (0, jsx_runtime_1.jsx)(dnd_1.Droppable, Object.assign({ droppableId: "droppable-2" }, { children: (outerProvider) => ((0, jsx_runtime_1.jsxs)(material_1.TableBody, Object.assign({ ref: outerProvider.innerRef }, outerProvider.droppableProps, { children: [lessons.map((lesson, i, array) => ((0, jsx_runtime_1.jsx)(dnd_1.Draggable, Object.assign({ draggableId: i.toString(), index: i, isDragDisabled: isDisabled }, { children: (innerProvider) => ((0, jsx_runtime_1.jsx)(LessonRow_1.default, { provider: innerProvider, course: course, section: section, lesson: lesson, isNewRow: isNewLocalRow && i + 1 === array.length, handleManageLesson: handleManageLesson }, i)) }), i))), outerProvider.placeholder] }))) })) }) })) })), open && (0, jsx_runtime_1.jsx)(ConfirmDialog_1.default, { open: true, onClose: handleOpenDialog, onConfirm: handleDeleteSection })] })) })] }));
147
148
  }
148
149
  exports.default = (0, react_1.memo)(SectionRow);
@@ -108,9 +108,11 @@ function Lessons(props) {
108
108
  }, [setSections]);
109
109
  const handleManageSection = (0, react_1.useCallback)((section, type, newRow = false) => {
110
110
  switch (type) {
111
- case types_1.ActionLessonType.ADD:
112
- setCourse(Object.assign(Object.assign({}, course), { num_sections: course.num_sections + 1, sections: [...course.sections, section] }));
111
+ case types_1.ActionLessonType.ADD: {
112
+ const newSection = Object.assign(Object.assign({}, section), { lessons: [] });
113
+ setCourse(Object.assign(Object.assign({}, course), { num_sections: course.num_sections + 1, sections: [...course.sections, newSection] }));
113
114
  break;
115
+ }
114
116
  case types_1.ActionLessonType.RENAME:
115
117
  setCourse(Object.assign(Object.assign({}, course), { sections: course.sections.map((prevSection) => {
116
118
  if (prevSection.id === section.id) {
@@ -46,7 +46,6 @@ function Users(props) {
46
46
  } } = props;
47
47
  // STATES
48
48
  const [state, dispatch] = (0, react_1.useReducer)(widget_1.dataWidgetReducer, {
49
- isLoadingPrevious: false,
50
49
  isLoadingNext: false,
51
50
  next: null,
52
51
  cacheKey: react_core_1.SCCache.getWidgetStateCacheKey(react_core_1.SCCache.USER_PARTECIPANTS_COURSES_STATE_CACHE_PREFIX_KEY, course.id),
@@ -103,6 +102,10 @@ function Users(props) {
103
102
  type: widget_1.actionWidgetTypes.LOAD_PREVIOUS_SUCCESS,
104
103
  payload: { count: state.count + newUsers.length, results: newUsers, initialized: true }
105
104
  });
105
+ enqueueSnackbar((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editCourse.tab.users.table.snackbar.success", defaultMessage: "ui.editCourse.tab.users.table.snackbar.success" }), {
106
+ variant: 'success',
107
+ autoHideDuration: 3000
108
+ });
106
109
  })
107
110
  .catch((error) => {
108
111
  dispatch({ type: widget_1.actionWidgetTypes.LOAD_NEXT_FAILURE, payload: { errorLoadNext: error } });
@@ -116,6 +119,6 @@ function Users(props) {
116
119
  return ((0, jsx_runtime_1.jsxs)(material_1.Box, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h6", className: classes.contrastColor }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editCourse.tab.users.title", defaultMessage: "ui.editCourse.tab.users.title", values: { usersNumber: state.results.length } }) })), (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.usersStatusWrapper }, { children: [(0, jsx_runtime_1.jsx)(Status_1.default, { course: course }), (0, jsx_runtime_1.jsx)(AddUsersButton_1.default, { label: "ui.editCourse.tab.users.addUsersButton.label", endpoint: {
117
120
  url: () => api_services_1.Endpoints.GetCourseSuggestedUsers.url({ id: course.id }),
118
121
  method: api_services_1.Endpoints.GetCourseSuggestedUsers.method
119
- }, onConfirm: handleConfirm, isUpdating: state.isLoadingPrevious, className: classes.contrastBgColor })] })), (0, jsx_runtime_1.jsx)(CourseUsersTable_1.default, { course: course, state: state, dispatch: dispatch, headerCells: headerCells, mode: "edit", emptyStatusTitle: "ui.courseUsersTable.empty.users.title", emptyStatusDescription: "ui.courseUsersTable.empty.users.description" })] }));
122
+ }, onConfirm: handleConfirm, className: classes.contrastBgColor })] })), (0, jsx_runtime_1.jsx)(CourseUsersTable_1.default, { course: course, state: state, dispatch: dispatch, headerCells: headerCells, mode: "edit", emptyStatusTitle: "ui.courseUsersTable.empty.users.title", emptyStatusDescription: "ui.courseUsersTable.empty.users.description" })] }));
120
123
  }
121
124
  exports.default = (0, react_1.memo)(Users);
@@ -179,15 +179,10 @@ function LessonCommentObject(inProps) {
179
179
  * @param comment
180
180
  */
181
181
  function renderComment(comment) {
182
- if (!scUserContext.user || (scUserContext.user && !react_core_1.UserUtils.isStaff(scUserContext.user) && scUserContext.user.id !== comment.created_by.id)) {
183
- // render the comment if user is logged and is staff (admin, moderator)
184
- // or the comment author is the logged user
185
- return null;
186
- }
187
182
  const summaryHtml = (0, contribution_1.getCommentContributionHtml)(comment.html, scRoutingContext.url);
188
183
  return ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: editComment && editComment.id === comment.id ? ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.comment }, { children: (0, jsx_runtime_1.jsx)(CommentObjectReply_1.default, Object.assign({ text: comment.html, medias: comment.medias, autoFocus: true, id: `edit-${comment.id}`, onSave: handleUpdate, onCancel: handleCancel, editable: !isSavingComment, EditorProps: { uploadFile: true, uploadImage: false } }, CommentObjectReplyProps)) }))) : ((0, jsx_runtime_1.jsx)(BaseItem_1.default, { elevation: 0, className: classes.comment, image: (0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({}, (!comment.created_by.deleted && { to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, comment.created_by) }), { onClick: comment.created_by.deleted ? () => setOpenAlert(true) : null }, { children: (0, jsx_runtime_1.jsx)(UserAvatar_1.default, Object.assign({ hide: !obj.created_by.community_badge }, { children: (0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: obj.created_by.username, variant: "circular", src: comment.created_by.avatar, className: classes.avatar }) })) })), disableTypography: true, primary: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsxs)(Widget_1.default, Object.assign({ className: classes.content, elevation: elevation }, rest, { children: [(0, jsx_runtime_1.jsxs)(material_1.CardContent, { children: [(0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ className: classes.author }, (!comment.created_by.deleted && { to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, comment.created_by) }), { onClick: comment.created_by.deleted ? () => setOpenAlert(true) : null }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: "span" }, { children: comment.created_by.username })) })), (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Bullet_1.default, {}), (0, jsx_runtime_1.jsx)(DateTimeAgo_1.default, { date: comment.created_at, showStartIcon: false })] }), (0, jsx_runtime_1.jsx)(material_1.Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: summaryHtml } }), obj.medias && obj.medias.length > 0 && ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: obj.medias.map((media) => {
189
184
  return (0, jsx_runtime_1.jsx)(LessonFilePreview_1.default, { className: classes.mediaContent, media: media }, media.id);
190
- }) }))] }), scUserContext.user && ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.commentActionsMenu }, { children: (0, jsx_runtime_1.jsx)(LessonCommentActionsMenu_1.default, { lesson: lessonObject, commentObject: comment, onDelete: handleDelete, onEdit: handleEdit }) })))] })) }) })) }, comment.id));
185
+ }) }))] }), scUserContext.user && scUserContext.user.id === comment.created_by.id && ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.commentActionsMenu }, { children: (0, jsx_runtime_1.jsx)(LessonCommentActionsMenu_1.default, { lesson: lessonObject, commentObject: comment, onDelete: handleDelete, onEdit: handleEdit }) })))] })) }) })) }, comment.id));
191
186
  }
192
187
  /**
193
188
  * Render comments
@@ -88,7 +88,7 @@ function LessonCommentObjects(inProps) {
88
88
  id: lessonObject.id,
89
89
  lessonObject: lessonObject,
90
90
  pageSize: 8,
91
- orderBy: types_1.SCCommentsOrderBy.CONNECTION_ASC,
91
+ orderBy: types_1.SCCommentsOrderBy.ADDED_AT_ASC,
92
92
  cacheStrategy
93
93
  });
94
94
  // EFFECTS
@@ -165,7 +165,6 @@ function LessonCommentObjects(inProps) {
165
165
  }
166
166
  commentsObject.updateLessonComments([...updated]);
167
167
  };
168
- console.log(commentsObject.isLoadingNext);
169
168
  /**
170
169
  * Renders root object(if obj)
171
170
  */
@@ -1,7 +1,8 @@
1
1
  import { HTMLAttributes } from 'react';
2
- import { SCCourseType } from '@selfcommunity/types';
2
+ import { SCCourseJoinStatusType, SCCourseType } from '@selfcommunity/types';
3
3
  export interface AccordionLessonsProps {
4
4
  course: SCCourseType | null;
5
+ viewerJoinStatus?: SCCourseJoinStatusType;
5
6
  className?: HTMLAttributes<HTMLDivElement>['className'];
6
7
  }
7
8
  export default function AccordionLessons(inProps: AccordionLessonsProps): JSX.Element;
@@ -7,16 +7,27 @@ const react_intl_1 = require("react-intl");
7
7
  const classnames_1 = tslib_1.__importDefault(require("classnames"));
8
8
  const react_1 = require("react");
9
9
  const types_1 = require("@selfcommunity/types");
10
+ const react_core_1 = require("@selfcommunity/react-core");
10
11
  const constants_1 = require("./constants");
11
12
  const Skeleton_1 = tslib_1.__importDefault(require("./Skeleton"));
13
+ const react_core_2 = require("@selfcommunity/react-core");
12
14
  const classes = {
13
15
  root: `${constants_1.PREFIX}-root`,
14
16
  empty: `${constants_1.PREFIX}-empty`,
15
17
  accordion: `${constants_1.PREFIX}-accordion`,
16
18
  summary: `${constants_1.PREFIX}-summary`,
17
19
  details: `${constants_1.PREFIX}-details`,
18
- circle: `${constants_1.PREFIX}-circle`
20
+ circle: `${constants_1.PREFIX}-circle`,
21
+ link: `${constants_1.PREFIX}-link`
19
22
  };
23
+ function getUrlLesson(course, section, lesson) {
24
+ return {
25
+ id: course.id,
26
+ slug: course.slug,
27
+ section_id: section.id,
28
+ lesson_id: lesson.id
29
+ };
30
+ }
20
31
  const Root = (0, material_1.styled)(material_1.Box, {
21
32
  name: constants_1.PREFIX,
22
33
  slot: 'Root',
@@ -29,12 +40,14 @@ function AccordionLessons(inProps) {
29
40
  props: inProps,
30
41
  name: constants_1.PREFIX
31
42
  });
32
- const { course, className } = props;
43
+ const { course, viewerJoinStatus, className } = props;
33
44
  //STATES
34
45
  const [expanded, setExpanded] = (0, react_1.useState)(false);
35
46
  // HOOKS
36
47
  const theme = (0, material_1.useTheme)();
37
48
  const isMobile = (0, material_1.useMediaQuery)(theme.breakpoints.down('sm'));
49
+ // CONTEXTS
50
+ const scRoutingContext = (0, react_core_1.useSCRouting)();
38
51
  // HANDLERS
39
52
  const handleChange = (0, react_1.useCallback)((panel) => (_, newExpanded) => {
40
53
  setExpanded(newExpanded ? panel : false);
@@ -44,6 +57,6 @@ function AccordionLessons(inProps) {
44
57
  }
45
58
  return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, { children: ((_a = course.sections) === null || _a === void 0 ? void 0 : _a.length) > 0 ? (course.sections.map((section) => ((0, jsx_runtime_1.jsxs)(material_1.Accordion, Object.assign({ className: classes.accordion, expanded: expanded === section.id, onChange: handleChange(section.id), disableGutters: true, elevation: 0, square: true }, { children: [(0, jsx_runtime_1.jsxs)(material_1.AccordionSummary, Object.assign({ className: classes.summary, expandIcon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "expand_less" }) }, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: "span", variant: "body1" }, { children: section.name })), !isMobile && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ component: "span", variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.course.table.lessons.title", defaultMessage: "ui.course.table.lessons.title", values: {
46
59
  lessonsNumber: section.lessons.length
47
- } }) })))] })), section.lessons.map((lesson) => ((0, jsx_runtime_1.jsxs)(material_1.AccordionDetails, Object.assign({ className: classes.details }, { children: [lesson.completion_status === types_1.SCCourseLessonCompletionStatusType.COMPLETED ? ((0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ fontSize: "small", color: "primary" }, { children: "circle_checked" }))) : lesson.locked ? ((0, jsx_runtime_1.jsx)(material_1.Icon, { children: "private" })) : ((0, jsx_runtime_1.jsx)(material_1.Box, { className: classes.circle })), (0, jsx_runtime_1.jsx)(material_1.Typography, { children: lesson.name })] }), lesson.id)))] }), section.id)))) : ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1", className: classes.empty }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.course.accordionLessons.empty", defaultMessage: "ui.course.accordionLessons.empty" }) }))) })));
60
+ } }) })))] })), section.lessons.map((lesson) => ((0, jsx_runtime_1.jsxs)(material_1.AccordionDetails, Object.assign({ className: classes.details }, { children: [lesson.completion_status === types_1.SCCourseLessonCompletionStatusType.COMPLETED ? ((0, jsx_runtime_1.jsx)(material_1.Icon, Object.assign({ fontSize: "small", color: "primary" }, { children: "circle_checked" }))) : lesson.locked ? ((0, jsx_runtime_1.jsx)(material_1.Icon, { children: "private" })) : ((0, jsx_runtime_1.jsx)(material_1.Box, { className: classes.circle })), course.join_status === null || viewerJoinStatus === types_1.SCCourseJoinStatusType.CREATOR || lesson.locked ? ((0, jsx_runtime_1.jsx)(material_1.Typography, { children: lesson.name })) : ((0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ component: react_core_2.Link, to: scRoutingContext.url(react_core_1.SCRoutes.COURSE_LESSON_ROUTE_NAME, getUrlLesson(course, section, lesson)), variant: "text", color: "inherit", className: classes.link }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, { children: lesson.name }) })))] }), lesson.id)))] }), section.id)))) : ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1", className: classes.empty }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.course.accordionLessons.empty", defaultMessage: "ui.course.accordionLessons.empty" }) }))) })));
48
61
  }
49
62
  exports.default = AccordionLessons;
@@ -4,11 +4,6 @@ import { SCUserType } from '@selfcommunity/types';
4
4
  import { EndpointType } from '@selfcommunity/api-services';
5
5
  export interface AddUsersButtonProps extends ButtonProps {
6
6
  label: string;
7
- /**
8
- * Handles component update
9
- * @default false
10
- */
11
- isUpdating?: boolean;
12
7
  /**
13
8
  * Event API Endpoint
14
9
  * @default Endpoints.GetCourseSuggestedUsers
@@ -43,7 +43,7 @@ function AddUsersButton(inProps) {
43
43
  props: inProps,
44
44
  name: PREFIX
45
45
  });
46
- const { label, variant = 'outlined', color = 'inherit', size = 'small', isUpdating = false, endpoint = api_services_1.Endpoints.GetCourseSuggestedUsers, endpointQueryParams = { limit: Pagination_1.DEFAULT_PAGINATION_LIMIT, offset: Pagination_1.DEFAULT_PAGINATION_OFFSET, search: '' }, onConfirm, className } = props, rest = tslib_1.__rest(props, ["label", "variant", "color", "size", "isUpdating", "endpoint", "endpointQueryParams", "onConfirm", "className"]);
46
+ const { label, variant = 'outlined', color = 'inherit', size = 'small', endpoint = api_services_1.Endpoints.GetCourseSuggestedUsers, endpointQueryParams = { limit: Pagination_1.DEFAULT_PAGINATION_LIMIT, offset: Pagination_1.DEFAULT_PAGINATION_OFFSET, search: '' }, onConfirm, className } = props, rest = tslib_1.__rest(props, ["label", "variant", "color", "size", "endpoint", "endpointQueryParams", "onConfirm", "className"]);
47
47
  // STATES
48
48
  const [openDialog, setOpenDialog] = (0, react_1.useState)(false);
49
49
  const [invited, setInvited] = (0, react_1.useState)([]);
@@ -86,17 +86,16 @@ function AddUsersButton(inProps) {
86
86
  * @param reason
87
87
  */
88
88
  const handleToggleDialogOpen = (0, react_1.useCallback)(() => {
89
- if (!isUpdating) {
90
- setOpenDialog((prev) => !prev);
91
- }
92
- }, [isUpdating, setOpenDialog]);
89
+ setOpenDialog((prev) => !prev);
90
+ }, [setOpenDialog]);
93
91
  /**
94
92
  * Handles action confirm
95
93
  */
96
94
  const handleConfirm = (0, react_1.useCallback)(() => {
97
95
  onConfirm === null || onConfirm === void 0 ? void 0 : onConfirm(invited);
98
96
  setInvited([]);
99
- }, [invited, onConfirm]);
97
+ handleToggleDialogOpen();
98
+ }, [invited, onConfirm, handleToggleDialogOpen]);
100
99
  // HANDLERS AUTOCOMPLETE
101
100
  const handleInputChange = (0, react_1.useCallback)((_, newValue, reason) => {
102
101
  switch (reason) {
@@ -129,7 +128,7 @@ function AddUsersButton(inProps) {
129
128
  const handleDelete = (0, react_1.useCallback)((userToDelete) => {
130
129
  setInvited((prev) => prev.filter((user) => user.id !== userToDelete.id));
131
130
  }, [setInvited]);
132
- return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Root, Object.assign({ onClick: handleToggleDialogOpen, variant: variant, color: color, size: size, className: (0, classnames_1.default)(classes.root, className) }, rest, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: label, defaultMessage: label }) })), openDialog && ((0, jsx_runtime_1.jsx)(DialogRoot, Object.assign({ DialogContentProps: { dividers: false }, open: true, onClose: handleToggleDialogOpen, title: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h5" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.addUserButton.dialog.title", defaultMessage: "ui.addUserButton.dialog.title" }) })), actions: (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ onClick: handleConfirm, size: "medium", variant: "contained", autoFocus: true, disabled: !invited.length, loading: isUpdating }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.addUserButton.dialog.confirm", defaultMessage: "ui.addUserButton.dialog.confirm" }) })) })), className: classes.dialogRoot }, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.dialogAutocompleteWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Autocomplete, { loading: loading, size: "small", multiple: true, options: suggested, onChange: handleChange, onInputChange: handleInputChange, inputValue: value, filterOptions: filterOptions, value: invited, getOptionLabel: (option) => (option === null || option === void 0 ? void 0 : option.username) || '...', isOptionEqualToValue: (option, value) => (option === null || option === void 0 ? void 0 : option.id) === value.id, loadingText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.addUserButton.autocomplete.loading", defaultMessage: "ui.addUserButton.autocomplete.loading" }), noOptionsText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.addUserButton.autocomplete.noResults", defaultMessage: "ui.addUserButton.autocomplete.noResults" }), renderTags: () => null, popupIcon: null, disableClearable: true, renderOption: (props, option) => ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ component: "li", flexDirection: "row", gap: "5px" }, props, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: option.username, src: option.avatar }), (0, jsx_runtime_1.jsx)(material_1.Typography, { children: option.username })] }))), renderInput: (params) => ((0, jsx_runtime_1.jsx)(material_1.TextField, Object.assign({}, params, { variant: "outlined", placeholder: `${intl.formatMessage(messages.placeholder)}`, InputProps: Object.assign({}, params.InputProps) }))) }), (0, jsx_runtime_1.jsx)(material_1.Stack, Object.assign({ className: classes.dialogChipWrapper }, { children: invited.map((option, index) => ((0, jsx_runtime_1.jsx)(material_1.Chip, { avatar: (0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: option.username, src: option.avatar }), label: option.username, onDelete: () => {
131
+ return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Root, Object.assign({ onClick: handleToggleDialogOpen, variant: variant, color: color, size: size, className: (0, classnames_1.default)(classes.root, className) }, rest, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: label, defaultMessage: label }) })), openDialog && ((0, jsx_runtime_1.jsx)(DialogRoot, Object.assign({ DialogContentProps: { dividers: false }, open: true, onClose: handleToggleDialogOpen, title: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h5" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.addUserButton.dialog.title", defaultMessage: "ui.addUserButton.dialog.title" }) })), actions: (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ onClick: handleConfirm, size: "medium", variant: "contained", autoFocus: true, disabled: !invited.length }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.addUserButton.dialog.confirm", defaultMessage: "ui.addUserButton.dialog.confirm" }) })) })), className: classes.dialogRoot }, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.dialogAutocompleteWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Autocomplete, { loading: loading, size: "small", multiple: true, options: suggested, onChange: handleChange, onInputChange: handleInputChange, inputValue: value, filterOptions: filterOptions, value: invited, getOptionLabel: (option) => (option === null || option === void 0 ? void 0 : option.username) || '...', isOptionEqualToValue: (option, value) => (option === null || option === void 0 ? void 0 : option.id) === value.id, loadingText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.addUserButton.autocomplete.loading", defaultMessage: "ui.addUserButton.autocomplete.loading" }), noOptionsText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.addUserButton.autocomplete.noResults", defaultMessage: "ui.addUserButton.autocomplete.noResults" }), renderTags: () => null, popupIcon: null, disableClearable: true, renderOption: (props, option) => ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ component: "li", flexDirection: "row", gap: "5px" }, props, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: option.username, src: option.avatar }), (0, jsx_runtime_1.jsx)(material_1.Typography, { children: option.username })] }))), renderInput: (params) => ((0, jsx_runtime_1.jsx)(material_1.TextField, Object.assign({}, params, { variant: "outlined", placeholder: `${intl.formatMessage(messages.placeholder)}`, InputProps: Object.assign({}, params.InputProps) }))) }), (0, jsx_runtime_1.jsx)(material_1.Stack, Object.assign({ className: classes.dialogChipWrapper }, { children: invited.map((option, index) => ((0, jsx_runtime_1.jsx)(material_1.Chip, { avatar: (0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: option.username, src: option.avatar }), label: option.username, onDelete: () => {
133
132
  handleDelete(option);
134
133
  } }, index))) }))] })) })))] }));
135
134
  }
@@ -12,6 +12,7 @@ const AccordionLessons_1 = tslib_1.__importDefault(require("../AccordionLessons"
12
12
  const api_services_1 = require("@selfcommunity/api-services");
13
13
  const utils_1 = require("@selfcommunity/utils");
14
14
  const Errors_1 = require("../../constants/Errors");
15
+ const UserAvatar_1 = tslib_1.__importDefault(require("../UserAvatar"));
15
16
  const classes = {
16
17
  dialogRoot: `${constants_1.PREFIX}-dialog-root`,
17
18
  contentWrapper: `${constants_1.PREFIX}-content-wrapper`,
@@ -48,6 +49,8 @@ function SeeProgressButton(props) {
48
49
  const handleToggleOpen = (0, react_1.useCallback)(() => {
49
50
  setOpen((prev) => !prev);
50
51
  }, [setOpen]);
51
- return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [isMobile ? ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ size: "small", color: "inherit", onClick: handleToggleOpen }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "chevron_right" }) }))) : ((0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ variant: "outlined", size: "small", color: "inherit", onClick: handleToggleOpen }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.action.btn.label", defaultMessage: "ui.courseUsersTable.action.btn.label" }) })) }))), open && ((0, jsx_runtime_1.jsx)(DialogRoot, Object.assign({ DialogContentProps: { dividers: isMobile }, open: true, scroll: "paper", onClose: handleToggleOpen, title: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h3" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.dialog.title", defaultMessage: "ui.courseUsersTable.dialog.title" }) })), className: classes.dialogRoot }, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.contentWrapper }, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.infoOuterWrapper }, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.infoInnerWrapper }, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.avatarWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { className: classes.avatar, src: user.avatar, alt: user.username }), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: user.username }))] })), (0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user), variant: "outlined", size: "small", color: "inherit" }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.dialog.btn.label", defaultMessage: "ui.courseUsersTable.dialog.btn.label" }) })) }))] })), student ? ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.dialog.info.text1", defaultMessage: "ui.courseUsersTable.dialog.info.text1", values: { lessonsCompleted: student.num_lessons_completed } }) }))) : ((0, jsx_runtime_1.jsx)(material_1.Skeleton, { animation: "wave", variant: "text", width: "100px", height: "21px" })), student ? ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.dialog.info.text2", defaultMessage: "ui.courseUsersTable.dialog.info.text2", values: { courseCompleted: student.user_completion_rate } }) }))) : ((0, jsx_runtime_1.jsx)(material_1.Skeleton, { animation: "wave", variant: "text", width: "100px", height: "21px" }))] })), (0, jsx_runtime_1.jsx)(AccordionLessons_1.default, { course: student })] })) })))] }));
52
+ return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [isMobile ? ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ size: "small", color: "inherit", onClick: handleToggleOpen }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "chevron_right" }) }))) : ((0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ variant: "outlined", size: "small", color: "inherit", onClick: handleToggleOpen }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.action.btn.label", defaultMessage: "ui.courseUsersTable.action.btn.label" }) })) }))), open && ((0, jsx_runtime_1.jsx)(DialogRoot, Object.assign({ DialogContentProps: { dividers: isMobile }, open: true, scroll: "paper", onClose: handleToggleOpen, title: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h3" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.dialog.title", defaultMessage: "ui.courseUsersTable.dialog.title" }) })), className: classes.dialogRoot }, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.contentWrapper }, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.infoOuterWrapper }, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.infoInnerWrapper }, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.avatarWrapper }, { children: [(0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({}, (!course.created_by.deleted && {
53
+ to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, course.created_by)
54
+ }), { children: (0, jsx_runtime_1.jsx)(UserAvatar_1.default, Object.assign({ hide: !course.created_by.community_badge, smaller: true }, { children: (0, jsx_runtime_1.jsx)(material_1.Avatar, { className: classes.avatar, src: user.avatar, alt: user.username }) })) })), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: user.username }))] })), (0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user), variant: "outlined", size: "small", color: "inherit" }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.dialog.btn.label", defaultMessage: "ui.courseUsersTable.dialog.btn.label" }) })) }))] })), student ? ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.dialog.info.text1", defaultMessage: "ui.courseUsersTable.dialog.info.text1", values: { lessonsCompleted: student.num_lessons_completed } }) }))) : ((0, jsx_runtime_1.jsx)(material_1.Skeleton, { animation: "wave", variant: "text", width: "100px", height: "21px" })), student ? ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.courseUsersTable.dialog.info.text2", defaultMessage: "ui.courseUsersTable.dialog.info.text2", values: { courseCompleted: student.user_completion_rate } }) }))) : ((0, jsx_runtime_1.jsx)(material_1.Skeleton, { animation: "wave", variant: "text", width: "100px", height: "21px" }))] })), (0, jsx_runtime_1.jsx)(AccordionLessons_1.default, { course: student, viewerJoinStatus: course.join_status })] })) })))] }));
52
55
  }
53
56
  exports.default = (0, react_1.memo)(SeeProgressButton);
@@ -9,7 +9,7 @@ import { SCCourseJoinStatusType, SCCourseLessonCompletionStatusType, SCCoursePri
9
9
  import { FormattedMessage, useIntl } from 'react-intl';
10
10
  import ActionButton from './Student/ActionButton';
11
11
  import { CLAPPING } from '../../assets/courses/clapping';
12
- import { SCRoutes, useSCFetchCourse, useSCRouting, Link } from '@selfcommunity/react-core';
12
+ import { SCRoutes, useSCFetchCourse, useSCRouting, Link, useSCUser, useSCContext } from '@selfcommunity/react-core';
13
13
  import AccordionLessons from '../../shared/AccordionLessons';
14
14
  import { CourseService } from '@selfcommunity/api-services';
15
15
  import { Logger } from '@selfcommunity/utils';
@@ -50,6 +50,7 @@ const classes = {
50
50
  contrastBgColor: `${PREFIX}-contrast-bg-color`
51
51
  };
52
52
  function getUrlNextLesson(course) {
53
+ var _a;
53
54
  const data = {
54
55
  id: course.id,
55
56
  slug: course.slug
@@ -61,7 +62,7 @@ function getUrlNextLesson(course) {
61
62
  });
62
63
  return data;
63
64
  }
64
- course.sections.some((section) => {
65
+ (_a = course.sections) === null || _a === void 0 ? void 0 : _a.some((section) => {
65
66
  const isNextLessonInThisSection = section.num_lessons_completed < section.num_lessons;
66
67
  if (isNextLessonInThisSection) {
67
68
  Object.assign(data, {
@@ -74,7 +75,8 @@ function getUrlNextLesson(course) {
74
75
  return data;
75
76
  }
76
77
  function getIsNextLessonLocked(course) {
77
- return course.sections.every((section) => {
78
+ var _a;
79
+ return (_a = course.sections) === null || _a === void 0 ? void 0 : _a.every((section) => {
78
80
  var _a, _b;
79
81
  return (section.num_lessons_completed < section.num_lessons &&
80
82
  ((_b = (_a = section.lessons) === null || _a === void 0 ? void 0 : _a.find((lesson) => lesson.completion_status === SCCourseLessonCompletionStatusType.UNCOMPLETED)) === null || _b === void 0 ? void 0 : _b.locked));
@@ -97,6 +99,8 @@ function Student(inProps) {
97
99
  const [loadingRequest, setLoadingRequest] = useState(false);
98
100
  // CONTEXTS
99
101
  const scRoutingContext = useSCRouting();
102
+ const scContext = useSCContext();
103
+ const scUserContext = useSCUser();
100
104
  // HOOKS
101
105
  const { scCourse, setSCCourse } = useSCFetchCourse({ id: courseId, course });
102
106
  const intl = useIntl();
@@ -138,6 +142,9 @@ function Student(inProps) {
138
142
  Logger.error(SCOPE_SC_UI, error);
139
143
  });
140
144
  }, [scCourse, sentRequest, setLoadingRequest]);
145
+ const handleAnonymousAction = useCallback(() => {
146
+ scContext.settings.handleAnonymousAction();
147
+ }, [scContext.settings.handleAnonymousAction]);
141
148
  // MEMOS
142
149
  const actionButton = useMemo(() => {
143
150
  if (!scCourse) {
@@ -151,7 +158,7 @@ function Student(inProps) {
151
158
  ? BUTTON_MESSAGES.start
152
159
  : scCourse.user_completion_rate === 100
153
160
  ? BUTTON_MESSAGES.review
154
- : BUTTON_MESSAGES.continue, to: scCourse.join_status !== null ? scRoutingContext.url(SCRoutes.COURSE_LESSON_ROUTE_NAME, getUrlNextLesson(scCourse)) : undefined, disabled: scCourse.join_status !== null ? getIsNextLessonLocked(scCourse) : undefined, color: scCourse.user_completion_rate === 100 ? 'inherit' : undefined, variant: scCourse.user_completion_rate === 100 ? 'outlined' : undefined, loading: scCourse.join_status === null ? loadingRequest : undefined, onClick: scCourse.join_status === null ? handleRequest : undefined })), scCourse.privacy === SCCoursePrivacyType.PRIVATE &&
161
+ : BUTTON_MESSAGES.continue, to: scCourse.join_status !== null ? scRoutingContext.url(SCRoutes.COURSE_LESSON_ROUTE_NAME, getUrlNextLesson(scCourse)) : undefined, disabled: scCourse.join_status !== null ? getIsNextLessonLocked(scCourse) : undefined, color: scCourse.user_completion_rate === 100 ? 'inherit' : undefined, variant: scCourse.user_completion_rate === 100 ? 'outlined' : undefined, loading: scCourse.join_status === null ? loadingRequest : undefined, onClick: !scUserContext.user ? handleAnonymousAction : scCourse.join_status === null ? handleRequest : undefined })), scCourse.privacy === SCCoursePrivacyType.PRIVATE &&
155
162
  (scCourse.join_status === null || scCourse.join_status === SCCourseJoinStatusType.REQUESTED) && (_jsx(ActionButton, { labelId: sentRequest ? BUTTON_MESSAGES.cancel : BUTTON_MESSAGES.request, color: "inherit", variant: "outlined", loading: loadingRequest, onClick: handleRequest }))] })));
156
163
  }, [scCourse, sentRequest, loadingRequest, handleRequest]);
157
164
  if (!scCourse) {
@@ -69,6 +69,7 @@ export default function CourseParticipantsButton(inProps) {
69
69
  const { className, courseId, course, hideCaption = false, DialogProps = {} } = props, rest = __rest(props, ["className", "courseId", "course", "hideCaption", "DialogProps"]);
70
70
  // STATE
71
71
  const [loading, setLoading] = useState(true);
72
+ const [count, setCount] = useState(0);
72
73
  const [next, setNext] = useState(null);
73
74
  const [offset, setOffset] = useState(null);
74
75
  const [enrolled, setEnrolled] = useState([]);
@@ -85,17 +86,18 @@ export default function CourseParticipantsButton(inProps) {
85
86
  if (!scCourse) {
86
87
  return;
87
88
  }
88
- if (!enrolled.length && participantsAvailable) {
89
+ if (!count && participantsAvailable) {
89
90
  CourseService.getCourseJoinedUsers(scCourse.id, { limit: 3 }).then((res) => {
90
91
  setEnrolled([...res.results]);
91
92
  setOffset(4);
93
+ setCount(res.count);
92
94
  setLoading(false);
93
95
  });
94
96
  }
95
97
  else {
96
98
  setOffset(0);
97
99
  }
98
- }, [scCourse, participantsAvailable, enrolled]);
100
+ }, [scCourse, participantsAvailable, count, setEnrolled, setOffset, setLoading]);
99
101
  useEffect(() => {
100
102
  if (open && offset !== null) {
101
103
  setLoading(true);
@@ -106,7 +108,7 @@ export default function CourseParticipantsButton(inProps) {
106
108
  setOffset(null);
107
109
  });
108
110
  }
109
- }, [open, enrolled, offset]);
111
+ }, [open, enrolled, offset, setLoading, setNext]);
110
112
  /**
111
113
  * Memoized fetchEnrolledUsers
112
114
  */
@@ -125,8 +127,8 @@ export default function CourseParticipantsButton(inProps) {
125
127
  })
126
128
  .catch((error) => Logger.error(SCOPE_SC_UI, error))
127
129
  .then(() => setLoading(false));
128
- }, [enrolled, scCourse, next]);
129
- const renderSurplus = useCallback(() => numberFormatter(enrolled.length), [enrolled]);
130
+ }, [enrolled, next, setLoading]);
131
+ const renderSurplus = useCallback(() => numberFormatter(count), [count]);
130
132
  /**
131
133
  * Opens participants dialog
132
134
  */
@@ -139,7 +141,7 @@ export default function CourseParticipantsButton(inProps) {
139
141
  if (!participantsAvailable) {
140
142
  return _jsx(HiddenPlaceholder, {});
141
143
  }
142
- return (_jsxs(_Fragment, { children: [_jsxs(Root, Object.assign({ className: classNames(classes.root, className), onClick: handleToggleDialogOpen, disabled: loading || !scCourse || enrolled.length === 0,
144
+ return (_jsxs(_Fragment, { children: [_jsxs(Root, Object.assign({ className: classNames(classes.root, className), onClick: handleToggleDialogOpen, disabled: loading || !scCourse || count === 0,
143
145
  // @ts-expect-error this is needed to use enrolled into SCCourseParticipantsButton
144
- enrolled: enrolled }, rest, { children: [!hideCaption && (_jsxs(Typography, Object.assign({ className: classes.participants }, { children: [_jsx(Icon, { children: "people_alt" }), _jsx(FormattedMessage, { defaultMessage: "ui.courseParticipantsButton.participants", id: "ui.courseParticipantsButton.participants", values: { total: enrolled.length } })] }))), !enrolled.length && (loading || !scCourse) ? (_jsx(AvatarGroupSkeleton, Object.assign({}, rest, (!participantsAvailable && { skeletonsAnimation: false }), { count: 4 }))) : (_jsx(AvatarGroup, Object.assign({ total: enrolled.length, renderSurplus: renderSurplus }, { children: enrolled.map((c) => (_jsx(Avatar, { alt: c.username, src: c.avatar }, c.id))) })))] })), open && (_jsx(DialogRoot, Object.assign({ className: classes.dialogRoot, title: _jsx(FormattedMessage, { defaultMessage: "ui.courseParticipantsButton.dialogTitle", id: "ui.courseParticipantsButton.dialogTitle", values: { total: enrolled.length } }), onClose: handleToggleDialogOpen, open: true }, DialogProps, { children: _jsx(InfiniteScroll, Object.assign({ dataLength: enrolled.length, next: fetchEnrolledUsers, hasMoreNext: next !== null || loading, loaderNext: _jsx(UserSkeleton, { elevation: 0 }), className: classes.infiniteScroll, endMessage: _jsx(Typography, Object.assign({ className: classes.endMessage }, { children: _jsx(FormattedMessage, { id: "ui.courseParticipantsButton.noOtherParticipants", defaultMessage: "ui.courseParticipantsButton.noOtherParticipants" }) })) }, { children: _jsx(List, { children: enrolled.map((e) => (_jsx(ListItem, { children: _jsx(User, { elevation: 0, user: e }) }, e.id))) }) })) })))] }));
146
+ enrolled: enrolled }, rest, { children: [!hideCaption && (_jsxs(Typography, Object.assign({ className: classes.participants }, { children: [_jsx(Icon, { children: "people_alt" }), _jsx(FormattedMessage, { defaultMessage: "ui.courseParticipantsButton.participants", id: "ui.courseParticipantsButton.participants", values: { total: count } })] }))), !count && (loading || !scCourse) ? (_jsx(AvatarGroupSkeleton, Object.assign({}, rest, (!participantsAvailable && { skeletonsAnimation: false }), { count: 4 }))) : (_jsx(AvatarGroup, Object.assign({ total: count, renderSurplus: renderSurplus }, { children: enrolled.map((c) => (_jsx(Avatar, { alt: c.username, src: c.avatar }, c.id))) })))] })), open && (_jsx(DialogRoot, Object.assign({ className: classes.dialogRoot, title: _jsx(FormattedMessage, { defaultMessage: "ui.courseParticipantsButton.dialogTitle", id: "ui.courseParticipantsButton.dialogTitle", values: { total: count } }), onClose: handleToggleDialogOpen, open: true }, DialogProps, { children: _jsx(InfiniteScroll, Object.assign({ dataLength: count, next: fetchEnrolledUsers, hasMoreNext: next !== null || loading, loaderNext: _jsx(UserSkeleton, { elevation: 0 }), className: classes.infiniteScroll, endMessage: _jsx(Typography, Object.assign({ className: classes.endMessage }, { children: _jsx(FormattedMessage, { id: "ui.courseParticipantsButton.noOtherParticipants", defaultMessage: "ui.courseParticipantsButton.noOtherParticipants" }) })) }, { children: _jsx(List, { children: enrolled.map((e) => (_jsx(ListItem, { children: _jsx(User, { elevation: 0, user: e }) }, e.id))) }) })) })))] }));
145
147
  }
@@ -42,7 +42,7 @@ function LessonRow(props) {
42
42
  const { isDisabled } = useDisabled();
43
43
  const { enqueueSnackbar } = useSnackbar();
44
44
  // HANDLERS
45
- const handleAbleEditMode = useCallback(() => setTimeout(() => setEditMode(true), 100), [setEditMode]);
45
+ const handleAbleEditMode = useCallback(() => setTimeout(() => setEditMode(true)), [setEditMode]);
46
46
  const handleDisableEditMode = useCallback(() => setEditMode(false), [setEditMode]);
47
47
  const handleDeleteLesson = useCallback(() => {
48
48
  CourseService.deleteCourseLesson(course.id, section.id, lesson.id)