PageEditorByHackmd.jsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import * as toastr from 'toastr';
  4. import HackmdEditor from './PageEditorByHackmd/HackmdEditor';
  5. export default class PageEditorByHackmd extends React.PureComponent {
  6. constructor(props) {
  7. super(props);
  8. this.state = {
  9. isInitialized: false,
  10. isInitializing: false,
  11. pageIdOnHackmd: this.props.pageIdOnHackmd,
  12. };
  13. this.getHackmdUri = this.getHackmdUri.bind(this);
  14. this.syncAndStartToEdit = this.syncAndStartToEdit.bind(this);
  15. this.resumeToEdit = this.resumeToEdit.bind(this);
  16. this.apiErrorHandler = this.apiErrorHandler.bind(this);
  17. }
  18. componentWillMount() {
  19. }
  20. getHackmdUri() {
  21. const envVars = this.props.crowi.config.env;
  22. return envVars.HACKMD_URI;
  23. }
  24. syncToLatestRevision() {
  25. }
  26. /**
  27. * Start integration with HackMD
  28. */
  29. syncAndStartToEdit() {
  30. const hackmdUri = this.getHackmdUri();
  31. if (hackmdUri == null) {
  32. // do nothing
  33. return;
  34. }
  35. this.setState({
  36. isInitialized: false,
  37. isInitializing: true,
  38. });
  39. const params = {
  40. pageId: this.props.pageId,
  41. };
  42. this.props.crowi.apiPost('/hackmd.integrate', params)
  43. .then(res => {
  44. if (!res.ok) {
  45. throw new Error(res.error);
  46. }
  47. this.setState({
  48. isInitialized: true,
  49. pageIdOnHackmd: res.pageIdOnHackmd,
  50. revisionIdHackmdSynced: res.revisionIdHackmdSynced,
  51. });
  52. })
  53. .catch(this.apiErrorHandler)
  54. .then(() => {
  55. this.setState({isInitializing: false});
  56. });
  57. }
  58. /**
  59. * Start to edit w/o any api request
  60. */
  61. resumeToEdit() {
  62. this.setState({isInitialized: true});
  63. }
  64. apiErrorHandler(error) {
  65. toastr.error(error.message, 'Error occured', {
  66. closeButton: true,
  67. progressBar: true,
  68. newestOnTop: false,
  69. showDuration: '100',
  70. hideDuration: '100',
  71. timeOut: '3000',
  72. });
  73. }
  74. render() {
  75. const hackmdUri = this.getHackmdUri();
  76. if (this.state.isInitialized) {
  77. return (
  78. <HackmdEditor
  79. markdown={this.props.markdown}
  80. hackmdUri={hackmdUri}
  81. pageIdOnHackmd={this.state.pageIdOnHackmd}
  82. >
  83. </HackmdEditor>
  84. );
  85. }
  86. let content = undefined;
  87. const isPageExistsOnHackmd = (this.state.pageIdOnHackmd != null);
  88. const isRevisionMatch = (this.props.revisionId === this.props.revisionIdHackmdSynced);
  89. // HackMD is not setup
  90. if (hackmdUri == null) {
  91. content = (
  92. <div>
  93. <p className="text-center hackmd-status-label"><i className="fa fa-file-text"></i> HackMD is not set up.</p>
  94. </div>
  95. );
  96. }
  97. // page is exists, revisions are match, hasDraftOnHackmd is true
  98. else if (isPageExistsOnHackmd && isRevisionMatch && this.props.hasDraftOnHackmd) {
  99. content = (
  100. <div>
  101. <p className="text-center hackmd-status-label"><i className="fa fa-file-text"></i> HackMD is READY!</p>
  102. <p className="text-center">
  103. <button className="btn btn-success btn-lg waves-effect waves-light" type="button"
  104. onClick={() => this.resumeToEdit()}>
  105. <span className="btn-label"><i className="icon-control-end"></i></span>
  106. Resume to edit with HackMD
  107. </button>
  108. </p>
  109. <p className="text-center">Click to edit from the previous continuation.</p>
  110. </div>
  111. );
  112. }
  113. else {
  114. content = (
  115. <div>
  116. <p className="text-center hackmd-status-label"><i className="fa fa-file-text"></i> HackMD is READY!</p>
  117. <p className="text-center">
  118. <button className="btn btn-info btn-lg waves-effect waves-light" type="button"
  119. onClick={() => this.syncAndStartToEdit()} disabled={this.state.isInitializing}>
  120. <span className="btn-label"><i className="icon-paper-plane"></i></span>
  121. Start to edit with HackMD
  122. </button>
  123. </p>
  124. <p className="text-center">Click to clone page content and start to edit.</p>
  125. </div>
  126. );
  127. }
  128. return (
  129. <div className="hackmd-preinit d-flex justify-content-center align-items-center">
  130. {content}
  131. </div>
  132. );
  133. }
  134. }
  135. PageEditorByHackmd.propTypes = {
  136. crowi: PropTypes.object.isRequired,
  137. markdown: PropTypes.string.isRequired,
  138. pageId: PropTypes.string,
  139. revisionId: PropTypes.string,
  140. pageIdOnHackmd: PropTypes.string,
  141. revisionIdHackmdSynced: PropTypes.string,
  142. hasDraftOnHackmd: PropTypes.bool,
  143. };