Skip to content

Commit

Permalink
Merge pull request #7586 from weseek/feat/115447-119721-update-dnd-ro…
Browse files Browse the repository at this point in the history
…ot-move

feat: Update bookmarks tree move to root features
  • Loading branch information
Ryoji Shimizu authored Apr 28, 2023
2 parents 83c54af + 1b6e811 commit afe9941
Show file tree
Hide file tree
Showing 18 changed files with 340 additions and 449 deletions.
3 changes: 2 additions & 1 deletion apps/app/public/static/locales/en_US/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,8 @@
"new_folder": "New Folder",
"delete": "Delete Folder",
"drop_item_here": "Drag and drop item here",
"cancel_bookmark": "Un-bookmark this page"
"cancel_bookmark": "Un-bookmark this page",
"Move to the root": "Move to the root"
},
"v5_page_migration": {
"page_tree_not_avaliable" : "Page tree feature is not available yet.",
Expand Down
3 changes: 2 additions & 1 deletion apps/app/public/static/locales/ja_JP/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,8 @@
"new_folder": "新しいフォルダ",
"delete": "フォルダを削除",
"drop_item_here": "ルートに配置する",
"cancel_bookmark": "このページのブックマークを解除"
"cancel_bookmark": "このページのブックマークを解除",
"move_to_root": "ルートに配置する"
},
"v5_page_migration": {
"page_tree_not_avaliable" : "Page Tree 機能は現在使用できません。",
Expand Down
3 changes: 2 additions & 1 deletion apps/app/public/static/locales/zh_CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,8 @@
"new_folder": "新建文件夹",
"delete": "删除文件夹",
"drop_item_here": "将项目拖放到此处",
"cancel_bookmark": "取消收藏此页面"
"cancel_bookmark": "取消收藏此页面",
"move_to_root": "移动到根部"
},
"v5_page_migration": {
"page_tree_not_avaliable": "Page Tree 功能不可用",
Expand Down
95 changes: 37 additions & 58 deletions apps/app/src/components/Bookmarks/BookmarkFolderItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,53 @@ import {
FC, useCallback, useState,
} from 'react';

import { useTranslation } from 'next-i18next';
import { DropdownToggle } from 'reactstrap';

import {
addBookmarkToFolder, addNewFolder, hasChildren, updateBookmarkFolder,
} from '~/client/util/bookmark-utils';
import { toastError, toastSuccess } from '~/client/util/toastr';
import { toastError } from '~/client/util/toastr';
import { FolderIcon } from '~/components/Icons/FolderIcon';
import { TriangleIcon } from '~/components/Icons/TriangleIcon';
import {
BookmarkFolderItems, DragItemDataType, DragItemType, DRAG_ITEM_TYPE,
} from '~/interfaces/bookmark-info';
import { IPageToDeleteWithMeta } from '~/interfaces/page';
import { onDeletedBookmarkFolderFunction, OnDeletedFunction } from '~/interfaces/ui';
import { useSWRBookmarkInfo, useSWRxCurrentUserBookmarks } from '~/stores/bookmark';
import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
import { useBookmarkFolderDeleteModal, usePageDeleteModal } from '~/stores/modal';
import { useSWRxCurrentPage } from '~/stores/page';
import { onDeletedBookmarkFolderFunction } from '~/interfaces/ui';
import { useBookmarkFolderDeleteModal } from '~/stores/modal';

import { BookmarkFolderItemControl } from './BookmarkFolderItemControl';
import { BookmarkFolderNameInput } from './BookmarkFolderNameInput';
import { BookmarkItem } from './BookmarkItem';
import { DragAndDropWrapper } from './DragAndDropWrapper';


type BookmarkFolderItemProps = {
bookmarkFolder: BookmarkFolderItems
isOpen?: boolean
level: number
root: string
isUserHomePage?: boolean
onClickDeleteBookmarkHandler: (pageToDelete: IPageToDeleteWithMeta) => void
bookmarkFolderTreeMutation: () => void
}

export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkFolderItemProps) => {
const BASE_FOLDER_PADDING = 15;
const acceptedTypes: DragItemType[] = [DRAG_ITEM_TYPE.FOLDER, DRAG_ITEM_TYPE.BOOKMARK];
const {
bookmarkFolder, isOpen: _isOpen = false, level, root, isUserHomePage,
onClickDeleteBookmarkHandler, bookmarkFolderTreeMutation,
} = props;

const { t } = useTranslation();
const {
name, _id: folderId, children, parent, bookmarks,
} = bookmarkFolder;

const [targetFolder, setTargetFolder] = useState<string | null>(folderId);
const [isOpen, setIsOpen] = useState(_isOpen);
const { mutate: mutateBookmarkData } = useSWRxBookamrkFolderAndChild();
const { mutate: mutateUserBookmarks } = useSWRxCurrentUserBookmarks();
const [isRenameAction, setIsRenameAction] = useState<boolean>(false);
const [isCreateAction, setIsCreateAction] = useState<boolean>(false);
const { data: currentPage } = useSWRxCurrentPage();
const { mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(currentPage?._id);
const { open: openDeleteModal } = usePageDeleteModal();

const { open: openDeleteBookmarkFolderModal } = useBookmarkFolderDeleteModal();

const childrenExists = hasChildren(children);
Expand All @@ -67,31 +60,30 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
setTargetFolder(folderId);
}, [folderId, isOpen]);

