@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
@@ -12,10 +12,12 @@ import { LoadingButton } from '@mui/lab';
12
12
  import BaseItem from '../../shared/BaseItem';
13
13
  import UserAvatar from '../../shared/UserAvatar';
14
14
  import { useThemeProps } from '@mui/system';
15
+ import PreviewComponent from '../../shared/Media/File/PreviewComponent';
15
16
  const PREFIX = 'SCCommentObjectReply';
16
17
  const classes = {
17
18
  root: `${PREFIX}-root`,
18
19
  comment: `${PREFIX}-comment`,
20
+ media: `${PREFIX}-media`,
19
21
  hasValue: `${PREFIX}-has-value`,
20
22
  avatar: `${PREFIX}-avatar`,
21
23
  actions: `${PREFIX}-actions`,
@@ -68,7 +70,8 @@ export default function CommentObjectReply(inProps) {
68
70
  const scUserContext = useSCUser();
69
71
  // RETRIEVE OBJECTS
70
72
  const [html, setHtml] = useState(text);
71
- const [media, setMedia] = useState(medias);
73
+ const [media, setMedia] = useState(medias !== null && medias !== void 0 ? medias : []);
74
+ const [uploadingMedia, setUploadingMedia] = useState(false);
72
75
  // HOOKS
73
76
  const theme = useTheme();
74
77
  const isMobile = useMediaQuery(theme.breakpoints.down('md'));
@@ -113,8 +116,11 @@ export default function CommentObjectReply(inProps) {
113
116
  const handleChangeText = (value) => {
114
117
  setHtml(value);
115
118
  };
116
- const handleChangeMedia = (medias) => {
117
- setMedia(medias);
119
+ const handleChangeMedia = (value) => {
120
+ setMedia((prev) => [...prev, value]);
121
+ };
122
+ const handleChangeMedias = (value) => {
123
+ setMedia([...value]);
118
124
  };
119
125
  /**
120
126
  * Check if editor is empty
@@ -125,6 +131,6 @@ export default function CommentObjectReply(inProps) {
125
131
  }, [html]);
126
132
  // RENDER
127
133
  return (_jsx(Root, Object.assign({ id: id }, rest, { disableTypography: true, onClick: handleEditorFocus, elevation: elevation, className: classNames(classes.root, className), image: showAvatar &&
128
- (!scUserContext.user ? (_jsx(Avatar, { variant: "circular", className: classes.avatar })) : (_jsx(UserAvatar, Object.assign({ hide: !scUserContext.user.community_badge }, { children: _jsx(Avatar, { alt: scUserContext.user.username, variant: "circular", src: scUserContext.user.avatar, classes: { root: classes.avatar } }) })))), secondary: _jsxs(Widget, Object.assign({ className: classNames(classes.comment, { [classes.hasValue]: !isEditorEmpty }) }, WidgetProps, { children: [_jsx(Editor, Object.assign({ ref: editor, onChange: handleChangeText, onMediaChange: handleChangeMedia, defaultValue: html, editable: editable, uploadImage: true, action: replyIcon &&
129
- onReply && (_jsx(IconButton, Object.assign({ onClick: handleReply, className: classes.iconReply }, { children: _jsx(Icon, { children: "send" }) }))) }, EditorProps)), !isEditorEmpty && (_jsxs(Stack, Object.assign({ direction: "row", spacing: 2, className: classes.actions }, { children: [onReply && !replyIcon && (_jsx(LoadingButton, Object.assign({ variant: "outlined", size: "small", onClick: handleReply, loading: !editable, className: classes.buttonReply }, { children: _jsx(FormattedMessage, { id: "ui.commentObject.replyComment.reply", defaultMessage: "ui.commentObject.replyComment.reply" }) }))), onSave && (_jsxs(_Fragment, { children: [onCancel && (_jsx(LoadingButton, Object.assign({ variant: 'text', size: "small", onClick: handleCancel, disabled: !editable, color: "inherit", className: classes.buttonCancel }, { children: _jsx(FormattedMessage, { id: "ui.commentObject.replyComment.cancel", defaultMessage: "ui.commentObject.replyComment.cancel" }) }))), _jsx(LoadingButton, Object.assign({ variant: "outlined", size: "small", onClick: handleSave, loading: !editable, className: classes.buttonSave }, { children: _jsx(FormattedMessage, { id: "ui.commentObject.replyComment.save", defaultMessage: "ui.commentObject.replyComment.save" }) }))] }))] })))] })) })));
134
+ (!scUserContext.user ? (_jsx(Avatar, { variant: "circular", className: classes.avatar })) : (_jsx(UserAvatar, Object.assign({ hide: !scUserContext.user.community_badge }, { children: _jsx(Avatar, { alt: scUserContext.user.username, variant: "circular", src: scUserContext.user.avatar, classes: { root: classes.avatar } }) })))), secondary: _jsxs(Widget, Object.assign({ className: classNames(classes.comment, { [classes.hasValue]: !isEditorEmpty }) }, WidgetProps, { children: [media && media.length > 0 && _jsx(PreviewComponent, { value: media, onChange: handleChangeMedias, className: classes.media }), _jsx(Editor, Object.assign({ ref: editor, onChange: handleChangeText, defaultValue: html, editable: editable, uploadImage: true, action: replyIcon &&
135
+ onReply && (_jsx(IconButton, Object.assign({ onClick: handleReply, className: classes.iconReply, disabled: uploadingMedia }, { children: _jsx(Icon, { children: "send" }) }))) }, EditorProps, { MediaPluginProps: { isUploading: setUploadingMedia, onMediaAdd: handleChangeMedia } })), !isEditorEmpty && (_jsxs(Stack, Object.assign({ direction: "row", spacing: 2, className: classes.actions }, { children: [onReply && !replyIcon && (_jsx(LoadingButton, Object.assign({ variant: "outlined", size: "small", onClick: handleReply, loading: !editable, className: classes.buttonReply }, { children: _jsx(FormattedMessage, { id: "ui.commentObject.replyComment.reply", defaultMessage: "ui.commentObject.replyComment.reply" }) }))), onSave && (_jsxs(_Fragment, { children: [onCancel && (_jsx(LoadingButton, Object.assign({ variant: 'text', size: "small", onClick: handleCancel, disabled: !editable, color: "inherit", className: classes.buttonCancel }, { children: _jsx(FormattedMessage, { id: "ui.commentObject.replyComment.cancel", defaultMessage: "ui.commentObject.replyComment.cancel" }) }))), _jsx(LoadingButton, Object.assign({ variant: "outlined", size: "small", onClick: handleSave, loading: !editable, className: classes.buttonSave }, { children: _jsx(FormattedMessage, { id: "ui.commentObject.replyComment.save", defaultMessage: "ui.commentObject.replyComment.save" }) }))] }))] })))] })) })));
130
136
  }
@@ -1,17 +1,20 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback } from 'react';
3
- import { Box, Typography } from '@mui/material';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
+ import { Box, Icon, IconButton, InputAdornment, Typography } from '@mui/material';
4
4
  import { styled } from '@mui/material/styles';
5
5
  import classNames from 'classnames';
6
6
  import Editor from '../../../Editor';
7
7
  import { FormattedMessage } from 'react-intl';
8
8
  import { PREFIX } from '../../constants';
9
+ import { File, Link } from '../../../../shared/Media';
10
+ import UrlTextField from '../../../../shared/Media/Link/UrlTextField';
9
11
  const classes = {
10
12
  root: `${PREFIX}-content-lesson-root`,
11
13
  generalError: `${PREFIX}-general-error`,
12
14
  title: `${PREFIX}-content-lesson-title`,
13
15
  medias: `${PREFIX}-content-lesson-medias`,
14
- editor: `${PREFIX}-content-lesson-editor`
16
+ editor: `${PREFIX}-content-lesson-editor`,
17
+ link: `${PREFIX}-content-lesson-link`
15
18
  };
16
19
  const Root = styled(Box, {
17
20
  name: PREFIX,
@@ -21,13 +24,41 @@ export default (props) => {
21
24
  // PROPS
22
25
  const { className = null, value, error = {}, disabled = false, onChange, onMediaChange, EditorProps = {} } = props;
23
26
  const { error: generalError = null } = Object.assign({}, error);
27
+ const mediaObjectTypes = [File, Link];
28
+ const [medias, setMedias] = useState((value === null || value === void 0 ? void 0 : value.medias) || []);
29
+ const [openLink, setOpenLink] = useState();
30
+ const linkInputRef = useRef(null);
24
31
  // HANDLERS
25
32
  const handleChangeHtml = useCallback((html) => {
26
33
  onChange(html);
27
34
  }, [value]);
28
- const handleChangeMedia = useCallback((medias) => {
29
- onMediaChange(medias);
35
+ const handleChangeMedias = useCallback((value) => {
36
+ setMedias([...value]);
37
+ onMediaChange([...value]);
30
38
  }, []);
39
+ const handleChangeMedia = (value) => {
40
+ setMedias((prev) => [...prev, value]);
41
+ onMediaChange([...medias, value]);
42
+ };
43
+ const handleLinkAdd = useCallback((media) => {
44
+ setMedias([...medias, media]);
45
+ setOpenLink(false);
46
+ }, [medias]);
47
+ useEffect(() => {
48
+ if (openLink && linkInputRef.current) {
49
+ linkInputRef.current.scrollIntoView({ behavior: 'smooth' });
50
+ }
51
+ }, [openLink]);
31
52
  // RENDER
32
- return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, { children: [generalError && (_jsx(Typography, Object.assign({ className: classes.generalError }, { children: _jsx(FormattedMessage, { id: `ui.composer.error.${generalError}`, defaultMessage: `ui.composer.error.${generalError}` }) }))), _jsx(Editor, Object.assign({}, EditorProps, { editable: !disabled, className: classes.editor, onChange: handleChangeHtml, onMediaChange: handleChangeMedia, defaultValue: value.html }))] })));
53
+ return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, { children: [generalError && (_jsx(Typography, Object.assign({ className: classes.generalError }, { children: _jsx(FormattedMessage, { id: `ui.composer.error.${generalError}`, defaultMessage: `ui.composer.error.${generalError}` }) }))), _jsx(Editor, Object.assign({}, EditorProps, { editable: !disabled, className: classes.editor, onChange: handleChangeHtml, onMediaChange: handleChangeMedia, defaultValue: value.html, ToolBarProps: {
54
+ customLink: _jsx(Link.triggerButton, { color: "default", onClick: () => setOpenLink(true) }, Link.name),
55
+ uploadImage: false,
56
+ uploadFile: true
57
+ } })), openLink && (_jsx(UrlTextField, { inputRef: linkInputRef, className: classes.link, id: "page", name: "page", label: _jsx(FormattedMessage, { id: "ui.composer.media.link.add.label", defaultMessage: "ui.composer.media.link.add.label" }), fullWidth: true, variant: "outlined", placeholder: "https://", onSuccess: handleLinkAdd, InputProps: {
58
+ endAdornment: (_jsx(InputAdornment, Object.assign({ position: "end" }, { children: _jsx(IconButton, Object.assign({ onClick: () => setOpenLink(false) }, { children: _jsx(Icon, { children: "close" }) })) })))
59
+ } })), medias && medias.length > 0 && (_jsx(Box, Object.assign({ className: classes.medias }, { children: mediaObjectTypes.map((mediaObjectType) => {
60
+ if (mediaObjectType.previewComponent) {
61
+ return _jsx(mediaObjectType.previewComponent, { value: medias, onChange: handleChangeMedias }, mediaObjectType.name);
62
+ }
63
+ }) })))] })));
33
64
  };
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Avatar, Box, Button, Divider, Skeleton, Stack, Typography } from '@mui/material';
3
- import { memo, useCallback, useEffect, useMemo, useReducer, useState } from 'react';
3
+ import { Fragment, memo, useCallback, useEffect, useMemo, useReducer, useState } from 'react';
4
4
  import { CacheStrategies, Logger } from '@selfcommunity/utils';
5
5
  import { SCOPE_SC_UI } from '../../../constants/Errors';
6
6
  import { FormattedMessage } from 'react-intl';
@@ -94,11 +94,11 @@ function Comments(props) {
94
94
  map.set(name, [...map.get(name), comment]);
95
95
  }
96
96
  });
97
- 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, Object.assign({ variant: "body1" }, { children: 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)));
97
+ 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)));
98
98
  }, [state.results]);
99
99
  if (!state.initialized) {
100
100
  return _jsx(CommentsSkeleton, {});
101
101
  }
102
- return (_jsxs(Box, Object.assign({ className: classes.container }, { 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, isLoadingComments && _jsx(CommentSkeleton, { id: 1 }), state.results.length > 0 && (_jsx(LoadingButton, Object.assign({ size: "small", variant: "outlined", color: "inherit", loading: isLoadingComments, 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" }) })) })))] })));
102
+ 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, isLoadingComments && _jsx(CommentSkeleton, { id: 1 }), _jsx(LoadingButton, Object.assign({ size: "small", variant: "outlined", color: "inherit", loading: isLoadingComments, 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" }) }))) })));
103
103
  }
104
104
  export default memo(Comments);
@@ -136,7 +136,7 @@ export default function CourseParticipantsButton(inProps) {
136
136
  /**
137
137
  * Rendering
138
138
  */
139
- if (!participantsAvailable || !scCourse.privacy) {
139
+ if (!participantsAvailable) {
140
140
  return _jsx(HiddenPlaceholder, {});
141
141
  }
142
142
  return (_jsxs(_Fragment, { children: [_jsxs(Root, Object.assign({ className: classNames(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
@@ -67,8 +67,7 @@ const editorTheme = {
67
67
  superscript: `${PREFIX}-textSuperscript`,
68
68
  underline: `${PREFIX}-textUnderline`,
69
69
  underlineStrikethrough: `${PREFIX}-textUnderlineStrikethrough`
70
- },
71
- document: `${PREFIX}-document`
70
+ }
72
71
  };
73
72
  /**
74
73
  * > API documentation for the Community-JS Editor component. Learn about the available props and the CSS API.
@@ -105,7 +104,7 @@ const Editor = (inProps, ref) => {
105
104
  props: inProps,
106
105
  name: PREFIX
107
106
  });
108
- 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 = _jsx(FormattedMessage, { id: "ui.editor.placeholder", defaultMessage: "ui.editor.placeholder" }) } = props;
107
+ 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 = _jsx(FormattedMessage, { id: "ui.editor.placeholder", defaultMessage: "ui.editor.placeholder" }) } = props;
109
108
  const apiRef = useRef();
110
109
  // STATE
111
110
  const [focused, setFocused] = useState(false);
@@ -146,6 +145,6 @@ const Editor = (inProps, ref) => {
146
145
  nodes: [...nodes],
147
146
  theme: editorTheme
148
147
  }), [editable]);
149
- return (_jsx(Root, Object.assign({ id: id, className: classNames(classes.root, className, { [classes.toolbar]: toolbar, [classes.focused]: focused }) }, { children: _jsxs(LexicalComposer, Object.assign({ initialConfig: initialConfig }, { children: [toolbar ? (_jsxs(_Fragment, { children: [_jsx(ToolbarPlugin, { uploadImage: uploadImage, uploadFile: uploadFile, MediaPluginProps: { onMediaAdd: handleMediaChange } }), _jsx(ListPlugin, {}), _jsx(HorizontalRulePlugin, {})] })) : (_jsxs(Stack, Object.assign({ className: classes.actions, direction: "row" }, { children: [uploadImage && _jsx(ImagePlugin, {}), uploadFile && _jsx(MediaPlugin, { onMediaAdd: handleMediaChange }), _jsx(EmojiPlugin, {}), action && action] }))), _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: classes.content }), placeholder: _jsx(Box, Object.assign({ className: classes.placeholder, onClick: handleFocus }, { children: placeholder })), ErrorBoundary: LexicalErrorBoundary }), _jsx(DefaultHtmlValuePlugin, { defaultValue: defaultValue }), _jsx(HistoryPlugin, {}), _jsx(OnChangePlugin, { onChange: handleChange }), _jsx(OnBlurPlugin, { onBlur: handleHasBlur }), _jsx(OnFocusPlugin, { onFocus: handleHasFocus }), _jsx(AutoLinkPlugin, {}), _jsx(MentionsPlugin, {}), _jsx(LinkPlugin, {}), _jsx(FloatingLinkPlugin, {}), _jsx(ApiPlugin, { ref: apiRef })] })) })));
148
+ return (_jsx(Root, Object.assign({ id: id, className: classNames(classes.root, className, { [classes.toolbar]: toolbar, [classes.focused]: focused }) }, { children: _jsxs(LexicalComposer, Object.assign({ initialConfig: initialConfig }, { children: [toolbar ? (_jsxs(_Fragment, { children: [_jsx(ToolbarPlugin, Object.assign({ uploadImage: uploadImage, uploadFile: uploadFile, MediaPluginProps: { onMediaAdd: handleMediaChange } }, ToolBarProps)), _jsx(ListPlugin, {}), _jsx(HorizontalRulePlugin, {})] })) : (_jsxs(Stack, Object.assign({ className: classes.actions, direction: "row" }, { children: [uploadImage && _jsx(ImagePlugin, {}), uploadFile && _jsx(MediaPlugin, Object.assign({}, MediaPluginProps)), _jsx(EmojiPlugin, {}), action && action] }))), _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: classes.content }), placeholder: _jsx(Box, Object.assign({ className: classes.placeholder, onClick: handleFocus }, { children: placeholder })), ErrorBoundary: LexicalErrorBoundary }), _jsx(DefaultHtmlValuePlugin, { defaultValue: defaultValue }), _jsx(HistoryPlugin, {}), _jsx(OnChangePlugin, { onChange: handleChange }), _jsx(OnBlurPlugin, { onBlur: handleHasBlur }), _jsx(OnFocusPlugin, { onFocus: handleHasFocus }), _jsx(AutoLinkPlugin, {}), _jsx(MentionsPlugin, {}), _jsx(LinkPlugin, {}), _jsx(FloatingLinkPlugin, {}), _jsx(ApiPlugin, { ref: apiRef })] })) })));
150
149
  };
151
150
  export default 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;
@@ -5,7 +5,6 @@ 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
8
  const nodes = [
10
9
  HorizontalRuleNode,
11
10
  HeadingNode,
@@ -17,7 +16,6 @@ const nodes = [
17
16
  AutoLinkNode,
18
17
  LinkNode,
19
18
  ImageNode,
20
- MentionNode,
21
- DocNode
19
+ MentionNode
22
20
  ];
23
21
  export 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;
@@ -14,7 +14,6 @@ import { asUploadButton } from '@rpldy/upload-button';
14
14
  import { useSnackbar } from 'notistack';
15
15
  import { $createImageNode, ImageNode } from '../nodes/ImageNode';
16
16
  import { PREFIX } from '../constants';
17
- import { $createDocNode, DocNode } from '../nodes/DocNode';
18
17
  import { INSERT_IMAGE_COMMAND } from './ImagePlugin';
19
18
  import classNames from 'classnames';
20
19
  export const INSERT_DOC_COMMAND = createCommand();
@@ -31,11 +30,10 @@ const Root = styled(Box, {
31
30
  })(() => ({}));
32
31
  export default function MediaPlugin(props) {
33
32
  var _a;
34
- const { className = '', onMediaAdd = null } = props;
33
+ const { className = '', onMediaAdd = null, isUploading } = props;
35
34
  // STATE
36
35
  const [uploading, setUploading] = useState({});
37
36
  const [mediaType, setMediaType] = useState('');
38
- const [uploadedMedia, setUploadedMedia] = useState([]);
39
37
  const [editor] = useLexicalComposerContext();
40
38
  // CONTEXT
41
39
  const scContext = useSCContext();
@@ -61,27 +59,6 @@ export default function MediaPlugin(props) {
61
59
  return true;
62
60
  }, COMMAND_PRIORITY_EDITOR);
63
61
  }, [editor]);
64
- useEffect(() => {
65
- // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
66
- // @ts-ignore
67
- if (!editor.hasNodes([DocNode])) {
68
- return;
69
- }
70
- editor.registerCommand(INSERT_DOC_COMMAND, (payload) => {
71
- const docNode = $createDocNode({
72
- src: payload.src,
73
- name: payload.name,
74
- type: payload.type
75
- });
76
- $insertNodeToNearestRoot(docNode);
77
- return true;
78
- }, COMMAND_PRIORITY_EDITOR);
79
- }, [editor]);
80
- useEffect(() => {
81
- if (uploadedMedia.length > 0) {
82
- onMediaAdd && onMediaAdd(uploadedMedia);
83
- }
84
- }, [uploadedMedia, onMediaAdd]);
85
62
  // HANDLERS
86
63
  const handleFileUploadFilter = (file) => {
87
64
  if (file.type.startsWith('image/')) {
@@ -111,11 +88,12 @@ export default function MediaPlugin(props) {
111
88
  };
112
89
  editor.focus();
113
90
  editor.dispatchCommand(INSERT_DOC_COMMAND, data);
114
- setUploadedMedia((prev) => [...prev, media]);
91
+ onMediaAdd && onMediaAdd(media);
115
92
  }
116
93
  };
117
94
  const handleUploadProgress = (chunks) => {
118
95
  setUploading(Object.assign({}, chunks));
96
+ isUploading && isUploading(Object.keys(chunks).length !== 0);
119
97
  };
120
98
  const handleUploadError = (chunk, error) => {
121
99
  enqueueSnackbar(error, {
@@ -125,14 +103,14 @@ export default function MediaPlugin(props) {
125
103
  };
126
104
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
127
105
  // @ts-ignore
128
- if (!scUserContext.user || !editor.hasNodes([ImageNode, DocNode])) {
106
+ if (!scUserContext.user || !editor.hasNodes([ImageNode])) {
129
107
  return null;
130
108
  }
131
109
  return (_jsx(Root, Object.assign({ className: classNames(classes.root, className) }, { children: _jsxs(ChunkedUploady, Object.assign({ destination: {
132
110
  url: `${scContext.settings.portal}${Endpoints.ComposerChunkUploadMedia.url()}`,
133
111
  headers: ((_a = scContext.settings.session) === null || _a === void 0 ? void 0 : _a.authToken) ? { Authorization: `Bearer ${scContext.settings.session.authToken.accessToken}` } : {},
134
112
  method: Endpoints.ComposerChunkUploadMedia.method
135
- }, chunkSize: 204800, accept: "image/*,application/*", fileFilter: handleFileUploadFilter }, { children: [_jsx(MediaChunkUploader, { type: mediaType, onSuccess: handleUploadSuccess, onProgress: handleUploadProgress, onError: handleUploadError }), _jsx(UploadButton, { className: className, extraProps: {
113
+ }, chunkSize: 204800, accept: "image/*,application/*", fileFilter: handleFileUploadFilter, multiple: true }, { children: [_jsx(MediaChunkUploader, { type: mediaType, onSuccess: handleUploadSuccess, onProgress: handleUploadProgress, onError: handleUploadError }), _jsx(UploadButton, { className: className, extraProps: {
136
114
  disabled: Object.keys(uploading).length !== 0,
137
115
  progress: Object.keys(uploading).length !== 0 ? Object.values(uploading)[0].completed : null
138
116
  } })] })) })));
@@ -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;
@@ -126,7 +126,7 @@ export default function ToolbarPlugin(inProps) {
126
126
  props: inProps,
127
127
  name: PREFIX
128
128
  });
129
- const { uploadImage = false, uploadFile = false, MediaPluginProps = {} } = props;
129
+ const { uploadImage = false, uploadFile = false, MediaPluginProps = {}, customLink = null } = props;
130
130
  // STATE
131
131
  const [editor] = useLexicalComposerContext();
132
132
  const [activeEditor, setActiveEditor] = useState(editor);
@@ -269,5 +269,5 @@ export default function ToolbarPlugin(inProps) {
269
269
  activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
270
270
  } }, { children: _jsx(Tooltip, Object.assign({ title: _jsx(FormattedMessage, { id: `ui.editor.toolbarPlugin.${format}`, defaultMessage: `ui.editor.toolbarPlugin.${format}` }) }, { children: _jsx(Icon, { children: `format_${format}` }) })) }), format))) })), _jsx(IconButton, Object.assign({ disabled: !isEditable, onClick: clearFormatting }, { children: _jsx(Tooltip, Object.assign({ title: _jsx(FormattedMessage, { id: "ui.editor.toolbarPlugin.clear", defaultMessage: "ui.editor.toolbarPlugin.clear" }) }, { children: _jsx(Icon, { children: "format_clear" }) })) })), _jsx(IconButton, Object.assign({ disabled: !isEditable, onClick: () => {
271
271
  activeEditor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined);
272
- } }, { children: _jsx(Tooltip, Object.assign({ title: _jsx(FormattedMessage, { id: "ui.editor.toolbarPlugin.horizontalRule", defaultMessage: "ui.editor.toolbarPlugin.horizontalRule" }) }, { children: _jsx(Icon, { children: "format_horizontal_rule" }) })) })), uploadImage && _jsx(ImagePlugin, {}), uploadFile && _jsx(MediaPlugin, Object.assign({}, MediaPluginProps)), _jsx(IconButton, Object.assign({ disabled: !isEditable, onClick: insertLink }, { children: _jsx(Tooltip, Object.assign({ title: _jsx(FormattedMessage, { id: "ui.editor.toolbarPlugin.link", defaultMessage: "ui.editor.toolbarPlugin.link" }) }, { children: _jsx(Icon, { children: "format_link" }) })) })), _jsx(EmojiPlugin, {})] })));
272
+ } }, { children: _jsx(Tooltip, Object.assign({ title: _jsx(FormattedMessage, { id: "ui.editor.toolbarPlugin.horizontalRule", defaultMessage: "ui.editor.toolbarPlugin.horizontalRule" }) }, { children: _jsx(Icon, { children: "format_horizontal_rule" }) })) })), uploadImage && _jsx(ImagePlugin, {}), uploadFile && _jsx(MediaPlugin, Object.assign({}, MediaPluginProps)), customLink !== null && customLink !== void 0 ? customLink : (_jsx(IconButton, Object.assign({ disabled: !isEditable, onClick: insertLink }, { children: _jsx(Tooltip, Object.assign({ title: _jsx(FormattedMessage, { id: "ui.editor.toolbarPlugin.link", defaultMessage: "ui.editor.toolbarPlugin.link" }) }, { children: _jsx(Icon, { children: "format_link" }) })) }))), _jsx(EmojiPlugin, {})] })));
273
273
  }
@@ -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
 
@@ -22,6 +22,7 @@ import UserDeletedSnackBar from '../../shared/UserDeletedSnackBar';
22
22
  import UserAvatar from '../../shared/UserAvatar';
23
23
  import { PREFIX } from './constants';
24
24
  import LessonCommentActionsMenu from '../../shared/LessonCommentActionsMenu';
25
+ import LessonFilePreview from '../../shared/LessonFilePreview';
25
26
  const classes = {
26
27
  root: `${PREFIX}-root`,
27
28
  comment: `${PREFIX}-comment`,
@@ -29,6 +30,7 @@ const classes = {
29
30
  content: `${PREFIX}-content`,
30
31
  author: `${PREFIX}-author`,
31
32
  textContent: `${PREFIX}-text-content`,
33
+ mediaContent: `${PREFIX}-media-content`,
32
34
  commentActionsMenu: `${PREFIX}-comment-actions-menu`
33
35
  };
34
36
  const Root = styled(Box, {
@@ -63,6 +65,7 @@ const Root = styled(Box, {
63
65
  |author|.SCCommentObject-author|Styles applied to the author section.|
64
66
  |content|.SCCommentObject-content|Styles applied to content section.|
65
67
  |textContent|.SCCommentObject-text-content|Styles applied to text content section.|
68
+ |mediaContent|.SCCommentObject-media-content|Styles applied to media content section.|
66
69
  |commentActionsMenu|.SCCommentObject-comment-actions-menu|Styles applied to comment action menu element.|
67
70
 
68
71
 
@@ -152,7 +155,8 @@ export default function LessonCommentObject(inProps) {
152
155
  const newObj = Object.assign({}, obj, {
153
156
  text: data.text,
154
157
  html: data.html,
155
- created_at: data.created_at
158
+ created_at: data.created_at,
159
+ medias: medias
156
160
  });
157
161
  updateObject(newObj);
158
162
  setEditComment(null);
@@ -179,7 +183,9 @@ export default function LessonCommentObject(inProps) {
179
183
  return null;
180
184
  }
181
185
  const summaryHtml = getCommentContributionHtml(comment.html, scRoutingContext.url);
182
- return (_jsx(React.Fragment, { children: editComment && editComment.id === comment.id ? (_jsx(Box, Object.assign({ className: classes.comment }, { children: _jsx(CommentObjectReply, 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)) }))) : (_jsx(BaseItem, { elevation: 0, className: classes.comment, image: _jsx(Link, Object.assign({}, (!comment.created_by.deleted && { to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, comment.created_by) }), { onClick: comment.created_by.deleted ? () => setOpenAlert(true) : null }, { children: _jsx(UserAvatar, Object.assign({ hide: !obj.created_by.community_badge }, { children: _jsx(Avatar, { alt: obj.created_by.username, variant: "circular", src: comment.created_by.avatar, className: classes.avatar }) })) })), disableTypography: true, primary: _jsx(_Fragment, { children: _jsxs(Widget, Object.assign({ className: classes.content, elevation: elevation }, rest, { children: [_jsxs(CardContent, { children: [_jsx(Link, Object.assign({ className: classes.author }, (!comment.created_by.deleted && { to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, comment.created_by) }), { onClick: comment.created_by.deleted ? () => setOpenAlert(true) : null }, { children: _jsx(Typography, Object.assign({ component: "span" }, { children: comment.created_by.username })) })), _jsxs(_Fragment, { children: [_jsx(Bullet, {}), _jsx(DateTimeAgo, { date: comment.created_at, showStartIcon: false })] }), _jsx(Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: summaryHtml } })] }), scUserContext.user && (_jsx(Box, Object.assign({ className: classes.commentActionsMenu }, { children: _jsx(LessonCommentActionsMenu, { lesson: lessonObject, commentObject: comment, onDelete: handleDelete, onEdit: handleEdit }) })))] })) }) })) }, comment.id));
186
+ return (_jsx(React.Fragment, { children: editComment && editComment.id === comment.id ? (_jsx(Box, Object.assign({ className: classes.comment }, { children: _jsx(CommentObjectReply, 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)) }))) : (_jsx(BaseItem, { elevation: 0, className: classes.comment, image: _jsx(Link, Object.assign({}, (!comment.created_by.deleted && { to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, comment.created_by) }), { onClick: comment.created_by.deleted ? () => setOpenAlert(true) : null }, { children: _jsx(UserAvatar, Object.assign({ hide: !obj.created_by.community_badge }, { children: _jsx(Avatar, { alt: obj.created_by.username, variant: "circular", src: comment.created_by.avatar, className: classes.avatar }) })) })), disableTypography: true, primary: _jsx(_Fragment, { children: _jsxs(Widget, Object.assign({ className: classes.content, elevation: elevation }, rest, { children: [_jsxs(CardContent, { children: [_jsx(Link, Object.assign({ className: classes.author }, (!comment.created_by.deleted && { to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, comment.created_by) }), { onClick: comment.created_by.deleted ? () => setOpenAlert(true) : null }, { children: _jsx(Typography, Object.assign({ component: "span" }, { children: comment.created_by.username })) })), _jsxs(_Fragment, { children: [_jsx(Bullet, {}), _jsx(DateTimeAgo, { date: comment.created_at, showStartIcon: false })] }), _jsx(Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: summaryHtml } }), obj.medias && obj.medias.length > 0 && (_jsx(_Fragment, { children: obj.medias.map((media) => {
187
+ return _jsx(LessonFilePreview, { className: classes.mediaContent, media: media }, media.id);
188
+ }) }))] }), scUserContext.user && (_jsx(Box, Object.assign({ className: classes.commentActionsMenu }, { children: _jsx(LessonCommentActionsMenu, { lesson: lessonObject, commentObject: comment, onDelete: handleDelete, onEdit: handleEdit }) })))] })) }) })) }, comment.id));
183
189
  }
184
190
  /**
185
191
  * Render comments
@@ -103,6 +103,11 @@ export default function LessonCommentObjects(inProps) {
103
103
  var _a;
104
104
  (_a = commentsEndRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ block: 'end', behavior: 'instant' });
105
105
  };
106
+ useEffect(() => {
107
+ if (commentsObject.comments.length > 0) {
108
+ scrollToBottom();
109
+ }
110
+ }, [commentsObject.comments]);
106
111
  /**
107
112
  * Perform save/update comment
108
113
  */
@@ -138,7 +143,6 @@ export default function LessonCommentObjects(inProps) {
138
143
  handleCommentsUpdate(data);
139
144
  setReplyKey(comment.id);
140
145
  setIsCommenting(false);
141
- scrollToBottom();
142
146
  })
143
147
  .catch((error) => {
144
148
  Logger.error(SCOPE_SC_UI, error);
@@ -1,5 +1,5 @@
1
1
  import { __rest } from "tslib";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback } from 'react';
4
4
  import { styled } from '@mui/material/styles';
5
5
  import { useThemeProps } from '@mui/system';
@@ -12,12 +12,16 @@ import { getContributionHtml } from '../../utils/contribution';
12
12
  import Widget from '../Widget';
13
13
  import ContentLesson from '../Composer/Content/ContentLesson';
14
14
  import HiddenPlaceholder from '../../shared/HiddenPlaceholder';
15
+ import DisplayComponent from '../../shared/Media/Link/DisplayComponent';
16
+ import LessonFilePreview from '../../shared/LessonFilePreview';
17
+ import { MediaTypes } from '@selfcommunity/api-services';
15
18
  const classes = {
16
19
  root: `${PREFIX}-root`,
17
20
  content: `${PREFIX}-content`,
18
21
  contentEdit: `${PREFIX}-content-edit`,
19
22
  title: `${PREFIX}-title`,
20
23
  text: `${PREFIX}-text`,
24
+ mediasSection: `${PREFIX}-medias-section`,
21
25
  navigation: `${PREFIX}-navigation`,
22
26
  editor: `${PREFIX}-editor`
23
27
  };
@@ -52,7 +56,7 @@ export default function LessonObject(inProps) {
52
56
  }
53
57
  return (_jsx(Root, Object.assign({ className: classNames(className, classes.root) }, rest, { children: _jsx(Widget, { children: _jsx(CardContent, Object.assign({ classes: { root: editMode ? classes.contentEdit : classes.content } }, { children: editMode ? (_jsx(ContentLesson, { value: lesson,
54
58
  //error={{error}}
55
- onChange: handleChangeLesson, onMediaChange: handleChangeMedia, disabled: isSubmitting, EditorProps: Object.assign({ toolbar: true, uploadImage: false, uploadFile: true }, EditorProps) })) : (_jsx(Typography, { component: "div", gutterBottom: true, className: classes.text, dangerouslySetInnerHTML: {
56
- __html: getContributionHtml(lesson.html, scRoutingContext.url)
57
- } })) })) }) })));
59
+ onChange: handleChangeLesson, onMediaChange: handleChangeMedia, disabled: isSubmitting, EditorProps: Object.assign({ toolbar: true }, EditorProps) })) : (_jsxs(_Fragment, { children: [_jsx(Typography, { component: "div", gutterBottom: true, className: classes.text, dangerouslySetInnerHTML: {
60
+ __html: getContributionHtml(lesson.html, scRoutingContext.url)
61
+ } }), lesson.medias && lesson.medias.length > 0 && (_jsx(Box, Object.assign({ className: classes.mediasSection }, { children: lesson.medias.map((media) => media.type === MediaTypes.URL ? (_jsx(DisplayComponent, { medias: [media] }, media.id)) : (_jsx(LessonFilePreview, { media: media }, media.id))) })))] })) })) }) })));
58
62
  }
