PageTimeline.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import React, { type JSX } from 'react';
  2. import Link from 'next/link';
  3. import type { IPageHasId } from '@growi/core';
  4. import { useTranslation } from 'next-i18next';
  5. import { useCurrentPagePath } from '~/states/page';
  6. import { useSWRINFxPageTimeline } from '~/stores/page-timeline';
  7. import { useTimelineOptions } from '~/stores/renderer';
  8. import InfiniteScroll from './InfiniteScroll';
  9. import { RevisionLoader } from './Page/RevisionLoader';
  10. import styles from './PageTimeline.module.scss';
  11. type TimelineCardProps = {
  12. page: IPageHasId;
  13. };
  14. const TimelineCard = ({ page }: TimelineCardProps): JSX.Element => {
  15. const { data: rendererOptions } = useTimelineOptions(page.path);
  16. return (
  17. <div className={`card card-timeline ${styles['card-timeline']}`}>
  18. <div className="card-header h4 p-3">
  19. <Link href={page.path} prefetch={false}>
  20. {page.path}
  21. </Link>
  22. </div>
  23. <div className="card-body">
  24. {rendererOptions != null && page.revision != null && (
  25. <RevisionLoader
  26. rendererOptions={rendererOptions}
  27. pageId={page._id}
  28. revisionId={page.revision}
  29. />
  30. )}
  31. </div>
  32. </div>
  33. );
  34. };
  35. export const PageTimeline = (): JSX.Element => {
  36. const PER_PAGE = 3;
  37. const { t } = useTranslation();
  38. const currentPagePath = useCurrentPagePath();
  39. const swrInfinitexPageTimeline = useSWRINFxPageTimeline(
  40. currentPagePath ?? undefined,
  41. PER_PAGE,
  42. );
  43. const { data } = swrInfinitexPageTimeline;
  44. const isEmpty = data?.[0]?.pages.length === 0;
  45. const isReachingEnd =
  46. isEmpty || (data != null && data[data.length - 1]?.pages.length < PER_PAGE);
  47. if (data == null || isEmpty) {
  48. return (
  49. <div className="mt-2">
  50. <p>{t('custom_navigation.no_pages_under_this_page')}</p>
  51. </div>
  52. );
  53. }
  54. return (
  55. <div>
  56. <InfiniteScroll
  57. swrInifiniteResponse={swrInfinitexPageTimeline}
  58. isReachingEnd={isReachingEnd}
  59. >
  60. {data != null &&
  61. data
  62. .flatMap((apiResult) => apiResult.pages)
  63. .map((page) => <TimelineCard key={page._id} page={page} />)}
  64. </InfiniteScroll>
  65. </div>
  66. );
  67. };