ReplayComments.jsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import Button from 'react-bootstrap/es/Button';
  4. import Collapse from 'react-bootstrap/es/Collapse';
  5. import AppContainer from '../../services/AppContainer';
  6. import PageContainer from '../../services/PageContainer';
  7. import Comment from './Comment';
  8. import { createSubscribedElement } from '../UnstatedUtils';
  9. class ReplayComments extends React.PureComponent {
  10. constructor() {
  11. super();
  12. this.state = {
  13. isOlderRepliesShown: false,
  14. };
  15. this.toggleIsOlderRepliesShown = this.toggleIsOlderRepliesShown.bind(this);
  16. }
  17. toggleIsOlderRepliesShown() {
  18. this.setState({ isOlderRepliesShown: !this.state.isOlderRepliesShown });
  19. }
  20. renderReply(reply) {
  21. return (
  22. <div key={reply._id} className="page-comment-reply">
  23. <Comment
  24. comment={reply}
  25. deleteBtnClicked={this.props.deleteBtnClicked}
  26. growiRenderer={this.props.growiRenderer}
  27. />
  28. </div>
  29. );
  30. }
  31. render() {
  32. const layoutType = this.props.appContainer.getConfig().layoutType;
  33. const isBaloonStyle = layoutType.match(/crowi-plus|growi|kibela/);
  34. const isAllReplyShown = this.props.appContainer.getConfig().isAllReplyShown || false;
  35. let replyList = this.props.replyList;
  36. if (!isBaloonStyle) {
  37. replyList = replyList.slice().reverse();
  38. }
  39. if (isAllReplyShown) {
  40. return (
  41. <React.Fragment>
  42. {replyList.map((reply) => {
  43. return this.renderReply(reply);
  44. })}
  45. </React.Fragment>
  46. );
  47. }
  48. const areThereHiddenReplies = (replyList.length > 2);
  49. const { isOlderRepliesShown } = this.state;
  50. const toggleButtonIconName = isOlderRepliesShown ? 'icon-arrow-up' : 'icon-options-vertical';
  51. const toggleButtonIcon = <i className={`icon-fw ${toggleButtonIconName}`}></i>;
  52. const toggleButtonLabel = isOlderRepliesShown ? '' : 'more';
  53. const shownReplies = replyList.slice(replyList.length - 2, replyList.length);
  54. const hiddenReplies = replyList.slice(0, replyList.length - 2);
  55. const hiddenElements = hiddenReplies.map((reply) => {
  56. return this.renderReply(reply);
  57. });
  58. const shownElements = shownReplies.map((reply) => {
  59. return this.renderReply(reply);
  60. });
  61. return (
  62. <React.Fragment>
  63. {areThereHiddenReplies && (
  64. <div className="page-comments-hidden-replies">
  65. <Collapse in={this.state.isOlderRepliesShown}>
  66. <div>{hiddenElements}</div>
  67. </Collapse>
  68. <div className="text-center">
  69. <Button
  70. bsStyle="link"
  71. className="page-comments-list-toggle-older"
  72. onClick={this.toggleIsOlderRepliesShown}
  73. >
  74. {toggleButtonIcon} {toggleButtonLabel}
  75. </Button>
  76. </div>
  77. </div>
  78. )}
  79. {shownElements}
  80. </React.Fragment>
  81. );
  82. }
  83. }
  84. /**
  85. * Wrapper component for using unstated
  86. */
  87. const ReplayCommentsWrapper = (props) => {
  88. return createSubscribedElement(ReplayComments, props, [AppContainer, PageContainer]);
  89. };
  90. ReplayComments.propTypes = {
  91. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  92. pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
  93. growiRenderer: PropTypes.object.isRequired,
  94. deleteBtnClicked: PropTypes.func.isRequired,
  95. replyList: PropTypes.array,
  96. };
  97. export default ReplayCommentsWrapper;