@selfcommunity/react-ui 0.10.2-courses.186 → 0.10.2-courses.188
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 +12 -4
- package/lib/cjs/components/CourseDashboard/Header.js +2 -22
- package/lib/cjs/components/CourseDashboard/Student.js +4 -5
- package/lib/cjs/components/CourseDashboard/Teacher/Comments.js +7 -10
- package/lib/cjs/components/CourseDashboard/Teacher/Info.js +2 -4
- package/lib/cjs/components/CourseDashboard/Teacher/Students.js +2 -1
- package/lib/cjs/components/CourseForm/CourseForm.js +6 -7
- package/lib/cjs/components/CourseForm/Edit.js +2 -1
- package/lib/cjs/components/Courses/Courses.js +16 -19
- package/lib/cjs/components/EditCourse/EditCourse.js +27 -26
- package/lib/cjs/components/EditCourse/Lessons/Skeleton.js +1 -2
- package/lib/cjs/components/EditCourse/Lessons.d.ts +3 -1
- package/lib/cjs/components/EditCourse/Lessons.js +6 -12
- package/lib/cjs/components/EditCourse/Options.js +3 -4
- package/lib/cjs/components/EditCourse/Requests.d.ts +3 -1
- package/lib/cjs/components/EditCourse/Requests.js +5 -3
- package/lib/cjs/components/EditCourse/Status.d.ts +3 -0
- package/lib/cjs/components/EditCourse/Status.js +15 -9
- package/lib/cjs/components/EditCourse/Users.d.ts +3 -1
- package/lib/cjs/components/EditCourse/Users.js +5 -5
- package/lib/cjs/components/EventHeader/EventHeader.js +1 -1
- package/lib/cjs/index.d.ts +2 -1
- package/lib/cjs/index.js +8 -6
- package/lib/cjs/shared/AddUsersButton/AddUsersButton.js +3 -2
- package/lib/cjs/shared/CourseTypePopover/CourseTypePopover.d.ts +9 -0
- package/lib/cjs/shared/CourseTypePopover/CourseTypePopover.js +48 -0
- package/lib/cjs/shared/CourseTypePopover/index.d.ts +3 -0
- package/lib/cjs/shared/CourseTypePopover/index.js +5 -0
- package/lib/cjs/shared/CourseUsersTable/CourseUsersTable.d.ts +2 -1
- package/lib/cjs/shared/CourseUsersTable/CourseUsersTable.js +6 -7
- package/lib/cjs/shared/EventActionsMenu/index.js +5 -1
- package/lib/cjs/types/course.d.ts +5 -0
- package/lib/cjs/types/course.js +7 -1
- package/lib/cjs/utils/course.js +2 -1
- package/lib/cjs/utils/events.d.ts +1 -0
- package/lib/cjs/utils/events.js +6 -1
- package/lib/esm/components/Course/Course.js +12 -4
- package/lib/esm/components/CourseDashboard/Header.js +4 -24
- package/lib/esm/components/CourseDashboard/Student.js +4 -5
- package/lib/esm/components/CourseDashboard/Teacher/Comments.js +7 -9
- package/lib/esm/components/CourseDashboard/Teacher/Info.js +2 -4
- package/lib/esm/components/CourseDashboard/Teacher/Students.js +2 -1
- package/lib/esm/components/CourseForm/CourseForm.js +6 -7
- package/lib/esm/components/CourseForm/Edit.js +2 -1
- package/lib/esm/components/Courses/Courses.js +16 -19
- package/lib/esm/components/EditCourse/EditCourse.js +28 -27
- package/lib/esm/components/EditCourse/Lessons/Skeleton.js +2 -3
- package/lib/esm/components/EditCourse/Lessons.d.ts +3 -1
- package/lib/esm/components/EditCourse/Lessons.js +7 -13
- package/lib/esm/components/EditCourse/Options.js +5 -6
- package/lib/esm/components/EditCourse/Requests.d.ts +3 -1
- package/lib/esm/components/EditCourse/Requests.js +5 -3
- package/lib/esm/components/EditCourse/Status.d.ts +3 -0
- package/lib/esm/components/EditCourse/Status.js +16 -10
- package/lib/esm/components/EditCourse/Users.d.ts +3 -1
- package/lib/esm/components/EditCourse/Users.js +5 -5
- package/lib/esm/components/EventHeader/EventHeader.js +1 -1
- package/lib/esm/index.d.ts +2 -1
- package/lib/esm/index.js +2 -1
- package/lib/esm/shared/AddUsersButton/AddUsersButton.js +3 -2
- package/lib/esm/shared/CourseTypePopover/CourseTypePopover.d.ts +9 -0
- package/lib/esm/shared/CourseTypePopover/CourseTypePopover.js +45 -0
- package/lib/esm/shared/CourseTypePopover/index.d.ts +3 -0
- package/lib/esm/shared/CourseTypePopover/index.js +2 -0
- package/lib/esm/shared/CourseUsersTable/CourseUsersTable.d.ts +2 -1
- package/lib/esm/shared/CourseUsersTable/CourseUsersTable.js +6 -7
- package/lib/esm/shared/EventActionsMenu/index.js +6 -2
- package/lib/esm/types/course.d.ts +5 -0
- package/lib/esm/types/course.js +6 -0
- package/lib/esm/utils/course.js +2 -1
- package/lib/esm/utils/events.d.ts +1 -0
- package/lib/esm/utils/events.js +4 -0
- package/lib/umd/react-ui.js +1 -1
- package/package.json +8 -8
package/lib/cjs/utils/course.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getDripDelayAndUnit = exports.isCourseCompleted = exports.isCourseNew = void 0;
|
|
4
|
+
const types_1 = require("@selfcommunity/types");
|
|
4
5
|
function isCourseNew(course) {
|
|
5
|
-
if (course && course.
|
|
6
|
+
if (course && course.join_status === types_1.SCCourseJoinStatusType.JOINED) {
|
|
6
7
|
const createdAtDate = new Date(course.created_at);
|
|
7
8
|
const twoWeeksAgo = new Date();
|
|
8
9
|
twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14);
|
package/lib/cjs/utils/events.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.checkEventFinished = void 0;
|
|
3
|
+
exports.formatDateForGC = exports.checkEventFinished = void 0;
|
|
4
4
|
function checkEventFinished(event) {
|
|
5
5
|
if (event && !event.running) {
|
|
6
6
|
return new Date().getTime() > new Date(event.end_date || event.start_date).getTime();
|
|
@@ -8,3 +8,8 @@ function checkEventFinished(event) {
|
|
|
8
8
|
return false;
|
|
9
9
|
}
|
|
10
10
|
exports.checkEventFinished = checkEventFinished;
|
|
11
|
+
function formatDateForGC(eventDate) {
|
|
12
|
+
const date = new Date(eventDate);
|
|
13
|
+
return date.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z';
|
|
14
|
+
}
|
|
15
|
+
exports.formatDateForGC = formatDateForGC;
|
|
@@ -135,6 +135,9 @@ export default function Course(inProps) {
|
|
|
135
135
|
else if (isCourseCompleted(scCourse)) {
|
|
136
136
|
return _jsx(FormattedMessage, { defaultMessage: "ui.course.status.completed", id: "ui.course.status.completed" });
|
|
137
137
|
}
|
|
138
|
+
else if (scCourse.join_status === SCCourseJoinStatusType.JOINED) {
|
|
139
|
+
return _jsx(FormattedMessage, { defaultMessage: "ui.course.status.joined", id: "ui.course.status.joined" });
|
|
140
|
+
}
|
|
138
141
|
else if (isCourseNew(scCourse)) {
|
|
139
142
|
return _jsx(FormattedMessage, { defaultMessage: "ui.course.status.new", id: "ui.course.status.new" });
|
|
140
143
|
}
|
|
@@ -145,22 +148,27 @@ export default function Course(inProps) {
|
|
|
145
148
|
*/
|
|
146
149
|
let contentObj;
|
|
147
150
|
if (template === SCCourseTemplateType.PREVIEW) {
|
|
148
|
-
contentObj = (_jsxs(PreviewRoot, Object.assign({ className: classes.previewRoot }, { children: [_jsxs(Box, Object.assign({ className: classes.previewImageWrapper }, { children: [_jsx(CardMedia, { component: "img", image: scCourse.image_medium, alt: scCourse.name, className: classes.previewImage }), (isCourseAdmin || isCourseCompleted(scCourse) || isCourseNew(scCourse)) && (_jsx(Chip, { size: "small", component: "div", color: isCourseCompleted(scCourse) || (isCourseAdmin && scCourse.privacy)
|
|
151
|
+
contentObj = (_jsxs(PreviewRoot, Object.assign({ className: classes.previewRoot }, { children: [_jsxs(Box, Object.assign({ className: classes.previewImageWrapper }, { children: [_jsx(CardMedia, { component: "img", image: scCourse.image_medium, alt: scCourse.name, className: classes.previewImage }), (isCourseAdmin || isCourseCompleted(scCourse) || isCourseNew(scCourse) || scCourse.join_status === SCCourseJoinStatusType.JOINED) && (_jsx(Chip, { size: "small", component: "div", color: isCourseCompleted(scCourse) || (isCourseAdmin && scCourse.privacy)
|
|
149
152
|
? 'primary'
|
|
150
153
|
: isCourseAdmin && !scCourse.privacy
|
|
151
154
|
? 'default'
|
|
152
|
-
:
|
|
155
|
+
: scCourse.join_status === SCCourseJoinStatusType.JOINED
|
|
156
|
+
? 'warning'
|
|
157
|
+
: 'secondary', label: chipLabel, className: classes.chip })), _jsx(Link, Object.assign({}, (!((_a = scCourse.created_by) === null || _a === void 0 ? void 0 : _a.deleted) && {
|
|
153
158
|
to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
154
159
|
}), { 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) && {
|
|
155
160
|
to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
156
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}` })] })), _jsx(Box, Object.assign({ className: classes.previewCategory }, { children: scCourse.categories.map((category) => (_jsx(Chip, { size: "small", label: category.name }, category.id))) })), _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" }) })) })))] })));
|
|
157
162
|
}
|
|
158
163
|
else {
|
|
159
|
-
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 &&
|
|
164
|
+
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 &&
|
|
165
|
+
(isCourseAdmin || isCourseCompleted(scCourse) || isCourseNew(scCourse) || scCourse.join_status === SCCourseJoinStatusType.JOINED) && (_jsx(Chip, { size: "small", component: "div", color: isCourseCompleted(scCourse) || (isCourseAdmin && scCourse.privacy)
|
|
160
166
|
? 'primary'
|
|
161
167
|
: isCourseAdmin && !scCourse.privacy
|
|
162
168
|
? 'default'
|
|
163
|
-
:
|
|
169
|
+
: scCourse.join_status === SCCourseJoinStatusType.JOINED
|
|
170
|
+
? 'warning'
|
|
171
|
+
: 'secondary', label: chipLabel, className: classes.chip }))] })), primary: _jsxs(_Fragment, { children: [!userProfileSnippet && (_jsx(Link, Object.assign({}, (!((_f = scCourse.created_by) === null || _f === void 0 ? void 0 : _f.deleted) && {
|
|
164
172
|
to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
165
173
|
}), { children: _jsx(Typography, Object.assign({ component: "span" }, { children: (_g = scCourse.created_by) === null || _g === void 0 ? void 0 : _g.username })) }))), _jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.COURSE_ROUTE_NAME, scCourse) }, { children: _jsx(Typography, Object.assign({ variant: "body1" }, { children: scCourse.name })) }))] }), secondary: _jsx(_Fragment, { children: userProfileSnippet ? (_jsx(_Fragment, { children: !scCourse.hide_member_count && (_jsx(FormattedMessage, { id: "ui.course.userProfileSnippet.students", defaultMessage: "ui.course.userProfileSnippet.students", values: { students: scCourse.member_count } })) })) : (_jsxs(_Fragment, { 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}` })] })) }), actions: actions !== null && actions !== void 0 ? actions : (_jsx(Button, Object.assign({ size: "small", variant: "outlined", component: Link, to: scRoutingContext.url(SCRoutes.COURSE_ROUTE_NAME, scCourse) }, { children: _jsx(FormattedMessage, { defaultMessage: "ui.course.see", id: "ui.course.see" }) }))) }));
|
|
166
174
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Button, Icon,
|
|
2
|
+
import { Box, Button, Icon, Stack, Typography } from '@mui/material';
|
|
3
3
|
import { SCCoursePrivacyType } from '@selfcommunity/types';
|
|
4
4
|
import { FormattedMessage, useIntl } from 'react-intl';
|
|
5
5
|
import { PREFIX } from './constants';
|
|
6
|
-
import { memo
|
|
6
|
+
import { memo } from 'react';
|
|
7
7
|
import { Link, SCRoutes, useSCRouting } from '@selfcommunity/react-core';
|
|
8
8
|
import { SCCourseEditTabType } from '../../types';
|
|
9
9
|
import classNames from 'classnames';
|
|
10
|
+
import CourseTypePopover from '../../shared/CourseTypePopover';
|
|
10
11
|
const classes = {
|
|
11
12
|
header: `${PREFIX}-header`,
|
|
12
13
|
img: `${PREFIX}-header-img`,
|
|
@@ -26,36 +27,15 @@ function getUrlEditDashboard(course) {
|
|
|
26
27
|
function HeaderCourseDashboard(props) {
|
|
27
28
|
// PROPS
|
|
28
29
|
const { course, hasAction = false } = props;
|
|
29
|
-
// STATES
|
|
30
|
-
const [anchorEl, setAnchorEl] = useState(null);
|
|
31
|
-
const open = Boolean(anchorEl);
|
|
32
30
|
// CONTEXTS
|
|
33
31
|
const scRoutingContext = useSCRouting();
|
|
34
32
|
// INTL
|
|
35
33
|
const intl = useIntl();
|
|
36
|
-
// HANDLERS
|
|
37
|
-
const handleOpenPopover = useCallback((e) => {
|
|
38
|
-
setAnchorEl(e.currentTarget);
|
|
39
|
-
}, [setAnchorEl]);
|
|
40
|
-
const handlePopoverClose = useCallback(() => {
|
|
41
|
-
setAnchorEl(null);
|
|
42
|
-
}, [setAnchorEl]);
|
|
43
34
|
return (_jsxs(Box, Object.assign({ className: classes.header }, { children: [_jsx("img", { src: course.image_bigger, alt: course.image_bigger, className: classes.img }), _jsx(Typography, Object.assign({ variant: "h3", className: classes.contrastColor }, { children: course.name })), _jsxs(Stack, Object.assign({ className: classes.outerWrapper }, { children: [_jsxs(Stack, Object.assign({ className: classes.innerWrapper }, { children: [_jsxs(Stack, Object.assign({ className: classNames(classes.iconWrapper, classes.contrastColor) }, { children: [_jsx(Icon, Object.assign({ fontSize: "small" }, { children: "public" })), _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.course.label", defaultMessage: "ui.course.label", values: {
|
|
44
35
|
privacy: intl.formatMessage({
|
|
45
36
|
id: `ui.course.privacy.${course.privacy === SCCoursePrivacyType.DRAFT ? 'draft' : course.privacy}`,
|
|
46
37
|
defaultMessage: `ui.course.privacy.${course.privacy === SCCoursePrivacyType.DRAFT ? 'draft' : course.privacy}`
|
|
47
38
|
})
|
|
48
|
-
} }) }))] })),
|
|
49
|
-
typeOfCourse: intl.formatMessage({
|
|
50
|
-
id: `ui.course.type.${course.type}`,
|
|
51
|
-
defaultMessage: `ui.course.type.${course.type}`
|
|
52
|
-
})
|
|
53
|
-
} }) })) })), open && (_jsx(Popover, Object.assign({ open: true, anchorEl: anchorEl, anchorOrigin: {
|
|
54
|
-
vertical: 'bottom',
|
|
55
|
-
horizontal: 'left'
|
|
56
|
-
}, transformOrigin: {
|
|
57
|
-
vertical: 'top',
|
|
58
|
-
horizontal: 'left'
|
|
59
|
-
}, onClose: handlePopoverClose }, { children: _jsx(Box, Object.assign({ sx: { padding: '10px' } }, { children: _jsx(Typography, Object.assign({ component: "span", variant: "body2", sx: { whiteSpace: 'pre-line' } }, { children: _jsx(FormattedMessage, { id: `ui.courseForm.${course.type}.info`, defaultMessage: `ui.courseForm.${course.type}.info` }) })) })) })))] }))] })), hasAction && (_jsx(Button, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.COURSE_EDIT_ROUTE_NAME, getUrlEditDashboard(course)), size: "small", color: "primary", variant: "contained" }, { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.teacher.btn.label", defaultMessage: "ui.course.dashboard.teacher.btn.label" }) })) })))] }))] })));
|
|
39
|
+
} }) }))] })), _jsx(CourseTypePopover, { course: course })] })), hasAction && (_jsx(Button, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.COURSE_EDIT_ROUTE_NAME, getUrlEditDashboard(course)), size: "small", color: "primary", variant: "contained" }, { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.teacher.btn.label", defaultMessage: "ui.course.dashboard.teacher.btn.label" }) })) })))] }))] })));
|
|
60
40
|
}
|
|
61
41
|
export default memo(HeaderCourseDashboard);
|
|
@@ -47,8 +47,7 @@ const classes = {
|
|
|
47
47
|
box: `${PREFIX}-box`,
|
|
48
48
|
percentageWrapper: `${PREFIX}-percentage-wrapper`,
|
|
49
49
|
completedWrapper: `${PREFIX}-completed-wrapper`,
|
|
50
|
-
contrastColor: `${PREFIX}-contrast-color
|
|
51
|
-
contrastBgColor: `${PREFIX}-contrast-bg-color`
|
|
50
|
+
contrastColor: `${PREFIX}-contrast-color`
|
|
52
51
|
};
|
|
53
52
|
function getUrlNextLesson(course) {
|
|
54
53
|
var _a;
|
|
@@ -178,7 +177,7 @@ function Student(inProps) {
|
|
|
178
177
|
if (!scCourse) {
|
|
179
178
|
return _jsx(StudentSkeleton, {});
|
|
180
179
|
}
|
|
181
|
-
return (_jsxs(Root, Object.assign({ className: classNames(classes.root, classes.studentContainer, className) }, rest, { children: [_jsx(HeaderCourseDashboard, { course: scCourse }), _jsx(Divider, {}), _jsxs(Stack, Object.assign({ className:
|
|
180
|
+
return (_jsxs(Root, Object.assign({ className: classNames(classes.root, classes.studentContainer, className) }, rest, { children: [_jsx(HeaderCourseDashboard, { course: scCourse }), _jsx(Divider, {}), _jsxs(Stack, Object.assign({ className: classes.userWrapper }, { children: [_jsxs(Stack, Object.assign({ className: classes.user }, { children: [_jsx(Link, Object.assign({}, (!scCourse.created_by.deleted && {
|
|
182
181
|
to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
183
182
|
}), { children: _jsx(UserAvatar, Object.assign({ hide: !scCourse.created_by.community_badge, smaller: true }, { children: _jsx(Avatar, { className: classes.avatar, src: scCourse.created_by.avatar, alt: scCourse.created_by.username }) })) })), _jsxs(Box, { children: [_jsx(Link, Object.assign({}, (!scCourse.created_by.deleted && {
|
|
184
183
|
to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, scCourse.created_by)
|
|
@@ -188,9 +187,9 @@ function Student(inProps) {
|
|
|
188
187
|
scCourse.join_status === SCCourseJoinStatusType.JOINED)) ||
|
|
189
188
|
scCourse.privacy === SCCoursePrivacyType.OPEN ||
|
|
190
189
|
scCourse.privacy === SCCoursePrivacyType.DRAFT) &&
|
|
191
|
-
scCourse.description && (_jsxs(Fragment, { children: [_jsx(Typography, Object.assign({ variant: "h6", className: classNames(classes.margin, classes.contrastColor) }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.student.description", defaultMessage: "ui.course.dashboard.student.description" }) })), _jsx(Stack, Object.assign({ className:
|
|
190
|
+
scCourse.description && (_jsxs(Fragment, { children: [_jsx(Typography, Object.assign({ variant: "h6", className: classNames(classes.margin, classes.contrastColor) }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.student.description", defaultMessage: "ui.course.dashboard.student.description" }) })), _jsx(Stack, Object.assign({ className: classes.box }, { children: _jsx(Typography, Object.assign({ variant: "body1", className: classes.description }, { children: scCourse.description })) }))] })), (((scCourse.privacy === SCCoursePrivacyType.PRIVATE || scCourse.privacy === SCCoursePrivacyType.SECRET) &&
|
|
192
191
|
(scCourse.join_status === SCCourseJoinStatusType.MANAGER || scCourse.join_status === SCCourseJoinStatusType.JOINED)) ||
|
|
193
|
-
(scCourse.privacy === SCCoursePrivacyType.OPEN && scCourse.join_status !== SCCourseJoinStatusType.CREATOR)) && (_jsxs(Fragment, { children: [_jsx(Typography, Object.assign({ variant: "h6", className: classNames(classes.margin, classes.contrastColor) }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.student.progress", defaultMessage: "ui.course.dashboard.student.
|
|
192
|
+
(scCourse.privacy === SCCoursePrivacyType.OPEN && scCourse.join_status !== SCCourseJoinStatusType.CREATOR)) && (_jsxs(Fragment, { children: [scCourse.join_status !== null && (_jsxs(Fragment, { children: [_jsx(Typography, Object.assign({ variant: "h6", className: classNames(classes.margin, classes.contrastColor) }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.student.progress", defaultMessage: "ui.course.dashboard.student.progress" }) })), _jsxs(Stack, Object.assign({ className: classes.box }, { children: [_jsxs(Stack, Object.assign({ className: classes.percentageWrapper }, { children: [_jsx(Typography, Object.assign({ variant: "body1" }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.student.progress.described", defaultMessage: "ui.course.dashboard.student.progress.described", values: { progress: scCourse.num_lessons_completed, end: scCourse.num_lessons } }) })), _jsx(Typography, Object.assign({ variant: "body1" }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.student.progress.percentage", defaultMessage: "ui.course.dashboard.student.progress.percentage", values: { percentage: scCourse.user_completion_rate } }) }))] })), _jsx(LinearProgress, { className: classes.progress, variant: "determinate", value: scCourse.user_completion_rate })] }))] })), scCourse.user_completion_rate === 100 && (_jsxs(Stack, Object.assign({ className: classNames(classes.completedWrapper, classes.margin) }, { children: [_jsx(Typography, Object.assign({ variant: "h3", className: classes.contrastColor }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.student.completed", defaultMessage: "ui.course.dashboard.student.completed" }) })), _jsx("img", { src: CLAPPING, alt: intl.formatMessage({ id: 'ui.course.dashboard.student.completed', defaultMessage: 'ui.course.dashboard.student.completed' }), width: 32, height: 32 })] }))), _jsx(Typography, Object.assign({ variant: "h6", className: classNames(classes.margin, classes.contrastColor) }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.student.contents", defaultMessage: "ui.course.dashboard.student.contents" }) })), _jsxs(Stack, Object.assign({ className: classes.lessonsSections }, { children: [_jsx(Typography, Object.assign({ variant: "h5" }, { children: _jsx(FormattedMessage, { id: "ui.course.table.sections.title", defaultMessage: "ui.course.table.sections.title", values: {
|
|
194
193
|
sectionsNumber: scCourse.num_sections
|
|
195
194
|
} }) })), _jsx(Box, { className: classes.circle }), _jsx(Typography, Object.assign({ variant: "h5" }, { children: _jsx(FormattedMessage, { id: "ui.course.table.lessons.title", defaultMessage: "ui.course.table.lessons.title", values: {
|
|
196
195
|
lessonsNumber: scCourse.num_lessons
|
|
@@ -10,7 +10,6 @@ import { DEFAULT_PAGINATION_OFFSET } from '../../../constants/Pagination';
|
|
|
10
10
|
import { actionWidgetTypes, dataWidgetReducer, stateWidgetInitializer } from '../../../utils/widget';
|
|
11
11
|
import { Link, SCCache, SCRoutes, useSCRouting, useSCUser } from '@selfcommunity/react-core';
|
|
12
12
|
import { CourseService, Endpoints, http } from '@selfcommunity/api-services';
|
|
13
|
-
import classNames from 'classnames';
|
|
14
13
|
const classes = {
|
|
15
14
|
container: `${PREFIX}-comments-container`,
|
|
16
15
|
outerWrapper: `${PREFIX}-outer-wrapper`,
|
|
@@ -20,8 +19,7 @@ const classes = {
|
|
|
20
19
|
userInfo: `${PREFIX}-user-info`,
|
|
21
20
|
circle: `${PREFIX}-circle`,
|
|
22
21
|
button: `${PREFIX}-button`,
|
|
23
|
-
contrastColor: `${PREFIX}-contrast-color
|
|
24
|
-
contrastBgColor: `${PREFIX}-contrast-bg-color`
|
|
22
|
+
contrastColor: `${PREFIX}-contrast-color`
|
|
25
23
|
};
|
|
26
24
|
function CommentSkeleton({ id }) {
|
|
27
25
|
return (_jsxs(Box, Object.assign({ className: classes.outerWrapper }, { children: [_jsx(Skeleton, { animation: "wave", variant: "text", width: "90px", height: "21px" }), _jsx(Divider, {}), _jsxs(Stack, Object.assign({ className: classes.innerWrapper }, { children: [Array.from(new Array(id)).map((_, i) => (_jsxs(Stack, Object.assign({ className: classes.userWrapper }, { children: [_jsx(Skeleton, { animation: "wave", variant: "circular", className: classes.avatar }), _jsxs(Box, { children: [_jsxs(Stack, Object.assign({ className: classes.userInfo }, { children: [_jsx(Skeleton, { animation: "wave", variant: "text", width: "90px", height: "21px" }), _jsx(Box, { className: classes.circle }), _jsx(Skeleton, { animation: "wave", variant: "text", width: "90px", height: "21px" })] })), _jsx(Skeleton, { animation: "wave", variant: "text", width: "180px", height: "21px" })] })] }), i))), _jsx(Skeleton, { animation: "wave", variant: "rounded", width: "112px", height: "36px", className: classes.button })] }))] })));
|
|
@@ -40,7 +38,7 @@ function Comments(props) {
|
|
|
40
38
|
cacheStrategy: CacheStrategies.CACHE_FIRST,
|
|
41
39
|
visibleItems: endpointQueryParams.limit
|
|
42
40
|
}, stateWidgetInitializer);
|
|
43
|
-
const [
|
|
41
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
44
42
|
// CONTEXTS
|
|
45
43
|
const scUserContext = useSCUser();
|
|
46
44
|
const scRoutingContext = useSCRouting();
|
|
@@ -70,7 +68,7 @@ function Comments(props) {
|
|
|
70
68
|
}, [scUserContext.user, _init]);
|
|
71
69
|
// HANDLERS
|
|
72
70
|
const handleNext = useCallback(() => {
|
|
73
|
-
|
|
71
|
+
setIsLoading(true);
|
|
74
72
|
dispatch({ type: actionWidgetTypes.LOADING_NEXT });
|
|
75
73
|
http
|
|
76
74
|
.request({
|
|
@@ -79,12 +77,12 @@ function Comments(props) {
|
|
|
79
77
|
})
|
|
80
78
|
.then((res) => {
|
|
81
79
|
dispatch({ type: actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: res.data });
|
|
82
|
-
|
|
80
|
+
setIsLoading(false);
|
|
83
81
|
})
|
|
84
82
|
.catch((error) => {
|
|
85
83
|
Logger.error(SCOPE_SC_UI, error);
|
|
86
84
|
});
|
|
87
|
-
}, [state.next, dispatch,
|
|
85
|
+
}, [state.next, dispatch, setIsLoading]);
|
|
88
86
|
// MEMOS
|
|
89
87
|
const renderComments = useMemo(() => {
|
|
90
88
|
const map = new Map();
|
|
@@ -97,11 +95,11 @@ function Comments(props) {
|
|
|
97
95
|
map.set(name, [...map.get(name), comment]);
|
|
98
96
|
}
|
|
99
97
|
});
|
|
100
|
-
return Array.from(map.entries()).map(([name, comments]) => (_jsxs(Box, Object.assign({ className:
|
|
98
|
+
return Array.from(map.entries()).map(([name, comments]) => (_jsxs(Box, Object.assign({ className: classes.outerWrapper }, { children: [_jsx(Typography, Object.assign({ variant: "h5" }, { children: name })), _jsx(Divider, {}), _jsxs(Stack, Object.assign({ className: classes.innerWrapper }, { children: [comments.map((comment) => (_jsxs(Stack, Object.assign({ className: classes.userWrapper }, { children: [_jsx(Avatar, { src: comment.created_by.avatar, alt: comment.created_by.username, className: classes.avatar }), _jsxs(Box, { children: [_jsxs(Stack, Object.assign({ className: classes.userInfo }, { children: [_jsx(Typography, Object.assign({ variant: "body1" }, { children: comment.created_by.username })), _jsx(Box, { className: classes.circle }), _jsx(Typography, Object.assign({ variant: "body2" }, { children: new Date(comment.created_at).toLocaleDateString() }))] })), _jsx(Typography, { variant: "body1", component: "div", dangerouslySetInnerHTML: { __html: comment.html } })] })] }), comment.id))), _jsx(Button, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.COURSE_ROUTE_NAME, course), size: "small", variant: "outlined", color: "inherit", className: classes.button }, { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.teacher.tab.comments.lessons.btn.label", defaultMessage: "ui.course.dashboard.teacher.tab.comments.lessons.btn.label" }) })) }))] }))] }), name)));
|
|
101
99
|
}, [state.results]);
|
|
102
100
|
if (!state.initialized) {
|
|
103
101
|
return _jsx(CommentsSkeleton, {});
|
|
104
102
|
}
|
|
105
|
-
return (_jsx(Box, Object.assign({ className: classes.container }, { children: state.count > 0 ? (_jsxs(Fragment, { children: [_jsx(Typography, Object.assign({ variant: "body1"
|
|
103
|
+
return (_jsx(Box, Object.assign({ className: classes.container }, { children: state.count > 0 ? (_jsxs(Fragment, { children: [_jsx(Typography, Object.assign({ variant: "body1" }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.teacher.tab.comments.number", defaultMessage: "ui.course.dashboard.teacher.tab.comments.number", values: { commentsNumber: state.count } }) })), renderComments, isLoading && _jsx(CommentSkeleton, { id: 1 }), _jsx(LoadingButton, Object.assign({ size: "small", variant: "outlined", color: "inherit", loading: isLoading, disabled: !state.next, onClick: handleNext }, { children: _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.teacher.tab.comments.btn.label", defaultMessage: "ui.course.dashboard.teacher.tab.comments.btn.label" }) })) }))] })) : (_jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: "ui.course.dashboard.teacher.tab.comments.empty", defaultMessage: "ui.course.dashboard.teacher.tab.comments.empty" }) }))) })));
|
|
106
104
|
}
|
|
107
105
|
export default memo(Comments);
|
|
@@ -5,14 +5,12 @@ import { PREFIX } from '../constants';
|
|
|
5
5
|
import CourseParticipantsButton from '../../CourseParticipantsButton';
|
|
6
6
|
import { memo } from 'react';
|
|
7
7
|
import { InfoPositionType } from '../types';
|
|
8
|
-
import classNames from 'classnames';
|
|
9
8
|
const classes = {
|
|
10
|
-
info: `${PREFIX}-info
|
|
11
|
-
contrastBgColor: `${PREFIX}-contrast-bg-color`
|
|
9
|
+
info: `${PREFIX}-info`
|
|
12
10
|
};
|
|
13
11
|
function InfoCourseDashboard(props) {
|
|
14
12
|
// PROPS
|
|
15
13
|
const { title, course, position } = props;
|
|
16
|
-
return (_jsxs(Stack, Object.assign({ className:
|
|
14
|
+
return (_jsxs(Stack, Object.assign({ className: classes.info }, { children: [_jsx(Typography, Object.assign({ variant: "h4" }, { children: _jsx(FormattedMessage, { id: title, defaultMessage: title }) })), position === InfoPositionType.FIRST && _jsx(CourseParticipantsButton, { course: course }), position === InfoPositionType.SECOND && _jsxs(Typography, Object.assign({ variant: "h5" }, { children: [course.avg_completion_rate, "%"] }))] })));
|
|
17
15
|
}
|
|
18
16
|
export default memo(InfoCourseDashboard);
|
|
@@ -7,6 +7,7 @@ import { CourseService } from '@selfcommunity/api-services';
|
|
|
7
7
|
import { SCCache, useSCUser } from '@selfcommunity/react-core';
|
|
8
8
|
import { actionWidgetTypes, dataWidgetReducer, stateWidgetInitializer } from '../../../utils/widget';
|
|
9
9
|
import { DEFAULT_PAGINATION_OFFSET } from '../../../constants/Pagination';
|
|
10
|
+
import { SCCourseUsersTableModeType } from '../../../types/course';
|
|
10
11
|
const headerCells = [
|
|
11
12
|
{
|
|
12
13
|
id: 'ui.course.dashboard.teacher.tab.students.table.header.name'
|
|
@@ -59,6 +60,6 @@ function Students(props) {
|
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
}, [scUserContext.user, _init]);
|
|
62
|
-
return (_jsx(CourseUsersTable, { course: course, state: state, dispatch: dispatch, headerCells: headerCells, mode:
|
|
63
|
+
return (_jsx(CourseUsersTable, { course: course, state: state, dispatch: dispatch, headerCells: headerCells, mode: SCCourseUsersTableModeType.DASHBOARD, emptyStatusTitle: "ui.courseUsersTable.empty.users.title", emptyStatusDescription: "ui.courseUsersTable.empty.users.description" }));
|
|
63
64
|
}
|
|
64
65
|
export default memo(Students);
|
|
@@ -55,8 +55,7 @@ const classes = {
|
|
|
55
55
|
stepOne: `${PREFIX}-step-one`,
|
|
56
56
|
stepTwo: `${PREFIX}-step-two`,
|
|
57
57
|
title: `${PREFIX}-title`,
|
|
58
|
-
contrastColor: `${PREFIX}-contrast-color
|
|
59
|
-
contrastBgColor: `${PREFIX}-contrast-bg-color`
|
|
58
|
+
contrastColor: `${PREFIX}-contrast-color`
|
|
60
59
|
};
|
|
61
60
|
const Root = styled(Box, {
|
|
62
61
|
name: PREFIX,
|
|
@@ -248,11 +247,11 @@ export default function CourseForm(inProps) {
|
|
|
248
247
|
/**
|
|
249
248
|
* Renders root object
|
|
250
249
|
*/
|
|
251
|
-
return (_jsxs(Fragment, { children: [_jsx(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { children: _jsxs(Box, Object.assign({ className: _step === SCCourseFormStepType.GENERAL ? classes.stepOne : classes.stepTwo }, { children: [_step === SCCourseFormStepType.GENERAL && (_jsx(_Fragment, { children: Object.values(SCCourseTypologyType).map((option, index) => (_jsx(Card, Object.assign({ className: classNames(classes.card, { [classes.selected]: option === field.type }) }, { children: _jsx(CardActionArea, Object.assign({ onClick: () => setField((prev) => (Object.assign(Object.assign({}, prev), { ['type']: option }))) }, { children: _jsxs(CardContent, { children: [_jsx(Typography, Object.assign({ variant: "subtitle2" }, { children: _jsx(FormattedMessage, { id: `ui.courseForm.${option}.title`, defaultMessage: `ui.courseForm.${option}.title` }) })), _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: `ui.courseForm.${option}.info`, defaultMessage: `ui.courseForm.${option}.info` }) }))] }) })) }), index))) })), _step === SCCourseFormStepType.CUSTOMIZATION && (_jsxs(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
250
|
+
return (_jsxs(Fragment, { children: [_jsx(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { children: _jsxs(Box, Object.assign({ className: _step === SCCourseFormStepType.GENERAL ? classes.stepOne : classes.stepTwo }, { children: [_step === SCCourseFormStepType.GENERAL && (_jsx(_Fragment, { children: Object.values(SCCourseTypologyType).map((option, index) => (_jsx(Card, Object.assign({ className: classNames(classes.card, { [classes.selected]: option === field.type }) }, { children: _jsx(CardActionArea, Object.assign({ onClick: () => setField((prev) => (Object.assign(Object.assign({}, prev), { ['type']: option }))) }, { children: _jsxs(CardContent, { children: [_jsx(Typography, Object.assign({ variant: "subtitle2" }, { children: _jsx(FormattedMessage, { id: `ui.courseForm.${option}.title`, defaultMessage: `ui.courseForm.${option}.title` }) })), _jsx(Typography, Object.assign({ variant: "body2" }, { children: _jsx(FormattedMessage, { id: `ui.courseForm.${option}.info`, defaultMessage: `ui.courseForm.${option}.info` }) }))] }) })) }), index))) })), _step === SCCourseFormStepType.CUSTOMIZATION && (_jsxs(Fragment, { children: [course && (_jsx(Typography, Object.assign({ variant: "h5", className: classes.contrastColor }, { children: _jsx(FormattedMessage, { id: "ui.courseForm.edit.title.general", defaultMessage: "ui.courseForm.edit.title.general" }) }))), _jsxs(FormGroup, Object.assign({ className: classes.form }, { children: [_jsx(Paper, Object.assign({ style: _backgroundCover, classes: { root: classes.cover } }, { children: _jsx(UploadCourseCover, { isUploading: field.isSubmitting, onChange: handleChangeCover }) })), _jsx(TextField, { required: true, className: classes.name, placeholder: `${intl.formatMessage(messages.name)}`, margin: "normal", value: field.name, name: "name", onChange: handleChange, InputProps: {
|
|
251
|
+
endAdornment: _jsx(Typography, Object.assign({ variant: "body2" }, { children: COURSE_TITLE_MAX_LENGTH - field.name.length }))
|
|
252
|
+
}, error: Boolean(field.name.length > COURSE_TITLE_MAX_LENGTH) || Boolean(error['nameError']), helperText: field.name.length > COURSE_TITLE_MAX_LENGTH ? (_jsx(FormattedMessage, { id: "ui.courseForm.name.error.maxLength", defaultMessage: "ui.courseForm.name.error.maxLength" })) : error['nameError'] ? (error['nameError']) : null }), _jsx(TextField, { multiline: true, className: classes.description, placeholder: `${intl.formatMessage(messages.description)}`, margin: "normal", value: field.description, name: "description", onChange: handleChange, InputProps: {
|
|
253
|
+
endAdornment: (_jsx(Typography, Object.assign({ variant: "body2" }, { children: ((_a = field.description) === null || _a === void 0 ? void 0 : _a.length) ? COURSE_DESCRIPTION_MAX_LENGTH - field.description.length : COURSE_DESCRIPTION_MAX_LENGTH })))
|
|
254
|
+
}, error: Boolean(((_b = field.description) === null || _b === void 0 ? void 0 : _b.length) > COURSE_DESCRIPTION_MAX_LENGTH), helperText: ((_c = field.description) === null || _c === void 0 ? void 0 : _c.length) > COURSE_DESCRIPTION_MAX_LENGTH ? (_jsx(FormattedMessage, { id: "ui.courseForm.description.error.maxLength", defaultMessage: "ui.courseForm.description.error.maxLength" })) : null }), _jsx(CategoryAutocomplete, { defaultValue: field.categories, TextFieldProps: { label: intl.formatMessage(Object.keys(field.categories).length ? messages.category : messages.categoryEmpty) }, multiple: true, onChange: handleOnChangeCategory }), course && _jsx(CourseEdit, { course: course, onPrivacyChange: (privacy) => setField((prev) => (Object.assign(Object.assign({}, prev), { ['privacy']: privacy }))) })] }))] })), _jsx(Box, Object.assign({ className: classes.actions }, { children: _jsx(LoadingButton, Object.assign({ size: "small", loading: field.isSubmitting, disabled: _step === SCCourseFormStepType.GENERAL
|
|
256
255
|
? !field.type || Object.keys(error).length !== 0
|
|
257
256
|
: _step === SCCourseFormStepType.CUSTOMIZATION &&
|
|
258
257
|
(!field.name ||
|
|
@@ -25,6 +25,7 @@ const Root = styled(Box, {
|
|
|
25
25
|
slot: 'Root'
|
|
26
26
|
})(() => ({}));
|
|
27
27
|
export default function CourseEdit(inProps) {
|
|
28
|
+
var _a;
|
|
28
29
|
//PROPS
|
|
29
30
|
const props = useThemeProps({
|
|
30
31
|
props: inProps,
|
|
@@ -34,7 +35,7 @@ export default function CourseEdit(inProps) {
|
|
|
34
35
|
// STATE
|
|
35
36
|
const [privacy, setPrivacy] = useState(course.privacy);
|
|
36
37
|
const notPublishable = course.num_lessons === 0 ||
|
|
37
|
-
!course.sections.some((section) => section.lessons.some((lesson) => lesson.status === SCCourseLessonStatusType.PUBLISHED));
|
|
38
|
+
!((_a = course.sections) === null || _a === void 0 ? void 0 : _a.some((section) => section.lessons.some((lesson) => lesson.status === SCCourseLessonStatusType.PUBLISHED)));
|
|
38
39
|
//HANDLERS
|
|
39
40
|
const handleChange = (event) => {
|
|
40
41
|
setPrivacy(event.target.value);
|
|
@@ -42,7 +42,7 @@ const Root = styled(Box, {
|
|
|
42
42
|
export const CoursesChipRoot = styled(Chip, {
|
|
43
43
|
name: PREFIX,
|
|
44
44
|
slot: 'CoursesChipRoot',
|
|
45
|
-
shouldForwardProp: (prop) => prop !== '
|
|
45
|
+
shouldForwardProp: (prop) => prop !== 'showMine' && prop !== 'showManagedCourses'
|
|
46
46
|
})(() => ({}));
|
|
47
47
|
/**
|
|
48
48
|
* > API documentation for the Community-JS Courses component. Learn about the available props and the CSS API.
|
|
@@ -93,8 +93,8 @@ export default function Courses(inProps) {
|
|
|
93
93
|
const [next, setNext] = useState(null);
|
|
94
94
|
const [query, setQuery] = useState('');
|
|
95
95
|
const [_categories, setCategories] = useState([]);
|
|
96
|
-
const [
|
|
97
|
-
const [
|
|
96
|
+
const [showMine, setShowMine] = useState(false);
|
|
97
|
+
const [showManagedCourses, setShowManagedCourses] = useState(false);
|
|
98
98
|
// CONTEXT
|
|
99
99
|
const scUserContext = useContext(SCUserContext);
|
|
100
100
|
const { preferences } = useSCPreferences();
|
|
@@ -103,14 +103,11 @@ export default function Courses(inProps) {
|
|
|
103
103
|
const onlyStaffEnabled = useMemo(() => { var _a; return (_a = preferences[SCPreferences.CONFIGURATIONS_COURSES_ONLY_STAFF_ENABLED]) === null || _a === void 0 ? void 0 : _a.value; }, [preferences]);
|
|
104
104
|
const canCreateCourse = useMemo(() => { var _a, _b; return (_b = (_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.create_course; }, [(_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.permission]);
|
|
105
105
|
const endpoint = useMemo(() => {
|
|
106
|
-
if (
|
|
106
|
+
if (showManagedCourses) {
|
|
107
107
|
return Endpoints.GetJoinedCourses;
|
|
108
108
|
}
|
|
109
|
-
else if (showForMe) {
|
|
110
|
-
return Endpoints.CourseSuggestion;
|
|
111
|
-
}
|
|
112
109
|
return Endpoints.SearchCourses;
|
|
113
|
-
}, [
|
|
110
|
+
}, [showManagedCourses]);
|
|
114
111
|
// CONST
|
|
115
112
|
const authUserId = scUserContext.user ? scUserContext.user.id : null;
|
|
116
113
|
const theme = useTheme();
|
|
@@ -119,10 +116,10 @@ export default function Courses(inProps) {
|
|
|
119
116
|
const updatesSubscription = useRef(null);
|
|
120
117
|
// HANDLERS
|
|
121
118
|
const handleChipClick = () => {
|
|
122
|
-
|
|
119
|
+
setShowMine(!showMine);
|
|
123
120
|
};
|
|
124
121
|
const handleDeleteClick = () => {
|
|
125
|
-
|
|
122
|
+
setShowMine(false);
|
|
126
123
|
};
|
|
127
124
|
/**
|
|
128
125
|
* Fetches courses list
|
|
@@ -132,7 +129,7 @@ export default function Courses(inProps) {
|
|
|
132
129
|
.request({
|
|
133
130
|
url: endpoint.url({}),
|
|
134
131
|
method: endpoint.method,
|
|
135
|
-
params: Object.assign(Object.assign(Object.assign(Object.assign({}, endpointQueryParams), (_categories.length && { categories: JSON.stringify(_categories) })), (query && { search: query })), (
|
|
132
|
+
params: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, endpointQueryParams), (_categories.length && { categories: JSON.stringify(_categories) })), (query && { search: query })), (showManagedCourses && { statuses: JSON.stringify(['creator', 'manager']) })), (showMine && { statuses: JSON.stringify(['joined', 'manager']) }))
|
|
136
133
|
})
|
|
137
134
|
.then((res) => {
|
|
138
135
|
setCourses(res.data.results);
|
|
@@ -153,7 +150,7 @@ export default function Courses(inProps) {
|
|
|
153
150
|
else {
|
|
154
151
|
fetchCourses();
|
|
155
152
|
}
|
|
156
|
-
}, [contentAvailability, authUserId,
|
|
153
|
+
}, [contentAvailability, authUserId, showMine, showManagedCourses, _categories]);
|
|
157
154
|
/**
|
|
158
155
|
* Subscriber for pubsub callback
|
|
159
156
|
*/
|
|
@@ -183,7 +180,7 @@ export default function Courses(inProps) {
|
|
|
183
180
|
return http
|
|
184
181
|
.request({
|
|
185
182
|
url: next,
|
|
186
|
-
method:
|
|
183
|
+
method: showManagedCourses ? Endpoints.GetJoinedCourses.method : Endpoints.SearchCourses.method
|
|
187
184
|
})
|
|
188
185
|
.then((res) => {
|
|
189
186
|
setCourses([...courses, ...res.data.results]);
|
|
@@ -220,15 +217,15 @@ export default function Courses(inProps) {
|
|
|
220
217
|
}
|
|
221
218
|
}, InputProps: {
|
|
222
219
|
endAdornment: (_jsx(InputAdornment, Object.assign({ position: "end" }, { children: isMobile ? (_jsx(IconButton, Object.assign({ onClick: () => fetchCourses(), disabled: loading }, { children: _jsx(Icon, { children: "search" }) }))) : (_jsx(Button, { size: "small", variant: "contained", color: "secondary", onClick: () => fetchCourses(), endIcon: _jsx(Icon, { children: "search" }), disabled: loading })) })))
|
|
223
|
-
} }) })), authUserId && ((onlyStaffEnabled && canCreateCourse) || !onlyStaffEnabled) && (_jsx(Grid, Object.assign({ item: true }, { children: _jsx(CoursesChipRoot, { color:
|
|
224
|
-
// @ts-expect-error this is needed to use
|
|
225
|
-
|
|
226
|
-
// @ts-expect-error this is needed to use
|
|
227
|
-
|
|
220
|
+
} }) })), authUserId && ((onlyStaffEnabled && canCreateCourse) || !onlyStaffEnabled) && (_jsx(Grid, Object.assign({ item: true }, { children: _jsx(CoursesChipRoot, { color: showManagedCourses ? 'primary' : 'default', variant: showManagedCourses ? 'filled' : 'outlined', label: _jsx(FormattedMessage, { id: "ui.courses.filterByManagedByMe", defaultMessage: "ui.courses.filterByManagedByMe" }), onClick: () => setShowManagedCourses(!showManagedCourses),
|
|
221
|
+
// @ts-expect-error this is needed to use showMine into SCCourses
|
|
222
|
+
showManagedCourses: showManagedCourses, deleteIcon: showManagedCourses ? _jsx(Icon, { children: "close" }) : null, onDelete: showManagedCourses ? () => setShowManagedCourses(false) : null, disabled: loading || showMine }) }))), _jsx(Grid, Object.assign({ item: true, xs: 12, md: "auto" }, { children: _jsx(FormControl, Object.assign({ fullWidth: true }, { children: _jsx(CategoryAutocomplete, { onChange: handleOnChangeCategory, className: classes.category, size: "small", multiple: true }) })) })), authUserId && (_jsx(Grid, Object.assign({ item: true }, { children: _jsx(CoursesChipRoot, { color: showMine ? 'primary' : 'default', variant: showMine ? 'filled' : 'outlined', label: _jsx(FormattedMessage, { id: "ui.courses.filterByMine", defaultMessage: "ui.courses.filterByMine" }), onClick: handleChipClick,
|
|
223
|
+
// @ts-expect-error this is needed to use showMine into SCCourses
|
|
224
|
+
showMine: showMine, deleteIcon: showMine ? _jsx(Icon, { children: "close" }) : null, onDelete: showMine ? handleDeleteClick : null, disabled: loading || showManagedCourses }) })))] })) }))), _jsx(_Fragment, { children: !courses.length ? (_jsx(Box, Object.assign({ className: classes.noResults }, { children: !canCreateCourse && onlyStaffEnabled ? (_jsxs(Stack, Object.assign({ className: classes.studentEmptyView }, { children: [_jsx(Stack, Object.assign({ className: classes.emptyBox }, { children: _jsx(Stack, Object.assign({ className: classes.emptyRotatedBox }, { children: _jsx(Icon, Object.assign({ className: classes.emptyIcon, color: "disabled", fontSize: "large" }, { children: "courses" })) })) })), _jsx(Typography, Object.assign({ variant: "h5", textAlign: "center" }, { children: _jsx(FormattedMessage, { id: "ui.courses.empty.title", defaultMessage: "ui.courses.empty.title" }) })), _jsx(Typography, Object.assign({ variant: "body1", textAlign: "center" }, { children: _jsx(FormattedMessage, { id: "ui.courses.empty.info", defaultMessage: "ui.courses.empty.info" }) }))] }))) : (_jsx(Box, Object.assign({ className: classes.teacherEmptyView }, { children: _jsx(Skeleton, Object.assign({ teacherView: (onlyStaffEnabled && canCreateCourse) || !onlyStaffEnabled, coursesNumber: 1 }, CoursesSkeletonComponentProps, { CourseSkeletonProps: CourseSkeletonComponentProps })) }))) }))) : (_jsx(InfiniteScroll, Object.assign({ dataLength: courses.length, next: handleNext, hasMoreNext: Boolean(next), loaderNext: isMobile ? (_jsx(CourseSkeleton, { template: SCCourseTemplateType.PREVIEW })) : (_jsx(Skeleton, Object.assign({ coursesNumber: 4 }, CoursesSkeletonComponentProps, { CourseSkeletonProps: CourseSkeletonComponentProps }))), endMessage: _jsx(Typography, Object.assign({ component: "div", className: classes.endMessage }, { children: _jsx(FormattedMessage, { id: "ui.courses.endMessage", defaultMessage: "ui.courses.endMessage", values: {
|
|
228
225
|
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
|
229
226
|
// @ts-ignore
|
|
230
227
|
button: (chunk) => (_jsx(Button, Object.assign({ color: "secondary", variant: "text", onClick: handleScrollUp }, { children: chunk })))
|
|
231
|
-
} }) })) }, { children: _jsx(Grid, Object.assign({ container: true, spacing: { xs: 2 }, 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 && 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"))] }) })) }))) })] }));
|
|
228
|
+
} }) })) }, { children: _jsx(Grid, Object.assign({ container: true, spacing: { xs: 2 }, 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"))] }) })) }))) })] }));
|
|
232
229
|
/**
|
|
233
230
|
* Renders root object (if content availability community option is false and user is anonymous, component is hidden)
|
|
234
231
|
*/
|
|
@@ -2,7 +2,7 @@ import { __rest } from "tslib";
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Box, Icon, IconButton, Stack, styled, Tab, Typography, useMediaQuery, useTheme, useThemeProps } from '@mui/material';
|
|
4
4
|
import { PREFIX } from './constants';
|
|
5
|
-
import { useCallback, useState } from 'react';
|
|
5
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
6
6
|
import classNames from 'classnames';
|
|
7
7
|
import { TabContext, TabList, TabPanel } from '@mui/lab';
|
|
8
8
|
import { FormattedMessage } from 'react-intl';
|
|
@@ -45,30 +45,6 @@ const TAB_DATA = [
|
|
|
45
45
|
value: SCCourseEditTabType.OPTIONS
|
|
46
46
|
}
|
|
47
47
|
];
|
|
48
|
-
function getPanelData(course, setCourse) {
|
|
49
|
-
return [
|
|
50
|
-
{
|
|
51
|
-
value: SCCourseEditTabType.LESSONS,
|
|
52
|
-
children: _jsx(Lessons, { course: course, setCourse: setCourse })
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
value: SCCourseEditTabType.CUSTOMIZE,
|
|
56
|
-
children: _jsx(Customize, { course: course, setCourse: setCourse })
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
value: SCCourseEditTabType.USERS,
|
|
60
|
-
children: _jsx(Users, { course: course })
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
value: SCCourseEditTabType.REQUESTS,
|
|
64
|
-
children: _jsx(Requests, { course: course })
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
value: SCCourseEditTabType.OPTIONS,
|
|
68
|
-
children: _jsx(Options, { course: course, setCourse: setCourse })
|
|
69
|
-
}
|
|
70
|
-
];
|
|
71
|
-
}
|
|
72
48
|
const Root = styled(Box, {
|
|
73
49
|
name: PREFIX,
|
|
74
50
|
slot: 'Root',
|
|
@@ -90,7 +66,7 @@ export default function EditCourse(inProps) {
|
|
|
90
66
|
const theme = useTheme();
|
|
91
67
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
|
92
68
|
// HANDLERS
|
|
93
|
-
const handleTabChange = useCallback((
|
|
69
|
+
const handleTabChange = useCallback((_e, newTabValue) => {
|
|
94
70
|
if (onTabSelect) {
|
|
95
71
|
onTabSelect(newTabValue);
|
|
96
72
|
}
|
|
@@ -99,8 +75,33 @@ export default function EditCourse(inProps) {
|
|
|
99
75
|
onTabChange === null || onTabChange === void 0 ? void 0 : onTabChange(newTabValue);
|
|
100
76
|
}
|
|
101
77
|
}, [setTabValue, onTabChange, onTabSelect]);
|
|
78
|
+
// MEMOS
|
|
79
|
+
const panelData = useMemo(() => {
|
|
80
|
+
return [
|
|
81
|
+
{
|
|
82
|
+
value: SCCourseEditTabType.LESSONS,
|
|
83
|
+
children: _jsx(Lessons, { course: scCourse, setCourse: setSCCourse, handleTabChange: handleTabChange })
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
value: SCCourseEditTabType.CUSTOMIZE,
|
|
87
|
+
children: _jsx(Customize, { course: scCourse, setCourse: setSCCourse })
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
value: SCCourseEditTabType.USERS,
|
|
91
|
+
children: _jsx(Users, { course: scCourse, handleTabChange: handleTabChange })
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
value: SCCourseEditTabType.REQUESTS,
|
|
95
|
+
children: _jsx(Requests, { course: scCourse, handleTabChange: handleTabChange })
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
value: SCCourseEditTabType.OPTIONS,
|
|
99
|
+
children: _jsx(Options, { course: scCourse, setCourse: setSCCourse })
|
|
100
|
+
}
|
|
101
|
+
];
|
|
102
|
+
}, [scCourse, handleTabChange]);
|
|
102
103
|
if (!scCourse) {
|
|
103
104
|
return _jsx(EditCourseSkeleton, { tab: tab });
|
|
104
105
|
}
|
|
105
|
-
return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { children: [_jsxs(Stack, Object.assign({ className: classes.header }, { children: [_jsx(IconButton, Object.assign({ href: scRoutingContext.url(SCRoutes.COURSE_DASHBOARD_ROUTE_NAME, scCourse), size: "small" }, { children: _jsx(Icon, Object.assign({ className: classes.contrastColor }, { children: "arrow_back" })) })), _jsx(Typography, Object.assign({ variant: "h5", className: classes.contrastColor }, { children: scCourse.name }))] })), _jsxs(TabContext, Object.assign({ value: tabValue }, { children: [_jsx(TabList, Object.assign({ className: classes.tabList, onChange: handleTabChange, textColor: "primary", indicatorColor: "primary", variant: isMobile ? 'scrollable' : 'standard', scrollButtons: isMobile, centered: !isMobile }, { children: TAB_DATA.map((data, i) => (_jsx(Tab, { label: _jsx(Typography, Object.assign({ variant: "h6" }, { children: _jsx(FormattedMessage, { id: data.label, defaultMessage: data.label }) })), value: data.value, className: classNames(classes.tab, classes.contrastColor) }, i))) })),
|
|
106
|
+
return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { children: [_jsxs(Stack, Object.assign({ className: classes.header }, { children: [_jsx(IconButton, Object.assign({ href: scRoutingContext.url(SCRoutes.COURSE_DASHBOARD_ROUTE_NAME, scCourse), size: "small" }, { children: _jsx(Icon, Object.assign({ className: classes.contrastColor }, { children: "arrow_back" })) })), _jsx(Typography, Object.assign({ variant: "h5", className: classes.contrastColor }, { children: scCourse.name }))] })), _jsxs(TabContext, Object.assign({ value: tabValue }, { children: [_jsx(TabList, Object.assign({ className: classes.tabList, onChange: handleTabChange, textColor: "primary", indicatorColor: "primary", variant: isMobile ? 'scrollable' : 'standard', scrollButtons: isMobile, centered: !isMobile }, { children: TAB_DATA.map((data, i) => (_jsx(Tab, { label: _jsx(Typography, Object.assign({ variant: "h6" }, { children: _jsx(FormattedMessage, { id: data.label, defaultMessage: data.label }) })), value: data.value, className: classNames(classes.tab, classes.contrastColor) }, i))) })), panelData.map((data, i) => (_jsx(TabPanel, Object.assign({ className: classes.tabPanel, value: data.value }, { children: data.children }), i)))] }))] })));
|
|
106
107
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Stack, Skeleton, TableContainer, Table, TableHead, TableRow, TableCell, TableBody } from '@mui/material';
|
|
2
|
+
import { Stack, Skeleton, TableContainer, Table, TableHead, TableRow, TableCell, TableBody, Box } from '@mui/material';
|
|
3
3
|
import { PREFIX } from '../constants';
|
|
4
|
-
import { Fragment } from 'react';
|
|
5
4
|
const classes = {
|
|
6
5
|
lessonTitle: `${PREFIX}-lesson-title`,
|
|
7
6
|
lessonInfoWrapper: `${PREFIX}-lesson-info-wrapper`,
|
|
@@ -14,5 +13,5 @@ const classes = {
|
|
|
14
13
|
actionsWrapper: `${PREFIX}-actions-wrapper`
|
|
15
14
|
};
|
|
16
15
|
export default function LessonsSkeleton() {
|
|
17
|
-
return (_jsxs(
|
|
16
|
+
return (_jsxs(Box, { children: [_jsx(Skeleton, { animation: "wave", variant: "text", width: "150px", height: "21px", className: classes.lessonTitle }), _jsxs(Stack, Object.assign({ className: classes.lessonInfoWrapper }, { children: [_jsxs(Stack, Object.assign({ className: classes.lessonInfo }, { children: [_jsx(Skeleton, { animation: "wave", variant: "rectangular", width: "14px", height: "14px" }), _jsx(Skeleton, { animation: "wave", variant: "text", width: "150px", height: "21px" })] })), _jsx(Skeleton, { animation: "wave", variant: "rectangular", width: "105px", height: "32px" })] })), _jsxs(Stack, Object.assign({ className: classes.lessonsSectionsWrapper }, { children: [_jsx(Skeleton, { animation: "wave", width: "159px", height: "21px" }), _jsx(Skeleton, { animation: "wave", width: "100px", height: "32px" })] })), _jsx(TableContainer, Object.assign({ className: classes.tableContainer }, { children: _jsxs(Table, { children: [_jsx(TableHead, { children: _jsxs(TableRow, { children: [_jsx(TableCell, {}), _jsx(TableCell, { children: _jsx(Skeleton, { animation: "wave", variant: "text", width: "102px", height: "32px" }) }), _jsx(TableCell, { children: _jsx(Skeleton, { animation: "wave", variant: "text", width: "87px", height: "32px", className: classes.margin }) }), _jsx(TableCell, { children: _jsx(Skeleton, { animation: "wave", variant: "text", width: "48px", height: "32px", className: classes.marginLeft }) })] }) }), _jsx(TableBody, { children: _jsxs(TableRow, { children: [_jsx(TableCell, {}), _jsx(TableCell, { children: _jsx(Skeleton, { animation: "wave", variant: "text", width: "102px", height: "21px" }) }), _jsx(TableCell, { children: _jsx(Skeleton, { animation: "wave", variant: "rectangular", width: "250px", height: "54px", className: classes.margin }) }), _jsx(TableCell, { children: _jsxs(Stack, Object.assign({ className: classes.actionsWrapper }, { children: [_jsx(Skeleton, { animation: "wave", variant: "rounded", width: "105px", height: "37px" }), _jsx(Skeleton, { animation: "wave", variant: "circular", width: "36px", height: "36px" })] })) })] }) })] }) }))] }));
|
|
18
17
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { SyntheticEvent } from 'react';
|
|
2
2
|
import { SCCourseType } from '@selfcommunity/types';
|
|
3
|
+
import { SCCourseEditTabType } from '../../types';
|
|
3
4
|
interface LessonsProps {
|
|
4
5
|
course: SCCourseType;
|
|
5
6
|
setCourse: (course: SCCourseType) => void;
|
|
7
|
+
handleTabChange: (_e: SyntheticEvent, newTabValue: SCCourseEditTabType) => void;
|
|
6
8
|
}
|
|
7
9
|
declare function Lessons(props: LessonsProps): JSX.Element;
|
|
8
10
|
declare const _default: import("react").MemoExoticComponent<typeof Lessons>;
|