PageStatusAlert.jsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import AppContainer from '../services/AppContainer';
  5. import PageContainer from '../services/PageContainer';
  6. import { withUnstatedContainers } from './UnstatedUtils';
  7. /**
  8. *
  9. * @author Yuki Takei <yuki@weseek.co.jp>
  10. *
  11. * @export
  12. * @class PageStatusAlert
  13. * @extends {React.Component}
  14. */
  15. class PageStatusAlert extends React.Component {
  16. constructor(props) {
  17. super(props);
  18. this.state = {
  19. };
  20. this.getContentsForSomeoneEditingAlert = this.getContentsForSomeoneEditingAlert.bind(this);
  21. this.getContentsForDraftExistsAlert = this.getContentsForDraftExistsAlert.bind(this);
  22. this.getContentsForUpdatedAlert = this.getContentsForUpdatedAlert.bind(this);
  23. }
  24. refreshPage() {
  25. window.location.reload();
  26. }
  27. getContentsForSomeoneEditingAlert() {
  28. const { t } = this.props;
  29. return [
  30. ['bg-success', 'd-hackmd-none'],
  31. <>
  32. <i className="icon-fw icon-people"></i>
  33. {t('hackmd.someone_editing')}
  34. </>,
  35. <a href="#hackmd" className="btn btn-outline-white">
  36. <i className="fa fa-fw fa-file-text-o mr-1"></i>
  37. Open HackMD Editor
  38. </a>,
  39. ];
  40. }
  41. getContentsForDraftExistsAlert(isRealtime) {
  42. const { t } = this.props;
  43. return [
  44. ['bg-success', 'd-hackmd-none'],
  45. <>
  46. <i className="icon-fw icon-pencil"></i>
  47. {t('hackmd.this_page_has_draft')}
  48. </>,
  49. <a href="#hackmd" className="btn btn-outline-white">
  50. <i className="fa fa-fw fa-file-text-o mr-1"></i>
  51. Open HackMD Editor
  52. </a>,
  53. ];
  54. }
  55. getContentsForUpdatedAlert() {
  56. const { t } = this.props;
  57. const label1 = t('edited this page');
  58. const label2 = t('Load latest');
  59. return [
  60. ['bg-warning'],
  61. <>
  62. <i className="icon-fw icon-bulb"></i>
  63. {this.props.pageContainer.state.lastUpdateUsername} {label1}
  64. </>,
  65. <a href="#" className="btn btn-outline-white" onClick={this.refreshPage}>
  66. <i className="icon-fw icon-reload mr-1"></i>
  67. {label2}
  68. </a>,
  69. ];
  70. }
  71. render() {
  72. const {
  73. revisionId, revisionIdHackmdSynced, remoteRevisionId, hasDraftOnHackmd, isHackmdDraftUpdatingInRealtime,
  74. } = this.props.pageContainer.state;
  75. const isRevisionOutdated = revisionId !== remoteRevisionId;
  76. const isHackmdDocumentOutdated = revisionIdHackmdSynced !== remoteRevisionId;
  77. let getContentsFunc = null;
  78. // when remote revision is newer than both
  79. if (isHackmdDocumentOutdated && isRevisionOutdated) {
  80. getContentsFunc = this.getContentsForUpdatedAlert;
  81. }
  82. // when someone editing with HackMD
  83. else if (isHackmdDraftUpdatingInRealtime) {
  84. getContentsFunc = this.getContentsForSomeoneEditingAlert;
  85. }
  86. // when the draft of HackMD is newest
  87. else if (hasDraftOnHackmd) {
  88. getContentsFunc = this.getContentsForDraftExistsAlert;
  89. }
  90. // do not render anything
  91. else {
  92. return null;
  93. }
  94. const [additionalClasses, label, btn] = getContentsFunc();
  95. return (
  96. <div className={`card grw-page-status-alert text-white fixed-bottom animated fadeInUp faster ${additionalClasses.join(' ')}`}>
  97. <div className="card-body">
  98. <p className="card-text grw-card-label-container">
  99. {label}
  100. </p>
  101. <p className="card-text grw-card-btn-container">
  102. {btn}
  103. </p>
  104. </div>
  105. </div>
  106. );
  107. }
  108. }
  109. /**
  110. * Wrapper component for using unstated
  111. */
  112. const PageStatusAlertWrapper = withUnstatedContainers(PageStatusAlert, [AppContainer, PageContainer]);
  113. PageStatusAlert.propTypes = {
  114. t: PropTypes.func.isRequired, // i18next
  115. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  116. pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
  117. };
  118. export default withTranslation()(PageStatusAlertWrapper);