| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import { useCallback } from 'react';
- import { useTranslation } from 'next-i18next';
- import { useDrop } from 'react-dnd';
- import { apiv3Post, apiv3Put } from '~/client/util/apiv3-client';
- import { toastError, toastSuccess } from '~/client/util/toastr';
- import { BookmarkFolderItems, DragItemType, DRAG_ITEM_TYPE } from '~/interfaces/bookmark-info';
- import { IPageHasId, IPageToDeleteWithMeta } from '~/interfaces/page';
- import { OnDeletedFunction } from '~/interfaces/ui';
- import { useSWRBookmarkInfo, useSWRxCurrentUserBookmarks } from '~/stores/bookmark';
- import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
- import { usePageDeleteModal } from '~/stores/modal';
- import { useSWRxCurrentPage } from '~/stores/page';
- import BookmarkFolderItem from './BookmarkFolderItem';
- import BookmarkItem from './BookmarkItem';
- import styles from './BookmarkFolderTree.module.scss';
- type BookmarkFolderTreeProps = {
- isUserHomePage?: boolean
- }
- type DragItemDataType = {
- bookmarkFolder: BookmarkFolderItems
- level: number
- parentFolder: BookmarkFolderItems | null
- } & IPageHasId
- const BookmarkFolderTree = (props: BookmarkFolderTreeProps): JSX.Element => {
- const acceptedTypes: DragItemType[] = [DRAG_ITEM_TYPE.FOLDER, DRAG_ITEM_TYPE.BOOKMARK];
- const { t } = useTranslation();
- const { isUserHomePage } = props;
- const { data: currentPage } = useSWRxCurrentPage();
- const { data: bookmarkFolderData, mutate: mutateBookamrkData } = useSWRxBookamrkFolderAndChild();
- const { data: userBookmarks, mutate: mutateUserBookmarks } = useSWRxCurrentUserBookmarks();
- const { mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(currentPage?._id);
- const { open: openDeleteModal } = usePageDeleteModal();
- const onUnbookmarkHandler = useCallback(() => {
- mutateUserBookmarks();
- mutateBookmarkInfo();
- }, [mutateBookmarkInfo, mutateUserBookmarks]);
- const onClickDeleteBookmarkHandler = useCallback((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 }));
- }
- mutateUserBookmarks();
- mutateBookmarkInfo();
- mutateBookamrkData();
- };
- openDeleteModal([pageToDelete], { onDeleted: pageDeletedHandler });
- }, [mutateBookmarkInfo, mutateBookamrkData, mutateUserBookmarks, openDeleteModal, t]);
- const itemDropHandler = async(item: DragItemDataType, dragType: string | null | symbol) => {
- if (dragType === DRAG_ITEM_TYPE.FOLDER) {
- try {
- await apiv3Put('/bookmark-folder', { bookmarkFolderId: item.bookmarkFolder._id, name: item.bookmarkFolder.name, parent: null });
- await mutateBookamrkData();
- toastSuccess(t('toaster.update_successed', { target: t('bookmark_folder.bookmark_folder'), ns: 'commons' }));
- }
- catch (err) {
- toastError(err);
- }
- }
- else {
- try {
- await apiv3Post('/bookmark-folder/add-boookmark-to-folder', { pageId: item._id, folderId: null });
- await mutateUserBookmarks();
- toastSuccess(t('toaster.add_succeeded', { target: t('bookmark_folder.bookmark'), ns: 'commons' }));
- }
- catch (err) {
- toastError(err);
- }
- }
- };
- const isDroppable = (item: DragItemDataType, dragType: string | null | symbol) => {
- if (dragType === DRAG_ITEM_TYPE.FOLDER) {
- const isRootFolder = item.level === 0;
- return !isRootFolder;
- }
- const isRootBookmark = item.parentFolder == null;
- return !isRootBookmark;
- };
- const [{ isOver, canDrop }, dropRef] = useDrop(() => ({
- accept: acceptedTypes,
- drop: (item: DragItemDataType, monitor) => {
- const dragType = monitor.getItemType();
- itemDropHandler(item, dragType);
- },
- canDrop: (item: DragItemDataType, monitor) => {
- const dragType = monitor.getItemType();
- return isDroppable(item, dragType);
- },
- collect: monitor => ({
- isOver: monitor.isOver({ shallow: true }) && monitor.canDrop(),
- canDrop: monitor.canDrop(),
- }),
- }));
- return (
- <>
- <div className={`grw-folder-tree-container ${styles['grw-folder-tree-container']}` } >
- <ul className={`grw-foldertree ${styles['grw-foldertree']} list-group px-2 py-2`}>
- {bookmarkFolderData?.map((item) => {
- return (
- <BookmarkFolderItem
- key={item._id}
- bookmarkFolder={item}
- isOpen={false}
- level={0}
- root={item._id}
- isUserHomePage={isUserHomePage}
- />
- );
- })}
- {userBookmarks?.map(page => (
- <div key={page._id} className="grw-foldertree-item-container grw-root-bookmarks">
- <BookmarkItem
- bookmarkedPage={page}
- key={page._id}
- onUnbookmarked={onUnbookmarkHandler}
- onRenamed={mutateUserBookmarks}
- onClickDeleteMenuItem={onClickDeleteBookmarkHandler}
- parentFolder={null}
- />
- </div>
- ))}
- </ul>
- { bookmarkFolderData && bookmarkFolderData.length > 0 && (
- <div ref={(c) => { dropRef(c) }} className= 'grw-drop-item-area' >
- { canDrop && isOver && (
- <div className='grw-accept-drop-item' >{t('bookmark_folder.drop_item_here')}</div>
- )}
- </div>
- ) }
- </div>
- </>
- );
- };
- export default BookmarkFolderTree;
|