DisplaySwitcher.tsx 5.7 KB

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