import React, {PropTypes} from 'react'; import {notifyForNewCommentStatus} from 'coral-plugin-commentbox/CommentBox'; import {CommentForm} from 'coral-plugin-commentbox/CommentForm'; import styles from './Comment.css'; import {CountdownSeconds} from './CountdownSeconds'; import {getEditableUntilDate} from './util'; import {can} from 'coral-framework/services/perms'; import {forEachError} from 'coral-framework/utils'; import {Icon} from 'coral-ui'; import t from 'coral-framework/services/i18n'; /** * Renders a Comment's body in such a way that the end-user can edit it and save changes */ export class EditableCommentContent extends React.Component { static propTypes = { // show notification to the user (e.g. for errors) addNotification: PropTypes.func.isRequired, asset: PropTypes.shape({ settings: PropTypes.shape({ charCountEnable: PropTypes.bool, }), }).isRequired, // comment that is being edited comment: PropTypes.shape({ body: PropTypes.string, editing: PropTypes.shape({ edited: PropTypes.bool, // ISO8601 editableUntil: PropTypes.string, }) }).isRequired, // logged in user currentUser: PropTypes.shape({ id: PropTypes.string.isRequired }), maxCharCount: PropTypes.number, // edit a comment, passed {{ body }} editComment: React.PropTypes.func, // called when editing should be stopped stopEditing: React.PropTypes.func, } constructor(props) { super(props); this.editWindowExpiryTimeout = null; this.state = { body: props.comment.body, loadingState: '', }; } componentDidMount() { const editableUntil = getEditableUntilDate(this.props.comment); const now = new Date(); const editWindowRemainingMs = editableUntil && (editableUntil - now); if (editWindowRemainingMs > 0) { this.editWindowExpiryTimeout = setTimeout(() => { this.forceUpdate(); }, editWindowRemainingMs); } } componentWillUnmount() { if (this.editWindowExpiryTimeout) { this.editWindowExpiryTimeout = clearTimeout(this.editWindowExpiryTimeout); } } handleBodyChange = (body) => { this.setState({body}); } handleSubmit = async () => { if (!can(this.props.currentUser, 'INTERACT_WITH_COMMUNITY')) { this.props.addNotification('error', t('error.NOT_AUTHORIZED')); return; } this.setState({loadingState: 'loading'}); const {editComment, addNotification, stopEditing} = this.props; if (typeof editComment !== 'function') {return;} let response; try { response = await editComment({body: this.state.body}); this.setState({loadingState: 'success'}); const status = response.data.editComment.comment.status; notifyForNewCommentStatus(this.props.addNotification, status); if (typeof stopEditing === 'function') { stopEditing(); } } catch (error) { this.setState({loadingState: 'error'}); forEachError(error, ({msg}) => addNotification('error', msg)); } } getEditableUntil = (props = this.props) => { return getEditableUntilDate(props.comment); } isEditWindowExpired = (props = this.props) => { return (this.getEditableUntil(props) - new Date()) < 0; } isSubmitEnabled = (comment) => { // should be disabled if user hasn't actually changed their // original comment return (comment.body !== this.props.comment.body) && !this.isEditWindowExpired(); } render() { return (