@selfcommunity/react-ui 0.10.2-courses.159 → 0.10.2-courses.161

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 (46) hide show
  1. package/lib/cjs/components/CommentObjectReply/CommentObjectReply.js +11 -5
  2. package/lib/cjs/components/Composer/Content/ContentLesson/ContentLesson.js +35 -4
  3. package/lib/cjs/components/CourseDashboard/Teacher/Comments.js +2 -2
  4. package/lib/cjs/components/CourseParticipantsButton/CourseParticipantsButton.js +1 -1
  5. package/lib/cjs/components/Editor/Editor.d.ts +13 -1
  6. package/lib/cjs/components/Editor/Editor.js +3 -4
  7. package/lib/cjs/components/Editor/nodes/index.d.ts +1 -2
  8. package/lib/cjs/components/Editor/nodes/index.js +1 -3
  9. package/lib/cjs/components/Editor/plugins/MediaPlugin.d.ts +2 -1
  10. package/lib/cjs/components/Editor/plugins/MediaPlugin.js +5 -27
  11. package/lib/cjs/components/Editor/plugins/ToolbarPlugin.d.ts +2 -0
  12. package/lib/cjs/components/Editor/plugins/ToolbarPlugin.js +2 -2
  13. package/lib/cjs/components/LessonCommentObject/LessonCommentObject.d.ts +1 -0
  14. package/lib/cjs/components/LessonCommentObject/LessonCommentObject.js +8 -2
  15. package/lib/cjs/components/LessonCommentObjects/LessonCommentObjects.js +5 -1
  16. package/lib/cjs/components/LessonObject/LessonObject.js +7 -3
  17. package/lib/cjs/shared/AccordionLessons/AccordionLessons.js +5 -4
  18. package/lib/cjs/shared/LessonFilePreview/index.d.ts +12 -0
  19. package/lib/cjs/shared/LessonFilePreview/index.js +29 -0
  20. package/lib/cjs/shared/Media/Link/UrlTextField/index.js +2 -3
  21. package/lib/esm/components/CommentObjectReply/CommentObjectReply.js +11 -5
  22. package/lib/esm/components/Composer/Content/ContentLesson/ContentLesson.js +37 -6
  23. package/lib/esm/components/CourseDashboard/Teacher/Comments.js +3 -3
  24. package/lib/esm/components/CourseParticipantsButton/CourseParticipantsButton.js +1 -1
  25. package/lib/esm/components/Editor/Editor.d.ts +13 -1
  26. package/lib/esm/components/Editor/Editor.js +3 -4
  27. package/lib/esm/components/Editor/nodes/index.d.ts +1 -2
  28. package/lib/esm/components/Editor/nodes/index.js +1 -3
  29. package/lib/esm/components/Editor/plugins/MediaPlugin.d.ts +2 -1
  30. package/lib/esm/components/Editor/plugins/MediaPlugin.js +5 -27
  31. package/lib/esm/components/Editor/plugins/ToolbarPlugin.d.ts +2 -0
  32. package/lib/esm/components/Editor/plugins/ToolbarPlugin.js +2 -2
  33. package/lib/esm/components/LessonCommentObject/LessonCommentObject.d.ts +1 -0
  34. package/lib/esm/components/LessonCommentObject/LessonCommentObject.js +8 -2
  35. package/lib/esm/components/LessonCommentObjects/LessonCommentObjects.js +5 -1
  36. package/lib/esm/components/LessonObject/LessonObject.js +8 -4
  37. package/lib/esm/shared/AccordionLessons/AccordionLessons.js +6 -5
  38. package/lib/esm/shared/LessonFilePreview/index.d.ts +12 -0
  39. package/lib/esm/shared/LessonFilePreview/index.js +25 -0
  40. package/lib/esm/shared/Media/Link/UrlTextField/index.js +3 -4
  41. package/lib/umd/react-ui.js +1 -1
  42. package/package.json +8 -8
  43. package/lib/cjs/components/Editor/nodes/DocNode.d.ts +0 -39
  44. package/lib/cjs/components/Editor/nodes/DocNode.js +0 -181
  45. package/lib/esm/components/Editor/nodes/DocNode.d.ts +0 -39
  46. package/lib/esm/components/Editor/nodes/DocNode.js +0 -175
@@ -14,10 +14,12 @@ const lab_1 = require("@mui/lab");
14
14
  const BaseItem_1 = tslib_1.__importDefault(require("../../shared/BaseItem"));
15
15
  const UserAvatar_1 = tslib_1.__importDefault(require("../../shared/UserAvatar"));
16
16
  const system_1 = require("@mui/system");
17
+ const PreviewComponent_1 = tslib_1.__importDefault(require("../../shared/Media/File/PreviewComponent"));
17
18
  const PREFIX = 'SCCommentObjectReply';