// Rename for bookmark folder handler
// Rename for bookmark folder handler
const onPressEnterHandlerForRename = useCallback(async(folderName: string) => {
try {
await updateBookmarkFolder(folderId, folderName, parent);
mutateBookmarkData();
bookmarkFolderTreeMutation();
setIsRenameAction(false);
}
catch (err) {
toastError(err);
}
}, [folderId, mutateBookmarkData, parent]);
}, [bookmarkFolderTreeMutation, folderId, parent]);

// Create new folder / subfolder handler
const onPressEnterHandlerForCreate = useCallback(async(folderName: string) => {
try {
await addNewFolder(folderName, targetFolder);
setIsOpen(true);
setIsCreateAction(false);
mutateBookmarkData();
bookmarkFolderTreeMutation();
}
catch (err) {
toastError(err);
}
}, [mutateBookmarkData, targetFolder]);

}, [bookmarkFolderTreeMutation, targetFolder]);

const onClickPlusButton = useCallback(async(e) => {
e.stopPropagation();
Expand All @@ -101,37 +93,12 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
setIsCreateAction(true);
}, [childrenExists, isOpen]);

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 }));
}
mutateBookmarkData();
mutateBookmarkInfo();
};
openDeleteModal([pageToDelete], { onDeleted: pageDeletedHandler });
}, [mutateBookmarkInfo, mutateBookmarkData, openDeleteModal, t]);

const onUnbookmarkHandler = useCallback(() => {
mutateBookmarkData();
mutateBookmarkInfo();
}, [mutateBookmarkInfo, mutateBookmarkData]);


