import React, { memo, useCallback, useEffect, useMemo, useRef, useState, } from 'react'; import { useTranslation } from 'next-i18next'; import { debounce } from 'throttle-debounce'; import { useTargetAndAncestors, useIsGuestUser, useIsReadOnlyUser } from '~/stores/context'; import { useCurrentPagePath, useCurrentPageId } from '~/stores/page'; import { mutatePageTree, useSWRxPageAncestorsChildren, useSWRxRootPage, useSWRxV5MigrationStatus, } from '~/stores/page-listing'; import { useSidebarScrollerRef } from '~/stores/ui'; import loggerFactory from '~/utils/logger'; import { ItemsTree } from '../../ItemsTree/ItemsTree'; import { PageTreeItem } from '../PageTreeItem'; import { SidebarHeaderReloadButton } from '../SidebarHeaderReloadButton'; import { PrivateLegacyPagesLink } from './PrivateLegacyPagesLink'; const logger = loggerFactory('growi:cli:PageTreeSubstance'); type HeaderProps = { isWipPageShown: boolean, onWipPageShownChange?: () => void } export const PageTreeHeader = memo(({ isWipPageShown, onWipPageShownChange }: HeaderProps) => { const { t } = useTranslation(); const { mutate: mutateRootPage } = useSWRxRootPage({ suspense: true }); useSWRxV5MigrationStatus({ suspense: true }); const mutate = useCallback(() => { mutateRootPage(); mutatePageTree(); }, [mutateRootPage]); return ( <> mutate()} />
); }); PageTreeHeader.displayName = 'PageTreeHeader'; const PageTreeUnavailable = () => { const { t } = useTranslation(); // TODO : improve design // Story : https://redmine.weseek.co.jp/issues/83755 return (

{t('v5_page_migration.page_tree_not_avaliable')}

{t('v5_page_migration.go_to_settings')}
); }; type PageTreeContentProps = { isWipPageShown: boolean, } export const PageTreeContent = memo(({ isWipPageShown }: PageTreeContentProps) => { const { data: isGuestUser } = useIsGuestUser(); const { data: isReadOnlyUser } = useIsReadOnlyUser(); const { data: currentPath } = useCurrentPagePath(); const { data: targetId } = useCurrentPageId(); const { data: targetAndAncestorsData } = useTargetAndAncestors(); const { data: migrationStatus } = useSWRxV5MigrationStatus({ suspense: true }); const targetPathOrId = targetId || currentPath; const path = currentPath || '/'; const { data: ancestorsChildrenResult } = useSWRxPageAncestorsChildren(path, { suspense: true }); const { data: rootPageResult } = useSWRxRootPage({ suspense: true }); const { data: sidebarScrollerRef } = useSidebarScrollerRef(); const [isInitialScrollCompleted, setIsInitialScrollCompleted] = useState(false); const rootElemRef = useRef(null); // *************************** Scroll on init *************************** const scrollOnInit = useCallback(() => { const scrollTargetElement = document.getElementById('grw-pagetree-current-page-item'); if (sidebarScrollerRef?.current == null || scrollTargetElement == null) { return; } logger.debug('scrollOnInit has invoked'); const scrollElement = sidebarScrollerRef.current; // NOTE: could not use scrollIntoView // https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move // calculate the center point const scrollTop = scrollTargetElement.offsetTop - scrollElement.getBoundingClientRect().height / 2; scrollElement.scrollTo({ top: scrollTop }); setIsInitialScrollCompleted(true); }, [sidebarScrollerRef]); const scrollOnInitDebounced = useMemo(() => debounce(500, scrollOnInit), [scrollOnInit]); useEffect(() => { if (isInitialScrollCompleted || ancestorsChildrenResult == null || rootPageResult == null) { return; } const rootElement = rootElemRef.current as HTMLElement | null; if (rootElement == null) { return; } const observerCallback = (mutationRecords: MutationRecord[]) => { mutationRecords.forEach(() => scrollOnInitDebounced()); }; const observer = new MutationObserver(observerCallback); observer.observe(rootElement, { childList: true, subtree: true }); // first call for the situation that all rendering is complete at this point scrollOnInitDebounced(); return () => { observer.disconnect(); }; }, [isInitialScrollCompleted, scrollOnInitDebounced, ancestorsChildrenResult, rootPageResult]); // ******************************* end ******************************* if (!migrationStatus?.isV5Compatible) { return ; } /* * dependencies */ if (isGuestUser == null) { return null; } return (
{!isGuestUser && !isReadOnlyUser && migrationStatus?.migratablePagesCount != null && migrationStatus.migratablePagesCount !== 0 && (
)}
); }); PageTreeContent.displayName = 'PageTreeContent';