Yuki Takei 2 лет назад
Родитель
Сommit
242537b375

+ 12 - 12
apps/app/src/components/Sidebar/PageCreateButton/DropendMenu.tsx

@@ -7,17 +7,17 @@ import type { LabelType } from '~/interfaces/template';
 
 
 type DropendMenuProps = {
-  onClickCreateNewPageButtonHandler: () => Promise<void>
-  onClickCreateTodaysButtonHandler: () => Promise<void>
-  onClickTemplateButtonHandler?: (label: LabelType) => Promise<void>
+  onClickCreateNewPageButton: () => Promise<void>
+  onClickCreateTodaysButton: () => Promise<void>
+  onClickTemplateButton?: (label: LabelType) => Promise<void>
   todaysPath: string | null,
 }
 
 export const DropendMenu = React.memo((props: DropendMenuProps): JSX.Element => {
   const {
-    onClickCreateNewPageButtonHandler,
-    onClickCreateTodaysButtonHandler,
-    onClickTemplateButtonHandler,
+    onClickCreateNewPageButton,
+    onClickCreateTodaysButton,
+    onClickTemplateButton,
     todaysPath,
   } = props;
 
@@ -28,34 +28,34 @@ export const DropendMenu = React.memo((props: DropendMenuProps): JSX.Element =>
       container="body"
     >
       <DropdownItem
-        onClick={onClickCreateNewPageButtonHandler}
+        onClick={onClickCreateNewPageButton}
       >
         {t('create_page_dropdown.new_page')}
       </DropdownItem>
 
-      {todaysPath != null && (
+      { todaysPath != null && (
         <>
           <DropdownItem divider />
           <li><span className="text-muted px-3">{t('create_page_dropdown.todays.desc')}</span></li>
           <DropdownItem
-            onClick={onClickCreateTodaysButtonHandler}
+            onClick={onClickCreateTodaysButton}
           >
             {todaysPath}
           </DropdownItem>
         </>
       )}
 
-      { onClickTemplateButtonHandler != null && (
+      { onClickTemplateButton != null && (
         <>
           <DropdownItem divider />
           <li><span className="text-muted text-nowrap px-3">{t('create_page_dropdown.template.desc')}</span></li>
           <DropdownItem
-            onClick={() => onClickTemplateButtonHandler('_template')}
+            onClick={() => onClickTemplateButton('_template')}
           >
             {t('create_page_dropdown.template.children')}
           </DropdownItem>
           <DropdownItem
-            onClick={() => onClickTemplateButtonHandler('__template')}
+            onClick={() => onClickTemplateButton('__template')}
           >
             {t('create_page_dropdown.template.descendants')}
           </DropdownItem>

+ 20 - 37
apps/app/src/components/Sidebar/PageCreateButton/PageCreateButton.tsx

@@ -1,62 +1,45 @@
 import React, { useState, useCallback } from 'react';
 
-import type { IUserHasId } from '@growi/core';
-import { pagePathUtils } from '@growi/core/dist/utils';
-import { format } from 'date-fns';
-import { useTranslation } from 'react-i18next';
 import { Dropdown } from 'reactstrap';
 
 import { useCreateTemplatePage } from '~/client/services/create-page';
 import { toastError } from '~/client/util/toastr';
-import type { LabelType } from '~/interfaces/template';
-import { useCurrentUser } from '~/stores/context';
-import { useSWRxCurrentPage } from '~/stores/page';
 
 import { CreateButton } from './CreateButton';
 import { DropendMenu } from './DropendMenu';
 import { DropendToggle } from './DropendToggle';
-import { useOnNewButtonClicked, useOnTodaysButtonClicked } from './hooks';
+import { useCreateNewPage, useCreateTodaysMemo } from './hooks';
 
 
-const generateTodaysPath = (currentUser: IUserHasId, parentDirName: string) => {
-  const now = format(new Date(), 'yyyy/MM/dd');
-  const userHomepagePath = pagePathUtils.userHomepagePath(currentUser);
-  return `${userHomepagePath}/${parentDirName}/${now}`;
+const useToastrOnError = <P, R>(method?: (param?: P) => Promise<R|undefined>): (param?: P) => Promise<R|undefined> => {
+  return useCallback(async(param) => {
+    try {
+      return await method?.(param);
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }, [method]);
 };
 
-export const PageCreateButton = React.memo((): JSX.Element => {
-  const { t } = useTranslation('commons');
-
-  const { data: currentPage, isLoading } = useSWRxCurrentPage();
-  const { data: currentUser } = useCurrentUser();
 
+export const PageCreateButton = React.memo((): JSX.Element => {
   const [isHovered, setIsHovered] = useState(false);
 
   const [dropdownOpen, setDropdownOpen] = useState(false);
 
-  const todaysPath = currentUser == null
-    ? null
-    : generateTodaysPath(currentUser, t('create_page_dropdown.todays.memo'));
-
-  const { onClickHandler: onClickNewButton, isPageCreating: isNewPageCreating } = useOnNewButtonClicked(
-    currentPage?.path, isLoading,
-  );
+  const { createNewPage, isCreating: isNewPageCreating } = useCreateNewPage();
   // TODO: https://redmine.weseek.co.jp/issues/138806
-  const { onClickHandler: onClickTodaysButton, isPageCreating: isTodaysPageCreating } = useOnTodaysButtonClicked(todaysPath);
+  const { createTodaysMemo, isCreating: isTodaysPageCreating, todaysPath } = useCreateTodaysMemo();
   // TODO: https://redmine.weseek.co.jp/issues/138805
   const {
     createTemplate,
     isCreating: isTemplatePageCreating, isCreatable: isTemplatePageCreatable,
   } = useCreateTemplatePage();
 
-  const onClickTemplateButtonHandler = useCallback(async(label: LabelType) => {
-    try {
-      await createTemplate?.(label);
-    }
-    catch (err) {
-      toastError(err);
-    }
-  }, [createTemplate]);
+  const createNewPageWithToastr = useToastrOnError(createNewPage);
+  const createTodaysMemoWithToastr = useToastrOnError(createTodaysMemo);
+  const createTemplateWithToastr = useToastrOnError(createTemplate);
 
   const onMouseEnterHandler = () => {
     setIsHovered(true);
@@ -78,7 +61,7 @@ export const PageCreateButton = React.memo((): JSX.Element => {
       <div className="btn-group flex-grow-1">
         <CreateButton
           className="z-2"
-          onClick={onClickNewButton}
+          onClick={createNewPageWithToastr}
           disabled={isNewPageCreating || isTodaysPageCreating || isTemplatePageCreating}
         />
       </div>
@@ -91,9 +74,9 @@ export const PageCreateButton = React.memo((): JSX.Element => {
         >
           <DropendToggle />
           <DropendMenu
-            onClickCreateNewPageButtonHandler={onClickNewButton}
-            onClickCreateTodaysButtonHandler={onClickTodaysButton}
-            onClickTemplateButtonHandler={isTemplatePageCreatable ? onClickTemplateButtonHandler : undefined}
+            onClickCreateNewPageButton={createNewPageWithToastr}
+            onClickCreateTodaysButton={createTodaysMemoWithToastr}
+            onClickTemplateButton={isTemplatePageCreatable ? createTemplateWithToastr : undefined}
             todaysPath={todaysPath}
           />
         </Dropdown>

+ 68 - 79
apps/app/src/components/Sidebar/PageCreateButton/hooks.tsx

@@ -1,82 +1,71 @@
-import { useCallback, useState } from 'react';
-
-import { useRouter } from 'next/router';
-
-import { createPage, exist } from '~/client/services/page-operation';
-import { toastError } from '~/client/util/toastr';
-import { EditorMode, useEditorMode } from '~/stores/ui';
-
-export const useOnNewButtonClicked = (
-    currentPagePath?: string,
-    isLoading?: boolean,
-): {
-  onClickHandler: () => Promise<void>,
-  isPageCreating: boolean
-} => {
-  const router = useRouter();
-  const [isPageCreating, setIsPageCreating] = useState(false);
-
-  const { mutate: mutateEditorMode } = useEditorMode();
-
-  const onClickHandler = useCallback(async() => {
-    if (isLoading) return;
-
-    try {
-      setIsPageCreating(true);
-
-      const response = await createPage({
-        parentPath: currentPagePath,
-        optionalParentPath: '/',
-      });
-
-      await router.push(`/${response.page._id}#edit`);
-      mutateEditorMode(EditorMode.Editor);
-    }
-    catch (err) {
-      toastError(err);
-    }
-    finally {
-      setIsPageCreating(false);
-    }
-  }, [currentPagePath, isLoading, mutateEditorMode, router]);
-
-  return { onClickHandler, isPageCreating };
+import { useCallback } from 'react';
+
+import { userHomepagePath } from '@growi/core/dist/utils/page-path-utils';
+import { format } from 'date-fns';
+import { useTranslation } from 'react-i18next';
+
+import { useCreatePageAndTransit } from '~/client/services/create-page';
+import { useCurrentUser } from '~/stores/context';
+import { useCurrentPagePath } from '~/stores/page';
+
+
+type UseCreateNewPage = () => {
+  isCreating: boolean,
+  createNewPage: () => Promise<void>,
+}
+
+export const useCreateNewPage: UseCreateNewPage = () => {
+  const { data: currentPagePath, isLoading: isLoadingPagePath } = useCurrentPagePath();
+
+  const { isCreating, createAndTransit } = useCreatePageAndTransit();
+
+  const createNewPage = useCallback(async() => {
+    if (isLoadingPagePath) return;
+
+    return createAndTransit(
+      { parentPath: currentPagePath },
+    );
+  }, [createAndTransit, currentPagePath, isLoadingPagePath]);
+
+  return {
+    isCreating,
+    createNewPage,
+  };
 };
 
-export const useOnTodaysButtonClicked = (
-    todaysPath: string | null,
-): {
-  onClickHandler: () => Promise<void>,
-  isPageCreating: boolean
-} => {
-  const router = useRouter();
-  const [isPageCreating, setIsPageCreating] = useState(false);
-
-  const { mutate: mutateEditorMode } = useEditorMode();
-
-  const onClickHandler = useCallback(async() => {
-    if (todaysPath == null) {
-      return;
-    }
-
-    try {
-      setIsPageCreating(true);
-
-      const res = await exist(JSON.stringify([todaysPath]));
-      if (!res.pages[todaysPath]) {
-        await createPage({ path: todaysPath });
-      }
-
-      await router.push(`${todaysPath}#edit`);
-      mutateEditorMode(EditorMode.Editor);
-    }
-    catch (err) {
-      toastError(err);
-    }
-    finally {
-      setIsPageCreating(false);
-    }
-  }, [mutateEditorMode, router, todaysPath]);
-
-  return { onClickHandler, isPageCreating };
+
+type UseCreateTodaysMemo = () => {
+  isCreating: boolean,
+  todaysPath: string | null,
+  createTodaysMemo: () => Promise<void>,
+}
+
+export const useCreateTodaysMemo: UseCreateTodaysMemo = () => {
+  const { t } = useTranslation('commons');
+
+  const { data: currentUser } = useCurrentUser();
+  const { isCreating, createAndTransit } = useCreatePageAndTransit();
+
+  const isCreatable = currentUser != null;
+
+  const parentDirName = t('create_page_dropdown.todays.memo');
+  const now = format(new Date(), 'yyyy/MM/dd');
+  const todaysPath = isCreatable
+    ? `${userHomepagePath(currentUser)}/${parentDirName}/${now}`
+    : null;
+
+  const createTodaysMemo = useCallback(async() => {
+    if (!isCreatable || todaysPath == null) return;
+
+    return createAndTransit(
+      { path: todaysPath },
+      { shouldCheckPageExists: true },
+    );
+  }, [createAndTransit, isCreatable, todaysPath]);
+
+  return {
+    isCreating,
+    todaysPath,
+    createTodaysMemo,
+  };
 };