@@ -2,12 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Accordion, AccordionDetails, AccordionSummary, Box, Icon, styled, Typography, useMediaQuery, useTheme, useThemeProps } from '@mui/material';
3
3
  import { FormattedMessage } from 'react-intl';
4
4
  import classNames from 'classnames';
5
- import { Fragment, useCallback, useState } from 'react';
5
+ import { useCallback, useState } from 'react';
6
6
  import { SCCourseLessonCompletionStatusType } from '@selfcommunity/types';
7
7
  import { PREFIX } from './constants';
8
8
  import AccordionLessonSkeleton from './Skeleton';
9
9
  const classes = {
10
- root: `${PREFIX}-skeleton-root`,
10
+ root: `${PREFIX}-root`,
11
+ empty: `${PREFIX}-empty`,
11
12
  accordion: `${PREFIX}-accordion`,
12
13
  summary: `${PREFIX}-summary`,
13
14
  details: `${PREFIX}-details`,
@@ -38,7 +39,7 @@ export default function AccordionLessons(inProps) {
38
39
  if (!course) {
39
40
  return _jsx(AccordionLessonSkeleton, {});
40
41
  }
41
- return (_jsx(Fragment, { children: ((_a = course.sections) === null || _a === void 0 ? void 0 : _a.length) > 0 ? (_jsx(Root, Object.assign({ className: classNames(classes.root, className) }, { children: course.sections.map((section) => (_jsxs(Accordion, Object.assign({ className: classes.accordion, expanded: expanded === section.id, onChange: handleChange(section.id), disableGutters: true, elevation: 0, square: true }, { children: [_jsxs(AccordionSummary, Object.assign({ className: classes.summary, expandIcon: _jsx(Icon, { children: "expand_less" }) }, { children: [_jsx(Typography, Object.assign({ component: "span", variant: "body1" }, { children: section.name })), !isMobile && (_jsx(Typography, Object.assign({ component: "span", variant: "body1" }, { children: _jsx(FormattedMessage, { id: "ui.course.table.lessons.title", defaultMessage: "ui.course.table.lessons.title", values: {
42
- lessonsNumber: section.lessons.length
43
- } }) })))] })), section.lessons.map((lesson) => (_jsxs(AccordionDetails, Object.assign({ className: classes.details }, { children: [lesson.completion_status === SCCourseLessonCompletionStatusType.COMPLETED ? (_jsx(Icon, Object.assign({ fontSize: "small", color: "primary" }, { children: "circle_checked" }))) : lesson.locked ? (_jsx(Icon, { children: "private" })) : (_jsx(Box, { className: classes.circle })), _jsx(Typography, { children: lesson.name })] }), lesson.id)))] }), section.id))) }))) : (_jsx(Typography, Object.assign({ variant: "body1" }, { children: _jsx(FormattedMessage, { id: "ui.course.accordionLessons.empty", defaultMessage: "ui.course.accordionLessons.empty" }) }))) }));
42
+ return (_jsx(Root, Object.assign({ className: classNames(classes.root, className) }, { children: ((_a = course.sections) === null || _a === void 0 ? void 0 : _a.length) > 0 ? (course.sections.map((section) => (_jsxs(Accordion, Object.assign({ className: classes.accordion, expanded: expanded === section.id, onChange: handleChange(section.id), disableGutters: true, elevation: 0, square: true }, { children: [_jsxs(AccordionSummary, Object.assign({ className: classes.summary, expandIcon: _jsx(Icon, { children: "expand_less" }) }, { children: [_jsx(Typography, Object.assign({ component: "span", variant: "body1" }, { children: section.name })), !isMobile && (_jsx(Typography, Object.assign({ component: "span", variant: "body1" }, { children: _jsx(FormattedMessage, { id: "ui.course.table.lessons.title", defaultMessage: "ui.course.table.lessons.title", values: {
43
+ lessonsNumber: section.lessons.length
44
+ } }) })))] })), section.lessons.map((lesson) => (_jsxs(AccordionDetails, Object.assign({ className: classes.details }, { children: [lesson.completion_status === SCCourseLessonCompletionStatusType.COMPLETED ? (_jsx(Icon, Object.assign({ fontSize: "small", color: "primary" }, { children: "circle_checked" }))) : lesson.locked ? (_jsx(Icon, { children: "private" })) : (_jsx(Box, { className: classes.circle })), _jsx(Typography, { children: lesson.name })] }), lesson.id)))] }), section.id)))) : (_jsx(Typography, Object.assign({ variant: "body1", className: classes.empty }, { children: _jsx(FormattedMessage, { id: "ui.course.accordionLessons.empty", defaultMessage: "ui.course.accordionLessons.empty" }) }))) })));
44
45
  }
@@ -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,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { styled } from '@mui/material/styles';
3
+ import classNames from 'classnames';
4
+ import { Box, Link, Typography } from '@mui/material';
5
+ import Icon from '@mui/material/Icon';
6
+ import { MEDIA_TYPE_DOCUMENT } from '../../constants/Media';
7
+ const PREFIX = 'SCLessonFilePreview';
8
+ const classes = {
9
+ root: `${PREFIX}-root`,
10
+ item: `${PREFIX}-item`,
11
+ title: `${PREFIX}-title`
12
+ };
13
+ const Root = styled(Box, {
14
+ name: PREFIX,
15
+ slot: 'Root',
16
+ overridesResolver: (props, styles) => styles.root
17
+ })(() => ({}));
18
+ export default function LessonFilePreview(props) {
19
+ // PROPS
20
+ const { className, media } = props;
21
+ /**
22
+ * Renders component
23
+ */
24
+ return (_jsx(Root, Object.assign({ className: classNames(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 && (_jsx(Link, Object.assign({ href: media.url, target: "_blank", rel: "noopener noreferrer" }, { children: _jsxs(Typography, Object.assign({ className: classes.title }, { children: [media.type === MEDIA_TYPE_DOCUMENT && _jsx(Icon, { children: "picture_as_pdf" }), media.title] })) }))) }), media.id));
25
+ }
@@ -1,5 +1,5 @@
1
1
  import { __rest } from "tslib";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import React, { useEffect, useState } from 'react';
4
4
  import InputAdornment from '@mui/material/InputAdornment';
5
5
  import IconButton from '@mui/material/IconButton';
@@ -14,6 +14,7 @@ const INITIAL_STATE = {
14
14
  urlError: null
15
15
  };
16
16
  export default (props) => {
17
+ var _a, _b;
17
18
  // STATE
18
19
  const [isCreating, setIsCreating] = useState(false);
19
20
  const [state, setState] = useState(Object.assign({}, INITIAL_STATE));
@@ -73,7 +74,5 @@ export default (props) => {
73
74
  * Renders url text field
74
75
  */
75
76
  return (_jsx("form", Object.assign({ method: "post", onSubmit: handleSubmit }, { children: _jsx(TextField, Object.assign({ value: url, type: "url", onChange: handleChange, onPaste: handlePaste, error: error || Boolean(urlError), helperText: helperText ||
76
- (urlError && (_jsx(FormattedMessage, { id: `ui.composer.media.link.add.error.${urlError}`, defaultMessage: `ui.composer.media.link.add.error.${urlError}` }))) || _jsx(FormattedMessage, { id: "ui.composer.media.link.add.help", defaultMessage: "ui.composer.media.link.add.help" }), disabled: isCreating }, rest, { InputProps: {
77
- endAdornment: (_jsx(InputAdornment, Object.assign({ position: "end" }, { children: _jsx(Fade, Object.assign({ in: urlError === null && url !== '' }, { children: _jsx(IconButton, Object.assign({ size: "small", disabled: isCreating, type: "submit" }, { children: isCreating ? _jsx(CircularProgress, { color: "primary", size: 20 }) : _jsx(FormattedMessage, { id: "ui.composer.media.link.add.submit", defaultMessage: "ui.composer.media.link.add.submit" }) })) })) })))
78
- } })) })));
77
+ (urlError && (_jsx(FormattedMessage, { id: `ui.composer.media.link.add.error.${urlError}`, defaultMessage: `ui.composer.media.link.add.error.${urlError}` }))) || _jsx(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: (_jsx(_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) : (_jsx(InputAdornment, Object.assign({ position: "end" }, { children: _jsx(Fade, Object.assign({ in: urlError === null && url !== '' }, { children: _jsx(IconButton, Object.assign({ size: "small", disabled: isCreating, type: "submit" }, { children: isCreating ? (_jsx(CircularProgress, { color: "primary", size: 20 })) : (_jsx(FormattedMessage, { id: "ui.composer.media.link.add.submit", defaultMessage: "ui.composer.media.link.add.submit" })) })) })) }))) })) }) })) })));
79
78
  };