page.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import { IPageInfoForEntity, IPagePopulatedToShowRevision, Nullable } from '@growi/core';
  2. import useSWR, { SWRResponse } from 'swr';
  3. import useSWRImmutable from 'swr/immutable';
  4. import { apiGet } from '~/client/util/apiv1-client';
  5. import { apiv3Get } from '~/client/util/apiv3-client';
  6. import {
  7. IPageInfo, IPageInfoForOperation,
  8. } from '~/interfaces/page';
  9. import { IRecordApplicableGrant, IResIsGrantNormalized } from '~/interfaces/page-grant';
  10. import { IRevisionsForPagination } from '~/interfaces/revision';
  11. import { IPageTagsInfo } from '../interfaces/tag';
  12. import { useCurrentPageId } from './context';
  13. export const useSWRxPage = (pageId?: string|null, shareLinkId?: string): SWRResponse<IPagePopulatedToShowRevision|null, Error> => {
  14. return useSWR<IPagePopulatedToShowRevision|null, Error>(
  15. pageId != null ? ['/page', pageId, shareLinkId] : null,
  16. (endpoint, pageId, shareLinkId) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { pageId, shareLinkId })
  17. .then(result => result.data.page)
  18. .catch((errs) => {
  19. if (!Array.isArray(errs)) { throw Error('error is not array') }
  20. const statusCode = errs[0].status;
  21. if (statusCode === 403 || statusCode === 404) {
  22. // for NotFoundPage
  23. return null;
  24. }
  25. throw Error('failed to get page');
  26. }),
  27. );
  28. };
  29. export const useSWRxPageByPath = (path?: string): SWRResponse<IPagePopulatedToShowRevision, Error> => {
  30. return useSWR<IPagePopulatedToShowRevision, Error>(
  31. path != null ? ['/page', path] : null,
  32. (endpoint, path) => apiv3Get<{ page: IPagePopulatedToShowRevision }>(endpoint, { path }).then(result => result.data.page),
  33. );
  34. };
  35. export const useSWRxCurrentPage = (shareLinkId?: string, initialData?: IPagePopulatedToShowRevision): SWRResponse<IPagePopulatedToShowRevision|null, Error> => {
  36. const { data: currentPageId } = useCurrentPageId();
  37. const swrResult = useSWRxPage(currentPageId, shareLinkId);
  38. // use mutate because fallbackData does not work
  39. // see: https://github.com/weseek/growi/commit/5038473e8d6028c9c91310e374a7b5f48b921a15
  40. if (initialData != null) {
  41. swrResult.mutate(initialData);
  42. }
  43. return swrResult;
  44. };
  45. export const useSWRxTagsInfo = (pageId: Nullable<string>): SWRResponse<IPageTagsInfo | undefined, Error> => {
  46. const endpoint = `/pages.getPageTag?pageId=${pageId}`;
  47. const key = [endpoint, pageId];
  48. const fetcher = async(endpoint: string, pageId: Nullable<string>) => {
  49. let tags: string[] = [];
  50. // when the page exists
  51. if (pageId != null) {
  52. const res = await apiGet<IPageTagsInfo>(endpoint, { pageId });
  53. tags = res?.tags;
  54. }
  55. return { tags };
  56. };
  57. return useSWRImmutable(key, fetcher);
  58. };
  59. export const useSWRxPageInfo = (
  60. pageId: string | null | undefined,
  61. shareLinkId?: string | null,
  62. initialData?: IPageInfoForEntity,
  63. ): SWRResponse<IPageInfo | IPageInfoForOperation, Error> => {
  64. // assign null if shareLinkId is undefined in order to identify SWR key only by pageId
  65. const fixedShareLinkId = shareLinkId ?? null;
  66. const swrResult = useSWRImmutable<IPageInfo | IPageInfoForOperation, Error>(
  67. pageId != null ? ['/page/info', pageId, fixedShareLinkId] : null,
  68. (endpoint, pageId, shareLinkId) => apiv3Get(endpoint, { pageId, shareLinkId }).then(response => response.data),
  69. { fallbackData: initialData },
  70. );
  71. // use mutate because fallbackData does not work
  72. if (initialData != null) {
  73. swrResult.mutate(initialData);
  74. }
  75. return swrResult;
  76. };
  77. export const useSWRxPageRevisions = (
  78. pageId: string,
  79. page: number, // page number of pagination
  80. limit: number, // max number of pages in one paginate
  81. ): SWRResponse<IRevisionsForPagination, Error> => {
  82. return useSWRImmutable<IRevisionsForPagination, Error>(
  83. ['/revisions/list', pageId, page, limit],
  84. (endpoint, pageId, page, limit) => {
  85. return apiv3Get(endpoint, { pageId, page, limit }).then((response) => {
  86. const revisions = {
  87. revisions: response.data.docs,
  88. totalCounts: response.data.totalDocs,
  89. };
  90. return revisions;
  91. });
  92. },
  93. );
  94. };
  95. /*
  96. * Grant normalization fetching hooks
  97. */
  98. export const useSWRxIsGrantNormalized = (
  99. pageId: string | null | undefined,
  100. ): SWRResponse<IResIsGrantNormalized, Error> => {
  101. return useSWRImmutable(
  102. pageId != null ? ['/page/is-grant-normalized', pageId] : null,
  103. (endpoint, pageId) => apiv3Get(endpoint, { pageId }).then(response => response.data),
  104. );
  105. };
  106. export const useSWRxApplicableGrant = (
  107. pageId: string | null | undefined,
  108. ): SWRResponse<IRecordApplicableGrant, Error> => {
  109. return useSWRImmutable(
  110. pageId != null ? ['/page/applicable-grant', pageId] : null,
  111. (endpoint, pageId) => apiv3Get(endpoint, { pageId }).then(response => response.data),
  112. );
  113. };