SearchResultContent.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import React, { FC, useCallback } from 'react';
  2. import { DropdownItem } from 'reactstrap';
  3. import { useTranslation } from 'react-i18next';
  4. import { IPageWithMeta } from '~/interfaces/page';
  5. import { IPageSearchMeta } from '~/interfaces/search';
  6. import { exportAsMarkdown } from '~/client/services/page-operation';
  7. import RevisionLoader from '../Page/RevisionLoader';
  8. import AppContainer from '../../client/services/AppContainer';
  9. import { GrowiSubNavigation } from '../Navbar/GrowiSubNavigation';
  10. import { SubNavButtons } from '../Navbar/SubNavButtons';
  11. import { AdditionalMenuItemsRendererProps } from '../Common/Dropdown/PageItemControl';
  12. import { usePageDeleteModalStatus } from '~/stores/ui';
  13. type AdditionalMenuItemsProps = AdditionalMenuItemsRendererProps & {
  14. pageId: string,
  15. revisionId: string,
  16. }
  17. const AdditionalMenuItems = (props: AdditionalMenuItemsProps): JSX.Element => {
  18. const { t } = useTranslation();
  19. const { pageId, revisionId } = props;
  20. return (
  21. <>
  22. <DropdownItem divider />
  23. {/* Export markdown */}
  24. <DropdownItem onClick={() => exportAsMarkdown(pageId, revisionId, 'md')}>
  25. <i className="icon-fw icon-cloud-download"></i>
  26. {t('export_bulk.export_page_markdown')}
  27. </DropdownItem>
  28. </>
  29. );
  30. };
  31. type Props ={
  32. appContainer: AppContainer,
  33. searchingKeyword:string,
  34. focusedSearchResultData : IPageWithMeta<IPageSearchMeta>,
  35. showPageControlDropdown?: boolean,
  36. }
  37. const SearchResultContent: FC<Props> = (props: Props) => {
  38. const {
  39. appContainer,
  40. focusedSearchResultData,
  41. showPageControlDropdown,
  42. } = props;
  43. const { open: openDeleteModal } = usePageDeleteModalStatus();
  44. const page = focusedSearchResultData?.pageData;
  45. const growiRenderer = appContainer.getRenderer('searchresult');
  46. const deleteItemClickedHandler = useCallback(async(pageToDelete) => {
  47. openDeleteModal([pageToDelete]);
  48. }, [openDeleteModal]);
  49. const ControlComponents = useCallback(() => {
  50. if (page == null) {
  51. return <></>;
  52. }
  53. const revisionId = typeof page.revision === 'string'
  54. ? page.revision
  55. : page.revision._id;
  56. return (
  57. <>
  58. <div className="h-50 d-flex flex-column align-items-end justify-content-center">
  59. <SubNavButtons
  60. pageId={page._id}
  61. revisionId={revisionId}
  62. path={page.path}
  63. showPageControlDropdown={showPageControlDropdown}
  64. additionalMenuItemRenderer={props => <AdditionalMenuItems {...props} pageId={page._id} revisionId={revisionId} />}
  65. onClickDeleteMenuItem={deleteItemClickedHandler}
  66. />
  67. </div>
  68. <div className="h-50 d-flex flex-column align-items-end justify-content-center">
  69. </div>
  70. </>
  71. );
  72. }, [page, showPageControlDropdown, deleteItemClickedHandler]);
  73. // return if page is null
  74. if (page == null) return <></>;
  75. return (
  76. <div key={page._id} className="search-result-page grw-page-path-text-muted-container d-flex flex-column">
  77. <GrowiSubNavigation
  78. page={page}
  79. controls={ControlComponents}
  80. />
  81. <div className="search-result-page-content">
  82. <RevisionLoader
  83. growiRenderer={growiRenderer}
  84. pageId={page._id}
  85. pagePath={page.path}
  86. revisionId={page.revision}
  87. highlightKeywords={props.searchingKeyword}
  88. />
  89. </div>
  90. </div>
  91. );
  92. };
  93. export default SearchResultContent;