import React, { useState, useCallback } from 'react'; import { isPopulated } from '@growi/core'; import type { IPagePopulatedToShowRevision, IPageToRenameWithMeta, IPageWithMeta, IPageInfoForEntity, } from '@growi/core'; import { pagePathUtils } from '@growi/core/dist/utils'; import { useTranslation } from 'next-i18next'; import dynamic from 'next/dynamic'; import { useRouter } from 'next/router'; import { DropdownItem } from 'reactstrap'; import { exportAsMarkdown, updateContentWidth } from '~/client/services/page-operation'; import type { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui'; import { useCurrentPathname, useCurrentUser, useIsGuestUser, useIsReadOnlyUser, useIsSharedUser, useShareLinkId, useIsContainerFluid, } from '~/stores/context'; import { usePageAccessoriesModal, PageAccessoriesModalContents, type IPageForPageDuplicateModal, usePageDuplicateModal, usePageRenameModal, usePageDeleteModal, usePagePresentationModal, } from '~/stores/modal'; import { useSWRMUTxCurrentPage, useCurrentPageId, useSWRxPageInfo, } from '~/stores/page'; import { mutatePageTree } from '~/stores/page-listing'; import { useEditorMode, useIsAbleToShowPageManagement, useIsAbleToChangeEditorMode, useSelectedGrant, } from '~/stores/ui'; import { CreateTemplateModal } from '../CreateTemplateModal'; import AttachmentIcon from '../Icons/AttachmentIcon'; import HistoryIcon from '../Icons/HistoryIcon'; import PresentationIcon from '../Icons/PresentationIcon'; import ShareLinkIcon from '../Icons/ShareLinkIcon'; import { NotAvailable } from '../NotAvailable'; import { Skeleton } from '../Skeleton'; import styles from './GrowiContextualSubNavigation.module.scss'; import PageEditorModeManagerStyles from './PageEditorModeManager.module.scss'; const PageEditorModeManager = dynamic( () => import('./PageEditorModeManager').then(mod => mod.PageEditorModeManager), { ssr: false, loading: () => }, ); const PageControls = dynamic( () => import('../PageControls').then(mod => mod.PageControls), { ssr: false, loading: () => <> }, ); type PageOperationMenuItemsProps = { pageId: string, revisionId: string, isLinkSharingDisabled?: boolean, } const PageOperationMenuItems = (props: PageOperationMenuItemsProps): JSX.Element => { const { t } = useTranslation(); const { pageId, revisionId, isLinkSharingDisabled, } = props; const { data: isGuestUser } = useIsGuestUser(); const { data: isReadOnlyUser } = useIsReadOnlyUser(); const { data: isSharedUser } = useIsSharedUser(); const { open: openPresentationModal } = usePagePresentationModal(); const { open: openAccessoriesModal } = usePageAccessoriesModal(); return ( <> {/* Presentation */} openPresentationModal()} data-testid="open-presentation-modal-btn" className="grw-page-control-dropdown-item" > {t('Presentation Mode')} {/* Export markdown */} exportAsMarkdown(pageId, revisionId, 'md')} className="grw-page-control-dropdown-item" > {t('export_bulk.export_page_markdown')} {/* TODO: show Tooltip when menu is disabled refs: PageAccessoriesModalControl */} openAccessoriesModal(PageAccessoriesModalContents.PageHistory)} disabled={!!isGuestUser || !!isSharedUser} data-testid="open-page-accessories-modal-btn-with-history-tab" className="grw-page-control-dropdown-item" > {t('History')} openAccessoriesModal(PageAccessoriesModalContents.Attachment)} data-testid="open-page-accessories-modal-btn-with-attachment-data-tab" className="grw-page-control-dropdown-item" > {t('attachment_data')} {!isGuestUser && !isReadOnlyUser && !isSharedUser && ( openAccessoriesModal(PageAccessoriesModalContents.ShareLink)} data-testid="open-page-accessories-modal-btn-with-share-link-management-data-tab" className="grw-page-control-dropdown-item" > {t('share_links.share_link_management')} )} ); }; type CreateTemplateMenuItemsProps = { onClickTemplateMenuItem: (isPageTemplateModalShown: boolean) => void, } const CreateTemplateMenuItems = (props: CreateTemplateMenuItemsProps): JSX.Element => { const { t } = useTranslation(); const { onClickTemplateMenuItem } = props; const openPageTemplateModalHandler = () => { onClickTemplateMenuItem(true); }; return ( <> {/* Create template */} {t('template.option_label.create/edit')} ); }; type GrowiContextualSubNavigationProps = { currentPage?: IPagePopulatedToShowRevision | null, isLinkSharingDisabled?: boolean, }; const GrowiContextualSubNavigation = (props: GrowiContextualSubNavigationProps): JSX.Element => { const { currentPage } = props; const router = useRouter(); const { data: shareLinkId } = useShareLinkId(); const { trigger: mutateCurrentPage } = useSWRMUTxCurrentPage(); const { data: currentPathname } = useCurrentPathname(); const isSharedPage = pagePathUtils.isSharedPage(currentPathname ?? ''); const revision = currentPage?.revision; const revisionId = (revision != null && isPopulated(revision)) ? revision._id : undefined; const { data: editorMode } = useEditorMode(); const { data: pageId } = useCurrentPageId(); const { data: currentUser } = useCurrentUser(); const { data: isGuestUser } = useIsGuestUser(); const { data: isReadOnlyUser } = useIsReadOnlyUser(); const { data: isSharedUser } = useIsSharedUser(); const { data: isContainerFluid } = useIsContainerFluid(); const { data: grantData } = useSelectedGrant(); const { data: isAbleToShowPageManagement } = useIsAbleToShowPageManagement(); const { data: isAbleToChangeEditorMode } = useIsAbleToChangeEditorMode(); const { open: openDuplicateModal } = usePageDuplicateModal(); const { open: openRenameModal } = usePageRenameModal(); const { open: openDeleteModal } = usePageDeleteModal(); const { mutate: mutatePageInfo } = useSWRxPageInfo(pageId); const path = currentPage?.path ?? currentPathname; // const grant = currentPage?.grant ?? grantData?.grant; // const grantUserGroupId = currentPage?.grantedGroup?._id ?? grantData?.grantedGroup?.id; const [isPageTemplateModalShown, setIsPageTempleteModalShown] = useState(false); const { isLinkSharingDisabled } = props; const duplicateItemClickedHandler = useCallback(async(page: IPageForPageDuplicateModal) => { const duplicatedHandler: OnDuplicatedFunction = (fromPath, toPath) => { router.push(toPath); }; openDuplicateModal(page, { onDuplicated: duplicatedHandler }); }, [openDuplicateModal, router]); const renameItemClickedHandler = useCallback(async(page: IPageToRenameWithMeta) => { const renamedHandler: OnRenamedFunction = () => { mutateCurrentPage(); mutatePageInfo(); mutatePageTree(); }; openRenameModal(page, { onRenamed: renamedHandler }); }, [mutateCurrentPage, mutatePageInfo, openRenameModal]); const deleteItemClickedHandler = useCallback((pageWithMeta: IPageWithMeta) => { const deletedHandler: OnDeletedFunction = (pathOrPathsToDelete, isRecursively, isCompletely) => { if (typeof pathOrPathsToDelete !== 'string') { return; } const path = pathOrPathsToDelete; if (isCompletely) { // redirect to NotFound Page router.push(path); } else if (currentPathname != null) { router.push(currentPathname); } mutateCurrentPage(); mutatePageInfo(); mutatePageTree(); }; openDeleteModal([pageWithMeta], { onDeleted: deletedHandler }); }, [currentPathname, mutateCurrentPage, openDeleteModal, router, mutatePageInfo]); const switchContentWidthHandler = useCallback(async(pageId: string, value: boolean) => { if (!isSharedPage) { await updateContentWidth(pageId, value); mutateCurrentPage(); } }, [isSharedPage, mutateCurrentPage]); const additionalMenuItemsRenderer = useCallback(() => { if (revisionId == null || pageId == null) { return ( <> {!isReadOnlyUser && ( setIsPageTempleteModalShown(true)} /> ) } ); } return ( <> {!isReadOnlyUser && ( <> setIsPageTempleteModalShown(true)} /> ) } ); }, [isLinkSharingDisabled, isReadOnlyUser, pageId, revisionId]); return ( <>
{pageId != null && ( )} {isAbleToChangeEditorMode && ( )}
{path != null && currentUser != null && !isReadOnlyUser && ( setIsPageTempleteModalShown(false)} /> )} ); }; export default GrowiContextualSubNavigation;