ContextExtractor.tsx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import React, { FC, useEffect, useState } from 'react';
  2. import { pagePathUtils } from '@growi/core';
  3. import {
  4. useSiteUrl,
  5. useCurrentCreatedAt, useDeleteUsername, useDeletedAt, useHasChildren, useHasDraftOnHackmd,
  6. useIsDeleted, useIsNotCreatable, useIsTrashPage, useIsUserPage, useLastUpdateUsername,
  7. useCurrentPageId, usePageIdOnHackmd, usePageUser, useCurrentPagePath, useRevisionCreatedAt, useRevisionId, useRevisionIdHackmdSynced,
  8. useShareLinkId, useShareLinksNumber, useTemplateTagData, useCurrentUpdatedAt, useCreator, useRevisionAuthor, useCurrentUser, useTargetAndAncestors,
  9. useSlackChannels, useNotFoundTargetPathOrId, useEmptyPagePermalink, useIsSearchPage, useIsForbidden, useIsIdenticalPath,
  10. useIsAclEnabled, useIsSearchServiceConfigured, useIsSearchServiceReachable, useIsEnabledAttachTitleHeader, useIsNotFoundPermalink,
  11. } from '../../stores/context';
  12. import {
  13. useIsDeviceSmallerThanMd, useIsDeviceSmallerThanLg,
  14. usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser, useSidebarCollapsed, useCurrentSidebarContents, useCurrentProductNavWidth,
  15. useSelectedGrant, useSelectedGrantGroupId, useSelectedGrantGroupName,
  16. } from '~/stores/ui';
  17. import { useSetupGlobalSocket, useSetupGlobalAdminSocket } from '~/stores/websocket';
  18. import { IUserUISettings } from '~/interfaces/user-ui-settings';
  19. const { isTrashPage: _isTrashPage } = pagePathUtils;
  20. const jsonNull = 'null';
  21. const ContextExtractorOnce: FC = () => {
  22. const mainContent = document.querySelector('#content-main');
  23. const notFoundContentForPt = document.getElementById('growi-pagetree-not-found-context');
  24. const notFoundContent = document.getElementById('growi-not-found-context');
  25. const forbiddenContent = document.getElementById('forbidden-page');
  26. /*
  27. * App Context from DOM
  28. */
  29. const currentUser = JSON.parse(document.getElementById('growi-current-user')?.textContent || jsonNull);
  30. /*
  31. * Settings from context-hydrate DOM
  32. */
  33. const configByContextHydrate = JSON.parse(document.getElementById('growi-context-hydrate')?.textContent || jsonNull);
  34. /*
  35. * UserUISettings from DOM
  36. */
  37. const userUISettings: Partial<IUserUISettings> = JSON.parse(document.getElementById('growi-user-ui-settings')?.textContent || jsonNull);
  38. /*
  39. * Page Context from DOM
  40. */
  41. const revisionId = mainContent?.getAttribute('data-page-revision-id');
  42. const path = decodeURI(mainContent?.getAttribute('data-path') || '');
  43. const pageId = mainContent?.getAttribute('data-page-id') || null;
  44. const revisionCreatedAt = +(mainContent?.getAttribute('data-page-revision-created') || '');
  45. // createdAt
  46. const createdAtAttribute = mainContent?.getAttribute('data-page-created-at');
  47. const createdAt: Date | null = (createdAtAttribute != null) ? new Date(createdAtAttribute) : null;
  48. // updatedAt
  49. const updatedAtAttribute = mainContent?.getAttribute('data-page-updated-at');
  50. const updatedAt: Date | null = (updatedAtAttribute != null) ? new Date(updatedAtAttribute) : null;
  51. const deletedAt = mainContent?.getAttribute('data-page-deleted-at') || null;
  52. const isIdenticalPath = JSON.parse(mainContent?.getAttribute('data-identical-path') || jsonNull) ?? false;
  53. const isUserPage = JSON.parse(mainContent?.getAttribute('data-page-user') || jsonNull) != null;
  54. const isTrashPage = _isTrashPage(path);
  55. const isDeleted = JSON.parse(mainContent?.getAttribute('data-page-is-deleted') || jsonNull) ?? false;
  56. const isNotCreatable = JSON.parse(mainContent?.getAttribute('data-page-is-not-creatable') || jsonNull) ?? false;
  57. const isForbidden = forbiddenContent != null;
  58. const pageUser = JSON.parse(mainContent?.getAttribute('data-page-user') || jsonNull);
  59. const hasChildren = JSON.parse(mainContent?.getAttribute('data-page-has-children') || jsonNull);
  60. const templateTagData = mainContent?.getAttribute('data-template-tags') || null;
  61. const shareLinksNumber = mainContent?.getAttribute('data-share-links-number');
  62. const shareLinkId = JSON.parse(mainContent?.getAttribute('data-share-link-id') || jsonNull);
  63. const revisionIdHackmdSynced = mainContent?.getAttribute('data-page-revision-id-hackmd-synced') || null;
  64. const lastUpdateUsername = mainContent?.getAttribute('data-page-last-update-username') || null;
  65. const deleteUsername = mainContent?.getAttribute('data-page-delete-username') || null;
  66. const pageIdOnHackmd = mainContent?.getAttribute('data-page-id-on-hackmd') || null;
  67. const hasDraftOnHackmd = !!mainContent?.getAttribute('data-page-has-draft-on-hackmd');
  68. const creator = JSON.parse(mainContent?.getAttribute('data-page-creator') || jsonNull);
  69. const revisionAuthor = JSON.parse(mainContent?.getAttribute('data-page-revision-author') || jsonNull);
  70. const targetAndAncestors = JSON.parse(document.getElementById('growi-pagetree-target-and-ancestors')?.textContent || jsonNull);
  71. const notFoundTargetPathOrId = JSON.parse(notFoundContentForPt?.getAttribute('data-not-found-target-path-or-id') || jsonNull);
  72. const emptyPagePermalink = JSON.parse(notFoundContentForPt?.getAttribute('data-empty-page-permalink') || jsonNull);
  73. const isNotFoundPermalink = JSON.parse(notFoundContent?.getAttribute('data-is-not-found-permalink') || jsonNull);
  74. const slackChannels = mainContent?.getAttribute('data-slack-channels') || '';
  75. const isSearchPage = document.getElementById('search-page') != null;
  76. const grant = +(mainContent?.getAttribute('data-page-grant') || 1);
  77. const grantGroupId = mainContent?.getAttribute('data-page-grant-group') || null;
  78. const grantGroupName = mainContent?.getAttribute('data-page-grant-group-name') || null;
  79. /*
  80. * use static swr
  81. */
  82. // App
  83. useCurrentUser(currentUser);
  84. // UserUISettings
  85. usePreferDrawerModeByUser(userUISettings?.preferDrawerModeByUser);
  86. usePreferDrawerModeOnEditByUser(userUISettings?.preferDrawerModeOnEditByUser);
  87. useSidebarCollapsed(userUISettings?.isSidebarCollapsed);
  88. useCurrentSidebarContents(userUISettings?.currentSidebarContents);
  89. useCurrentProductNavWidth(userUISettings?.currentProductNavWidth);
  90. // hydrated config
  91. useSiteUrl(configByContextHydrate.crowi.url);
  92. useIsAclEnabled(configByContextHydrate.isAclEnabled);
  93. useIsSearchServiceConfigured(configByContextHydrate.isSearchServiceConfigured);
  94. useIsSearchServiceReachable(configByContextHydrate.isSearchServiceReachable);
  95. useIsEnabledAttachTitleHeader(configByContextHydrate.isEnabledAttachTitleHeader);
  96. // Page
  97. useCurrentCreatedAt(createdAt);
  98. useDeleteUsername(deleteUsername);
  99. useDeletedAt(deletedAt);
  100. useHasChildren(hasChildren);
  101. useHasDraftOnHackmd(hasDraftOnHackmd);
  102. useIsIdenticalPath(isIdenticalPath);
  103. useIsDeleted(isDeleted);
  104. useIsNotCreatable(isNotCreatable);
  105. useIsForbidden(isForbidden);
  106. useIsTrashPage(isTrashPage);
  107. useIsUserPage(isUserPage);
  108. useLastUpdateUsername(lastUpdateUsername);
  109. useCurrentPageId(pageId);
  110. usePageIdOnHackmd(pageIdOnHackmd);
  111. usePageUser(pageUser);
  112. useCurrentPagePath(path);
  113. useRevisionCreatedAt(revisionCreatedAt);
  114. useRevisionId(revisionId);
  115. useRevisionIdHackmdSynced(revisionIdHackmdSynced);
  116. useShareLinkId(shareLinkId);
  117. useShareLinksNumber(shareLinksNumber);
  118. useTemplateTagData(templateTagData);
  119. useCurrentUpdatedAt(updatedAt);
  120. useCreator(creator);
  121. useRevisionAuthor(revisionAuthor);
  122. useTargetAndAncestors(targetAndAncestors);
  123. useNotFoundTargetPathOrId(notFoundTargetPathOrId);
  124. useEmptyPagePermalink(emptyPagePermalink);
  125. useIsNotFoundPermalink(isNotFoundPermalink);
  126. useIsSearchPage(isSearchPage);
  127. // Navigation
  128. usePreferDrawerModeByUser();
  129. usePreferDrawerModeOnEditByUser();
  130. useIsDeviceSmallerThanMd();
  131. // Navigation
  132. usePreferDrawerModeByUser();
  133. usePreferDrawerModeOnEditByUser();
  134. useIsDeviceSmallerThanMd();
  135. // Editor
  136. useSlackChannels(slackChannels);
  137. useSelectedGrant(grant);
  138. useSelectedGrantGroupId(grantGroupId);
  139. useSelectedGrantGroupName(grantGroupName);
  140. // SearchResult
  141. useIsDeviceSmallerThanLg();
  142. // Global Socket
  143. useSetupGlobalSocket();
  144. useSetupGlobalAdminSocket();
  145. return null;
  146. };
  147. const ContextExtractor: FC = React.memo(() => {
  148. const [isRunOnce, setRunOnce] = useState(false);
  149. useEffect(() => {
  150. setRunOnce(true);
  151. }, []);
  152. return isRunOnce ? null : <ContextExtractorOnce></ContextExtractorOnce>;
  153. });
  154. export default ContextExtractor;