|
@@ -3,8 +3,10 @@ import PropTypes from 'prop-types';
|
|
|
|
|
|
|
|
import { format, formatDistanceStrict } from 'date-fns';
|
|
import { format, formatDistanceStrict } from 'date-fns';
|
|
|
|
|
|
|
|
|
|
+import Button from 'react-bootstrap/es/Button';
|
|
|
import Tooltip from 'react-bootstrap/es/Tooltip';
|
|
import Tooltip from 'react-bootstrap/es/Tooltip';
|
|
|
import OverlayTrigger from 'react-bootstrap/es/OverlayTrigger';
|
|
import OverlayTrigger from 'react-bootstrap/es/OverlayTrigger';
|
|
|
|
|
+import Collapse from 'react-bootstrap/es/Collapse';
|
|
|
|
|
|
|
|
import AppContainer from '../../services/AppContainer';
|
|
import AppContainer from '../../services/AppContainer';
|
|
|
import PageContainer from '../../services/PageContainer';
|
|
import PageContainer from '../../services/PageContainer';
|
|
@@ -15,7 +17,6 @@ import UserPicture from '../User/UserPicture';
|
|
|
import Username from '../User/Username';
|
|
import Username from '../User/Username';
|
|
|
import CommentEditor from './CommentEditor';
|
|
import CommentEditor from './CommentEditor';
|
|
|
import CommentControl from './CommentControl';
|
|
import CommentControl from './CommentControl';
|
|
|
-import ReplyComments from './ReplyComments';
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
*
|
|
*
|
|
@@ -32,6 +33,7 @@ class Comment extends React.PureComponent {
|
|
|
|
|
|
|
|
this.state = {
|
|
this.state = {
|
|
|
html: '',
|
|
html: '',
|
|
|
|
|
+ isOlderRepliesShown: false,
|
|
|
isReEdit: false,
|
|
isReEdit: false,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -143,6 +145,14 @@ class Comment extends React.PureComponent {
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ toggleOlderReplies() {
|
|
|
|
|
+ this.setState((prevState) => {
|
|
|
|
|
+ return {
|
|
|
|
|
+ showOlderReplies: !prevState.showOlderReplies,
|
|
|
|
|
+ };
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
async renderHtml() {
|
|
async renderHtml() {
|
|
|
|
|
|
|
|
const { growiRenderer, appContainer } = this.props;
|
|
const { growiRenderer, appContainer } = this.props;
|
|
@@ -162,6 +172,71 @@ class Comment extends React.PureComponent {
|
|
|
await interceptorManager.process('postRenderCommentHtml', context);
|
|
await interceptorManager.process('postRenderCommentHtml', context);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ renderReply(reply) {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div key={reply._id} className="page-comment-reply">
|
|
|
|
|
+ <CommentWrapper
|
|
|
|
|
+ comment={reply}
|
|
|
|
|
+ deleteBtnClicked={this.props.deleteBtnClicked}
|
|
|
|
|
+ growiRenderer={this.props.growiRenderer}
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ renderReplies() {
|
|
|
|
|
+ const layoutType = this.props.appContainer.getConfig().layoutType;
|
|
|
|
|
+ const isBaloonStyle = layoutType.match(/crowi-plus|growi|kibela/);
|
|
|
|
|
+
|
|
|
|
|
+ let replyList = this.props.replyList;
|
|
|
|
|
+ if (!isBaloonStyle) {
|
|
|
|
|
+ replyList = replyList.slice().reverse();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const areThereHiddenReplies = replyList.length > 2;
|
|
|
|
|
+
|
|
|
|
|
+ const { isOlderRepliesShown } = this.state;
|
|
|
|
|
+ const toggleButtonIconName = isOlderRepliesShown ? 'icon-arrow-up' : 'icon-options-vertical';
|
|
|
|
|
+ const toggleButtonIcon = <i className={`icon-fw ${toggleButtonIconName}`}></i>;
|
|
|
|
|
+ const toggleButtonLabel = isOlderRepliesShown ? '' : 'more';
|
|
|
|
|
+ const toggleButton = (
|
|
|
|
|
+ <Button
|
|
|
|
|
+ bsStyle="link"
|
|
|
|
|
+ className="page-comments-list-toggle-older"
|
|
|
|
|
+ onClick={() => { this.setState({ isOlderRepliesShown: !isOlderRepliesShown }) }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {toggleButtonIcon} {toggleButtonLabel}
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ const shownReplies = replyList.slice(replyList.length - 2, replyList.length);
|
|
|
|
|
+ const hiddenReplies = replyList.slice(0, replyList.length - 2);
|
|
|
|
|
+
|
|
|
|
|
+ const hiddenElements = hiddenReplies.map((reply) => {
|
|
|
|
|
+ return this.renderReply(reply);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const shownElements = shownReplies.map((reply) => {
|
|
|
|
|
+ return this.renderReply(reply);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <React.Fragment>
|
|
|
|
|
+ {areThereHiddenReplies && (
|
|
|
|
|
+ <div className="page-comments-hidden-replies">
|
|
|
|
|
+ <Collapse in={this.state.isOlderRepliesShown}>
|
|
|
|
|
+ <div>{hiddenElements}</div>
|
|
|
|
|
+ </Collapse>
|
|
|
|
|
+ <div className="text-center">{toggleButton}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+
|
|
|
|
|
+ {shownElements}
|
|
|
|
|
+ </React.Fragment>
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
render() {
|
|
render() {
|
|
|
const comment = this.props.comment;
|
|
const comment = this.props.comment;
|
|
|
const commentId = comment._id;
|
|
const commentId = comment._id;
|
|
@@ -215,21 +290,20 @@ class Comment extends React.PureComponent {
|
|
|
<OverlayTrigger overlay={commentDateTooltip} placement="bottom">
|
|
<OverlayTrigger overlay={commentDateTooltip} placement="bottom">
|
|
|
<span><a href={`#${commentId}`}>{commentDate}</a></span>
|
|
<span><a href={`#${commentId}`}>{commentDate}</a></span>
|
|
|
</OverlayTrigger>
|
|
</OverlayTrigger>
|
|
|
- { isEdited && (
|
|
|
|
|
- <OverlayTrigger overlay={editedDateTooltip} placement="bottom">
|
|
|
|
|
- <span> (edited)</span>
|
|
|
|
|
- </OverlayTrigger>
|
|
|
|
|
- ) }
|
|
|
|
|
|
|
+ {isEdited && (
|
|
|
|
|
+ <OverlayTrigger overlay={editedDateTooltip} placement="bottom">
|
|
|
|
|
+ <span> (edited)</span>
|
|
|
|
|
+ </OverlayTrigger>
|
|
|
|
|
+ )}
|
|
|
<span className="ml-2"><a className={revisionLavelClassName} href={revHref}>{revFirst8Letters}</a></span>
|
|
<span className="ml-2"><a className={revisionLavelClassName} href={revHref}>{revFirst8Letters}</a></span>
|
|
|
</div>
|
|
</div>
|
|
|
- { this.checkPermissionToControlComment()
|
|
|
|
|
|
|
+ {this.checkPermissionToControlComment()
|
|
|
&& <CommentControl onClickDeleteBtn={this.deleteBtnClickedHandler} onClickEditBtn={this.editBtnClickedHandler} />}
|
|
&& <CommentControl onClickDeleteBtn={this.deleteBtnClickedHandler} onClickEditBtn={this.editBtnClickedHandler} />}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- <ReplyComments {...this.props} />
|
|
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ {this.renderReplies()}
|
|
|
|
|
|
|
|
</React.Fragment>
|
|
</React.Fragment>
|
|
|
);
|
|
);
|