ShareLinkPageView.tsx 3.2 KB

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