PageContents.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import React, { useEffect } from 'react';
  2. import { pagePathUtils } from '@growi/core';
  3. import { useTranslation } from 'next-i18next';
  4. import type { HtmlElementNode } from 'rehype-toc';
  5. import { useDrawioModalLauncherForView } from '~/client/services/side-effects/drawio-modal-launcher-for-view';
  6. import { useHandsontableModalLauncherForView } from '~/client/services/side-effects/handsontable-modal-launcher-for-view';
  7. import { toastSuccess, toastError } from '~/client/util/toastr';
  8. import { useCurrentPathname } from '~/stores/context';
  9. import { useEditingMarkdown } from '~/stores/editor';
  10. import { useSWRxCurrentPage } from '~/stores/page';
  11. import { useViewOptions } from '~/stores/renderer';
  12. import { useCurrentPageTocNode } from '~/stores/ui';
  13. import { registerGrowiFacade } from '~/utils/growi-facade';
  14. import loggerFactory from '~/utils/logger';
  15. import RevisionRenderer from './RevisionRenderer';
  16. const logger = loggerFactory('growi:Page');
  17. export const PageContents = (): JSX.Element => {
  18. const { t } = useTranslation();
  19. const { data: currentPathname } = useCurrentPathname();
  20. const isSharedPage = pagePathUtils.isSharedPage(currentPathname ?? '');
  21. const { data: currentPage, mutate: mutateCurrentPage } = useSWRxCurrentPage();
  22. const { mutate: mutateEditingMarkdown } = useEditingMarkdown();
  23. const { mutate: mutateCurrentPageTocNode } = useCurrentPageTocNode();
  24. const { data: rendererOptions, mutate: mutateRendererOptions } = useViewOptions((toc: HtmlElementNode) => {
  25. mutateCurrentPageTocNode(toc);
  26. });
  27. // register to facade
  28. useEffect(() => {
  29. registerGrowiFacade({
  30. markdownRenderer: {
  31. optionsMutators: {
  32. viewOptionsMutator: mutateRendererOptions,
  33. },
  34. },
  35. });
  36. }, [mutateRendererOptions]);
  37. useHandsontableModalLauncherForView({
  38. onSaveSuccess: (newMarkdown) => {
  39. toastSuccess(t('toaster.save_succeeded'));
  40. // rerender
  41. if (!isSharedPage) {
  42. mutateCurrentPage();
  43. }
  44. mutateEditingMarkdown(newMarkdown);
  45. },
  46. onSaveError: (error) => {
  47. toastError(error);
  48. },
  49. });
  50. useDrawioModalLauncherForView({
  51. onSaveSuccess: (newMarkdown) => {
  52. toastSuccess(t('toaster.save_succeeded'));
  53. // rerender
  54. if (!isSharedPage) {
  55. mutateCurrentPage();
  56. }
  57. mutateEditingMarkdown(newMarkdown);
  58. },
  59. onSaveError: (error) => {
  60. toastError(error);
  61. },
  62. });
  63. if (currentPage == null || rendererOptions == null) {
  64. const entries = Object.entries({
  65. currentPage, rendererOptions,
  66. })
  67. .map(([key, value]) => [key, value == null ? 'null' : undefined])
  68. .filter(([, value]) => value != null);
  69. logger.warn('Some of materials are missing.', Object.fromEntries(entries));
  70. return <></>;
  71. }
  72. const { _id: revisionId, body: markdown } = currentPage.revision;
  73. return (
  74. <>
  75. { revisionId != null && (
  76. <RevisionRenderer rendererOptions={rendererOptions} markdown={markdown} />
  77. )}
  78. </>
  79. );
  80. };