PageEditorByHackmd.jsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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. });
  51. })
  52. .catch(this.apiErrorHandler)
  53. .then(() => {
  54. this.setState({isInitializing: false});
  55. });
  56. }
  57. resumeToEdit() {
  58. this.setState({isInitialized: true});
  59. }
  60. apiErrorHandler(error) {
  61. toastr.error(error.message, 'Error occured', {
  62. closeButton: true,
  63. progressBar: true,
  64. newestOnTop: false,
  65. showDuration: '100',
  66. hideDuration: '100',
  67. timeOut: '3000',
  68. });
  69. }
  70. render() {
  71. const hackmdUri = this.getHackmdUri();
  72. if (this.state.isInitialized) {
  73. return (
  74. <HackmdEditor
  75. markdown={this.props.markdown}
  76. hackmdUri={hackmdUri}
  77. pageIdOnHackmd={this.state.pageIdOnHackmd}
  78. >
  79. </HackmdEditor>
  80. );
  81. }
  82. let content = undefined;
  83. const isPageExistsOnHackmd = (this.state.pageIdOnHackmd != null);
  84. const isRevisionMatch = (this.props.revisionId === this.props.revisionIdHackmdSynced);
  85. // HackMD is not setup
  86. if (hackmdUri == null) {
  87. content = (
  88. <div>
  89. <p className="text-center hackmd-status-label"><i className="fa fa-file-text"></i> HackMD is not set up.</p>
  90. </div>
  91. );
  92. }
  93. // Page does not have 'pageIdOnHackmd' or revisions are mismatch
  94. else if (!isPageExistsOnHackmd || !isRevisionMatch) {
  95. content = (
  96. <div>
  97. <p className="text-center hackmd-status-label"><i className="fa fa-file-text"></i> HackMD is READY!</p>
  98. <p className="text-center">
  99. <button className="btn btn-info btn-lg waves-effect waves-light" type="button"
  100. onClick={() => this.syncAndStartToEdit()} disabled={this.state.isInitializing}>
  101. <span className="btn-label"><i className="icon-paper-plane"></i></span>
  102. Start to edit with HackMD
  103. </button>
  104. </p>
  105. <p className="text-center">Click to clone page content and start to edit.</p>
  106. </div>
  107. );
  108. }
  109. // revision match -> continue
  110. else {
  111. content = (
  112. <div>
  113. <p className="text-center hackmd-status-label"><i className="fa fa-file-text"></i> HackMD is READY!</p>
  114. <p className="text-center">
  115. <button className="btn btn-success btn-lg waves-effect waves-light" type="button"
  116. onClick={() => this.resumeToEdit()}>
  117. <span className="btn-label"><i className="icon-control-end"></i></span>
  118. Resume to edit with HackMD
  119. </button>
  120. </p>
  121. <p className="text-center">Click to edit from the previous continuation.</p>
  122. </div>
  123. );
  124. }
  125. return (
  126. <div className="hackmd-preinit d-flex justify-content-center align-items-center">
  127. {content}
  128. </div>
  129. );
  130. }
  131. }
  132. PageEditorByHackmd.propTypes = {
  133. crowi: PropTypes.object.isRequired,
  134. markdown: PropTypes.string.isRequired,
  135. pageId: PropTypes.string,
  136. revisionId: PropTypes.string,
  137. revisionIdHackmdSynced: PropTypes.string,
  138. pageIdOnHackmd: PropTypes.string,
  139. };