BookmarkFolderMenu.tsx 4.6 KB

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