ShareLinkPageView.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { useMemo } from 'react';
  2. import type { IPagePopulatedToShowRevision } from '@growi/core';
  3. import { useSlidesByFrontmatter } from '@growi/presentation/dist/services';
  4. import dynamic from 'next/dynamic';
  5. import { PagePathNavTitle } from '~/components-universal/Common/PagePathNavTitle';
  6. import type { RendererConfig } from '~/interfaces/services/renderer';
  7. import type { IShareLinkHasId } from '~/interfaces/share-link';
  8. import { useShouldExpandContent } from '~/services/layout/use-should-expand-content';
  9. import { generateSSRViewOptions } from '~/services/renderer/renderer';
  10. import { useIsNotFound } from '~/stores/page';
  11. import { useViewOptions } from '~/stores/renderer';
  12. import loggerFactory from '~/utils/logger';
  13. import { PageContentFooter } from '../PageView/PageContentFooter';
  14. import { PageViewLayout } from '../PageView/PageViewLayout';
  15. import RevisionRenderer from '../PageView/RevisionRenderer';
  16. import ShareLinkAlert from './ShareLinkAlert';
  17. const logger = loggerFactory('growi:Page');
  18. const PageSideContents = dynamic(() => import('../../components/PageSideContents').then(mod => mod.PageSideContents), { ssr: false });
  19. const ForbiddenPage = dynamic(() => import('../../components/ForbiddenPage'), { ssr: false });
  20. const SlideRenderer = dynamic(() => import('../../components/Page/SlideRenderer').then(mod => mod.SlideRenderer), { ssr: false });
  21. type Props = {
  22. pagePath: string,
  23. rendererConfig: RendererConfig,
  24. page?: IPagePopulatedToShowRevision,
  25. shareLink?: IShareLinkHasId,
  26. isExpired: boolean,
  27. disableLinkSharing: boolean,
  28. }
  29. export const ShareLinkPageView = (props: Props): JSX.Element => {
  30. const {
  31. pagePath, rendererConfig,
  32. page, shareLink,
  33. isExpired, disableLinkSharing,
  34. } = props;
  35. const { data: isNotFoundMeta } = useIsNotFound();
  36. const { data: viewOptions } = useViewOptions();
  37. const shouldExpandContent = useShouldExpandContent(page);
  38. const markdown = page?.revision?.body;
  39. const isSlide = useSlidesByFrontmatter(markdown, rendererConfig.isEnabledMarp);
  40. const isNotFound = isNotFoundMeta || page == null || shareLink == null;
  41. const specialContents = useMemo(() => {
  42. if (disableLinkSharing) {
  43. return <ForbiddenPage isLinkSharingDisabled={props.disableLinkSharing} />;
  44. }
  45. }, [disableLinkSharing, props.disableLinkSharing]);
  46. const headerContents = <PagePathNavTitle pageId={page?._id} pagePath={pagePath} />;
  47. const sideContents = !isNotFound
  48. ? (
  49. <PageSideContents page={page} />
  50. )
  51. : null;
  52. const footerContents = !isNotFound
  53. ? (
  54. <PageContentFooter page={page} />
  55. )
  56. : null;
  57. const Contents = () => {
  58. if (isNotFound || page.revision == null) {
  59. return <></>;
  60. }
  61. if (isExpired) {
  62. return (
  63. <>
  64. <h2 className="text-muted mt-4">
  65. <span className="material-symbols-outlined" aria-hidden="true">block</span>
  66. <span> Page is expired</span>
  67. </h2>
  68. </>
  69. );
  70. }
  71. const rendererOptions = viewOptions ?? generateSSRViewOptions(rendererConfig, pagePath);
  72. const markdown = page.revision.body;
  73. return isSlide != null
  74. ? <SlideRenderer marp={isSlide.marp} markdown={markdown} />
  75. : <RevisionRenderer rendererOptions={rendererOptions} markdown={markdown} />;
  76. };
  77. return (
  78. <PageViewLayout
  79. headerContents={headerContents}
  80. sideContents={sideContents}
  81. expandContentWidth={shouldExpandContent}
  82. footerContents={footerContents}
  83. >
  84. { specialContents }
  85. { specialContents == null && (
  86. <>
  87. { isNotFound && (
  88. <h2 className="text-muted mt-4">
  89. <span className="material-symbols-outlined" aria-hidden="true">block</span>
  90. <span> Page is not found</span>
  91. </h2>
  92. ) }
  93. { !isNotFound && (
  94. <>
  95. <ShareLinkAlert expiredAt={shareLink.expiredAt} createdAt={shareLink.createdAt} />
  96. <div className="mb-5">
  97. <Contents />
  98. </div>
  99. </>
  100. ) }
  101. </>
  102. ) }
  103. </PageViewLayout>
  104. );
  105. };