const itemDropHandler = async(item: DragItemDataType, dragItemType: string | symbol | null) => {
if (dragItemType === DRAG_ITEM_TYPE.FOLDER) {
try {
if (item.bookmarkFolder != null) {
await updateBookmarkFolder(item.bookmarkFolder._id, item.bookmarkFolder.name, bookmarkFolder._id);
mutateBookmarkData();
bookmarkFolderTreeMutation();
}
}
catch (err) {
Expand All @@ -142,8 +109,7 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
try {
if (item != null) {
await addBookmarkToFolder(item._id, bookmarkFolder._id);
mutateBookmarkData();
await mutateUserBookmarks();
bookmarkFolderTreeMutation();
}
}
catch (err) {
Expand Down Expand Up @@ -174,7 +140,6 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
return true;
};


const renderChildFolder = () => {
return isOpen && children?.map((childFolder) => {
return (
Expand All @@ -184,7 +149,9 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
bookmarkFolder={childFolder}
level={level + 1}
root={root}
isUserHomePage ={isUserHomePage}
isUserHomePage={isUserHomePage}
onClickDeleteBookmarkHandler={onClickDeleteBookmarkHandler}
bookmarkFolderTreeMutation={bookmarkFolderTreeMutation}
/>
</div>
);
Expand All @@ -195,13 +162,13 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
return isOpen && bookmarks?.map((bookmark) => {
return (
<BookmarkItem
bookmarkedPage={bookmark.page}
key={bookmark._id}
onUnbookmarked={onUnbookmarkHandler}
onRenamed={mutateBookmarkData}
onClickDeleteMenuItem={onClickDeleteBookmarkHandler}
parentFolder={bookmarkFolder}
bookmarkedPage={bookmark.page}
level={level + 1}
parentFolder={bookmarkFolder}
canMoveToRoot={true}
onClickDeleteBookmarkHandler={onClickDeleteBookmarkHandler}
bookmarkFolderTreeMutation={bookmarkFolderTreeMutation}
/>
);
});
Expand All @@ -216,16 +183,24 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
if (typeof folderId !== 'string') {
return;
}
mutateBookmarkInfo();
mutateBookmarkData();
bookmarkFolderTreeMutation();
};

if (bookmarkFolder == null) {
return;
}
openDeleteBookmarkFolderModal(bookmarkFolder, { onDeleted: bookmarkFolderDeleteHandler });
}, [bookmarkFolder, mutateBookmarkData, mutateBookmarkInfo, openDeleteBookmarkFolderModal]);
}, [bookmarkFolder, bookmarkFolderTreeMutation, openDeleteBookmarkFolderModal]);

const onClickMoveToRootHandlerForBookmarkFolderItemControl = useCallback(async() => {
try {
await updateBookmarkFolder(bookmarkFolder._id, bookmarkFolder.name, null);
bookmarkFolderTreeMutation();
}
catch (err) {
toastError(err);
}
}, [bookmarkFolder._id, bookmarkFolder.name, bookmarkFolderTreeMutation]);

return (
<div id={`grw-bookmark-folder-item-${folderId}`} className="grw-foldertree-item-container">
Expand Down Expand Up @@ -278,6 +253,10 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
<BookmarkFolderItemControl
onClickRename={onClickRenameHandler}
onClickDelete={onClickDeleteHandler}
onClickMoveToRoot={bookmarkFolder.parent != null
? onClickMoveToRootHandlerForBookmarkFolderItemControl
: undefined
}
>
<div onClick={e => e.stopPropagation()}>
<DropdownToggle color="transparent" className="border-0 rounded btn-page-item-control p-0 grw-visible-on-hover mr-1">
Expand Down
31 changes: 23 additions & 8 deletions apps/app/src/components/Bookmarks/BookmarkFolderItemControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import {
Dropdown, DropdownItem, DropdownMenu, DropdownToggle,
} from 'reactstrap';


type BookmarkFolderItemControlProps = {
export const BookmarkFolderItemControl: React.FC<{
children?: React.ReactNode
onClickMoveToRoot?: () => Promise<void>
onClickRename: () => void
onClickDelete: () => void
}
export const BookmarkFolderItemControl = (props: BookmarkFolderItemControlProps): JSX.Element => {
}> = ({
children,
onClickMoveToRoot,
onClickRename,
onClickDelete,
}): JSX.Element => {
const { t } = useTranslation();
const { children, onClickRename, onClickDelete } = props;
const [isOpen, setIsOpen] = useState(false);

return (
<Dropdown isOpen={isOpen} toggle={() => setIsOpen(!isOpen)}>
{ children ?? (
Expand All @@ -23,18 +27,29 @@ export const BookmarkFolderItemControl = (props: BookmarkFolderItemControlProps)
</DropdownToggle>
) }
<DropdownMenu
positionFixed
modifiers={{ preventOverflow: { boundariesElement: undefined } }}
right={true}
modifiers={{ preventOverflow: { boundariesElement: 'viewport' } }}
container="body"
style={{ zIndex: 1055 }} /* make it larger than $zindex-modal of bootstrap */
>
{onClickMoveToRoot && (
<DropdownItem
onClick={onClickMoveToRoot}
className="grw-page-control-dropdown-item"
>
<i className="fa fa-fw fa-bookmark-o grw-page-control-dropdown-icon"></i>
{t('bookmark_folder.move_to_root')}
</DropdownItem>
)}
<DropdownItem
onClick={onClickRename}
className="grw-page-control-dropdown-item"
>
<i className="icon-fw icon-action-redo grw-page-control-dropdown-icon"></i>
{t('Rename')}
</DropdownItem>

<DropdownItem divider/>

<DropdownItem
className='pt-2 grw-page-control-dropdown-item text-danger'
onClick={onClickDelete}
Expand Down
Loading

0 comments on commit afe9941

Please sign in to comment.