CommentForm.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import ReactUtils from '../ReactUtils';
  4. import CommentPreview from '../PageComment/CommentPreview';
  5. import Button from 'react-bootstrap/es/Button';
  6. import FormControl from 'react-bootstrap/es/FormControl';
  7. import Tab from 'react-bootstrap/es/Tab';
  8. import Tabs from 'react-bootstrap/es/Tabs';
  9. import UserPicture from '../User/UserPicture';
  10. /**
  11. *
  12. * @author Yuki Takei <yuki@weseek.co.jp>
  13. *
  14. * @export
  15. * @class Comment
  16. * @extends {React.Component}
  17. */
  18. export default class CommentForm extends React.Component {
  19. constructor(props) {
  20. super(props);
  21. this.state = {
  22. comment: '',
  23. isMarkdown: true,
  24. html: '',
  25. key: 1,
  26. };
  27. this.updateState = this.updateState.bind(this);
  28. this.postComment = this.postComment.bind(this);
  29. this.renderHtml = this.renderHtml.bind(this);
  30. this.handleSelect = this.handleSelect.bind(this);
  31. }
  32. updateState(event) {
  33. const target = event.target;
  34. const value = target.type === 'checkbox' ? target.checked : target.value;
  35. const name = target.name;
  36. this.setState({
  37. [name]: value
  38. });
  39. }
  40. handleSelect(key){
  41. this.setState({ key });
  42. this.renderHtml(this.state.comment)
  43. }
  44. /**
  45. * Load data of comments and rerender <PageComments />
  46. */
  47. postComment(event) {
  48. event.preventDefault();
  49. this.props.crowi.apiPost('/comments.add', {
  50. commentForm: {
  51. comment: this.state.comment,
  52. _csrf: this.props.crowi.csrfToken,
  53. page_id: this.props.pageId,
  54. revision_id: this.props.revisionId,
  55. is_markdown: this.state.isMarkdown,
  56. }
  57. })
  58. .then((res) => {
  59. if (this.props.onPostComplete != null) {
  60. this.props.onPostComplete(res.comment);
  61. }
  62. this.setState({
  63. comment: '',
  64. isMarkdown: true,
  65. html: '',
  66. key: 1,
  67. });
  68. });
  69. }
  70. getCommentHtml(){
  71. return(
  72. <CommentPreview
  73. html={this.state.html}
  74. inputRef={el => this.previewElement = el}/>
  75. )
  76. }
  77. renderHtml(markdown) {
  78. var context = {
  79. markdown,
  80. dom: this.previewElement,
  81. };
  82. const crowiRenderer = this.props.crowiRenderer;
  83. const interceptorManager = this.props.crowi.interceptorManager;
  84. interceptorManager.process('prePreviewRender', context)
  85. .then(() => interceptorManager.process('prePreviewPreProcess', context))
  86. .then(() => {
  87. context.markdown = crowiRenderer.preProcess(context.markdown);
  88. })
  89. .then(() => interceptorManager.process('postPreviewPreProcess', context))
  90. .then(() => {
  91. var parsedHTML = crowiRenderer.process(context.markdown);
  92. context['parsedHTML'] = parsedHTML;
  93. })
  94. .then(() => interceptorManager.process('prePreviewPostProcess', context))
  95. .then(() => {
  96. context.parsedHTML = crowiRenderer.postProcess(context.parsedHTML, context.dom);
  97. })
  98. .then(() => interceptorManager.process('postPreviewPostProcess', context))
  99. .then(() => interceptorManager.process('prePreviewRenderHtml', context))
  100. .then(() => {
  101.    this.setState({ html: context.parsedHTML });
  102. })
  103. // process interceptors for post rendering
  104. .then(() => interceptorManager.process('postPreviewRenderHtml', context));
  105. }
  106. generateInnerHtml(html) {
  107. return {__html: html};
  108. }
  109. render() {
  110. // const creatorsPage = `/user/${this.state.creator.username}`;
  111. // const crowi = this.props.crowi;
  112. const user = crowi.me;
  113. const comment = this.state.comment;
  114. const commentPreview = this.state.isMarkdown ? this.getCommentHtml(): ReactUtils.nl2br(comment);
  115. //{% if not user %}disabled{% endif %}をtextareaとbuttonに追加
  116. return (
  117. <div>
  118. <form className="form page-comment-form" id="page-comment-form" onSubmit={this.postComment}>
  119. { user &&
  120. <div className="comment-form">
  121. <div className="comment-form-user">
  122. {/* <a href={creatorsPage}> */}
  123. {/* <UserPicture user={user} /> */}
  124. {/* </a> */}
  125. </div>
  126. <div className="comment-form-main">
  127. <div className="comment-write">
  128. <Tabs activeKey={this.state.key} id="comment-form-tabs" onSelect={this.handleSelect} animation={false}>
  129. <Tab eventKey={1} title="Write">
  130. <textarea className="comment-form-comment form-control" id="comment-form-comment" name="comment" required placeholder="Write comments here..." value={this.state.comment} onChange={this.updateState} >
  131. </textarea>
  132. <div className="form-check">
  133. <input type="checkbox" id="comment-form-is-markdown" name="isMarkdown" checked={this.state.isMarkdown} value="1" onChange={this.updateState} /> Markdown<br />
  134. </div>
  135. </Tab>
  136. <Tab eventKey={2} title="Preview">
  137. <div className="comment-form-preview">
  138. {commentPreview}
  139. </div>
  140. </Tab>
  141. </Tabs>
  142. </div>
  143. <div className="comment-submit">
  144. <div className="pull-right">
  145. <Button type="submit" value="Submit" bsStyle="primary" className="fcbtn btn btn-sm btn-primary btn-outline btn-rounded btn-1b">
  146. Comment
  147. </Button>
  148. </div>
  149. <div className="clearfix">
  150. </div>
  151. </div>
  152. </div>
  153. </div>
  154. }
  155. </form>
  156. </div>
  157. );
  158. }
  159. }
  160. CommentForm.propTypes = {
  161. crowi: PropTypes.object.isRequired,
  162. onPostComplete: PropTypes.func,
  163. pageId: PropTypes.string,
  164. revisionId: PropTypes.string,
  165. crowiRenderer: PropTypes.object.isRequired,
  166. };