18
19
  const classes = {
19
20
  root: `${PREFIX}-root`,
20
21
  comment: `${PREFIX}-comment`,
22
+ media: `${PREFIX}-media`,
21
23
  hasValue: `${PREFIX}-has-value`,
22
24
  avatar: `${PREFIX}-avatar`,
23
25
  actions: `${PREFIX}-actions`,
@@ -70,7 +72,8 @@ function CommentObjectReply(inProps) {
70
72
  const scUserContext = (0, react_core_1.useSCUser)();
71
73
  // RETRIEVE OBJECTS
72
74
  const [html, setHtml] = (0, react_1.useState)(text);
73
- const [media, setMedia] = (0, react_1.useState)(medias);
75
+ const [media, setMedia] = (0, react_1.useState)(medias !== null && medias !== void 0 ? medias : []);
76
+ const [uploadingMedia, setUploadingMedia] = (0, react_1.useState)(false);
74
77
  // HOOKS
75
78
  const theme = (0, material_1.useTheme)();
76
79
  const isMobile = (0, material_1.useMediaQuery)(theme.breakpoints.down('md'));
@@ -115,8 +118,11 @@ function CommentObjectReply(inProps) {
115
118
  const handleChangeText = (value) => {
116
119
  setHtml(value);
117
120
  };
118
- const handleChangeMedia = (medias) => {
119
- setMedia(medias);
121
+ const handleChangeMedia = (value) => {
122
+ setMedia((prev) => [...prev, value]);
123
+ };
124
+ const handleChangeMedias = (value) => {
125
+ setMedia([...value]);
120
126
  };
121
127
  /**
122
128
  * Check if editor is empty
@@ -127,7 +133,7 @@ function CommentObjectReply(inProps) {
127
133
  }, [html]);
128
134
  // RENDER
129
135
  return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ id: id }, rest, { disableTypography: true, onClick: handleEditorFocus, elevation: elevation, className: (0, classnames_1.default)(classes.root, className), image: showAvatar &&
130
- (!scUserContext.user ? ((0, jsx_runtime_1.jsx)(material_1.Avatar, { variant: "circular", className: classes.avatar })) : ((0, jsx_runtime_1.jsx)(UserAvatar_1.default, Object.assign({ hide: !scUserContext.user.community_badge }, { children: (0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: scUserContext.user.username, variant: "circular", src: scUserContext.user.avatar, classes: { root: classes.avatar } }) })))), secondary: (0, jsx_runtime_1.jsxs)(Widget_1.default, Object.assign({ className: (0, classnames_1.default)(classes.comment, { [classes.hasValue]: !isEditorEmpty }) }, WidgetProps, { children: [(0, jsx_runtime_1.jsx)(Editor_1.default, Object.assign({ ref: editor, onChange: handleChangeText, onMediaChange: handleChangeMedia, defaultValue: html, editable: editable, uploadImage: true, action: replyIcon &&
131
- onReply && ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ onClick: handleReply, className: classes.iconReply }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "send" }) }))) }, EditorProps)), !isEditorEmpty && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ direction: "row", spacing: 2, className: classes.actions }, { children: [onReply && !replyIcon && ((0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ variant: "outlined", size: "small", onClick: handleReply, loading: !editable, className: classes.buttonReply }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentObject.replyComment.reply", defaultMessage: "ui.commentObject.replyComment.reply" }) }))), onSave && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [onCancel && ((0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ variant: 'text', size: "small", onClick: handleCancel, disabled: !editable, color: "inherit", className: classes.buttonCancel }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentObject.replyComment.cancel", defaultMessage: "ui.commentObject.replyComment.cancel" }) }))), (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ variant: "outlined", size: "small", onClick: handleSave, loading: !editable, className: classes.buttonSave }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentObject.replyComment.save", defaultMessage: "ui.commentObject.replyComment.save" }) }))] }))] })))] })) })));
136
+ (!scUserContext.user ? ((0, jsx_runtime_1.jsx)(material_1.Avatar, { variant: "circular", className: classes.avatar })) : ((0, jsx_runtime_1.jsx)(UserAvatar_1.default, Object.assign({ hide: !scUserContext.user.community_badge }, { children: (0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: scUserContext.user.username, variant: "circular", src: scUserContext.user.avatar, classes: { root: classes.avatar } }) })))), secondary: (0, jsx_runtime_1.jsxs)(Widget_1.default, Object.assign({ className: (0, classnames_1.default)(classes.comment, { [classes.hasValue]: !isEditorEmpty }) }, WidgetProps, { children: [media && media.length > 0 && (0, jsx_runtime_1.jsx)(PreviewComponent_1.default, { value: media, onChange: handleChangeMedias, className: classes.media }), (0, jsx_runtime_1.jsx)(Editor_1.default, Object.assign({ ref: editor, onChange: handleChangeText, defaultValue: html, editable: editable, uploadImage: true, action: replyIcon &&
137
+ onReply && ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ onClick: handleReply, className: classes.iconReply, disabled: uploadingMedia }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "send" }) }))) }, EditorProps, { MediaPluginProps: { isUploading: setUploadingMedia, onMediaAdd: handleChangeMedia } })), !isEditorEmpty && ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ direction: "row", spacing: 2, className: classes.actions }, { children: [onReply && !replyIcon && ((0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ variant: "outlined", size: "small", onClick: handleReply, loading: !editable, className: classes.buttonReply }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentObject.replyComment.reply", defaultMessage: "ui.commentObject.replyComment.reply" }) }))), onSave && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [onCancel && ((0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ variant: 'text', size: "small", onClick: handleCancel, disabled: !editable, color: "inherit", className: classes.buttonCancel }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentObject.replyComment.cancel", defaultMessage: "ui.commentObject.replyComment.cancel" }) }))), (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ variant: "outlined", size: "small", onClick: handleSave, loading: !editable, className: classes.buttonSave }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentObject.replyComment.save", defaultMessage: "ui.commentObject.replyComment.save" }) }))] }))] })))] })) })));
132
138
  }
133
139
  exports.default = CommentObjectReply;
@@ -9,12 +9,15 @@ const classnames_1 = tslib_1.__importDefault(require("classnames"));
9
9
  const Editor_1 = tslib_1.__importDefault(require("../../../Editor"));
10
10
  const react_intl_1 = require("react-intl");
11
11
  const constants_1 = require("../../constants");
12
+ const Media_1 = require("../../../../shared/Media");
13
+ const UrlTextField_1 = tslib_1.__importDefault(require("../../../../shared/Media/Link/UrlTextField"));
12
14
  const classes = {
13
15
  root: `${constants_1.PREFIX}-content-lesson-root`,
14
16
  generalError: `${constants_1.PREFIX}-general-error`,
15
17
  title: `${constants_1.PREFIX}-content-lesson-title`,
16
18
  medias: `${constants_1.PREFIX}-content-lesson-medias`,
17
- editor: `${constants_1.PREFIX}-content-lesson-editor`
19
+ editor: `${constants_1.PREFIX}-content-lesson-editor`,
20
+ link: `${constants_1.PREFIX}-content-lesson-link`
18
21
  };
19
22
  const Root = (0, styles_1.styled)(material_1.Box, {
20
23
  name: constants_1.PREFIX,
@@ -24,13 +27,41 @@ exports.default = (props) => {
24
27
  // PROPS
25
28
  const { className = null, value, error = {}, disabled = false, onChange, onMediaChange, EditorProps = {} } = props;
26
29
  const { error: generalError = null } = Object.assign({}, error);
30
+ const mediaObjectTypes = [Media_1.File, Media_1.Link];
31
+ const [medias, setMedias] = (0, react_1.useState)((value === null || value === void 0 ? void 0 : value.medias) || []);
32
+ const [openLink, setOpenLink] = (0, react_1.useState)();
33
+ const linkInputRef = (0, react_1.useRef)(null);
27
34
  // HANDLERS
28
35
  const handleChangeHtml = (0, react_1.useCallback)((html) => {
29
36
  onChange(html);
30
37
  }, [value]);
31
- const handleChangeMedia = (0, react_1.useCallback)((medias) => {
32
- onMediaChange(medias);
38
+ const handleChangeMedias = (0, react_1.useCallback)((value) => {
39
+ setMedias([...value]);
40
+ onMediaChange([...value]);
33
41
  }, []);
42
+ const handleChangeMedia = (value) => {
43
+ setMedias((prev) => [...prev, value]);
44
+ onMediaChange([...medias, value]);
45
+ };
46
+ const handleLinkAdd = (0, react_1.useCallback)((media) => {
47
+ setMedias([...medias, media]);
48
+ setOpenLink(false);
49
+ }, [medias]);
50
+ (0, react_1.useEffect)(() => {
51
+ if (openLink && linkInputRef.current) {
52
+ linkInputRef.current.scrollIntoView({ behavior: 'smooth' });
53
+ }
54
+ }, [openLink]);
34
55
  // RENDER
35
- return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, { children: [generalError && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ className: classes.generalError }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.composer.error.${generalError}`, defaultMessage: `ui.composer.error.${generalError}` }) }))), (0, jsx_runtime_1.jsx)(Editor_1.default, Object.assign({}, EditorProps, { editable: !disabled, className: classes.editor, onChange: handleChangeHtml, onMediaChange: handleChangeMedia, defaultValue: value.html }))] })));
56
+ return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, { children: [generalError && ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ className: classes.generalError }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.composer.error.${generalError}`, defaultMessage: `ui.composer.error.${generalError}` }) }))), (0, jsx_runtime_1.jsx)(Editor_1.default, Object.assign({}, EditorProps, { editable: !disabled, className: classes.editor, onChange: handleChangeHtml, onMediaChange: handleChangeMedia, defaultValue: value.html, ToolBarProps: {
57
+ customLink: (0, jsx_runtime_1.jsx)(Media_1.Link.triggerButton, { color: "default", onClick: () => setOpenLink(true) }, Media_1.Link.name),
58
+ uploadImage: false,
59
+ uploadFile: true
60
+ } })), openLink && ((0, jsx_runtime_1.jsx)(UrlTextField_1.default, { inputRef: linkInputRef, className: classes.link, id: "page", name: "page", label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.media.link.add.label", defaultMessage: "ui.composer.media.link.add.label" }), fullWidth: true, variant: "outlined", placeholder: "https://", onSuccess: handleLinkAdd, InputProps: {
61
+ endAdornment: ((0, jsx_runtime_1.jsx)(material_1.InputAdornment, Object.assign({ position: "end" }, { children: (0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ onClick: () => setOpenLink(false) }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "close" }) })) })))
62
+ } })), medias && medias.length > 0 && ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.medias }, { children: mediaObjectTypes.map((mediaObjectType) => {
63
+ if (mediaObjectType.previewComponent) {
64
+ return (0, jsx_runtime_1.jsx)(mediaObjectType.previewComponent, { value: medias, onChange: handleChangeMedias }, mediaObjectType.name);
65
+ }
66
+ }) })))] })));
36
67
  };
@@ -96,11 +96,11 @@ function Comments(props) {
96
96
  map.set(name, [...map.get(name), comment]);
97
97
  }
98
98
  });
99
- return Array.from(map.entries()).map(([name, comments]) => ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.outerWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h5" }, { children: name })), (0, jsx_runtime_1.jsx)(material_1.Divider, {}), (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.innerWrapper }, { children: [comments.map((comment) => ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.userWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { src: comment.created_by.avatar, alt: comment.created_by.username, className: classes.avatar }), (0, jsx_runtime_1.jsxs)(material_1.Box, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.userInfo }, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: comment.created_by.username })), (0, jsx_runtime_1.jsx)(material_1.Box, { className: classes.circle }), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: new Date(comment.created_at).toLocaleDateString() }))] })), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: comment.html }))] })] }), comment.id))), (0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.COURSE_ROUTE_NAME, course), size: "small", variant: "outlined", color: "inherit", className: classes.button }, { 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.course.dashboard.teacher.tab.comments.lessons.btn.label", defaultMessage: "ui.course.dashboard.teacher.tab.comments.lessons.btn.label" }) })) }))] }))] }), name)));
99
+ return Array.from(map.entries()).map(([name, comments]) => ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.outerWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "h5" }, { children: name })), (0, jsx_runtime_1.jsx)(material_1.Divider, {}), (0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.innerWrapper }, { children: [comments.map((comment) => ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.userWrapper }, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { src: comment.created_by.avatar, alt: comment.created_by.username, className: classes.avatar }), (0, jsx_runtime_1.jsxs)(material_1.Box, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.userInfo }, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body1" }, { children: comment.created_by.username })), (0, jsx_runtime_1.jsx)(material_1.Box, { className: classes.circle }), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: new Date(comment.created_at).toLocaleDateString() }))] })), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body1", component: "div", dangerouslySetInnerHTML: { __html: comment.html } })] })] }), comment.id))), (0, jsx_runtime_1.jsx)(material_1.Button, Object.assign({ component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.COURSE_ROUTE_NAME, course), size: "small", variant: "outlined", color: "inherit", className: classes.button }, { 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.course.dashboard.teacher.tab.comments.lessons.btn.label", defaultMessage: "ui.course.dashboard.teacher.tab.comments.lessons.btn.label" }) })) }))] }))] }), name)));
100
100
  }, [state.results]);
101
101
  if (!state.initialized) {
102
102
  return (0, jsx_runtime_1.jsx)(CommentsSkeleton, {});
103
103
  }
104
- return ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ className: classes.container }, { 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.course.dashboard.teacher.tab.comments.number", defaultMessage: "ui.course.dashboard.teacher.tab.comments.number", values: { commentsNumber: state.count } }) })), renderComments, isLoadingComments && (0, jsx_runtime_1.jsx)(CommentSkeleton, { id: 1 }), state.results.length > 0 && ((0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ size: "small", variant: "outlined", color: "inherit", loading: isLoadingComments, disabled: !state.next, 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.course.dashboard.teacher.tab.comments.btn.label", defaultMessage: "ui.course.dashboard.teacher.tab.comments.btn.label" }) })) })))] })));
104
+ return ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.container }, { children: state.count > 0 ? ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { 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.course.dashboard.teacher.tab.comments.number", defaultMessage: "ui.course.dashboard.teacher.tab.comments.number", values: { commentsNumber: state.count } }) })), renderComments, isLoadingComments && (0, jsx_runtime_1.jsx)(CommentSkeleton, { id: 1 }), (0, jsx_runtime_1.jsx)(lab_1.LoadingButton, Object.assign({ size: "small", variant: "outlined", color: "inherit", loading: isLoadingComments, disabled: !state.next, 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.course.dashboard.teacher.tab.comments.btn.label", defaultMessage: "ui.course.dashboard.teacher.tab.comments.btn.label" }) })) }))] })) : ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.course.dashboard.teacher.tab.comments.empty", defaultMessage: "ui.course.dashboard.teacher.tab.comments.empty" }) }))) })));
105
105
  }
106
106
  exports.default = (0, react_1.memo)(Comments);
@@ -138,7 +138,7 @@ function CourseParticipantsButton(inProps) {
138
138
  /**
139
139
  * Rendering
140
140
  */
141
- if (!participantsAvailable || !scCourse.privacy) {
141
+ if (!participantsAvailable) {
142
142
  return (0, jsx_runtime_1.jsx)(HiddenPlaceholder_1.default, {});
143
143
  }
144
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,
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
+ import { MediaPluginProps } from './plugins';
3
+ import { ToolbarPluginProps } from './plugins/ToolbarPlugin';
2
4
  import { SCMediaType } from '@selfcommunity/types';
3
5
  export declare type EditorRef = {
4
6
  focus: () => void;
@@ -48,7 +50,17 @@ export interface EditorProps {
48
50
  * Handler for change media in the editor
49
51
  * @default null
50
52
  * */
51
- onMediaChange?: (medias: SCMediaType[]) => void;
53
+ onMediaChange?: (media: SCMediaType) => void;
54
+ /**
55
+ * Props to spread to ToolBar.
56
+ * @default {}
57
+ */
58
+ ToolBarProps?: ToolbarPluginProps;
59
+ /**
60
+ * Props to spread to MediaPlugin.
61
+ * @default {}
62
+ */
63
+ MediaPluginProps?: MediaPluginProps;
52
64
  /**
53
65
  * Handler for blur event of the editor
54
66
  * @default null
@@ -70,8 +70,7 @@ const editorTheme = {
70
70
  superscript: `${constants_1.PREFIX}-textSuperscript`,
71
71
  underline: `${constants_1.PREFIX}-textUnderline`,
72
72
  underlineStrikethrough: `${constants_1.PREFIX}-textUnderlineStrikethrough`
73
- },
74
- document: `${constants_1.PREFIX}-document`
73
+ }
75
74
  };
76
75
  /**
77
76
  * > API documentation for the Community-JS Editor component. Learn about the available props and the CSS API.
@@ -108,7 +107,7 @@ const Editor = (inProps, ref) => {
108
107
  props: inProps,
109
108
  name: constants_1.PREFIX
110
109
  });
111
- const { id = 'editor', className = null, defaultValue = '', toolbar = false, uploadImage = false, uploadFile = false, editable = true, onChange = null, onMediaChange = null, onFocus = null, onBlur = null, action = null, placeholder = (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editor.placeholder", defaultMessage: "ui.editor.placeholder" }) } = props;
110
+ const { id = 'editor', className = null, defaultValue = '', toolbar = false, uploadImage = false, uploadFile = false, editable = true, onChange = null, onMediaChange = null, onFocus = null, onBlur = null, action = null, ToolBarProps = {}, MediaPluginProps = {}, placeholder = (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editor.placeholder", defaultMessage: "ui.editor.placeholder" }) } = props;
112
111
  const apiRef = (0, react_1.useRef)();
113
112
  // STATE
114
113
  const [focused, setFocused] = (0, react_1.useState)(false);
@@ -149,6 +148,6 @@ const Editor = (inProps, ref) => {
149
148
  nodes: [...nodes_1.default],
150
149
  theme: editorTheme
151
150
  }), [editable]);
152
- return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ id: id, className: (0, classnames_1.default)(classes.root, className, { [classes.toolbar]: toolbar, [classes.focused]: focused }) }, { children: (0, jsx_runtime_1.jsxs)(LexicalComposer_1.LexicalComposer, Object.assign({ initialConfig: initialConfig }, { children: [toolbar ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ToolbarPlugin_1.default, { uploadImage: uploadImage, uploadFile: uploadFile, MediaPluginProps: { onMediaAdd: handleMediaChange } }), (0, jsx_runtime_1.jsx)(LexicalListPlugin_1.ListPlugin, {}), (0, jsx_runtime_1.jsx)(LexicalHorizontalRulePlugin_1.HorizontalRulePlugin, {})] })) : ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.actions, direction: "row" }, { children: [uploadImage && (0, jsx_runtime_1.jsx)(plugins_1.ImagePlugin, {}), uploadFile && (0, jsx_runtime_1.jsx)(plugins_1.MediaPlugin, { onMediaAdd: handleMediaChange }), (0, jsx_runtime_1.jsx)(plugins_1.EmojiPlugin, {}), action && action] }))), (0, jsx_runtime_1.jsx)(LexicalRichTextPlugin_1.RichTextPlugin, { contentEditable: (0, jsx_runtime_1.jsx)(LexicalContentEditable_1.ContentEditable, { className: classes.content }), placeholder: (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.placeholder, onClick: handleFocus }, { children: placeholder })), ErrorBoundary: LexicalErrorBoundary_1.default }), (0, jsx_runtime_1.jsx)(plugins_1.DefaultHtmlValuePlugin, { defaultValue: defaultValue }), (0, jsx_runtime_1.jsx)(LexicalHistoryPlugin_1.HistoryPlugin, {}), (0, jsx_runtime_1.jsx)(plugins_1.OnChangePlugin, { onChange: handleChange }), (0, jsx_runtime_1.jsx)(OnBlurPlugin_1.default, { onBlur: handleHasBlur }), (0, jsx_runtime_1.jsx)(OnFocusPlugin_1.default, { onFocus: handleHasFocus }), (0, jsx_runtime_1.jsx)(plugins_1.AutoLinkPlugin, {}), (0, jsx_runtime_1.jsx)(plugins_1.MentionsPlugin, {}), (0, jsx_runtime_1.jsx)(LexicalLinkPlugin_1.LinkPlugin, {}), (0, jsx_runtime_1.jsx)(FloatingLinkPlugin_1.default, {}), (0, jsx_runtime_1.jsx)(ApiPlugin_1.default, { ref: apiRef })] })) })));
151
+ return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ id: id, className: (0, classnames_1.default)(classes.root, className, { [classes.toolbar]: toolbar, [classes.focused]: focused }) }, { children: (0, jsx_runtime_1.jsxs)(LexicalComposer_1.LexicalComposer, Object.assign({ initialConfig: initialConfig }, { children: [toolbar ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ToolbarPlugin_1.default, Object.assign({ uploadImage: uploadImage, uploadFile: uploadFile, MediaPluginProps: { onMediaAdd: handleMediaChange } }, ToolBarProps)), (0, jsx_runtime_1.jsx)(LexicalListPlugin_1.ListPlugin, {}), (0, jsx_runtime_1.jsx)(LexicalHorizontalRulePlugin_1.HorizontalRulePlugin, {})] })) : ((0, jsx_runtime_1.jsxs)(material_1.Stack, Object.assign({ className: classes.actions, direction: "row" }, { children: [uploadImage && (0, jsx_runtime_1.jsx)(plugins_1.ImagePlugin, {}), uploadFile && (0, jsx_runtime_1.jsx)(plugins_1.MediaPlugin, Object.assign({}, MediaPluginProps)), (0, jsx_runtime_1.jsx)(plugins_1.EmojiPlugin, {}), action && action] }))), (0, jsx_runtime_1.jsx)(LexicalRichTextPlugin_1.RichTextPlugin, { contentEditable: (0, jsx_runtime_1.jsx)(LexicalContentEditable_1.ContentEditable, { className: classes.content }), placeholder: (0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.placeholder, onClick: handleFocus }, { children: placeholder })), ErrorBoundary: LexicalErrorBoundary_1.default }), (0, jsx_runtime_1.jsx)(plugins_1.DefaultHtmlValuePlugin, { defaultValue: defaultValue }), (0, jsx_runtime_1.jsx)(LexicalHistoryPlugin_1.HistoryPlugin, {}), (0, jsx_runtime_1.jsx)(plugins_1.OnChangePlugin, { onChange: handleChange }), (0, jsx_runtime_1.jsx)(OnBlurPlugin_1.default, { onBlur: handleHasBlur }), (0, jsx_runtime_1.jsx)(OnFocusPlugin_1.default, { onFocus: handleHasFocus }), (0, jsx_runtime_1.jsx)(plugins_1.AutoLinkPlugin, {}), (0, jsx_runtime_1.jsx)(plugins_1.MentionsPlugin, {}), (0, jsx_runtime_1.jsx)(LexicalLinkPlugin_1.LinkPlugin, {}), (0, jsx_runtime_1.jsx)(FloatingLinkPlugin_1.default, {}), (0, jsx_runtime_1.jsx)(ApiPlugin_1.default, { ref: apiRef })] })) })));
153
152
  };
154
153
  exports.default = (0, react_1.forwardRef)(Editor);
@@ -5,6 +5,5 @@ import { ImageNode } from './ImageNode';
5
5
  import { MentionNode } from './MentionNode';
6
6
  import { TextNode } from 'lexical';
7
7
  import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
8
- import { DocNode } from './DocNode';
9
- declare const nodes: (typeof ImageNode | typeof TextNode | typeof MentionNode | typeof DocNode | typeof HorizontalRuleNode | typeof HeadingNode | typeof ListNode | typeof ListItemNode | typeof QuoteNode | typeof LinkNode)[];
8
+ declare const nodes: (typeof ImageNode | typeof TextNode | typeof MentionNode | typeof HorizontalRuleNode | typeof HeadingNode | typeof ListNode | typeof ListItemNode | typeof QuoteNode | typeof LinkNode)[];
10
9
  export default nodes;
@@ -7,7 +7,6 @@ const ImageNode_1 = require("./ImageNode");
7
7
  const MentionNode_1 = require("./MentionNode");
8
8
  const lexical_1 = require("lexical");
9
9
  const LexicalHorizontalRuleNode_1 = require("@lexical/react/LexicalHorizontalRuleNode");
10
- const DocNode_1 = require("./DocNode");
11
10
  const nodes = [
12
11
  LexicalHorizontalRuleNode_1.HorizontalRuleNode,
13
12
  rich_text_1.HeadingNode,
@@ -19,7 +18,6 @@ const nodes = [
19
18
  link_1.AutoLinkNode,
20
19
  link_1.LinkNode,
21
20
  ImageNode_1.ImageNode,
22
- MentionNode_1.MentionNode,
23
- DocNode_1.DocNode
21
+ MentionNode_1.MentionNode
24
22
  ];
25
23
  exports.default = nodes;
@@ -8,6 +8,7 @@ export interface InsertDocPayload {
8
8
  export declare const INSERT_DOC_COMMAND: LexicalCommand<InsertDocPayload>;
9
9
  export interface MediaPluginProps {
10
10
  className?: string;
11
- onMediaAdd?: (medias: SCMediaType[]) => void | null;
11
+ onMediaAdd?: (media: SCMediaType) => void | null;
12
+ isUploading?: (boolean: any) => void;
12
13
  }
13
14
  export default function MediaPlugin(props: MediaPluginProps): JSX.Element;
@@ -17,7 +17,6 @@ const upload_button_1 = require("@rpldy/upload-button");
17
17
  const notistack_1 = require("notistack");
18
18
  const ImageNode_1 = require("../nodes/ImageNode");
19
19
  const constants_1 = require("../constants");
20
- const DocNode_1 = require("../nodes/DocNode");
21
20
  const ImagePlugin_1 = require("./ImagePlugin");
22
21
  const classnames_1 = tslib_1.__importDefault(require("classnames"));
23
22
  exports.INSERT_DOC_COMMAND = (0, lexical_1.createCommand)();
@@ -34,11 +33,10 @@ const Root = (0, styles_1.styled)(material_1.Box, {
34
33
  })(() => ({}));
35
34
  function MediaPlugin(props) {
36
35
  var _a;
37
- const { className = '', onMediaAdd = null } = props;
36
+ const { className = '', onMediaAdd = null, isUploading } = props;
38
37
  // STATE
39
38
  const [uploading, setUploading] = (0, react_1.useState)({});
40
39
  const [mediaType, setMediaType] = (0, react_1.useState)('');
41
- const [uploadedMedia, setUploadedMedia] = (0, react_1.useState)([]);
42
40
  const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
43
41
  // CONTEXT
44
42
  const scContext = (0, react_core_1.useSCContext)();
@@ -64,27 +62,6 @@ function MediaPlugin(props) {
64
62
  return true;
65
63
  }, lexical_1.COMMAND_PRIORITY_EDITOR);
66
64
  }, [editor]);
67
- (0, react_1.useEffect)(() => {
68
- // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
69
- // @ts-ignore
70
- if (!editor.hasNodes([DocNode_1.DocNode])) {
71
- return;
72
- }
73
- editor.registerCommand(exports.INSERT_DOC_COMMAND, (payload) => {
74
- const docNode = (0, DocNode_1.$createDocNode)({
75
- src: payload.src,
76
- name: payload.name,
77
- type: payload.type
78
- });
79
- (0, utils_1.$insertNodeToNearestRoot)(docNode);
80
- return true;
81
- }, lexical_1.COMMAND_PRIORITY_EDITOR);
82
- }, [editor]);
83
- (0, react_1.useEffect)(() => {
84
- if (uploadedMedia.length > 0) {
85
- onMediaAdd && onMediaAdd(uploadedMedia);
86
- }
87
- }, [uploadedMedia, onMediaAdd]);
88
65
  // HANDLERS
89
66
  const handleFileUploadFilter = (file) => {
90
67
  if (file.type.startsWith('image/')) {
@@ -114,11 +91,12 @@ function MediaPlugin(props) {
114
91
  };
115
92
  editor.focus();
116
93
  editor.dispatchCommand(exports.INSERT_DOC_COMMAND, data);
117
- setUploadedMedia((prev) => [...prev, media]);
94
+ onMediaAdd && onMediaAdd(media);
118
95
  }
119
96
  };
120
97
  const handleUploadProgress = (chunks) => {
121
98
  setUploading(Object.assign({}, chunks));
99
+ isUploading && isUploading(Object.keys(chunks).length !== 0);
122
100
  };
123
101
  const handleUploadError = (chunk, error) => {
124
102
  enqueueSnackbar(error, {
@@ -128,14 +106,14 @@ function MediaPlugin(props) {
128
106
  };
129
107
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
130
108
  // @ts-ignore
131
- if (!scUserContext.user || !editor.hasNodes([ImageNode_1.ImageNode, DocNode_1.DocNode])) {
109
+ if (!scUserContext.user || !editor.hasNodes([ImageNode_1.ImageNode])) {
132
110
  return null;
133
111
  }
134
112
  return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, { children: (0, jsx_runtime_1.jsxs)(chunked_uploady_1.default, Object.assign({ destination: {
135
113
  url: `${scContext.settings.portal}${api_services_1.Endpoints.ComposerChunkUploadMedia.url()}`,
136
114
  headers: ((_a = scContext.settings.session) === null || _a === void 0 ? void 0 : _a.authToken) ? { Authorization: `Bearer ${scContext.settings.session.authToken.accessToken}` } : {},
137
115
  method: api_services_1.Endpoints.ComposerChunkUploadMedia.method
138
- }, chunkSize: 204800, accept: "image/*,application/*", fileFilter: handleFileUploadFilter }, { children: [(0, jsx_runtime_1.jsx)(MediaChunkUploader_1.default, { type: mediaType, onSuccess: handleUploadSuccess, onProgress: handleUploadProgress, onError: handleUploadError }), (0, jsx_runtime_1.jsx)(UploadButton, { className: className, extraProps: {
116
+ }, chunkSize: 204800, accept: "image/*,application/*", fileFilter: handleFileUploadFilter, multiple: true }, { children: [(0, jsx_runtime_1.jsx)(MediaChunkUploader_1.default, { type: mediaType, onSuccess: handleUploadSuccess, onProgress: handleUploadProgress, onError: handleUploadError }), (0, jsx_runtime_1.jsx)(UploadButton, { className: className, extraProps: {
139
117
  disabled: Object.keys(uploading).length !== 0,
140
118
  progress: Object.keys(uploading).length !== 0 ? Object.values(uploading)[0].completed : null
141
119
  } })] })) })));
@@ -5,10 +5,12 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  */
8
+ import * as React from 'react';
8
9
  import { MediaPluginProps } from './MediaPlugin';
9
10
  export interface ToolbarPluginProps {
10
11
  uploadImage: boolean;
11
12
  uploadFile?: boolean;
12
13
  MediaPluginProps?: MediaPluginProps;
14
+ customLink?: React.ReactNode;
13
15
  }
14
16
  export default function ToolbarPlugin(inProps: ToolbarPluginProps): JSX.Element;
@@ -129,7 +129,7 @@ function ToolbarPlugin(inProps) {
129
129
  props: inProps,
130
130
  name: constants_1.PREFIX
131
131
  });
132
- const { uploadImage = false, uploadFile = false, MediaPluginProps = {} } = props;
132
+ const { uploadImage = false, uploadFile = false, MediaPluginProps = {}, customLink = null } = props;
133
133
  // STATE
134
134
  const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
135
135
  const [activeEditor, setActiveEditor] = (0, react_1.useState)(editor);
@@ -272,6 +272,6 @@ function ToolbarPlugin(inProps) {
272
272
  activeEditor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, format);
273
273
  } }, { children: (0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.editor.toolbarPlugin.${format}`, defaultMessage: `ui.editor.toolbarPlugin.${format}` }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: `format_${format}` }) })) }), format))) })), (0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ disabled: !isEditable, onClick: clearFormatting }, { children: (0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editor.toolbarPlugin.clear", defaultMessage: "ui.editor.toolbarPlugin.clear" }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "format_clear" }) })) })), (0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ disabled: !isEditable, onClick: () => {
274
274
  activeEditor.dispatchCommand(LexicalHorizontalRuleNode_1.INSERT_HORIZONTAL_RULE_COMMAND, undefined);
275
- } }, { children: (0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editor.toolbarPlugin.horizontalRule", defaultMessage: "ui.editor.toolbarPlugin.horizontalRule" }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "format_horizontal_rule" }) })) })), uploadImage && (0, jsx_runtime_1.jsx)(ImagePlugin_1.default, {}), uploadFile && (0, jsx_runtime_1.jsx)(MediaPlugin_1.default, Object.assign({}, MediaPluginProps)), (0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ disabled: !isEditable, onClick: insertLink }, { children: (0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editor.toolbarPlugin.link", defaultMessage: "ui.editor.toolbarPlugin.link" }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "format_link" }) })) })), (0, jsx_runtime_1.jsx)(EmojiPlugin_1.default, {})] })));
275
+ } }, { children: (0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editor.toolbarPlugin.horizontalRule", defaultMessage: "ui.editor.toolbarPlugin.horizontalRule" }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "format_horizontal_rule" }) })) })), uploadImage && (0, jsx_runtime_1.jsx)(ImagePlugin_1.default, {}), uploadFile && (0, jsx_runtime_1.jsx)(MediaPlugin_1.default, Object.assign({}, MediaPluginProps)), customLink !== null && customLink !== void 0 ? customLink : ((0, jsx_runtime_1.jsx)(material_1.IconButton, Object.assign({ disabled: !isEditable, onClick: insertLink }, { children: (0, jsx_runtime_1.jsx)(material_1.Tooltip, Object.assign({ title: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.editor.toolbarPlugin.link", defaultMessage: "ui.editor.toolbarPlugin.link" }) }, { children: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "format_link" }) })) }))), (0, jsx_runtime_1.jsx)(EmojiPlugin_1.default, {})] })));
276
276
  }
277
277
  exports.default = ToolbarPlugin;
@@ -85,6 +85,7 @@ export interface LessonCommentObjectProps {
85
85
  |author|.SCCommentObject-author|Styles applied to the author section.|
86
86
  |content|.SCCommentObject-content|Styles applied to content section.|
87
87
  |textContent|.SCCommentObject-text-content|Styles applied to text content section.|
88
+ |mediaContent|.SCCommentObject-media-content|Styles applied to media content section.|
88
89
  |commentActionsMenu|.SCCommentObject-comment-actions-menu|Styles applied to comment action menu element.|
89
90
 
90
91
 
@@ -24,6 +24,7 @@ const UserDeletedSnackBar_1 = tslib_1.__importDefault(require("../../shared/User
24
24
  const UserAvatar_1 = tslib_1.__importDefault(require("../../shared/UserAvatar"));
25
25
  const constants_1 = require("./constants");
26
26
  const LessonCommentActionsMenu_1 = tslib_1.__importDefault(require("../../shared/LessonCommentActionsMenu"));
27
+ const LessonFilePreview_1 = tslib_1.__importDefault(require("../../shared/LessonFilePreview"));
27
28
  const classes = {
28
29
  root: `${constants_1.PREFIX}-root`,
29
30
  comment: `${constants_1.PREFIX}-comment`,
@@ -31,6 +32,7 @@ const classes = {
31
32
  content: `${constants_1.PREFIX}-content`,
32
33
  author: `${constants_1.PREFIX}-author`,
33
34
  textContent: `${constants_1.PREFIX}-text-content`,
35
+ mediaContent: `${constants_1.PREFIX}-media-content`,
34
36
  commentActionsMenu: `${constants_1.PREFIX}-comment-actions-menu`
35
37
  };
36
38
  const Root = (0, styles_1.styled)(material_1.Box, {
@@ -65,6 +67,7 @@ const Root = (0, styles_1.styled)(material_1.Box, {
65
67
  |author|.SCCommentObject-author|Styles applied to the author section.|
66
68
  |content|.SCCommentObject-content|Styles applied to content section.|
67
69
  |textContent|.SCCommentObject-text-content|Styles applied to text content section.|
70
+ |mediaContent|.SCCommentObject-media-content|Styles applied to media content section.|
68
71
  |commentActionsMenu|.SCCommentObject-comment-actions-menu|Styles applied to comment action menu element.|
69
72
 
70
73
 
@@ -154,7 +157,8 @@ function LessonCommentObject(inProps) {
154
157
  const newObj = Object.assign({}, obj, {
155
158
  text: data.text,
156
159
  html: data.html,
157
- created_at: data.created_at
160
+ created_at: data.created_at,
161
+ medias: medias
158
162
  });
159
163
  updateObject(newObj);
160
164
  setEditComment(null);
@@ -181,7 +185,9 @@ function LessonCommentObject(inProps) {
181
185
  return null;
182
186
  }
183
187
  const summaryHtml = (0, contribution_1.getCommentContributionHtml)(comment.html, scRoutingContext.url);
184
- 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 } })] }), 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));
188
+ 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
+ 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
191
  }
186
192
  /**
187
193
  * Render comments
@@ -105,6 +105,11 @@ function LessonCommentObjects(inProps) {
105
105
  var _a;
106
106
  (_a = commentsEndRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ block: 'end', behavior: 'instant' });
107
107
  };
108
+ (0, react_1.useEffect)(() => {
109
+ if (commentsObject.comments.length > 0) {
110
+ scrollToBottom();
111
+ }
112
+ }, [commentsObject.comments]);
108
113
  /**
109
114
  * Perform save/update comment
110
115
  */
@@ -140,7 +145,6 @@ function LessonCommentObjects(inProps) {
140
145
  handleCommentsUpdate(data);
141
146
  setReplyKey(comment.id);
142
147
  setIsCommenting(false);
143
- scrollToBottom();
144
148
  })
145
149
  .catch((error) => {
146
150
  utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
@@ -14,12 +14,16 @@ const contribution_1 = require("../../utils/contribution");
14
14
  const Widget_1 = tslib_1.__importDefault(require("../Widget"));
15
15
  const ContentLesson_1 = tslib_1.__importDefault(require("../Composer/Content/ContentLesson"));
16
16
  const HiddenPlaceholder_1 = tslib_1.__importDefault(require("../../shared/HiddenPlaceholder"));
17
+ const DisplayComponent_1 = tslib_1.__importDefault(require("../../shared/Media/Link/DisplayComponent"));
18
+ const LessonFilePreview_1 = tslib_1.__importDefault(require("../../shared/LessonFilePreview"));
19
+ const api_services_1 = require("@selfcommunity/api-services");
17
20
  const classes = {
18
21
  root: `${constants_1.PREFIX}-root`,
19
22
  content: `${constants_1.PREFIX}-content`,
20
23
  contentEdit: `${constants_1.PREFIX}-content-edit`,
21
24
  title: `${constants_1.PREFIX}-title`,
22
25
  text: `${constants_1.PREFIX}-text`,
26
+ mediasSection: `${constants_1.PREFIX}-medias-section`,
23
27
  navigation: `${constants_1.PREFIX}-navigation`,
24
28
  editor: `${constants_1.PREFIX}-editor`
25
29
  };
@@ -54,8 +58,8 @@ function LessonObject(inProps) {
54
58
  }
55
59
  return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root) }, rest, { children: (0, jsx_runtime_1.jsx)(Widget_1.default, { children: (0, jsx_runtime_1.jsx)(CardContent_1.default, Object.assign({ classes: { root: editMode ? classes.contentEdit : classes.content } }, { children: editMode ? ((0, jsx_runtime_1.jsx)(ContentLesson_1.default, { value: lesson,
56
60
  //error={{error}}
57
- onChange: handleChangeLesson, onMediaChange: handleChangeMedia, disabled: isSubmitting, EditorProps: Object.assign({ toolbar: true, uploadImage: false, uploadFile: true }, EditorProps) })) : ((0, jsx_runtime_1.jsx)(material_1.Typography, { component: "div", gutterBottom: true, className: classes.text, dangerouslySetInnerHTML: {
58
- __html: (0, contribution_1.getContributionHtml)(lesson.html, scRoutingContext.url)
59
- } })) })) }) })));
61
+ onChange: handleChangeLesson, onMediaChange: handleChangeMedia, disabled: isSubmitting, EditorProps: Object.assign({ toolbar: true }, EditorProps) })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { component: "div", gutterBottom: true, className: classes.text, dangerouslySetInnerHTML: {
62
+ __html: (0, contribution_1.getContributionHtml)(lesson.html, scRoutingContext.url)
63
+ } }), lesson.medias && lesson.medias.length > 0 && ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.mediasSection }, { children: lesson.medias.map((media) => media.type === api_services_1.MediaTypes.URL ? ((0, jsx_runtime_1.jsx)(DisplayComponent_1.default, { medias: [media] }, media.id)) : ((0, jsx_runtime_1.jsx)(LessonFilePreview_1.default, { media: media }, media.id))) })))] })) })) }) })));
60
64
  }
61
65
  exports.default = LessonObject;
@@ -10,7 +10,8 @@ const types_1 = require("@selfcommunity/types");
10
10
  const constants_1 = require("./constants");
11
11
  const Skeleton_1 = tslib_1.__importDefault(require("./Skeleton"));
12
12
  const classes = {
13
- root: `${constants_1.PREFIX}-skeleton-root`,
13
+ root: `${constants_1.PREFIX}-root`,
14
+ empty: `${constants_1.PREFIX}-empty`,
14
15
  accordion: `${constants_1.PREFIX}-accordion`,
15
16
  summary: `${constants_1.PREFIX}-summary`,
16
17
  details: `${constants_1.PREFIX}-details`,
@@ -41,8 +42,8 @@ function AccordionLessons(inProps) {
41
42
  if (!course) {
42
43
  return (0, jsx_runtime_1.jsx)(Skeleton_1.default, {});
43
44
  }
44
- return ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: ((_a = course.sections) === null || _a === void 0 ? void 0 : _a.length) > 0 ? ((0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, { children: 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: {
45
- lessonsNumber: section.lessons.length
46
- } }) })))] })), 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" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.course.accordionLessons.empty", defaultMessage: "ui.course.accordionLessons.empty" }) }))) }));
45
+ 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
+ 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" }) }))) })));
47
48
  }
48
49
  exports.default = AccordionLessons;
@@ -0,0 +1,12 @@
1
+ export interface LessonFilePreviewProps {
2
+ /**
3
+ * Overrides or extends the styles applied to the component.
4
+ * @default null
5
+ */
6
+ className?: string;
7
+ /**
8
+ * The media object to show
9
+ */
10
+ media: any;
11
+ }
12
+ export default function LessonFilePreview(props: LessonFilePreviewProps): JSX.Element;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const styles_1 = require("@mui/material/styles");
6
+ const classnames_1 = tslib_1.__importDefault(require("classnames"));
7
+ const material_1 = require("@mui/material");
8
+ const Icon_1 = tslib_1.__importDefault(require("@mui/material/Icon"));
9
+ const Media_1 = require("../../constants/Media");
10
+ const PREFIX = 'SCLessonFilePreview';
11
+ const classes = {
12
+ root: `${PREFIX}-root`,
13
+ item: `${PREFIX}-item`,
14
+ title: `${PREFIX}-title`
15
+ };
16
+ const Root = (0, styles_1.styled)(material_1.Box, {
17
+ name: PREFIX,
18
+ slot: 'Root',
19
+ overridesResolver: (props, styles) => styles.root
20
+ })(() => ({}));
21
+ function LessonFilePreview(props) {
22
+ // PROPS
23
+ const { className, media } = props;
24
+ /**
25
+ * Renders component
26
+ */
27
+ return ((0, jsx_runtime_1.jsx)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className), sx: { backgroundImage: `url(${(media === null || media === void 0 ? void 0 : media.image_thumbnail) ? media.image_thumbnail.url : media.image})` } }, { children: media.title && ((0, jsx_runtime_1.jsx)(material_1.Link, Object.assign({ href: media.url, target: "_blank", rel: "noopener noreferrer" }, { children: (0, jsx_runtime_1.jsxs)(material_1.Typography, Object.assign({ className: classes.title }, { children: [media.type === Media_1.MEDIA_TYPE_DOCUMENT && (0, jsx_runtime_1.jsx)(Icon_1.default, { children: "picture_as_pdf" }), media.title] })) }))) }), media.id));
28
+ }
29
+ exports.default = LessonFilePreview;
@@ -16,6 +16,7 @@ const INITIAL_STATE = {
16
16
  urlError: null
17
17
  };
18
18
  exports.default = (props) => {
19
+ var _a, _b;
19
20
  // STATE
20
21
  const [isCreating, setIsCreating] = (0, react_1.useState)(false);
21
22
  const [state, setState] = (0, react_1.useState)(Object.assign({}, INITIAL_STATE));
@@ -75,7 +76,5 @@ exports.default = (props) => {
75
76
  * Renders url text field
76
77
  */
77
78
  return ((0, jsx_runtime_1.jsx)("form", Object.assign({ method: "post", onSubmit: handleSubmit }, { children: (0, jsx_runtime_1.jsx)(TextField_1.default, Object.assign({ value: url, type: "url", onChange: handleChange, onPaste: handlePaste, error: error || Boolean(urlError), helperText: helperText ||
78
- (urlError && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.composer.media.link.add.error.${urlError}`, defaultMessage: `ui.composer.media.link.add.error.${urlError}` }))) || (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.media.link.add.help", defaultMessage: "ui.composer.media.link.add.help" }), disabled: isCreating }, rest, { InputProps: {
79
- endAdornment: ((0, jsx_runtime_1.jsx)(InputAdornment_1.default, Object.assign({ position: "end" }, { children: (0, jsx_runtime_1.jsx)(material_1.Fade, Object.assign({ in: urlError === null && url !== '' }, { children: (0, jsx_runtime_1.jsx)(IconButton_1.default, Object.assign({ size: "small", disabled: isCreating, type: "submit" }, { children: isCreating ? (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { color: "primary", size: 20 }) : (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.media.link.add.submit", defaultMessage: "ui.composer.media.link.add.submit" }) })) })) })))
80
- } })) })));
79
+ (urlError && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: `ui.composer.media.link.add.error.${urlError}`, defaultMessage: `ui.composer.media.link.add.error.${urlError}` }))) || (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.media.link.add.help", defaultMessage: "ui.composer.media.link.add.help" }), disabled: isCreating }, rest, { InputProps: Object.assign(Object.assign({}, rest.InputProps), { endAdornment: ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: url === '' && ((_a = rest.InputProps) === null || _a === void 0 ? void 0 : _a.endAdornment) ? ((_b = rest.InputProps) === null || _b === void 0 ? void 0 : _b.endAdornment) : ((0, jsx_runtime_1.jsx)(InputAdornment_1.default, Object.assign({ position: "end" }, { children: (0, jsx_runtime_1.jsx)(material_1.Fade, Object.assign({ in: urlError === null && url !== '' }, { children: (0, jsx_runtime_1.jsx)(IconButton_1.default, Object.assign({ size: "small", disabled: isCreating, type: "submit" }, { children: isCreating ? ((0, jsx_runtime_1.jsx)(material_1.CircularProgress, { color: "primary", size: 20 })) : ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.media.link.add.submit", defaultMessage: "ui.composer.media.link.add.submit" })) })) })) }))) })) }) })) })));
81
80
  };