BookmarkFolderMenu.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import React, {
  2. useCallback, useState,
  3. } from 'react';
  4. import { useTranslation } from 'next-i18next';
  5. import {
  6. DropdownItem, DropdownMenu, UncontrolledDropdown,
  7. } from 'reactstrap';
  8. import { apiv3Post } from '~/client/util/apiv3-client';
  9. import { toastError, toastSuccess } from '~/client/util/toastr';
  10. import { useSWRBookmarkInfo } from '~/stores/bookmark';
  11. import { useSWRxBookamrkFolderAndChild } from '~/stores/bookmark-folder';
  12. import { useSWRxCurrentPage } from '~/stores/page';
  13. import FolderIcon from '../Icons/FolderIcon';
  14. import BookmarkFolderMenuItem from './BookmarkFolderMenuItem';
  15. import BookmarkFolderNameInput from './BookmarkFolderNameInput';
  16. type Props = {
  17. children?: React.ReactNode
  18. }
  19. const BookmarkFolderMenu = (props: Props): JSX.Element => {
  20. const { t } = useTranslation();
  21. const { children } = props;
  22. const [isCreateAction, setIsCreateAction] = useState(false);
  23. const { data: bookmarkFolders, mutate: mutateBookmarkFolderData } = useSWRxBookamrkFolderAndChild();
  24. const [selectedItem, setSelectedItem] = useState<string | null>(null);
  25. const { data: currentPage } = useSWRxCurrentPage();
  26. const { mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(currentPage?._id);
  27. const onClickNewBookmarkFolder = useCallback(() => {
  28. setIsCreateAction(true);
  29. }, []);
  30. const toggleHandler = useCallback(() => {
  31. mutateBookmarkFolderData();
  32. bookmarkFolders?.forEach((bookmarkFolder) => {
  33. bookmarkFolder.bookmarks.forEach((bookmark) => {
  34. if (bookmark.page._id === currentPage?._id) {
  35. setSelectedItem(bookmarkFolder._id);
  36. }
  37. });
  38. });
  39. }, [bookmarkFolders, currentPage?._id, mutateBookmarkFolderData]);
  40. const isBookmarkFolderExists = useCallback((): boolean => {
  41. if (bookmarkFolders && bookmarkFolders.length > 0) {
  42. return true;
  43. }
  44. return false;
  45. }, [bookmarkFolders]);
  46. const onPressEnterHandlerForCreate = useCallback(async(folderName: string) => {
  47. try {
  48. await apiv3Post('/bookmark-folder', { name: folderName, parent: null });
  49. await mutateBookmarkFolderData();
  50. setIsCreateAction(false);
  51. toastSuccess(t('toaster.create_succeeded', { target: t('bookmark_folder.bookmark_folder') }));
  52. }
  53. catch (err) {
  54. toastError(err);
  55. }
  56. }, [mutateBookmarkFolderData, t]);
  57. const onMenuItemClickHandler = useCallback(async(itemId: string) => {
  58. try {
  59. await apiv3Post('/bookmark-folder/add-boookmark-to-folder', { pageId: currentPage?._id, folderId: itemId });
  60. mutateBookmarkInfo();
  61. toastSuccess('Bookmark added to bookmark folder successfully');
  62. }
  63. catch (err) {
  64. toastError(err);
  65. }
  66. mutateBookmarkFolderData();
  67. setSelectedItem(itemId);
  68. }, [currentPage?._id, mutateBookmarkFolderData, mutateBookmarkInfo]);
  69. const renderBookmarkMenuItem = useCallback(() => {
  70. return (
  71. <>
  72. { isCreateAction ? (
  73. <div className='mx-2'>
  74. <BookmarkFolderNameInput
  75. onClickOutside={() => setIsCreateAction(false)}
  76. onPressEnter={onPressEnterHandlerForCreate}
  77. />
  78. </div>
  79. ) : (
  80. <DropdownItem toggle={false} onClick={onClickNewBookmarkFolder} className='grw-bookmark-folder-menu-item'>
  81. <FolderIcon isOpen={false}/>
  82. <span className="mx-2 ">{t('bookmark_folder.new_folder')}</span>
  83. </DropdownItem>
  84. )}
  85. { isBookmarkFolderExists() && (
  86. <>
  87. <DropdownItem divider />
  88. {bookmarkFolders?.map(folder => (
  89. <div key={folder._id} >
  90. {
  91. <div className='dropdown-item grw-bookmark-folder-menu-item' tabIndex={0} role="menuitem" onClick={() => onMenuItemClickHandler(folder._id)}>
  92. <BookmarkFolderMenuItem
  93. item={folder}
  94. isSelected={selectedItem === folder._id}
  95. onSelectedChild={() => setSelectedItem(null)}
  96. />
  97. </div>
  98. }
  99. </div>
  100. ))}
  101. </>
  102. )}
  103. </>
  104. );
  105. }, [bookmarkFolders,
  106. isBookmarkFolderExists,
  107. isCreateAction,
  108. onClickNewBookmarkFolder,
  109. onMenuItemClickHandler,
  110. onPressEnterHandlerForCreate,
  111. t,
  112. selectedItem,
  113. ]);
  114. return (
  115. <UncontrolledDropdown
  116. onToggle={toggleHandler}
  117. direction={ isBookmarkFolderExists() ? 'up' : 'down' }
  118. className='grw-bookmark-folder-dropdown'>
  119. {children}
  120. <DropdownMenu
  121. right
  122. className='grw-bookmark-folder-menu'
  123. positionFixed
  124. >
  125. { renderBookmarkMenuItem() }
  126. </DropdownMenu>
  127. </UncontrolledDropdown>
  128. );
  129. };
  130. export default BookmarkFolderMenu;