Yuki Takei 7 месяцев назад
Родитель
Сommit
81f3efb363

+ 1 - 1
apps/app/src/client/components/Hotkeys/Subscribers/ShowShortcutsModal.tsx

@@ -1,6 +1,6 @@
 import React, { useEffect, type JSX } from 'react';
 
-import { useShortcutsModal } from '~/stores/modal';
+import { useShortcutsModal } from '~/states/ui/modal/shortcuts';
 
 type Props = {
   onDeleteRender: () => void,

+ 2 - 2
apps/app/src/client/components/ItemsTree/ItemsTree.tsx

@@ -14,8 +14,8 @@ import type { UpdateDescCountData, UpdateDescCountRawData } from '~/interfaces/w
 import { SocketEventName } from '~/interfaces/websocket';
 import { useCurrentPagePath, useFetchCurrentPage } from '~/states/page';
 import { usePageDeleteModal } from '~/states/ui/modal/page-delete';
-import type { IPageForPageDuplicateModal } from '~/stores/modal';
-import { usePageDuplicateModal } from '~/stores/modal';
+import type { IPageForPageDuplicateModal } from '~/states/ui/modal/page-duplicate';
+import { usePageDuplicateModal } from '~/states/ui/modal/page-duplicate';
 import { mutateAllPageInfo } from '~/stores/page';
 import {
   useSWRxRootPage, mutatePageTree, mutatePageList,

+ 4 - 4
apps/app/src/client/components/Navbar/GrowiContextualSubNavigation.tsx

@@ -36,11 +36,11 @@ import {
   isUploadEnabledAtom,
 } from '~/states/server-configurations';
 import { useEditorMode } from '~/states/ui/editor';
+import { PageAccessoriesModalContents, usePageAccessoriesModal } from '~/states/ui/modal/page-accessories';
 import { usePageDeleteModal } from '~/states/ui/modal/page-delete';
-import {
-  usePageAccessoriesModal, PageAccessoriesModalContents, type IPageForPageDuplicateModal,
-  usePageDuplicateModal, usePageRenameModal, usePagePresentationModal,
-} from '~/stores/modal';
+import { usePageDuplicateModal, type IPageForPageDuplicateModal } from '~/states/ui/modal/page-duplicate';
+import { usePageRenameModal } from '~/states/ui/modal/page-rename';
+import { usePagePresentationModal } from '~/stores/modal';
 import {
   useSWRxPageInfo,
 } from '~/stores/page';

+ 1 - 1
apps/app/src/client/components/PageAccessoriesModal/PageAccessoriesModal.tsx

@@ -9,7 +9,7 @@ import {
 
 import { useIsGuestUser, useIsReadOnlyUser, useIsSharedUser } from '~/states/context';
 import { disableLinkSharingAtom } from '~/states/server-configurations';
-import { usePageAccessoriesModal, PageAccessoriesModalContents } from '~/stores/modal';
+import { usePageAccessoriesModal, PageAccessoriesModalContents } from '~/states/ui/modal/page-accessories';
 import { useIsDeviceLargerThanLg } from '~/stores/ui';
 
 import { CustomNavDropdown, CustomNavTab } from '../CustomNavigation/CustomNav';

+ 1 - 1
apps/app/src/client/components/PageAccessoriesModal/hooks.tsx

@@ -1,6 +1,6 @@
 import { useEffect, useState } from 'react';
 
-import { usePageAccessoriesModal, PageAccessoriesModalContents } from '~/stores/modal';
+import { usePageAccessoriesModal, PageAccessoriesModalContents } from '~/states/ui/modal/page-accessories';
 
 function getURLQueryParamValue(key: string) {
 // window.location.href is page URL;

+ 2 - 1
apps/app/src/client/components/PageControls/PageControls.tsx

@@ -25,8 +25,9 @@ import { isUsersHomepageDeletionEnabledAtom } from '~/states/server-configuratio
 import {
   EditorMode, useEditorMode,
 } from '~/states/ui/editor';
+import { type IPageForPageDuplicateModal } from '~/states/ui/modal/page-duplicate';
+import { useTagEditModal } from '~/states/ui/modal/tag-edit';
 import { useSetPageControlsX } from '~/states/ui/page';
-import { useTagEditModal, type IPageForPageDuplicateModal } from '~/stores/modal';
 import { useIsDeviceLargerThanMd } from '~/stores/ui';
 import loggerFactory from '~/utils/logger';
 

+ 1 - 1
apps/app/src/client/components/PageDuplicateModal.tsx

@@ -13,7 +13,7 @@ import { apiv3Get, apiv3Post } from '~/client/util/apiv3-client';
 import { toastError } from '~/client/util/toastr';
 import { useSiteUrl } from '~/states/global';
 import { isSearchServiceReachableAtom } from '~/states/server-configurations';
-import { usePageDuplicateModal } from '~/stores/modal';
+import { usePageDuplicateModal } from '~/states/ui/modal/page-duplicate';
 
 import DuplicatePathsTable from './DuplicatedPathsTable';
 import ApiErrorMessageList from './PageManagement/ApiErrorMessageList';

+ 3 - 3
apps/app/src/client/components/PageList/PageListItemL.tsx

@@ -26,10 +26,10 @@ import type {
 } from '~/interfaces/ui';
 import LinkedPagePath from '~/models/linked-page-path';
 import { usePageDeleteModal } from '~/states/ui/modal/page-delete';
+import { usePageDuplicateModal } from '~/states/ui/modal/page-duplicate';
+import { usePageRenameModal } from '~/states/ui/modal/page-rename';
 import { useSWRMUTxCurrentUserBookmarks } from '~/stores/bookmark';
-import {
-  usePageRenameModal, usePageDuplicateModal, usePutBackPageModal,
-} from '~/stores/modal';
+import { usePutBackPageModal } from '~/stores/modal';
 import { useIsDeviceLargerThanLg } from '~/stores/ui';
 
 import { PagePathHierarchicalLink } from '../../../components/Common/PagePathHierarchicalLink';

+ 1 - 1
apps/app/src/client/components/PageRenameModal.tsx

@@ -15,7 +15,7 @@ import { apiv3Get, apiv3Put } from '~/client/util/apiv3-client';
 import { toastError } from '~/client/util/toastr';
 import { useSiteUrl } from '~/states/global';
 import { isSearchServiceReachableAtom } from '~/states/server-configurations';
-import { usePageRenameModal } from '~/stores/modal';
+import { usePageRenameModal } from '~/states/ui/modal/page-rename';
 import { useSWRxPageInfo } from '~/stores/page';
 
 import DuplicatedPathsTable from './DuplicatedPathsTable';

+ 2 - 1
apps/app/src/client/components/PageSideContents/PageSideContents.tsx

@@ -14,7 +14,8 @@ import { scroller } from 'react-scroll';
 
 import { useIsGuestUser, useIsReadOnlyUser } from '~/states/context';
 import { showPageSideAuthorsAtom } from '~/states/server-configurations';
-import { useDescendantsPageListModal, useTagEditModal } from '~/stores/modal';
+import { useTagEditModal } from '~/states/ui/modal/tag-edit';
+import { useDescendantsPageListModal } from '~/stores/modal';
 import { useSWRxPageInfo, useSWRxTagsInfo } from '~/stores/page';
 import { useIsAbleToShowTagLabel } from '~/stores/ui';
 

+ 1 - 1
apps/app/src/client/components/PageTags/TagEditModal.tsx

@@ -10,7 +10,7 @@ import {
 import { useUpdateStateAfterSave } from '~/client/services/page-operation';
 import { apiPost } from '~/client/util/apiv1-client';
 import { toastError, toastSuccess } from '~/client/util/toastr';
-import { useTagEditModal, type TagEditModalStatus } from '~/stores/modal';
+import { useTagEditModal, type TagEditModalStatus } from '~/states/ui/modal/tag-edit';
 
 import { TagsInput } from './TagsInput';
 

+ 2 - 3
apps/app/src/client/components/SearchPage/SearchResultContent.tsx

@@ -19,9 +19,8 @@ import type { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from
 import { useShouldExpandContent } from '~/services/layout/use-should-expand-content';
 import { useCurrentUser } from '~/states/global';
 import { usePageDeleteModal } from '~/states/ui/modal/page-delete';
-import {
-  usePageDuplicateModal, usePageRenameModal,
-} from '~/stores/modal';
+import { usePageDuplicateModal } from '~/states/ui/modal/page-duplicate';
+import { usePageRenameModal } from '~/states/ui/modal/page-rename';
 import { mutatePageList, mutatePageTree, mutateRecentlyUpdated } from '~/stores/page-listing';
 import { useSearchResultOptions } from '~/stores/renderer';
 import { mutateSearching } from '~/stores/search';

+ 1 - 1
apps/app/src/client/components/ShortcutsModal.tsx

@@ -3,7 +3,7 @@ import React, { type JSX } from 'react';
 import { useTranslation } from 'next-i18next';
 import { Modal, ModalHeader, ModalBody } from 'reactstrap';
 
-import { useShortcutsModal } from '~/stores/modal';
+import { useShortcutsModal } from '~/states/ui/modal/shortcuts';
 
 import styles from './ShortcutsModal.module.scss';
 

+ 1 - 1
apps/app/src/client/components/SystemVersion.tsx

@@ -1,7 +1,7 @@
 import React, { type JSX } from 'react';
 
 import { useGrowiVersion } from '~/states/global';
-import { useShortcutsModal } from '~/stores/modal';
+import { useShortcutsModal } from '~/states/ui/modal/shortcuts';
 
 import styles from './SystemVersion.module.scss';
 

+ 1 - 1
apps/app/src/client/components/TreeItem/interfaces/index.ts

@@ -1,7 +1,7 @@
 import type { IPageToDeleteWithMeta } from '@growi/core';
 
 import type { IPageForItem } from '~/interfaces/page';
-import type { IPageForPageDuplicateModal } from '~/stores/modal';
+import type { IPageForPageDuplicateModal } from '~/states/ui/modal/page-duplicate';
 
 import type { ItemNode } from '../ItemNode';
 

+ 62 - 0
apps/app/src/states/ui/modal/page-accessories.ts

@@ -0,0 +1,62 @@
+import { atom, useAtom } from 'jotai';
+import { useCallback } from 'react';
+
+// Constants to match the original implementation
+export const PageAccessoriesModalContents = {
+  PageHistory: 'PageHistory',
+  Attachment: 'Attachment',
+  ShareLink: 'ShareLink',
+} as const;
+export type PageAccessoriesModalContents =
+  (typeof PageAccessoriesModalContents)[keyof typeof PageAccessoriesModalContents];
+
+// Type definitions to match the original implementation
+export type PageAccessoriesModalStatus = {
+  isOpened: boolean;
+  activatedContents?: PageAccessoriesModalContents;
+};
+
+export type PageAccessoriesModalUtils = {
+  open: (activatedContents: PageAccessoriesModalContents) => void;
+  close: () => void;
+  selectContents: (activatedContents: PageAccessoriesModalContents) => void;
+};
+
+// Atom for page accessories modal
+const pageAccessoriesModalAtom = atom<PageAccessoriesModalStatus>({
+  isOpened: false,
+});
+
+/**
+ * Hook for managing page accessories modal state
+ */
+export const usePageAccessoriesModal = (): {
+  data: PageAccessoriesModalStatus;
+} & PageAccessoriesModalUtils => {
+  const [status, setStatus] = useAtom(pageAccessoriesModalAtom);
+
+  const open = useCallback(
+    (activatedContents: PageAccessoriesModalContents) => {
+      setStatus({ isOpened: true, activatedContents });
+    },
+    [setStatus],
+  );
+
+  const close = useCallback(() => {
+    setStatus({ isOpened: false });
+  }, [setStatus]);
+
+  const selectContents = useCallback(
+    (activatedContents: PageAccessoriesModalContents) => {
+      setStatus((current) => ({ ...current, activatedContents }));
+    },
+    [setStatus],
+  );
+
+  return {
+    data: status,
+    open,
+    close,
+    selectContents,
+  };
+};

+ 59 - 0
apps/app/src/states/ui/modal/page-duplicate.ts

@@ -0,0 +1,59 @@
+import { atom, useAtom } from 'jotai';
+import { useCallback } from 'react';
+
+import type { OnDuplicatedFunction } from '../../../interfaces/ui';
+
+// Type definitions to match the original implementation
+export type IPageForPageDuplicateModal = {
+  pageId: string;
+  path: string;
+};
+
+export type IDuplicateModalOption = {
+  onDuplicated?: OnDuplicatedFunction;
+};
+
+export type DuplicateModalStatus = {
+  isOpened: boolean;
+  page?: IPageForPageDuplicateModal;
+  opts?: IDuplicateModalOption;
+};
+
+export type DuplicateModalUtils = {
+  open: (
+    page?: IPageForPageDuplicateModal,
+    opts?: IDuplicateModalOption,
+  ) => void;
+  close: () => void;
+};
+
+// Atom for page duplicate modal
+const pageDuplicateModalAtom = atom<DuplicateModalStatus>({
+  isOpened: false,
+});
+
+/**
+ * Hook for managing page duplicate modal state
+ */
+export const usePageDuplicateModal = (): {
+  data: DuplicateModalStatus;
+} & DuplicateModalUtils => {
+  const [status, setStatus] = useAtom(pageDuplicateModalAtom);
+
+  const open = useCallback(
+    (page?: IPageForPageDuplicateModal, opts?: IDuplicateModalOption) => {
+      setStatus({ isOpened: true, page, opts });
+    },
+    [setStatus],
+  );
+
+  const close = useCallback(() => {
+    setStatus({ isOpened: false });
+  }, [setStatus]);
+
+  return {
+    data: status,
+    open,
+    close,
+  };
+};

+ 52 - 0
apps/app/src/states/ui/modal/page-rename.ts

@@ -0,0 +1,52 @@
+import type { IPageToRenameWithMeta } from '@growi/core';
+import { atom, useAtom } from 'jotai';
+import { useCallback } from 'react';
+
+import type { OnRenamedFunction } from '../../../interfaces/ui';
+
+// Type definitions to match the original implementation
+export type IRenameModalOption = {
+  onRenamed?: OnRenamedFunction;
+};
+
+export type RenameModalStatus = {
+  isOpened: boolean;
+  page?: IPageToRenameWithMeta;
+  opts?: IRenameModalOption;
+};
+
+export type RenameModalUtils = {
+  open: (page?: IPageToRenameWithMeta, opts?: IRenameModalOption) => void;
+  close: () => void;
+};
+
+// Atom for page rename modal
+const pageRenameModalAtom = atom<RenameModalStatus>({
+  isOpened: false,
+});
+
+/**
+ * Hook for managing page rename modal state
+ */
+export const usePageRenameModal = (): {
+  data: RenameModalStatus;
+} & RenameModalUtils => {
+  const [status, setStatus] = useAtom(pageRenameModalAtom);
+
+  const open = useCallback(
+    (page?: IPageToRenameWithMeta, opts?: IRenameModalOption) => {
+      setStatus({ isOpened: true, page, opts });
+    },
+    [setStatus],
+  );
+
+  const close = useCallback(() => {
+    setStatus({ isOpened: false });
+  }, [setStatus]);
+
+  return {
+    data: status,
+    open,
+    close,
+  };
+};

+ 40 - 0
apps/app/src/states/ui/modal/shortcuts.ts

@@ -0,0 +1,40 @@
+import { atom, useAtom } from 'jotai';
+import { useCallback } from 'react';
+
+// Type definitions
+export type ShortcutsModalStatus = {
+  isOpened: boolean;
+};
+
+export type ShortcutsModalUtils = {
+  open: () => void;
+  close: () => void;
+};
+
+// Atom for shortcuts modal
+const shortcutsModalAtom = atom<ShortcutsModalStatus>({
+  isOpened: false,
+});
+
+/**
+ * Hook for managing shortcuts modal state
+ */
+export const useShortcutsModal = (): {
+  data: ShortcutsModalStatus;
+} & ShortcutsModalUtils => {
+  const [status, setStatus] = useAtom(shortcutsModalAtom);
+
+  const open = useCallback(() => {
+    setStatus({ isOpened: true });
+  }, [setStatus]);
+
+  const close = useCallback(() => {
+    setStatus({ isOpened: false });
+  }, [setStatus]);
+
+  return {
+    data: status,
+    open,
+    close,
+  };
+};

+ 49 - 0
apps/app/src/states/ui/modal/tag-edit.ts

@@ -0,0 +1,49 @@
+import { atom, useAtom } from 'jotai';
+import { useCallback } from 'react';
+
+// Type definitions to match the original implementation
+export type TagEditModalStatus = {
+  isOpen: boolean;
+  tags: string[];
+  pageId: string;
+  revisionId: string;
+};
+
+export type TagEditModalUtils = {
+  open: (tags: string[], pageId: string, revisionId: string) => void;
+  close: () => void;
+};
+
+// Atom for tag edit modal
+const tagEditModalAtom = atom<TagEditModalStatus>({
+  isOpen: false,
+  tags: [],
+  pageId: '',
+  revisionId: '',
+});
+
+/**
+ * Hook for managing tag edit modal state
+ */
+export const useTagEditModal = (): {
+  data: TagEditModalStatus;
+} & TagEditModalUtils => {
+  const [status, setStatus] = useAtom(tagEditModalAtom);
+
+  const open = useCallback(
+    (tags: string[], pageId: string, revisionId: string) => {
+      setStatus({ isOpen: true, tags, pageId, revisionId });
+    },
+    [setStatus],
+  );
+
+  const close = useCallback(() => {
+    setStatus({ isOpen: false, tags: [], pageId: '', revisionId: '' });
+  }, [setStatus]);
+
+  return {
+    data: status,
+    open,
+    close,
+  };
+};

+ 4 - 210
apps/app/src/stores/modal.tsx

@@ -1,7 +1,7 @@
 import { useCallback, useMemo } from 'react';
 
 import type {
-  IAttachmentHasId, IPageToDeleteWithMeta, IPageToRenameWithMeta, IUserGroupHasId,
+  IAttachmentHasId, IPageToDeleteWithMeta, IUserGroupHasId,
 } from '@growi/core';
 import { useSWRStatic } from '@growi/core/dist/swr';
 import { MarkdownTable } from '@growi/editor';
@@ -9,7 +9,7 @@ import type { SWRResponse } from 'swr';
 
 import type { BookmarkFolderItems } from '~/interfaces/bookmark-info';
 import type {
-  OnDuplicatedFunction, OnRenamedFunction, OnPutBackedFunction, onDeletedBookmarkFolderFunction, OnSelectedFunction,
+  OnPutBackedFunction, onDeletedBookmarkFolderFunction, OnSelectedFunction,
 } from '~/interfaces/ui';
 import loggerFactory from '~/utils/logger';
 
@@ -88,84 +88,6 @@ export const useEmptyTrashModal = (status?: EmptyTrashModalStatus): SWRResponse<
   };
 };
 
-/*
-* PageDuplicateModal
-*/
-export type IPageForPageDuplicateModal = {
-  pageId: string,
-  path: string
-}
-
-export type IDuplicateModalOption = {
-  onDuplicated?: OnDuplicatedFunction,
-}
-
-type DuplicateModalStatus = {
-  isOpened: boolean,
-  page?: IPageForPageDuplicateModal,
-  opts?: IDuplicateModalOption,
-}
-
-type DuplicateModalStatusUtils = {
-  open(
-    page?: IPageForPageDuplicateModal,
-    opts?: IDuplicateModalOption
-  ): Promise<DuplicateModalStatus | undefined>
-  close(): Promise<DuplicateModalStatus | undefined>
-}
-
-export const usePageDuplicateModal = (status?: DuplicateModalStatus): SWRResponse<DuplicateModalStatus, Error> & DuplicateModalStatusUtils => {
-  const initialData: DuplicateModalStatus = { isOpened: false };
-  const swrResponse = useSWRStatic<DuplicateModalStatus, Error>('duplicateModalStatus', status, { fallbackData: initialData });
-
-  return {
-    ...swrResponse,
-    open: (
-        page?: IPageForPageDuplicateModal,
-        opts?: IDuplicateModalOption,
-    ) => swrResponse.mutate({ isOpened: true, page, opts }),
-    close: () => swrResponse.mutate({ isOpened: false }),
-  };
-};
-
-
-/*
- * PageRenameModal
- */
-export type IRenameModalOption = {
-  onRenamed?: OnRenamedFunction,
-}
-
-type RenameModalStatus = {
-  isOpened: boolean,
-  page?: IPageToRenameWithMeta,
-  opts?: IRenameModalOption
-}
-
-type RenameModalStatusUtils = {
-  open(
-    page?: IPageToRenameWithMeta,
-    opts?: IRenameModalOption
-  ): Promise<RenameModalStatus | undefined>
-  close(): Promise<RenameModalStatus | undefined>
-}
-
-export const usePageRenameModal = (status?: RenameModalStatus): SWRResponse<RenameModalStatus, Error> & RenameModalStatusUtils => {
-  const initialData: RenameModalStatus = { isOpened: false };
-  const swrResponse = useSWRStatic<RenameModalStatus, Error>('renameModalStatus', status, { fallbackData: initialData });
-
-  return {
-    ...swrResponse,
-    open: (
-        page?: IPageToRenameWithMeta,
-        opts?: IRenameModalOption,
-    ) => swrResponse.mutate({
-      isOpened: true, page, opts,
-    }),
-    close: () => swrResponse.mutate({ isOpened: false }),
-  };
-};
-
 
 /*
 * PutBackPageModal
@@ -288,7 +210,7 @@ type DescendantsPageListModalStatus = {
 
 type DescendantsPageListUtils = {
   open(path: string): Promise<DescendantsPageListModalStatus | undefined>
-  close(): Promise<DuplicateModalStatus | undefined>
+  close(): Promise<DescendantsPageListModalStatus | undefined>
 }
 
 export const useDescendantsPageListModal = (
@@ -305,62 +227,6 @@ export const useDescendantsPageListModal = (
   };
 };
 
-/*
-* PageAccessoriesModal
-*/
-export const PageAccessoriesModalContents = {
-  PageHistory: 'PageHistory',
-  Attachment: 'Attachment',
-  ShareLink: 'ShareLink',
-} as const;
-export type PageAccessoriesModalContents = typeof PageAccessoriesModalContents[keyof typeof PageAccessoriesModalContents];
-
-type PageAccessoriesModalStatus = {
-  isOpened: boolean,
-  activatedContents?: PageAccessoriesModalContents,
-}
-
-type PageAccessoriesModalUtils = {
-  open(activatedContents: PageAccessoriesModalContents): void
-  close(): void
-  selectContents(activatedContents: PageAccessoriesModalContents): void
-}
-
-export const usePageAccessoriesModal = (): SWRResponse<PageAccessoriesModalStatus, Error> & PageAccessoriesModalUtils => {
-
-  const initialStatus = { isOpened: false };
-  const swrResponse = useSWRStatic<PageAccessoriesModalStatus, Error>('pageAccessoriesModalStatus', undefined, { fallbackData: initialStatus });
-
-  const { data, mutate } = swrResponse;
-
-  return Object.assign(swrResponse, {
-    open: useCallback((activatedContents) => {
-      if (data == null) {
-        return;
-      }
-      mutate({
-        isOpened: true,
-        activatedContents,
-      });
-    }, [data, mutate]),
-    close: useCallback(() => {
-      if (data == null) {
-        return;
-      }
-      mutate({ isOpened: false });
-    }, [data, mutate]),
-    selectContents: useCallback((activatedContents) => {
-      if (data == null) {
-        return;
-      }
-      mutate({
-        isOpened: data.isOpened,
-        activatedContents,
-      });
-    }, [data, mutate]),
-  });
-};
-
 /*
  * UpdateUserGroupConfirmModal
  */
@@ -394,34 +260,6 @@ export const useUpdateUserGroupConfirmModal = (): SWRResponse<UpdateUserGroupCon
   };
 };
 
-/*
- * ShortcutsModal
- */
-type ShortcutsModalStatus = {
-  isOpened: boolean,
-}
-
-type ShortcutsModalUtils = {
-  open(): void,
-  close(): void,
-}
-
-export const useShortcutsModal = (): SWRResponse<ShortcutsModalStatus, Error> & ShortcutsModalUtils => {
-
-  const initialStatus: ShortcutsModalStatus = { isOpened: false };
-  const swrResponse = useSWRStatic<ShortcutsModalStatus, Error>('shortcutsModal', undefined, { fallbackData: initialStatus });
-
-  return {
-    ...swrResponse,
-    open() {
-      swrResponse.mutate({ isOpened: true });
-    },
-    close() {
-      swrResponse.mutate({ isOpened: false });
-    },
-  };
-};
-
 
 /*
 * DrawioModal
@@ -689,49 +527,5 @@ export const usePageSelectModal = (
 };
 
 /*
-* TagEditModal
+* OverwriteMergeModeModal
 */
-export type TagEditModalStatus = {
-  isOpen: boolean,
-  tags: string[],
-  pageId: string,
-  revisionId: string,
-}
-
-type TagEditModalUtils = {
-  open(tags: string[], pageId: string, revisionId: string): Promise<void>,
-  close(): Promise<void>,
-}
-
-export const useTagEditModal = (): SWRResponse<TagEditModalStatus, Error> & TagEditModalUtils => {
-  const initialStatus: TagEditModalStatus = useMemo(() => {
-    return {
-      isOpen: false,
-      tags: [],
-      pageId: '',
-      revisionId: '',
-    };
-  }, []);
-
-  const swrResponse = useSWRStatic<TagEditModalStatus, Error>('TagEditModal', undefined, { fallbackData: initialStatus });
-  const { mutate } = swrResponse;
-
-  const open = useCallback(async(tags: string[], pageId: string, revisionId: string) => {
-    mutate({
-      isOpen: true,
-      tags,
-      pageId,
-      revisionId,
-    });
-  }, [mutate]);
-
-  const close = useCallback(async() => {
-    mutate(initialStatus);
-  }, [initialStatus, mutate]);
-
-  return {
-    ...swrResponse,
-    open,
-    close,
-  };
-};