|
@@ -3,6 +3,7 @@ import {
|
|
|
} from 'react';
|
|
} from 'react';
|
|
|
|
|
|
|
|
import { useTranslation } from 'next-i18next';
|
|
import { useTranslation } from 'next-i18next';
|
|
|
|
|
+import { useDrag, useDrop } from 'react-dnd';
|
|
|
import { DropdownToggle } from 'reactstrap';
|
|
import { DropdownToggle } from 'reactstrap';
|
|
|
|
|
|
|
|
import { apiv3Delete, apiv3Post, apiv3Put } from '~/client/util/apiv3-client';
|
|
import { apiv3Delete, apiv3Post, apiv3Put } from '~/client/util/apiv3-client';
|
|
@@ -11,7 +12,7 @@ import CountBadge from '~/components/Common/CountBadge';
|
|
|
import FolderIcon from '~/components/Icons/FolderIcon';
|
|
import FolderIcon from '~/components/Icons/FolderIcon';
|
|
|
import TriangleIcon from '~/components/Icons/TriangleIcon';
|
|
import TriangleIcon from '~/components/Icons/TriangleIcon';
|
|
|
import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
|
|
import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
|
|
|
-import { IPageToDeleteWithMeta } from '~/interfaces/page';
|
|
|
|
|
|
|
+import { IPageHasId, IPageToDeleteWithMeta } from '~/interfaces/page';
|
|
|
import { OnDeletedFunction } from '~/interfaces/ui';
|
|
import { OnDeletedFunction } from '~/interfaces/ui';
|
|
|
import { useSWRBookmarkInfo } from '~/stores/bookmark';
|
|
import { useSWRBookmarkInfo } from '~/stores/bookmark';
|
|
|
import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
|
|
import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
|
|
@@ -27,9 +28,13 @@ import DeleteBookmarkFolderModal from './DeleteBookmarkFolderModal';
|
|
|
type BookmarkFolderItemProps = {
|
|
type BookmarkFolderItemProps = {
|
|
|
bookmarkFolder: BookmarkFolderItems
|
|
bookmarkFolder: BookmarkFolderItems
|
|
|
isOpen?: boolean
|
|
isOpen?: boolean
|
|
|
|
|
+ level: number
|
|
|
|
|
+ root: string
|
|
|
}
|
|
}
|
|
|
const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderItemProps) => {
|
|
const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderItemProps) => {
|
|
|
- const { bookmarkFolder, isOpen: _isOpen = false } = props;
|
|
|
|
|
|
|
+ const {
|
|
|
|
|
+ bookmarkFolder, isOpen: _isOpen = false, level, root,
|
|
|
|
|
+ } = props;
|
|
|
|
|
|
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
const {
|
|
const {
|
|
@@ -139,7 +144,7 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
|
|
|
}, [hasChildren, isOpen]);
|
|
}, [hasChildren, isOpen]);
|
|
|
|
|
|
|
|
const onClickDeleteBookmarkHandler = useCallback((pageToDelete: IPageToDeleteWithMeta) => {
|
|
const onClickDeleteBookmarkHandler = useCallback((pageToDelete: IPageToDeleteWithMeta) => {
|
|
|
- const pageDeletedHandler : OnDeletedFunction = (pathOrPathsToDelete, _isRecursively, isCompletely) => {
|
|
|
|
|
|
|
+ const pageDeletedHandler: OnDeletedFunction = (pathOrPathsToDelete, _isRecursively, isCompletely) => {
|
|
|
if (typeof pathOrPathsToDelete !== 'string') {
|
|
if (typeof pathOrPathsToDelete !== 'string') {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -162,6 +167,73 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
|
|
|
mutateBookmarkInfo();
|
|
mutateBookmarkInfo();
|
|
|
}, [mutateBookmarkInfo, mutateParentBookmarkFolder]);
|
|
}, [mutateBookmarkInfo, mutateParentBookmarkFolder]);
|
|
|
|
|
|
|
|
|
|
+ const [, bookmarkFolderDragRef] = useDrag({
|
|
|
|
|
+ type: 'FOLDER',
|
|
|
|
|
+ item: props,
|
|
|
|
|
+ end: (item, monitor) => {
|
|
|
|
|
+ const dropResult = monitor.getDropResult();
|
|
|
|
|
+ if (dropResult != null) {
|
|
|
|
|
+ mutateParentBookmarkFolder();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ collect: monitor => ({
|
|
|
|
|
+ isDragging: monitor.isDragging(),
|
|
|
|
|
+ canDrag: monitor.canDrag(),
|
|
|
|
|
+ }),
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ const folderItemDropHandler = async(item: BookmarkFolderItemProps) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await apiv3Put('/bookmark-folder', { bookmarkFolderId: item.bookmarkFolder._id, name: item.bookmarkFolder.name, parent: bookmarkFolder._id });
|
|
|
|
|
+ await mutateChildBookmarkData();
|
|
|
|
|
+ toastSuccess(t('toaster.update_successed', { target: t('bookmark_folder.bookmark_folder'), ns: 'commons' }));
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ toastError(err);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const bookmarkItemDropHandler = useCallback(async(item: IPageHasId) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await apiv3Post('/bookmark-folder/add-boookmark-to-folder', { pageId: item._id, folderId: bookmarkFolder._id });
|
|
|
|
|
+ mutateParentBookmarkFolder();
|
|
|
|
|
+ toastSuccess(t('toaster.add_succeeded', { target: t('bookmark_folder.bookmark'), ns: 'commons' }));
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ toastError(err);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }, [bookmarkFolder._id, mutateParentBookmarkFolder, t]);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ const isDroppable = (item: BookmarkFolderItemProps, targetRoot: string, targetLevel: number): boolean => {
|
|
|
|
|
+ if (item.bookmarkFolder.parent === bookmarkFolder._id || item.bookmarkFolder._id === bookmarkFolder._id) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return item.root !== targetRoot || item.level >= targetLevel;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const [, bookmarkFolderDropRef] = useDrop(() => ({
|
|
|
|
|
+ accept: 'FOLDER',
|
|
|
|
|
+ drop: folderItemDropHandler,
|
|
|
|
|
+ canDrop: (item) => {
|
|
|
|
|
+ // Implement isDropable function & improve
|
|
|
|
|
+ return isDroppable(item, root, level);
|
|
|
|
|
+ },
|
|
|
|
|
+ collect: monitor => ({
|
|
|
|
|
+ isOver: monitor.isOver(),
|
|
|
|
|
+ }),
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ const [, bookmarkItemDropRef] = useDrop(() => ({
|
|
|
|
|
+ accept: 'BOOKMARK',
|
|
|
|
|
+ drop: bookmarkItemDropHandler,
|
|
|
|
|
+ collect: monitor => ({
|
|
|
|
|
+ isOver: monitor.isOver(),
|
|
|
|
|
+ }),
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
const renderChildFolder = () => {
|
|
const renderChildFolder = () => {
|
|
|
return isOpen && currentChildren?.map((childFolder) => {
|
|
return isOpen && currentChildren?.map((childFolder) => {
|
|
|
return (
|
|
return (
|
|
@@ -169,6 +241,8 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
|
|
|
<BookmarkFolderItem
|
|
<BookmarkFolderItem
|
|
|
key={childFolder._id}
|
|
key={childFolder._id}
|
|
|
bookmarkFolder={childFolder}
|
|
bookmarkFolder={childFolder}
|
|
|
|
|
+ level={level + 1}
|
|
|
|
|
+ root={root}
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
);
|
|
);
|
|
@@ -184,6 +258,7 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
|
|
|
onUnbookmarked={onUnbookmarkHandler}
|
|
onUnbookmarked={onUnbookmarkHandler}
|
|
|
onRenamed={mutateParentBookmarkFolder}
|
|
onRenamed={mutateParentBookmarkFolder}
|
|
|
onClickDeleteMenuItem={onClickDeleteBookmarkHandler}
|
|
onClickDeleteMenuItem={onClickDeleteBookmarkHandler}
|
|
|
|
|
+ parentFolder={bookmarkFolder}
|
|
|
/>
|
|
/>
|
|
|
);
|
|
);
|
|
|
});
|
|
});
|
|
@@ -204,7 +279,10 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<div id={`grw-bookmark-folder-item-${folderId}`} className="grw-foldertree-item-container">
|
|
<div id={`grw-bookmark-folder-item-${folderId}`} className="grw-foldertree-item-container">
|
|
|
- <li className="list-group-item list-group-item-action border-0 py-0 pr-3 d-flex align-items-center" onClick={loadChildFolder}>
|
|
|
|
|
|
|
+ <li ref={(c) => { bookmarkFolderDragRef(c); bookmarkFolderDropRef(c); bookmarkItemDropRef(c) }}
|
|
|
|
|
+ className="list-group-item list-group-item-action border-0 py-0 pr-3 d-flex align-items-center"
|
|
|
|
|
+ onClick={loadChildFolder}
|
|
|
|
|
+ >
|
|
|
<div className="grw-triangle-container d-flex justify-content-center">
|
|
<div className="grw-triangle-container d-flex justify-content-center">
|
|
|
{hasChildren() && (
|
|
{hasChildren() && (
|
|
|
<button
|
|
<button
|
|
@@ -223,7 +301,7 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
|
|
|
<FolderIcon isOpen={isOpen} />
|
|
<FolderIcon isOpen={isOpen} />
|
|
|
</div>
|
|
</div>
|
|
|
}
|
|
}
|
|
|
- { isRenameAction ? (
|
|
|
|
|
|
|
+ {isRenameAction ? (
|
|
|
<BookmarkFolderNameInput
|
|
<BookmarkFolderNameInput
|
|
|
onClickOutside={() => setIsRenameAction(false)}
|
|
onClickOutside={() => setIsRenameAction(false)}
|
|
|
onPressEnter={onPressEnterHandlerForRename}
|
|
onPressEnter={onPressEnterHandlerForRename}
|
|
@@ -236,7 +314,7 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
|
|
|
</div>
|
|
</div>
|
|
|
{hasChildren() && (
|
|
{hasChildren() && (
|
|
|
<div className="grw-foldertree-count-wrapper">
|
|
<div className="grw-foldertree-count-wrapper">
|
|
|
- <CountBadge count={ childCount } />
|
|
|
|
|
|
|
+ <CountBadge count={childCount} />
|
|
|
</div>
|
|
</div>
|
|
|
)}
|
|
)}
|
|
|
</>
|
|
</>
|
|
@@ -283,7 +361,7 @@ const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderIt
|
|
|
bookmarkFolder={bookmarkFolder}
|
|
bookmarkFolder={bookmarkFolder}
|
|
|
isOpen={isDeleteFolderModalShown}
|
|
isOpen={isDeleteFolderModalShown}
|
|
|
onClickDeleteButton={onClickDeleteButtonHandler}
|
|
onClickDeleteButton={onClickDeleteButtonHandler}
|
|
|
- onModalClose={onDeleteFolderModalClose}/>
|
|
|
|
|
|
|
+ onModalClose={onDeleteFolderModalClose} />
|
|
|
</div>
|
|
</div>
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|