diff --git a/src/discussions/comments/comment/CommentEditor.jsx b/src/discussions/comments/comment/CommentEditor.jsx index eba1ed01..70afa449 100644 --- a/src/discussions/comments/comment/CommentEditor.jsx +++ b/src/discussions/comments/comment/CommentEditor.jsx @@ -10,6 +10,7 @@ import { AppContext } from '@edx/frontend-platform/react'; import { Button, Form, StatefulButton } from '@edx/paragon'; import { TinyMCEEditor } from '../../../components'; +import FormikErrorFeedback from '../../../components/FormikErrorFeedback'; import { useDispatchWithState } from '../../../data/hooks'; import { selectModerationSettings, selectUserIsPrivileged } from '../../data/selectors'; import { formikCompatibleHandler, isFormikFieldInvalid } from '../../utils'; @@ -22,14 +23,38 @@ function CommentEditor({ onCloseEditor, edit, }) { + const editorRef = useRef(null); const { authenticatedUser } = useContext(AppContext); const userIsPrivileged = useSelector(selectUserIsPrivileged); const { reasonCodesEnabled, editReasons } = useSelector(selectModerationSettings); const [submitting, dispatch] = useDispatchWithState(); - const editorRef = useRef(null); + + const canDisplayEditReason = (reasonCodesEnabled && userIsPrivileged && edit + && comment.author !== authenticatedUser.username + ); + + const editReasonCodeValidation = canDisplayEditReason && { + editReasonCode: Yup.string().required(intl.formatMessage(messages.editReasonCodeError)), + }; + + const validationSchema = Yup.object().shape({ + comment: Yup.string() + .required(), + ...editReasonCodeValidation, + }); + + const initialValues = { + comment: comment.rawBody, + editReasonCode: comment?.lastEdit?.reasonCode || '', + }; + const saveUpdatedComment = async (values) => { if (comment.id) { - await dispatch(editComment(comment.id, values)); + const payload = { + ...values, + editReasonCode: values.editReasonCode || undefined, + }; + await dispatch(editComment(comment.id, payload)); } else { await dispatch(addComment(values.comment, comment.threadId, comment.parentId)); } @@ -42,17 +67,11 @@ function CommentEditor({ // The editorId is used to autosave contents to localstorage. This format means that the autosave is scoped to // the current comment id, or the current comment parent or the curren thread. const editorId = `comment-editor-${comment.id || comment.parentId || comment.threadId}`; + return ( {({ @@ -64,12 +83,13 @@ function CommentEditor({ handleChange, }) => (
- {(reasonCodesEnabled - && userIsPrivileged - && comment.author !== authenticatedUser.username - && edit - ) && ( - + {canDisplayEditReason && ( + {label} ))} + )} { // If the user isn't privileged, they can't edit the cohort. // If the topic is being edited the cohort can't be changed. @@ -164,60 +172,48 @@ function PostEditor({ ); } - let initialValues = { - postType: 'discussion', - topic: topicId || nonCoursewareTopics?.[0]?.id, - title: '', - comment: '', - follow: true, - anonymous: false, - anonymousToPeers: false, + + const initialValues = { + postType: post?.type || 'discussion', + topic: post?.topicId || topicId || nonCoursewareTopics?.[0]?.id, + title: post?.title || '', + comment: post?.rawBody || '', + follow: isEmpty(post?.following) ? true : post?.following, + anonymous: allowAnonymous ? false : undefined, + anonymousToPeers: allowAnonymousToPeers ? false : undefined, + editReasonCode: post?.lastEdit?.reasonCode || '', }; - if (editExisting) { - initialValues = { - postType: post.type, - topic: post.topicId, - title: post.title, - comment: post.rawBody, - follow: (post.following === null || post.following === undefined) ? true : post.following, - anonymous: allowAnonymous ? false : undefined, - anonymousToPeers: allowAnonymousToPeers ? false : undefined, - }; - } + + const validationSchema = Yup.object().shape({ + postType: Yup.mixed() + .oneOf(['discussion', 'question']), + topic: Yup.string() + .required(), + title: Yup.string() + .required(intl.formatMessage(messages.titleError)), + comment: Yup.string() + .required(intl.formatMessage(messages.commentError)), + follow: Yup.bool() + .default(true), + anonymous: Yup.bool() + .default(false) + .nullable(), + anonymousToPeers: Yup.bool() + .default(false) + .nullable(), + cohort: Yup.string() + .nullable() + .default(null), + ...editReasonCodeValidation, + }); const postEditorId = `post-editor-${editExisting ? postId : 'new'}`; - const { reasonCodesEnabled, editReasons } = useSelector(selectModerationSettings); - return ( { ({ @@ -304,7 +300,7 @@ function PostEditor({
- {(reasonCodesEnabled - && editExisting - && userIsPrivileged - && post.author !== authenticatedUser.username) && ( - - - - {editReasons.map(({ code, label }) => ( - - ))} - - + {canDisplayEditReason && ( + + + + {editReasons.map(({ code, label }) => ( + + ))} + + + )}
diff --git a/src/discussions/posts/post-editor/messages.js b/src/discussions/posts/post-editor/messages.js index 224c7522..670146f3 100644 --- a/src/discussions/posts/post-editor/messages.js +++ b/src/discussions/posts/post-editor/messages.js @@ -106,6 +106,11 @@ const messages = defineMessages({ defaultMessage: 'Reason for editing', description: 'Label for field visible to moderators that allows them to select a reason for editing another user\'s post', }, + editReasonCodeError: { + id: 'discussions.editor.posts.editReasonCode.error', + defaultMessage: 'Select reason for editing', + description: 'Error message visible to moderators when they submit the post/response/comment without select reason for editing', + }, }); export default messages;