PageCreateButton.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import React, { useState, useCallback } from 'react';
  2. import type { IUserHasId } from '@growi/core';
  3. import { pagePathUtils } from '@growi/core/dist/utils';
  4. import { format } from 'date-fns';
  5. import { useTranslation } from 'react-i18next';
  6. import { Dropdown } from 'reactstrap';
  7. import { useCreateTemplatePage } from '~/client/services/create-page';
  8. import { toastError } from '~/client/util/toastr';
  9. import type { LabelType } from '~/interfaces/template';
  10. import { useCurrentUser } from '~/stores/context';
  11. import { useSWRxCurrentPage } from '~/stores/page';
  12. import { CreateButton } from './CreateButton';
  13. import { DropendMenu } from './DropendMenu';
  14. import { DropendToggle } from './DropendToggle';
  15. import { useOnNewButtonClicked, useOnTodaysButtonClicked } from './hooks';
  16. const generateTodaysPath = (currentUser: IUserHasId, parentDirName: string) => {
  17. const now = format(new Date(), 'yyyy/MM/dd');
  18. const userHomepagePath = pagePathUtils.userHomepagePath(currentUser);
  19. return `${userHomepagePath}/${parentDirName}/${now}`;
  20. };
  21. export const PageCreateButton = React.memo((): JSX.Element => {
  22. const { t } = useTranslation('commons');
  23. const { data: currentPage, isLoading } = useSWRxCurrentPage();
  24. const { data: currentUser } = useCurrentUser();
  25. const [isHovered, setIsHovered] = useState(false);
  26. const [dropdownOpen, setDropdownOpen] = useState(false);
  27. const todaysPath = currentUser == null
  28. ? null
  29. : generateTodaysPath(currentUser, t('create_page_dropdown.todays.memo'));
  30. const { onClickHandler: onClickNewButton, isPageCreating: isNewPageCreating } = useOnNewButtonClicked(
  31. currentPage?.path, isLoading,
  32. );
  33. // TODO: https://redmine.weseek.co.jp/issues/138806
  34. const { onClickHandler: onClickTodaysButton, isPageCreating: isTodaysPageCreating } = useOnTodaysButtonClicked(todaysPath);
  35. // TODO: https://redmine.weseek.co.jp/issues/138805
  36. const {
  37. createTemplate,
  38. isCreating: isTemplatePageCreating, isCreatable: isTemplatePageCreatable,
  39. } = useCreateTemplatePage();
  40. const onClickTemplateButtonHandler = useCallback(async(label: LabelType) => {
  41. try {
  42. await createTemplate?.(label);
  43. }
  44. catch (err) {
  45. toastError(err);
  46. }
  47. }, [createTemplate]);
  48. const onMouseEnterHandler = () => {
  49. setIsHovered(true);
  50. };
  51. const onMouseLeaveHandler = () => {
  52. setIsHovered(false);
  53. setDropdownOpen(false);
  54. };
  55. const toggle = () => setDropdownOpen(!dropdownOpen);
  56. return (
  57. <div
  58. className="d-flex flex-row"
  59. onMouseEnter={onMouseEnterHandler}
  60. onMouseLeave={onMouseLeaveHandler}
  61. >
  62. <div className="btn-group flex-grow-1">
  63. <CreateButton
  64. className="z-2"
  65. onClick={onClickNewButton}
  66. disabled={isNewPageCreating || isTodaysPageCreating || isTemplatePageCreating}
  67. />
  68. </div>
  69. { isHovered && (
  70. <Dropdown
  71. isOpen={dropdownOpen}
  72. toggle={toggle}
  73. direction="end"
  74. className="position-absolute"
  75. >
  76. <DropendToggle />
  77. <DropendMenu
  78. onClickCreateNewPageButtonHandler={onClickNewButton}
  79. onClickCreateTodaysButtonHandler={onClickTodaysButton}
  80. onClickTemplateButtonHandler={isTemplatePageCreatable ? onClickTemplateButtonHandler : undefined}
  81. todaysPath={todaysPath}
  82. />
  83. </Dropdown>
  84. )}
  85. </div>
  86. );
  87. });