import React, { useState, useCallback } from 'react'; import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem, } from 'reactstrap'; import toastr from 'toastr'; import { useTranslation } from 'react-i18next'; import loggerFactory from '~/utils/logger'; import { IPageInfoAll, isIPageInfoForOperation, } from '~/interfaces/page'; import { useSWRxPageInfo } from '~/stores/page'; const logger = loggerFactory('growi:cli:PageItemControl'); export type AdditionalMenuItemsRendererProps = { pageInfo: IPageInfoAll }; type CommonProps = { pageInfo?: IPageInfoAll, isEnableActions?: boolean, showBookmarkMenuItem?: boolean, onClickBookmarkMenuItem?: (pageId: string, newValue?: boolean) => Promise, onClickDuplicateMenuItem?: (pageId: string) => Promise | void, onClickRenameMenuItem?: (pageId: string) => Promise | void, onClickDeleteMenuItem?: (pageId: string) => Promise | void, additionalMenuItemRenderer?: React.FunctionComponent, } type DropdownMenuProps = CommonProps & { pageId: string, isLoading?: boolean, } const PageItemControlDropdownMenu = React.memo((props: DropdownMenuProps): JSX.Element => { const { t } = useTranslation(''); const { pageId, isLoading, pageInfo, isEnableActions, showBookmarkMenuItem, onClickBookmarkMenuItem, onClickDuplicateMenuItem, onClickRenameMenuItem, onClickDeleteMenuItem, additionalMenuItemRenderer: AdditionalMenuItems, } = props; // eslint-disable-next-line react-hooks/rules-of-hooks const bookmarkItemClickedHandler = useCallback(async() => { if (!isIPageInfoForOperation(pageInfo) || onClickBookmarkMenuItem == null) { return; } await onClickBookmarkMenuItem(pageId, !pageInfo.isBookmarked); }, [onClickBookmarkMenuItem, pageId, pageInfo]); // eslint-disable-next-line react-hooks/rules-of-hooks const duplicateItemClickedHandler = useCallback(async() => { if (onClickDuplicateMenuItem == null) { return; } await onClickDuplicateMenuItem(pageId); }, [onClickDuplicateMenuItem, pageId]); // eslint-disable-next-line react-hooks/rules-of-hooks const renameItemClickedHandler = useCallback(async() => { if (onClickRenameMenuItem == null) { return; } await onClickRenameMenuItem(pageId); }, [onClickRenameMenuItem, pageId]); // eslint-disable-next-line react-hooks/rules-of-hooks const deleteItemClickedHandler = useCallback(async() => { if (pageInfo == null || onClickDeleteMenuItem == null) { return; } if (!pageInfo.isDeletable) { logger.warn('This page could not be deleted.'); return; } await onClickDeleteMenuItem(pageId); }, [onClickDeleteMenuItem, pageId, pageInfo]); let contents = <>; if (isLoading) { contents = (
); } else if (pageId != null && pageInfo != null) { contents = ( <> { !isEnableActions && (

{t('search_result.currently_not_implemented')}

) } {/* Bookmark */} { showBookmarkMenuItem && isEnableActions && !pageInfo.isEmpty && isIPageInfoForOperation(pageInfo) && ( { pageInfo.isBookmarked ? t('remove_bookmark') : t('add_bookmark') } ) } {/* Duplicate */} { isEnableActions && ( {t('Duplicate')} ) } {/* Move/Rename */} { isEnableActions && pageInfo.isMovable && ( {t('Move/Rename')} ) } { AdditionalMenuItems && } {/* divider */} {/* Delete */} { isEnableActions && pageInfo.isMovable && ( <> {t('Delete')} )} ); } return ( {contents} ); }); type PageItemControlSubstanceProps = CommonProps & { pageId: string, fetchOnInit?: boolean, children?: React.ReactNode, } export const PageItemControlSubstance = (props: PageItemControlSubstanceProps): JSX.Element => { const { pageId, pageInfo: presetPageInfo, fetchOnInit, children, onClickBookmarkMenuItem, onClickDuplicateMenuItem, onClickRenameMenuItem, } = props; const [isOpen, setIsOpen] = useState(false); const shouldFetch = fetchOnInit === true || (!isIPageInfoForOperation(presetPageInfo) && isOpen); const shouldMutate = fetchOnInit === true || !isIPageInfoForOperation(presetPageInfo); const { data: fetchedPageInfo, mutate: mutatePageInfo } = useSWRxPageInfo(shouldFetch ? pageId : null); // mutate after handle event const bookmarkMenuItemClickHandler = useCallback(async(_pageId: string, _newValue: boolean) => { if (onClickBookmarkMenuItem != null) { await onClickBookmarkMenuItem(_pageId, _newValue); } if (shouldMutate) { mutatePageInfo(); } }, [mutatePageInfo, onClickBookmarkMenuItem, shouldMutate]); const isLoading = shouldFetch && fetchedPageInfo == null; const duplicateMenuItemClickHandler = useCallback(async() => { if (onClickDuplicateMenuItem == null) { return; } await onClickDuplicateMenuItem(pageId); }, [onClickDuplicateMenuItem, pageId]); const renameMenuItemClickHandler = useCallback(async() => { if (onClickRenameMenuItem == null) { return; } await onClickRenameMenuItem(pageId); }, [onClickRenameMenuItem, pageId]); return ( setIsOpen(!isOpen)}> { children ?? ( ) } ); }; type PageItemControlProps = CommonProps & { pageId?: string, children?: React.ReactNode, } export const PageItemControl = (props: PageItemControlProps): JSX.Element => { const { pageId } = props; if (pageId == null) { return <>; } return ; }; type AsyncPageItemControlProps = Omit & { pageId?: string, children?: React.ReactNode, } export const AsyncPageItemControl = (props: AsyncPageItemControlProps): JSX.Element => { const { pageId } = props; if (pageId == null) { return <>; } return ; };