import React, { useCallback, useState } from 'react'; import nodePath from 'path'; import { DevidedPagePath, pathUtils } from '@growi/core'; import { useTranslation } from 'react-i18next'; import { UncontrolledTooltip, DropdownToggle } from 'reactstrap'; import { unbookmark } from '~/client/services/page-operation'; import { toastError, toastSuccess } from '~/client/util/apiNotification'; import { apiv3Put } from '~/client/util/apiv3-client'; import { IPageHasId, IPageInfoAll, IPageToDeleteWithMeta } from '~/interfaces/page'; import { OnDeletedFunction } from '~/interfaces/ui'; import { useSWRxCurrentUserBookmarks } from '~/stores/bookmark'; import { useIsGuestUser } from '~/stores/context'; import { usePageDeleteModal } from '~/stores/modal'; import ClosableTextInput, { AlertInfo, AlertType } from '../Common/ClosableTextInput'; import { MenuItemType, PageItemControl } from '../Common/Dropdown/PageItemControl'; type Props = { bookmarkedPage: IPageHasId, onUnbookmarked: () => void, onRenamed: () => void, onClickDeleteMenuItem: (pageToDelete: IPageToDeleteWithMeta) => void } const BookmarkItem = (props: Props) => { const { bookmarkedPage, onUnbookmarked, onRenamed, onClickDeleteMenuItem, } = props; const { t } = useTranslation(); const [isRenameInputShown, setRenameInputShown] = useState(false); const dPagePath = new DevidedPagePath(bookmarkedPage.path, false, true); const { latter: pageTitle, former, isRoot } = dPagePath; const formerPagePath = isRoot ? pageTitle : pathUtils.addTrailingSlash(former); const bookmarkItemId = `bookmark-item-${bookmarkedPage._id}`; const bookmarkMenuItemClickHandler = useCallback(async() => { await unbookmark(bookmarkedPage._id); onUnbookmarked(); }, [onUnbookmarked, bookmarkedPage]); const renameMenuItemClickHandler = useCallback(() => { setRenameInputShown(true); }, []); const inputValidator = (title: string | null): AlertInfo | null => { if (title == null || title === '' || title.trim() === '') { return { type: AlertType.WARNING, message: t('form_validation.title_required'), }; } return null; }; const pressEnterForRenameHandler = useCallback(async(inputText: string) => { const parentPath = pathUtils.addTrailingSlash(nodePath.dirname(bookmarkedPage.path ?? '')); const newPagePath = nodePath.resolve(parentPath, inputText); if (newPagePath === bookmarkedPage.path) { setRenameInputShown(false); return; } try { setRenameInputShown(false); await apiv3Put('/pages/rename', { pageId: bookmarkedPage._id, revisionId: bookmarkedPage.revision, newPagePath, }); onRenamed(); toastSuccess(t('renamed_pages', { path: bookmarkedPage.path })); } catch (err) { setRenameInputShown(true); toastError(err); } }, [bookmarkedPage, onRenamed, t]); const deleteMenuItemClickHandler = useCallback(async(_pageId: string, pageInfo: IPageInfoAll | undefined): Promise => { if (bookmarkedPage._id == null || bookmarkedPage.path == null) { throw Error('_id and path must not be null.'); } const pageToDelete: IPageToDeleteWithMeta = { data: { _id: bookmarkedPage._id, revision: bookmarkedPage.revision as string, path: bookmarkedPage.path, }, meta: pageInfo, }; onClickDeleteMenuItem(pageToDelete); }, [bookmarkedPage, onClickDeleteMenuItem]); return (
  • { isRenameInputShown ? ( { setRenameInputShown(false) }} onPressEnter={pressEnterForRenameHandler} inputValidator={inputValidator} /> ) : (

    {pageTitle}

    )} { formerPagePath }
  • ); }; const Bookmarks = () : JSX.Element => { const { t } = useTranslation(); const { data: isGuestUser } = useIsGuestUser(); const { data: currentUserBookmarksData, mutate: mutateCurrentUserBookmarks } = useSWRxCurrentUserBookmarks(); const { open: openDeleteModal } = usePageDeleteModal(); const deleteMenuItemClickHandler = (pageToDelete: IPageToDeleteWithMeta) => { const pageDeletedHandler : OnDeletedFunction = (pathOrPathsToDelete, _isRecursively, isCompletely) => { if (typeof pathOrPathsToDelete !== 'string') { return; } const path = pathOrPathsToDelete; if (isCompletely) { toastSuccess(t('deleted_pages_completely', { path })); } else { toastSuccess(t('deleted_pages', { path })); } mutateCurrentUserBookmarks(); }; openDeleteModal([pageToDelete], { onDeleted: pageDeletedHandler }); }; const renderBookmarkList = () => { if (currentUserBookmarksData?.length === 0) { return (

    { t('No bookmarks yet') }

    ); } return ( ); }; return ( <>

    {t('Bookmarks')}

    { isGuestUser ? (

    { t('Not available for guest') }

    ) : renderBookmarkList() } ); }; export default Bookmarks;