RevisionLoader.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import React, { type JSX, useEffect, useState } from 'react';
  2. import type { IRevision, IRevisionHasId, Ref } from '@growi/core';
  3. import { LoadingSpinner } from '@growi/ui/dist/components';
  4. import { useTranslation } from 'next-i18next';
  5. import type { RendererOptions } from '~/interfaces/renderer-options';
  6. import { useSWRxPageRevision } from '~/stores/page';
  7. import loggerFactory from '~/utils/logger';
  8. import RevisionRenderer from '../../../components/PageView/RevisionRenderer';
  9. export const ROOT_ELEM_ID = 'revision-loader' as const;
  10. export type RevisionLoaderProps = {
  11. rendererOptions: RendererOptions;
  12. pageId: string;
  13. revisionId: Ref<IRevision>;
  14. onRevisionLoaded?: (revision: IRevisionHasId) => void;
  15. };
  16. const logger = loggerFactory('growi:Page:RevisionLoader');
  17. /**
  18. * Load data from server and render RevisionBody component
  19. */
  20. export const RevisionLoader = (props: RevisionLoaderProps): JSX.Element => {
  21. const { t } = useTranslation();
  22. const { rendererOptions, pageId, revisionId, onRevisionLoaded } = props;
  23. const {
  24. data: pageRevision,
  25. isLoading,
  26. error,
  27. } = useSWRxPageRevision(pageId, revisionId);
  28. const [markdown, setMarkdown] = useState<string>('');
  29. useEffect(() => {
  30. if (pageRevision != null) {
  31. setMarkdown(pageRevision?.body ?? '');
  32. if (onRevisionLoaded != null) {
  33. onRevisionLoaded(pageRevision);
  34. }
  35. }
  36. }, [onRevisionLoaded, pageRevision]);
  37. useEffect(() => {
  38. if (error != null) {
  39. const isForbidden = error != null && error[0].code === 'forbidden-page';
  40. if (isForbidden) {
  41. setMarkdown(
  42. `<span className="material-symbols-outlined p-1">cancel</span>${t('not_allowed_to_see_this_page')}`,
  43. );
  44. } else {
  45. const errorMessages = error.map((error) => {
  46. return `<span className="material-symbols-outlined p-1">cancel</span><span class="text-muted"><em>${error.message}</em></span>`;
  47. });
  48. setMarkdown(errorMessages.join('\n'));
  49. }
  50. }
  51. }, [error, t]);
  52. if (isLoading) {
  53. return (
  54. <div className="wiki">
  55. <div className="text-muted text-center">
  56. <LoadingSpinner className="me-1 fs-3" />
  57. </div>
  58. </div>
  59. );
  60. }
  61. return (
  62. <RevisionRenderer rendererOptions={rendererOptions} markdown={markdown} />
  63. );
  64. };