PageStatusAlert.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import React, { useCallback } from 'react';
  2. import { useTranslation } from 'next-i18next';
  3. export const PageStatusAlert = (): JSX.Element => {
  4. const { t } = useTranslation();
  5. const refreshPage = useCallback(() => {
  6. window.location.reload();
  7. }, []);
  8. const onClickResolveConflict = useCallback(() => {
  9. // this.props.pageContainer.setState({
  10. // isConflictDiffModalOpen: true,
  11. // });
  12. }, []);
  13. const getContentsForSomeoneEditingAlert = useCallback(() => {
  14. return [
  15. ['bg-success', 'd-hackmd-none'],
  16. <>
  17. <i className="icon-fw icon-people"></i>
  18. {t('hackmd.someone_editing')}
  19. </>,
  20. <a href="#hackmd" key="btnOpenHackmdSomeoneEditing" className="btn btn-outline-white">
  21. <i className="fa fa-fw fa-file-text-o mr-1"></i>
  22. Open HackMD Editor
  23. </a>,
  24. ];
  25. }, [t]);
  26. const getContentsForDraftExistsAlert = (isRealtime) => {
  27. return [
  28. ['bg-success', 'd-hackmd-none'],
  29. <>
  30. <i className="icon-fw icon-pencil"></i>
  31. {t('hackmd.this_page_has_draft')}
  32. </>,
  33. <a href="#hackmd" key="btnOpenHackmdPageHasDraft" className="btn btn-outline-white">
  34. <i className="fa fa-fw fa-file-text-o mr-1"></i>
  35. Open HackMD Editor
  36. </a>,
  37. ];
  38. };
  39. const getContentsForUpdatedAlert = () => {
  40. // const pageEditor = appContainer.getComponentInstance('PageEditor');
  41. const isConflictOnEdit = false;
  42. // if (pageEditor != null) {
  43. // const markdownOnEdit = pageEditor.getMarkdown();
  44. // isConflictOnEdit = markdownOnEdit !== pageContainer.state.markdown;
  45. // }
  46. // TODO: re-impl with Next.js way
  47. // const usernameComponentToString = ReactDOMServer.renderToString(<Username user={pageContainer.state.lastUpdateUser} />);
  48. // const label1 = isConflictOnEdit
  49. // ? t('modal_resolve_conflict.file_conflicting_with_newer_remote')
  50. // // eslint-disable-next-line react/no-danger
  51. // : <span dangerouslySetInnerHTML={{ __html: `${usernameComponentToString} ${t('edited this page')}` }} />;
  52. const label1 = '(TBD -- 2022.09.13)';
  53. return [
  54. ['bg-warning'],
  55. <>
  56. <i className="icon-fw icon-bulb"></i>
  57. {label1}
  58. </>,
  59. <>
  60. <button type="button" onClick={() => refreshPage()} className="btn btn-outline-white mr-4">
  61. <i className="icon-fw icon-reload mr-1"></i>
  62. {t('Load latest')}
  63. </button>
  64. { isConflictOnEdit && (
  65. <button
  66. type="button"
  67. onClick={onClickResolveConflict}
  68. className="btn btn-outline-white"
  69. >
  70. <i className="fa fa-fw fa-file-text-o mr-1"></i>
  71. {t('modal_resolve_conflict.resolve_conflict')}
  72. </button>
  73. )}
  74. </>,
  75. ];
  76. };
  77. const isRevisionOutdated = revisionId !== remoteRevisionId;
  78. const isHackmdDocumentOutdated = revisionIdHackmdSynced !== remoteRevisionId;
  79. let getContentsFunc = null;
  80. // when remote revision is newer than both
  81. if (isHackmdDocumentOutdated && isRevisionOutdated) {
  82. getContentsFunc = getContentsForUpdatedAlert;
  83. }
  84. // when someone editing with HackMD
  85. else if (isHackmdDraftUpdatingInRealtime) {
  86. getContentsFunc = getContentsForSomeoneEditingAlert;
  87. }
  88. // when the draft of HackMD is newest
  89. else if (hasDraftOnHackmd) {
  90. getContentsFunc = getContentsForDraftExistsAlert;
  91. }
  92. // do not render anything
  93. else {
  94. return <></>;
  95. }
  96. const [additionalClasses, label, btn] = getContentsFunc();
  97. return (
  98. <div className={`card grw-page-status-alert text-white fixed-bottom animated fadeInUp faster ${additionalClasses.join(' ')}`}>
  99. <div className="card-body">
  100. <p className="card-text grw-card-label-container">
  101. {label}
  102. </p>
  103. <p className="card-text grw-card-btn-container">
  104. {btn}
  105. </p>
  106. </div>
  107. </div>
  108. );
  109. };