import React from 'react'; import PropTypes from 'prop-types'; import t from 'coral-framework/services/i18n'; import { can } from 'coral-framework/services/perms'; import Slot from 'coral-framework/components/Slot'; import { connect } from 'react-redux'; import { CommentForm } from './CommentForm'; export const name = 'talk-plugin-commentbox'; const notifyReasons = ['LINKS', 'TRUST']; function shouldNotify(actions = []) { return actions.some( ({ __typename, reason }) => __typename === 'FlagAction' && notifyReasons.includes(reason) ); } // Given a newly posted comment's status, show a notification to the user // if needed export const notifyForNewCommentStatus = (notify, comment, actions) => { if (comment.status === 'REJECTED') { notify('error', t('comment_box.comment_post_banned_word')); } else if ( comment.status === 'PREMOD' || (comment.status === 'SYSTEM_WITHHELD' && shouldNotify(actions)) ) { notify('success', t('comment_box.comment_post_notif_premod')); } }; /** * Container for posting a new Comment */ class CommentBox extends React.Component { constructor(props) { super(props); this.state = { username: '', body: '', loadingState: '', hooks: { preSubmit: [], postSubmit: [], }, }; } handleSubmit = () => { const { commentPostedHandler, postComment, assetId, parentId, notify, currentUser, } = this.props; if (!can(currentUser, 'INTERACT_WITH_COMMUNITY')) { notify('error', t('error.NOT_AUTHORIZED')); return; } let input = { asset_id: assetId, parent_id: parentId, body: this.state.body, ...this.props.commentBox, }; // Execute preSubmit Hooks this.state.hooks.preSubmit.forEach(hook => hook(input)); this.setState({ loadingState: 'loading' }); postComment(input, 'comments') .then(({ data }) => { this.setState({ loadingState: 'success', body: '' }); const postedComment = data.createComment.comment; const actions = data.createComment.actions; // Execute postSubmit Hooks this.state.hooks.postSubmit.forEach(hook => hook(data)); notifyForNewCommentStatus(notify, postedComment, actions); if (commentPostedHandler) { commentPostedHandler(); } }) .catch(() => { this.setState({ loadingState: 'error' }); }); }; handleBodyChange = body => { this.setState({ body }); }; registerHook = (hookType = '', hook = () => {}) => { if (typeof hook !== 'function') { return console.warn( `Hooks must be functions. Please check your ${hookType} hooks` ); } else if (typeof hookType === 'string') { this.setState(state => ({ hooks: { ...state.hooks, [hookType]: [...state.hooks[hookType], hook], }, })); return { hookType, hook, }; } else { return console.warn( 'hookTypes must be a string. Please check your hooks' ); } }; unregisterHook = hookData => { const { hookType, hook } = hookData; this.setState(state => { let newHooks = state.hooks[newHooks]; const idx = state.hooks[hookType].indexOf(hook); if (idx !== -1) { newHooks = [ ...state.hooks[hookType].slice(0, idx), ...state.hooks[hookType].slice(idx + 1), ]; } return { hooks: { ...state.hooks, [hookType]: newHooks, }, }; }); }; render() { const { isReply, maxCharCount } = this.props; let { onCancel } = this.props; if (isReply && typeof onCancel !== 'function') { console.warn( 'the CommentBox component should have a onCancel callback defined if it lives in a Reply' ); onCancel = () => {}; } return (