Comment.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import dateFnsFormat from 'date-fns/format';
  4. import ReactUtils from '../ReactUtils';
  5. import UserPicture from '../User/UserPicture';
  6. /**
  7. *
  8. * @author Yuki Takei <yuki@weseek.co.jp>
  9. *
  10. * @export
  11. * @class Comment
  12. * @extends {React.Component}
  13. */
  14. export default class Comment extends React.Component {
  15. constructor(props) {
  16. super(props);
  17. this.isCurrentUserIsAuthor = this.isCurrentUserEqualsToAuthor.bind(this);
  18. this.isCurrentRevision = this.isCurrentRevision.bind(this);
  19. this.getRootClassName = this.getRootClassName.bind(this);
  20. this.getRevisionLabelClassName = this.getRevisionLabelClassName.bind(this);
  21. this.deleteBtnClickedHandler = this.deleteBtnClickedHandler.bind(this);
  22. this.renderHtml = this.renderHtml.bind(this);
  23. }
  24. componentWillMount() {
  25. this.renderHtml(this.props.comment.comment);
  26. }
  27. componentWillReceiveProps(nextProps) {
  28. this.renderHtml(nextProps.comment.comment);
  29. }
  30. //not used
  31. setMarkdown(markdown) {
  32. this.setState({ markdown });
  33. this.renderHtml(markdown);
  34. }
  35. isCurrentUserEqualsToAuthor() {
  36. return this.props.comment.creator.username === this.props.currentUserId;
  37. }
  38. isCurrentRevision() {
  39. return this.props.comment.revision === this.props.currentRevisionId;
  40. }
  41. getRootClassName() {
  42. return "page-comment "
  43. + (this.isCurrentUserEqualsToAuthor() ? 'page-comment-me ' : '');
  44. }
  45. getRevisionLabelClassName() {
  46. return 'page-comment-revision label '
  47. + (this.isCurrentRevision() ? 'label-primary' : 'label-default');
  48. }
  49. deleteBtnClickedHandler() {
  50. this.props.deleteBtnClicked(this.props.comment);
  51. }
  52. renderRevisionBody() {
  53. const config = this.props.crowi.getConfig();
  54. const isMathJaxEnabled = !!config.env.MATHJAX;
  55. return (
  56. <RevisionBody html={this.state.html}
  57. inputRef={el => this.revisionBodyElement = el}
  58. isMathJaxEnabled={isMathJaxEnabled}
  59. renderMathJaxOnInit={true} />
  60. );
  61. }
  62. renderHtml(markdown) {
  63. var context = {
  64. markdown,
  65. dom: this.revisionBodyElement,
  66. };
  67. const crowiRenderer = this.props.crowiRenderer;
  68. const interceptorManager = this.props.crowi.interceptorManager;
  69. interceptorManager.process('preCommentRender', context)
  70. .then(() => interceptorManager.process('preCommentPreProcess', context))
  71. .then(() => {
  72. context.markdown = crowiRenderer.preProcess(context.markdown);
  73. })
  74. .then(() => interceptorManager.process('postCommentPreProcess', context))
  75. .then(() => {
  76. var parsedHTML = crowiRenderer.process(context.markdown);
  77. context['parsedHTML'] = parsedHTML;
  78. })
  79. .then(() => interceptorManager.process('preCommentPostProcess', context))
  80. .then(() => {
  81. context.parsedHTML = crowiRenderer.postProcess(context.parsedHTML, context.dom);
  82. })
  83. .then(() => interceptorManager.process('postCommentPostProcess', context))
  84. .then(() => interceptorManager.process('preCommentRenderHtml', context))
  85. .then(() => {
  86. this.setState({ html: context.parsedHTML });
  87. })
  88. // process interceptors for post rendering
  89. .then(() => interceptorManager.process('postCommentRenderHtml', context));
  90. }
  91. render() {
  92. const comment = this.props.comment;
  93. const creator = comment.creator;
  94. // temporary from here
  95. const isMarkdown = comment.isMarkdown;
  96. let markdownText = isMarkdown ? 'markdown' : 'plain';
  97. // to here
  98. const rootClassName = this.getRootClassName();
  99. const commentDate = dateFnsFormat(comment.createdAt, 'YYYY/MM/DD HH:mm');
  100. const commentBody = ReactUtils.nl2br(comment.comment);
  101. const creatorsPage = `/user/${creator.username}`;
  102. const revHref = `?revision=${comment.revision}`;
  103. const revFirst8Letters = comment.revision.substr(-8);
  104. const revisionLavelClassName = this.getRevisionLabelClassName();
  105. return (
  106. <div className={rootClassName}>
  107. <a href={creatorsPage}>
  108. <UserPicture user={creator} />
  109. </a>
  110. <div className="page-comment-main">
  111. <div className="page-comment-creator">
  112. <a href={creatorsPage}>{creator.username}</a>
  113. <p>{markdownText}!!!</p>
  114. </div>
  115. <div className="page-comment-body">{commentBody}</div>
  116. <div className="page-comment-meta">
  117. {commentDate}&nbsp;
  118. <a className={revisionLavelClassName} href={revHref}>{revFirst8Letters}</a>
  119. </div>
  120. <div className="page-comment-control">
  121. <button className="btn btn-link" onClick={this.deleteBtnClickedHandler}>
  122. <i className="ti-close"></i>
  123. </button>
  124. </div>
  125. </div>
  126. </div>
  127. );
  128. }
  129. }
  130. Comment.propTypes = {
  131. comment: PropTypes.object.isRequired,
  132. currentRevisionId: PropTypes.string.isRequired,
  133. currentUserId: PropTypes.string.isRequired,
  134. deleteBtnClicked: PropTypes.func.isRequired,
  135. crowi: PropTypes.object.isRequired,
  136. crowiRenderer: PropTypes.object.isRequired,
  137. };