DisplaySwitcher.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import React, { useMemo } from 'react';
  2. import { pagePathUtils } from '@growi/core';
  3. import { useTranslation } from 'react-i18next';
  4. import { TabContent, TabPane } from 'reactstrap';
  5. import { smoothScrollIntoView } from '~/client/util/smooth-scroll';
  6. import {
  7. useCurrentPagePath, useIsSharedUser, useIsEditable, useCurrentPageId, useIsUserPage, usePageUser, useShareLinkId, useIsEmptyPage,
  8. } from '~/stores/context';
  9. import { useDescendantsPageListModal } from '~/stores/modal';
  10. import { useSWRxCurrentPage } from '~/stores/page';
  11. import { EditorMode, useEditorMode } from '~/stores/ui';
  12. import CountBadge from '../Common/CountBadge';
  13. import ContentLinkButtons from '../ContentLinkButtons';
  14. import HashChanged from '../EventListeneres/HashChanged';
  15. import PageListIcon from '../Icons/PageListIcon';
  16. import Page from '../Page';
  17. import PageEditor from '../PageEditor';
  18. import EditorNavbarBottom from '../PageEditor/EditorNavbarBottom';
  19. import PageEditorByHackmd from '../PageEditorByHackmd';
  20. import TableOfContents from '../TableOfContents';
  21. import UserInfo from '../User/UserInfo';
  22. const WIKI_HEADER_LINK = 120;
  23. const { isTopPage } = pagePathUtils;
  24. const DisplaySwitcher = (): JSX.Element => {
  25. const { t } = useTranslation();
  26. // get element for smoothScroll
  27. const getCommentListDom = useMemo(() => { return document.getElementById('page-comments-list') }, []);
  28. const { data: isEmptyPage } = useIsEmptyPage();
  29. const { data: currentPageId } = useCurrentPageId();
  30. const { data: currentPagePath } = useCurrentPagePath();
  31. const { data: isSharedUser } = useIsSharedUser();
  32. const { data: shareLinkId } = useShareLinkId();
  33. const { data: isUserPage } = useIsUserPage();
  34. const { data: isEditable } = useIsEditable();
  35. const { data: pageUser } = usePageUser();
  36. const { data: currentPage } = useSWRxCurrentPage(shareLinkId ?? undefined);
  37. const { data: editorMode } = useEditorMode();
  38. const { open: openDescendantPageListModal } = useDescendantsPageListModal();
  39. const isPageExist = currentPageId != null;
  40. const isViewMode = editorMode === EditorMode.View;
  41. const isTopPagePath = isTopPage(currentPagePath ?? '');
  42. return (
  43. <>
  44. <TabContent activeTab={editorMode}>
  45. <TabPane tabId={EditorMode.View}>
  46. <div className="d-flex flex-column flex-lg-row-reverse">
  47. { isPageExist && !isEmptyPage && (
  48. <div className="grw-side-contents-container">
  49. <div className="grw-side-contents-sticky-container">
  50. {/* Page list */}
  51. <div className="grw-page-accessories-control">
  52. { currentPagePath != null && !isSharedUser && (
  53. <button
  54. type="button"
  55. className="btn btn-block btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
  56. onClick={() => openDescendantPageListModal(currentPagePath)}
  57. >
  58. <div className="grw-page-accessories-control-icon">
  59. <PageListIcon />
  60. </div>
  61. {t('page_list')}
  62. <CountBadge count={currentPage?.descendantCount} offset={1} />
  63. </button>
  64. ) }
  65. </div>
  66. {/* Comments */}
  67. { getCommentListDom != null && !isTopPagePath && (
  68. <div className="grw-page-accessories-control mt-2">
  69. <button
  70. type="button"
  71. className="btn btn-block btn-outline-secondary grw-btn-page-accessories rounded-pill d-flex justify-content-between align-items-center"
  72. onClick={() => smoothScrollIntoView(getCommentListDom, WIKI_HEADER_LINK)}
  73. >
  74. <i className="icon-fw icon-bubbles grw-page-accessories-control-icon"></i>
  75. <span>Comments</span>
  76. <CountBadge count={currentPage?.commentCount} />
  77. </button>
  78. </div>
  79. ) }
  80. <div className="d-none d-lg-block">
  81. <div id="revision-toc" className="revision-toc">
  82. <TableOfContents />
  83. </div>
  84. <ContentLinkButtons />
  85. </div>
  86. </div>
  87. </div>
  88. ) }
  89. <div className="flex-grow-1 flex-basis-0 mw-0">
  90. { isUserPage && <UserInfo pageUser={pageUser} />}
  91. <Page />
  92. </div>
  93. </div>
  94. </TabPane>
  95. { isEditable && (
  96. <TabPane tabId={EditorMode.Editor}>
  97. <div data-testid="page-editor" id="page-editor">
  98. <PageEditor />
  99. </div>
  100. </TabPane>
  101. ) }
  102. { isEditable && (
  103. <TabPane tabId={EditorMode.HackMD}>
  104. <div id="page-editor-with-hackmd">
  105. <PageEditorByHackmd />
  106. </div>
  107. </TabPane>
  108. ) }
  109. </TabContent>
  110. { isEditable && !isViewMode && <EditorNavbarBottom /> }
  111. { isEditable && <HashChanged></HashChanged> }
  112. </>
  113. );
  114. };
  115. export default DisplaySwitcher;