@selfcommunity/react-ui 0.10.2-courses.200 → 0.10.2-courses.202
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/lib/cjs/components/Course/Course.js +4 -1
- package/lib/cjs/components/Courses/Courses.js +1 -1
- package/lib/cjs/shared/CourseUsersTable/CourseUsersTable.js +23 -9
- package/lib/esm/components/Course/Course.js +5 -2
- package/lib/esm/components/Courses/Courses.js +1 -1
- package/lib/esm/shared/CourseUsersTable/CourseUsersTable.js +23 -9
- package/lib/umd/react-ui.js +1 -1
- package/package.json +8 -8
|
@@ -110,6 +110,9 @@ function Course(inProps) {
|
|
|
110
110
|
const { id = `course_object_${props.courseId ? props.courseId : props.course ? props.course.id : ''}`, courseId = null, course = null, className = null, template = course_1.SCCourseTemplateType.PREVIEW, actions, CourseParticipantsButtonComponentProps = {}, CourseSkeletonComponentProps = {}, userProfileSnippet } = props, rest = tslib_1.__rest(props, ["id", "courseId", "course", "className", "template", "actions", "CourseParticipantsButtonComponentProps", "CourseSkeletonComponentProps", "userProfileSnippet"]);
|
|
111
111
|
// STATE
|
|
112
112
|
const { scCourse } = (0, react_core_1.useSCFetchCourse)({ id: courseId, course });
|
|
113
|
+
const theme = (0, material_1.useTheme)();
|
|
114
|
+
const isMobile = (0, material_1.useMediaQuery)(theme.breakpoints.between('xs', 'md'));
|
|
115
|
+
const MAX_VISIBLE_CATEGORIES = isMobile ? 3 : 1;
|
|
113
116
|
// CONTEXT
|
|
114
117
|
const scRoutingContext = (0, react_core_1.useSCRouting)();
|
|
115
118
|
const isCourseAdmin = (0, react_1.useMemo)(() => scCourse && (scCourse.join_status === types_1.SCCourseJoinStatusType.CREATOR || scCourse.join_status === types_1.SCCourseJoinStatusType.MANAGER), [scCourse]);
|
|
@@ -160,7 +163,7 @@ function Course(inProps) {
|
|
|
160
163
|
to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
161
164
|
}), { children: (0, jsx_runtime_1.jsx)(UserAvatar_1.default, Object.assign({ hide: !((_b = scCourse.created_by) === null || _b === void 0 ? void 0 : _b.community_badge), smaller: true }, { children: (0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: scCourse.name, src: (_c = scCourse.created_by) === null || _c === void 0 ? void 0 : _c.avatar, className: classes.previewAvatar }) })) }))] })), (0, jsx_runtime_1.jsxs)(material_1.CardContent, Object.assign({ className: classes.previewContent }, { children: [(0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ className: classes.previewCreator }, (!((_d = scCourse.created_by) === null || _d === void 0 ? void 0 : _d.deleted) && {
|
|
162
165
|
to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
163
|
-
}), { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (_e = scCourse.created_by) === null || _e === void 0 ? void 0 : _e.username })) })), (0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ to: scRoutingContext.url(react_core_1.SCRoutes.COURSE_ROUTE_NAME, scCourse), className: classes.previewNameWrapper }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h6", className: classes.previewName }, { children: scCourse.name })) })), (0, jsx_runtime_1.jsxs)(material_1.Typography, Object.assign({ className: classes.previewInfo }, { children: [(0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: scCourse.privacy ? `ui.course.privacy.${scCourse.privacy}` : 'ui.course.privacy.draft', defaultMessage: scCourse.privacy ? `ui.course.privacy.${scCourse.privacy}` : 'ui.course.privacy.draft' }), ' - ', (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.course.type.${scCourse.type}`, defaultMessage: `ui.course.type.${scCourse.type}` })] })), (0, jsx_runtime_1.
|
|
166
|
+
}), { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (_e = scCourse.created_by) === null || _e === void 0 ? void 0 : _e.username })) })), (0, jsx_runtime_1.jsx)(react_core_1.Link, Object.assign({ to: scRoutingContext.url(react_core_1.SCRoutes.COURSE_ROUTE_NAME, scCourse), className: classes.previewNameWrapper }, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h6", className: classes.previewName }, { children: scCourse.name })) })), (0, jsx_runtime_1.jsxs)(material_1.Typography, Object.assign({ className: classes.previewInfo }, { children: [(0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: scCourse.privacy ? `ui.course.privacy.${scCourse.privacy}` : 'ui.course.privacy.draft', defaultMessage: scCourse.privacy ? `ui.course.privacy.${scCourse.privacy}` : 'ui.course.privacy.draft' }), ' - ', (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.course.type.${scCourse.type}`, defaultMessage: `ui.course.type.${scCourse.type}` })] })), (0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.previewCategory }, { children: [scCourse.categories.slice(0, MAX_VISIBLE_CATEGORIES).map((category) => ((0, jsx_runtime_1.jsx)(material_1.Chip, { size: "small", label: category.name }, category.id))), scCourse.categories.length > MAX_VISIBLE_CATEGORIES && ((0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: scCourse.categories.slice(MAX_VISIBLE_CATEGORIES).map((cat) => ((0, jsx_runtime_1.jsx)(material_1.Box, { children: cat.name }, cat.id))) }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Chip, { size: "small", label: `+${scCourse.categories.length - MAX_VISIBLE_CATEGORIES}`, sx: { cursor: 'pointer' } }) })))] })), (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.previewProgress }, { children: renderProgress() }))] })), actions !== null && actions !== void 0 ? actions : ((0, jsx_runtime_1.jsx)(material_1.CardActions, Object.assign({ className: classes.previewActions }, { children: (0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ variant: "outlined", size: "small", component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.COURSE_ROUTE_NAME, scCourse) }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { defaultMessage: "ui.course.see", id: "ui.course.see" }) })) })))] })));
|
|
164
167
|
}
|
|
165
168
|
else {
|
|
166
169
|
contentObj = ((0, jsx_runtime_1.jsx)(SnippetRoot, { ButtonBaseProps: { component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.COURSE_ROUTE_NAME, scCourse) }, elevation: 0, className: classes.snippetRoot, image: (0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.snippetImage }, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { variant: "square", alt: scCourse.name, src: scCourse.image_medium, className: userProfileSnippet ? classes.snippetAvatarUserProfile : classes.snippetAvatar }), !userProfileSnippet &&
|
|
@@ -222,7 +222,7 @@ function Courses(inProps) {
|
|
|
222
222
|
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
|
223
223
|
// @ts-ignore
|
|
224
224
|
button: (chunk) => ((0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ color: "secondary", variant: "text", onClick: handleScrollUp }, { children: chunk })))
|
|
225
|
-
} }) })) }, { children: (0, jsx_runtime_1.jsx)(material_1.Grid, Object.assign({ container: true, spacing: { xs:
|
|
225
|
+
} }) })) }, { children: (0, jsx_runtime_1.jsx)(material_1.Grid, Object.assign({ container: true, spacing: { xs: 3 }, className: classes.courses }, GridContainerComponentProps, { children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [courses.map((course) => ((0, jsx_runtime_1.jsx)(material_1.Grid, Object.assign({ item: true, xs: 12, sm: 12, md: 6, lg: 3, className: classes.item }, GridItemComponentProps, { children: (0, jsx_runtime_1.jsx)(Course_1.default, Object.assign({ courseId: course.id }, CourseComponentProps)) }), course.id))), authUserId && ((onlyStaffEnabled && canCreateCourse) || !onlyStaffEnabled) && courses.length % 2 !== 0 && ((0, jsx_runtime_1.jsx)(material_1.Grid, Object.assign({ item: true, xs: 12, sm: 12, md: 6, lg: 3, className: classes.itemPlaceholder }, GridItemComponentProps, { children: (0, jsx_runtime_1.jsx)(CreatePlaceholder_1.default, { CreateCourseButtonComponentProps: CreateCourseButtonComponentProps }) }), "placeholder-item"))] }) })) }))) })] }));
|
|
226
226
|
/**
|
|
227
227
|
* Renders root object (if content availability community option is false and user is anonymous, component is hidden)
|
|
228
228
|
*/
|
|
@@ -51,15 +51,12 @@ function CourseUsersTable(inProps) {
|
|
|
51
51
|
const [value, setValue] = (0, react_1.useState)('');
|
|
52
52
|
const [dialog, setDialog] = (0, react_1.useState)(null);
|
|
53
53
|
// REFS
|
|
54
|
-
const
|
|
54
|
+
const buttonRef = (0, react_1.useRef)(null);
|
|
55
|
+
const inputRef = (0, react_1.useRef)(null);
|
|
55
56
|
// CONTEXTS
|
|
56
57
|
const scUserContext = (0, react_core_1.useSCUser)();
|
|
57
58
|
// INTL
|
|
58
59
|
const intl = (0, react_intl_1.useIntl)();
|
|
59
|
-
// EFFECTS
|
|
60
|
-
(0, react_1.useEffect)(() => {
|
|
61
|
-
setUsers(state.results);
|
|
62
|
-
}, [state.results, setUsers]);
|
|
63
60
|
// HANDLERS
|
|
64
61
|
const handleNext = (0, react_1.useCallback)(() => {
|
|
65
62
|
dispatch({ type: widget_1.actionWidgetTypes.LOADING_NEXT });
|
|
@@ -82,10 +79,10 @@ function CourseUsersTable(inProps) {
|
|
|
82
79
|
const handleConfirm = (0, react_1.useCallback)(() => {
|
|
83
80
|
switch (dialog.tab) {
|
|
84
81
|
case course_2.SCCourseEditTabType.USERS:
|
|
85
|
-
|
|
82
|
+
buttonRef.current.handleManageUser(dialog.user);
|
|
86
83
|
break;
|
|
87
84
|
case course_2.SCCourseEditTabType.REQUESTS:
|
|
88
|
-
|
|
85
|
+
buttonRef.current.handleManageUser(dialog.request);
|
|
89
86
|
}
|
|
90
87
|
handleOpenDialog(null);
|
|
91
88
|
}, [dialog, handleOpenDialog]);
|
|
@@ -119,10 +116,27 @@ function CourseUsersTable(inProps) {
|
|
|
119
116
|
utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
|
|
120
117
|
});
|
|
121
118
|
}, [value, endpointSearch, setUsers, setLoadingSearch, dispatch]);
|
|
119
|
+
const handleKeyUp = (0, react_1.useCallback)((e) => {
|
|
120
|
+
if (value.length > 0 && e.key === 'Enter') {
|
|
121
|
+
handleSearchStart();
|
|
122
|
+
}
|
|
123
|
+
}, [value, handleSearchStart]);
|
|
124
|
+
// EFFECTS
|
|
125
|
+
(0, react_1.useEffect)(() => {
|
|
126
|
+
setUsers(state.results);
|
|
127
|
+
}, [state.results, setUsers]);
|
|
128
|
+
(0, react_1.useEffect)(() => {
|
|
129
|
+
var _a;
|
|
130
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('keyup', handleKeyUp);
|
|
131
|
+
return () => {
|
|
132
|
+
var _a;
|
|
133
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('keyup', handleKeyUp);
|
|
134
|
+
};
|
|
135
|
+
}, [handleKeyUp]);
|
|
122
136
|
if (!users) {
|
|
123
137
|
return (0, jsx_runtime_1.jsx)(Skeleton_1.default, {});
|
|
124
138
|
}
|
|
125
|
-
return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [(0, jsx_runtime_1.jsx)(material_1.TextField, { placeholder: intl.formatMessage({
|
|
139
|
+
return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [(0, jsx_runtime_1.jsx)(material_1.TextField, { ref: inputRef, placeholder: intl.formatMessage({
|
|
126
140
|
id: 'ui.courseUsersTable.searchBar.placeholder',
|
|
127
141
|
defaultMessage: 'ui.courseUsersTable.searchBar.placeholder'
|
|
128
142
|
}), InputProps: {
|
|
@@ -136,6 +150,6 @@ function CourseUsersTable(inProps) {
|
|
|
136
150
|
}) }) }), (0, jsx_runtime_1.jsxs)(material_1.TableBody, { children: [users.length > 0 &&
|
|
137
151
|
users.map((user, i) => ((0, jsx_runtime_1.jsxs)(material_1.TableRow, { children: [(0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.avatarWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: user.username, src: user.avatar }), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: user.username }))] })) }), mode === course_1.SCCourseUsersTableModeType.DASHBOARD && ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.progressWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.LinearProgress, { className: classes.progress, variant: "determinate", value: user.user_completion_rate }), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: `${Math.round(user.user_completion_rate)}%` }))] })) })), mode === course_1.SCCourseUsersTableModeType.EDIT && ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: user.join_status !== types_1.SCCourseJoinStatusType.CREATOR && scUserContext.user.id !== user.id ? ((0, jsx_runtime_1.jsx)(ChangeUsersStatus_1.default, { course: course, user: user })) : ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.editCourse.tab.users.table.select.${user.join_status}`, defaultMessage: `ui.editCourse.tab.users.table.select.${user.join_status}` }) }))) })), (0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedDate, { value: mode === course_1.SCCourseUsersTableModeType.REQUESTS ? user.date_joined : user.joined_at || new Date() }) })) }), (0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedDate, { value: mode === course_1.SCCourseUsersTableModeType.REQUESTS ? user.date_joined : user.last_active_at || new Date() }) })) }), mode === course_1.SCCourseUsersTableModeType.EDIT &&
|
|
138
152
|
user.join_status !== types_1.SCCourseJoinStatusType.CREATOR &&
|
|
139
|
-
scUserContext.user.id !== user.id ? ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(RemoveButton_1.default, { ref:
|
|
153
|
+
scUserContext.user.id !== user.id ? ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(RemoveButton_1.default, { ref: buttonRef, course: course, user: user, handleOpenDialog: handleOpenDialog }) })) : (mode === course_1.SCCourseUsersTableModeType.EDIT && (0, jsx_runtime_1.jsx)(material_1.TableCell, {})), mode === course_1.SCCourseUsersTableModeType.DASHBOARD && ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(SeeProgressButton_1.default, { course: course, user: user }) })), mode === course_1.SCCourseUsersTableModeType.REQUESTS && ((0, jsx_runtime_1.jsx)(material_1.TableCell, { children: (0, jsx_runtime_1.jsx)(RequestButton_1.default, { ref: buttonRef, course: course, user: user, handleOpenDialog: handleOpenDialog }) }))] }, i))), state.isLoadingNext && (0, jsx_runtime_1.jsx)(RowSkeleton_1.default, { editMode: mode !== course_1.SCCourseUsersTableModeType.DASHBOARD })] })] }) }), users.length > 0 && ((0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ size: "small", variant: "outlined", color: "inherit", loading: state.isLoadingNext, disabled: value.length > 0 || !state.next, className: classes.loadingButton, onClick: handleNext }, { 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.btn.label", defaultMessage: "ui.courseUsersTable.btn.label" }) })) }))), users.length === 0 && ((0, jsx_runtime_1.jsx)(EmptyStatus_1.default, { icon: "face", title: value.length > 0 ? 'ui.courseUsersTable.empty.search.title' : emptyStatusTitle, description: value.length > 0 ? 'ui.courseUsersTable.empty.search.description' : emptyStatusDescription })), dialog && (0, jsx_runtime_1.jsx)(ConfirmDialog_1.default, { open: true, onClose: () => handleOpenDialog(null), onConfirm: handleConfirm })] })));
|
|
140
154
|
}
|
|
141
155
|
exports.default = (0, react_1.memo)(CourseUsersTable);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __rest } from "tslib";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { Avatar, Box, Button, CardActions, CardContent, CardMedia, Chip, Icon, LinearProgress, Typography } from '@mui/material';
|
|
3
|
+
import { Avatar, Box, Button, CardActions, CardContent, CardMedia, Chip, Icon, LinearProgress, Tooltip, Typography, useMediaQuery, useTheme } from '@mui/material';
|
|
4
4
|
import { styled } from '@mui/material/styles';
|
|
5
5
|
import { useThemeProps } from '@mui/system';
|
|
6
6
|
import { Link, SCRoutes, useSCFetchCourse, useSCRouting } from '@selfcommunity/react-core';
|
|
@@ -108,6 +108,9 @@ export default function Course(inProps) {
|
|
|
108
108
|
const { id = `course_object_${props.courseId ? props.courseId : props.course ? props.course.id : ''}`, courseId = null, course = null, className = null, template = SCCourseTemplateType.PREVIEW, actions, CourseParticipantsButtonComponentProps = {}, CourseSkeletonComponentProps = {}, userProfileSnippet } = props, rest = __rest(props, ["id", "courseId", "course", "className", "template", "actions", "CourseParticipantsButtonComponentProps", "CourseSkeletonComponentProps", "userProfileSnippet"]);
|
|
109
109
|
// STATE
|
|
110
110
|
const { scCourse } = useSCFetchCourse({ id: courseId, course });
|
|
111
|
+
const theme = useTheme();
|
|
112
|
+
const isMobile = useMediaQuery(theme.breakpoints.between('xs', 'md'));
|
|
113
|
+
const MAX_VISIBLE_CATEGORIES = isMobile ? 3 : 1;
|
|
111
114
|
// CONTEXT
|
|
112
115
|
const scRoutingContext = useSCRouting();
|
|
113
116
|
const isCourseAdmin = useMemo(() => scCourse && (scCourse.join_status === SCCourseJoinStatusType.CREATOR || scCourse.join_status === SCCourseJoinStatusType.MANAGER), [scCourse]);
|
|
@@ -158,7 +161,7 @@ export default function Course(inProps) {
|
|
|
158
161
|
to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
159
162
|
}), { children: _jsx(UserAvatar, Object.assign({ hide: !((_b = scCourse.created_by) === null || _b === void 0 ? void 0 : _b.community_badge), smaller: true }, { children: _jsx(Avatar, { alt: scCourse.name, src: (_c = scCourse.created_by) === null || _c === void 0 ? void 0 : _c.avatar, className: classes.previewAvatar }) })) }))] })), _jsxs(CardContent, Object.assign({ className: classes.previewContent }, { children: [_jsx(Link, Object.assign({ className: classes.previewCreator }, (!((_d = scCourse.created_by) === null || _d === void 0 ? void 0 : _d.deleted) && {
|
|
160
163
|
to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
161
|
-
}), { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: (_e = scCourse.created_by) === null || _e === void 0 ? void 0 : _e.username })) })), _jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.COURSE_ROUTE_NAME, scCourse), className: classes.previewNameWrapper }, { children: _jsx(Typography, Object.assign({ variant: "h6", className: classes.previewName }, { children: scCourse.name })) })), _jsxs(Typography, Object.assign({ className: classes.previewInfo }, { children: [_jsx(FormattedMessage, { id: scCourse.privacy ? `ui.course.privacy.${scCourse.privacy}` : 'ui.course.privacy.draft', defaultMessage: scCourse.privacy ? `ui.course.privacy.${scCourse.privacy}` : 'ui.course.privacy.draft' }), ' - ', _jsx(FormattedMessage, { id: `ui.course.type.${scCourse.type}`, defaultMessage: `ui.course.type.${scCourse.type}` })] })),
|
|
164
|
+
}), { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: (_e = scCourse.created_by) === null || _e === void 0 ? void 0 : _e.username })) })), _jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.COURSE_ROUTE_NAME, scCourse), className: classes.previewNameWrapper }, { children: _jsx(Typography, Object.assign({ variant: "h6", className: classes.previewName }, { children: scCourse.name })) })), _jsxs(Typography, Object.assign({ className: classes.previewInfo }, { children: [_jsx(FormattedMessage, { id: scCourse.privacy ? `ui.course.privacy.${scCourse.privacy}` : 'ui.course.privacy.draft', defaultMessage: scCourse.privacy ? `ui.course.privacy.${scCourse.privacy}` : 'ui.course.privacy.draft' }), ' - ', _jsx(FormattedMessage, { id: `ui.course.type.${scCourse.type}`, defaultMessage: `ui.course.type.${scCourse.type}` })] })), _jsxs(Box, Object.assign({ className: classes.previewCategory }, { children: [scCourse.categories.slice(0, MAX_VISIBLE_CATEGORIES).map((category) => (_jsx(Chip, { size: "small", label: category.name }, category.id))), scCourse.categories.length > MAX_VISIBLE_CATEGORIES && (_jsx(Tooltip, Object.assign({ title: _jsx(_Fragment, { children: scCourse.categories.slice(MAX_VISIBLE_CATEGORIES).map((cat) => (_jsx(Box, { children: cat.name }, cat.id))) }) }, { children: _jsx(Chip, { size: "small", label: `+${scCourse.categories.length - MAX_VISIBLE_CATEGORIES}`, sx: { cursor: 'pointer' } }) })))] })), _jsx(Box, Object.assign({ className: classes.previewProgress }, { children: renderProgress() }))] })), actions !== null && actions !== void 0 ? actions : (_jsx(CardActions, Object.assign({ className: classes.previewActions }, { children: _jsx(Button, Object.assign({ variant: "outlined", size: "small", component: Link, to: scRoutingContext.url(SCRoutes.COURSE_ROUTE_NAME, scCourse) }, { children: _jsx(FormattedMessage, { defaultMessage: "ui.course.see", id: "ui.course.see" }) })) })))] })));
|
|
162
165
|
}
|
|
163
166
|
else {
|
|
164
167
|
contentObj = (_jsx(SnippetRoot, { ButtonBaseProps: { component: Link, to: scRoutingContext.url(SCRoutes.COURSE_ROUTE_NAME, scCourse) }, elevation: 0, className: classes.snippetRoot, image: _jsxs(Box, Object.assign({ className: classes.snippetImage }, { children: [_jsx(Avatar, { variant: "square", alt: scCourse.name, src: scCourse.image_medium, className: userProfileSnippet ? classes.snippetAvatarUserProfile : classes.snippetAvatar }), !userProfileSnippet &&
|
|
@@ -219,7 +219,7 @@ export default function Courses(inProps) {
|
|
|
219
219
|
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
|
220
220
|
// @ts-ignore
|
|
221
221
|
button: (chunk) => (_jsx(Button, Object.assign({ color: "secondary", variant: "text", onClick: handleScrollUp }, { children: chunk })))
|
|
222
|
-
} }) })) }, { children: _jsx(Grid, Object.assign({ container: true, spacing: { xs:
|
|
222
|
+
} }) })) }, { children: _jsx(Grid, Object.assign({ container: true, spacing: { xs: 3 }, className: classes.courses }, GridContainerComponentProps, { children: _jsxs(_Fragment, { children: [courses.map((course) => (_jsx(Grid, Object.assign({ item: true, xs: 12, sm: 12, md: 6, lg: 3, className: classes.item }, GridItemComponentProps, { children: _jsx(Course, Object.assign({ courseId: course.id }, CourseComponentProps)) }), course.id))), authUserId && ((onlyStaffEnabled && canCreateCourse) || !onlyStaffEnabled) && courses.length % 2 !== 0 && (_jsx(Grid, Object.assign({ item: true, xs: 12, sm: 12, md: 6, lg: 3, className: classes.itemPlaceholder }, GridItemComponentProps, { children: _jsx(CourseCreatePlaceholder, { CreateCourseButtonComponentProps: CreateCourseButtonComponentProps }) }), "placeholder-item"))] }) })) }))) })] }));
|
|
223
223
|
/**
|
|
224
224
|
* Renders root object (if content availability community option is false and user is anonymous, component is hidden)
|
|
225
225
|
*/
|
|
@@ -48,15 +48,12 @@ function CourseUsersTable(inProps) {
|
|
|
48
48
|
const [value, setValue] = useState('');
|
|
49
49
|
const [dialog, setDialog] = useState(null);
|
|
50
50
|
// REFS
|
|
51
|
-
const
|
|
51
|
+
const buttonRef = useRef(null);
|
|
52
|
+
const inputRef = useRef(null);
|
|
52
53
|
// CONTEXTS
|
|
53
54
|
const scUserContext = useSCUser();
|
|
54
55
|
// INTL
|
|
55
56
|
const intl = useIntl();
|
|
56
|
-
// EFFECTS
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
setUsers(state.results);
|
|
59
|
-
}, [state.results, setUsers]);
|
|
60
57
|
// HANDLERS
|
|
61
58
|
const handleNext = useCallback(() => {
|
|
62
59
|
dispatch({ type: actionWidgetTypes.LOADING_NEXT });
|
|
@@ -79,10 +76,10 @@ function CourseUsersTable(inProps) {
|
|
|
79
76
|
const handleConfirm = useCallback(() => {
|
|
80
77
|
switch (dialog.tab) {
|
|
81
78
|
case SCCourseEditTabType.USERS:
|
|
82
|
-
|
|
79
|
+
buttonRef.current.handleManageUser(dialog.user);
|
|
83
80
|
break;
|
|
84
81
|
case SCCourseEditTabType.REQUESTS:
|
|
85
|
-
|
|
82
|
+
buttonRef.current.handleManageUser(dialog.request);
|
|
86
83
|
}
|
|
87
84
|
handleOpenDialog(null);
|
|
88
85
|
}, [dialog, handleOpenDialog]);
|
|
@@ -116,10 +113,27 @@ function CourseUsersTable(inProps) {
|
|
|
116
113
|
Logger.error(SCOPE_SC_UI, error);
|
|
117
114
|
});
|
|
118
115
|
}, [value, endpointSearch, setUsers, setLoadingSearch, dispatch]);
|
|
116
|
+
const handleKeyUp = useCallback((e) => {
|
|
117
|
+
if (value.length > 0 && e.key === 'Enter') {
|
|
118
|
+
handleSearchStart();
|
|
119
|
+
}
|
|
120
|
+
}, [value, handleSearchStart]);
|
|
121
|
+
// EFFECTS
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
setUsers(state.results);
|
|
124
|
+
}, [state.results, setUsers]);
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
var _a;
|
|
127
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('keyup', handleKeyUp);
|
|
128
|
+
return () => {
|
|
129
|
+
var _a;
|
|
130
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('keyup', handleKeyUp);
|
|
131
|
+
};
|
|
132
|
+
}, [handleKeyUp]);
|
|
119
133
|
if (!users) {
|
|
120
134
|
return _jsx(CourseUsersTableSkeleton, {});
|
|
121
135
|
}
|
|
122
|
-
return (_jsxs(Root, Object.assign({ className: classes.root }, { children: [_jsx(TextField, { placeholder: intl.formatMessage({
|
|
136
|
+
return (_jsxs(Root, Object.assign({ className: classes.root }, { children: [_jsx(TextField, { ref: inputRef, placeholder: intl.formatMessage({
|
|
123
137
|
id: 'ui.courseUsersTable.searchBar.placeholder',
|
|
124
138
|
defaultMessage: 'ui.courseUsersTable.searchBar.placeholder'
|
|
125
139
|
}), InputProps: {
|
|
@@ -133,6 +147,6 @@ function CourseUsersTable(inProps) {
|
|
|
133
147
|
}) }) }), _jsxs(TableBody, { children: [users.length > 0 &&
|
|
134
148
|
users.map((user, i) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsxs(Stack, Object.assign({ className: classes.avatarWrapper }, { children: [_jsx(Avatar, { alt: user.username, src: user.avatar }), _jsx(Typography, Object.assign({ variant: "body2" }, { children: user.username }))] })) }), mode === SCCourseUsersTableModeType.DASHBOARD && (_jsx(TableCell, { children: _jsxs(Stack, Object.assign({ className: classes.progressWrapper }, { children: [_jsx(LinearProgress, { className: classes.progress, variant: "determinate", value: user.user_completion_rate }), _jsx(Typography, Object.assign({ variant: "body1" }, { children: `${Math.round(user.user_completion_rate)}%` }))] })) })), mode === SCCourseUsersTableModeType.EDIT && (_jsx(TableCell, { children: user.join_status !== SCCourseJoinStatusType.CREATOR && scUserContext.user.id !== user.id ? (_jsx(ChangeUserStatus, { course: course, user: user })) : (_jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: `ui.editCourse.tab.users.table.select.${user.join_status}`, defaultMessage: `ui.editCourse.tab.users.table.select.${user.join_status}` }) }))) })), _jsx(TableCell, { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedDate, { value: mode === SCCourseUsersTableModeType.REQUESTS ? user.date_joined : user.joined_at || new Date() }) })) }), _jsx(TableCell, { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedDate, { value: mode === SCCourseUsersTableModeType.REQUESTS ? user.date_joined : user.last_active_at || new Date() }) })) }), mode === SCCourseUsersTableModeType.EDIT &&
|
|
135
149
|
user.join_status !== SCCourseJoinStatusType.CREATOR &&
|
|
136
|
-
scUserContext.user.id !== user.id ? (_jsx(TableCell, { children: _jsx(RemoveButton, { ref:
|
|
150
|
+
scUserContext.user.id !== user.id ? (_jsx(TableCell, { children: _jsx(RemoveButton, { ref: buttonRef, course: course, user: user, handleOpenDialog: handleOpenDialog }) })) : (mode === SCCourseUsersTableModeType.EDIT && _jsx(TableCell, {})), mode === SCCourseUsersTableModeType.DASHBOARD && (_jsx(TableCell, { children: _jsx(SeeProgressButton, { course: course, user: user }) })), mode === SCCourseUsersTableModeType.REQUESTS && (_jsx(TableCell, { children: _jsx(RequestButton, { ref: buttonRef, course: course, user: user, handleOpenDialog: handleOpenDialog }) }))] }, i))), state.isLoadingNext && _jsx(RowSkeleton, { editMode: mode !== SCCourseUsersTableModeType.DASHBOARD })] })] }) }), users.length > 0 && (_jsx(LoadingButton, Object.assign({ size: "small", variant: "outlined", color: "inherit", loading: state.isLoadingNext, disabled: value.length > 0 || !state.next, className: classes.loadingButton, onClick: handleNext }, { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.courseUsersTable.btn.label", defaultMessage: "ui.courseUsersTable.btn.label" }) })) }))), users.length === 0 && (_jsx(EmptyStatus, { icon: "face", title: value.length > 0 ? 'ui.courseUsersTable.empty.search.title' : emptyStatusTitle, description: value.length > 0 ? 'ui.courseUsersTable.empty.search.description' : emptyStatusDescription })), dialog && _jsx(ConfirmDialog, { open: true, onClose: () => handleOpenDialog(null), onConfirm: handleConfirm })] })));
|
|
137
151
|
}
|
|
138
152
|
export default memo(CourseUsersTable);
|