reply.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import React from 'react'; //jshint ignore:line
  2. import Editor from 'misago/components/editor'; //jshint ignore:line
  3. import Form from 'misago/components/form';
  4. import Container from './utils/container'; //jshint ignore:line
  5. import Loader from './utils/loader'; //jshint ignore:line
  6. import Message from './utils/message'; //jshint ignore:line
  7. import * as attachments from './utils/attachments'; //jshint ignore:line
  8. import { getPostValidators } from './utils/validators';
  9. import ajax from 'misago/services/ajax';
  10. import posting from 'misago/services/posting'; //jshint ignore:line
  11. import snackbar from 'misago/services/snackbar';
  12. export default class extends Form {
  13. constructor(props) {
  14. super(props);
  15. this.state = {
  16. isReady: false,
  17. isLoading: false,
  18. isErrored: false,
  19. post: '',
  20. attachments: [],
  21. validators: {
  22. post: getPostValidators()
  23. },
  24. errors: {}
  25. };
  26. }
  27. componentDidMount() {
  28. ajax.get(this.props.config, this.props.context || null).then(this.loadSuccess, this.loadError);
  29. }
  30. componentWillReceiveProps(nextProps) {
  31. const context = this.props.context;
  32. const newContext = nextProps.context;
  33. if (context && newContext && context.reply === newContext.reply) return;
  34. ajax.get(nextProps.config, nextProps.context || null).then(this.appendData, snackbar.apiError);
  35. }
  36. /* jshint ignore:start */
  37. loadSuccess = (data) => {
  38. this.setState({
  39. isReady: true,
  40. post: data.post ? ('[quote="@' + data.poster + '"]\n' + data.post + '\n[/quote]') : ''
  41. });
  42. };
  43. loadError = (rejection) => {
  44. this.setState({
  45. isErrored: rejection.detail
  46. });
  47. };
  48. appendData = (data) => {
  49. const newPost = data.post ? ('[quote="@' + data.poster + '"]\n' + data.post + '\n[/quote]\n\n') : '';
  50. this.setState((prevState, props) => {
  51. if (prevState.post.length > 0) {
  52. return {
  53. post: prevState.post + '\n\n' + newPost
  54. };
  55. }
  56. return {
  57. post: newPost
  58. };
  59. });
  60. };
  61. onCancel = () => {
  62. const cancel = confirm(gettext("Are you sure you want to discard your reply?"));
  63. if (cancel) {
  64. posting.close();
  65. }
  66. };
  67. onPostChange = (event) => {
  68. this.changeValue('post', event.target.value);
  69. };
  70. onAttachmentsChange = (attachments) => {
  71. this.setState({
  72. attachments
  73. });
  74. };
  75. /* jshint ignore:end */
  76. clean() {
  77. if (!this.state.post.trim().length) {
  78. snackbar.error(gettext("You have to enter a message."));
  79. return false;
  80. }
  81. const errors = this.validate();
  82. if (errors.post) {
  83. snackbar.error(errors.post[0]);
  84. return false;
  85. }
  86. return true;
  87. }
  88. send() {
  89. return ajax.post(this.props.submit, {
  90. post: this.state.post,
  91. attachments: attachments.clean(this.state.attachments)
  92. });
  93. }
  94. handleSuccess(success) {
  95. snackbar.success(gettext("Your reply has been posted."));
  96. window.location = success.url.index;
  97. // keep form loading
  98. this.setState({
  99. 'isLoading': true
  100. });
  101. }
  102. handleError(rejection) {
  103. if (rejection.status === 400) {
  104. if (rejection.category) {
  105. snackbar.error(rejection.category[0]);
  106. } else if (rejection.title) {
  107. snackbar.error(rejection.title[0]);
  108. } else if (rejection.post) {
  109. snackbar.error(rejection.post[0]);
  110. }
  111. } else {
  112. snackbar.apiError(rejection);
  113. }
  114. }
  115. render() {
  116. /* jshint ignore:start */
  117. if (this.state.isReady) {
  118. return (
  119. <Container className="posting-form">
  120. <form onSubmit={this.handleSubmit} method="POST">
  121. <div className="row">
  122. <div className="col-md-12">
  123. <Editor
  124. attachments={this.state.attachments}
  125. loading={this.state.isLoading}
  126. onAttachmentsChange={this.onAttachmentsChange}
  127. onCancel={this.onCancel}
  128. onChange={this.onPostChange}
  129. submitLabel={gettext("Post reply")}
  130. value={this.state.post}
  131. />
  132. </div>
  133. </div>
  134. </form>
  135. </Container>
  136. );
  137. } else if (this.state.isErrored) {
  138. return (
  139. <Message message={this.state.isErrored} />
  140. );
  141. } else {
  142. return (
  143. <Loader />
  144. );
  145. }
  146. /* jshint ignore:end */
  147. }
  148. }