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

+ 3 - 2
apps/app/src/client/components/Admin/UserGroupDetail/UpdateParentConfirmModal.tsx

@@ -6,7 +6,7 @@ import {
   Modal, ModalHeader, ModalBody, ModalFooter,
   Modal, ModalHeader, ModalBody, ModalFooter,
 } from 'reactstrap';
 } from 'reactstrap';
 
 
-import { useUpdateUserGroupConfirmModal } from '~/stores/modal';
+import { useUpdateUserGroupConfirmModalStatus, useUpdateUserGroupConfirmModalActions } from '~/states/ui/modal/update-user-group-confirm';
 
 
 
 
 export const UpdateParentConfirmModal: FC = () => {
 export const UpdateParentConfirmModal: FC = () => {
@@ -14,7 +14,8 @@ export const UpdateParentConfirmModal: FC = () => {
 
 
   const [isForceUpdate, setForceUpdate] = useState(false);
   const [isForceUpdate, setForceUpdate] = useState(false);
 
 
-  const { data: modalStatus, close: closeModal } = useUpdateUserGroupConfirmModal();
+  const modalStatus = useUpdateUserGroupConfirmModalStatus();
+  const { close: closeModal } = useUpdateUserGroupConfirmModalActions();
 
 
   if (modalStatus == null) {
   if (modalStatus == null) {
     closeModal();
     closeModal();

+ 2 - 2
apps/app/src/client/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx

@@ -20,7 +20,7 @@ import type { IExternalUserGroupHasId } from '~/features/external-user-group/int
 import type { PageActionOnGroupDelete, SearchType } from '~/interfaces/user-group';
 import type { PageActionOnGroupDelete, SearchType } from '~/interfaces/user-group';
 import { SearchTypes } from '~/interfaces/user-group';
 import { SearchTypes } from '~/interfaces/user-group';
 import { isAclEnabledAtom } from '~/states/server-configurations';
 import { isAclEnabledAtom } from '~/states/server-configurations';
-import { useUpdateUserGroupConfirmModal } from '~/stores/modal';
+import { useUpdateUserGroupConfirmModalActions } from '~/states/ui/modal/update-user-group-confirm';
 import { useSWRxUserGroupPages, useSWRxSelectableParentUserGroups, useSWRxSelectableChildUserGroups } from '~/stores/user-group';
 import { useSWRxUserGroupPages, useSWRxSelectableParentUserGroups, useSWRxSelectableChildUserGroups } from '~/stores/user-group';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
@@ -107,7 +107,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
 
 
   const isAclEnabled = useAtomValue(isAclEnabledAtom);
   const isAclEnabled = useAtomValue(isAclEnabledAtom);
 
 
-  const { open: openUpdateParentConfirmModal } = useUpdateUserGroupConfirmModal();
+  const { open: openUpdateParentConfirmModal } = useUpdateUserGroupConfirmModalActions();
 
 
   const parentUserGroup = (() => {
   const parentUserGroup = (() => {
     if (isExternalGroup) {
     if (isExternalGroup) {

+ 2 - 2
apps/app/src/client/components/Bookmarks/BookmarkFolderItem.tsx

@@ -12,7 +12,7 @@ import { toastError } from '~/client/util/toastr';
 import type { BookmarkFolderItems, DragItemDataType, DragItemType } from '~/interfaces/bookmark-info';
 import type { BookmarkFolderItems, DragItemDataType, DragItemType } from '~/interfaces/bookmark-info';
 import { DRAG_ITEM_TYPE } from '~/interfaces/bookmark-info';
 import { DRAG_ITEM_TYPE } from '~/interfaces/bookmark-info';
 import type { onDeletedBookmarkFolderFunction } from '~/interfaces/ui';
 import type { onDeletedBookmarkFolderFunction } from '~/interfaces/ui';
-import { useBookmarkFolderDeleteModal } from '~/stores/modal';
+import { useDeleteBookmarkFolderModalActions } from '~/states/ui/modal/delete-bookmark-folder';
 
 
 import { BookmarkFolderItemControl } from './BookmarkFolderItemControl';
 import { BookmarkFolderItemControl } from './BookmarkFolderItemControl';
 import { BookmarkFolderNameInput } from './BookmarkFolderNameInput';
 import { BookmarkFolderNameInput } from './BookmarkFolderNameInput';
@@ -49,7 +49,7 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
   const [isRenameAction, setIsRenameAction] = useState<boolean>(false);
   const [isRenameAction, setIsRenameAction] = useState<boolean>(false);
   const [isCreateAction, setIsCreateAction] = useState<boolean>(false);
   const [isCreateAction, setIsCreateAction] = useState<boolean>(false);
 
 
-  const { open: openDeleteBookmarkFolderModal } = useBookmarkFolderDeleteModal();
+  const { open: openDeleteBookmarkFolderModal } = useDeleteBookmarkFolderModalActions();
 
 
   const childrenExists = hasChildren({ childFolder, bookmarks });
   const childrenExists = hasChildren({ childFolder, bookmarks });
 
 

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

@@ -10,12 +10,13 @@ import {
 import { FolderIcon } from '~/client/components/Icons/FolderIcon';
 import { FolderIcon } from '~/client/components/Icons/FolderIcon';
 import { deleteBookmarkFolder } from '~/client/util/bookmark-utils';
 import { deleteBookmarkFolder } from '~/client/util/bookmark-utils';
 import { toastError } from '~/client/util/toastr';
 import { toastError } from '~/client/util/toastr';
-import { useBookmarkFolderDeleteModal } from '~/stores/modal';
+import { useDeleteBookmarkFolderModalStatus, useDeleteBookmarkFolderModalActions } from '~/states/ui/modal/delete-bookmark-folder';
 
 
 
 
 const DeleteBookmarkFolderModal: FC = () => {
 const DeleteBookmarkFolderModal: FC = () => {
   const { t } = useTranslation();
   const { t } = useTranslation();
-  const { data: deleteBookmarkFolderModalData, close: closeBookmarkFolderDeleteModal } = useBookmarkFolderDeleteModal();
+  const deleteBookmarkFolderModalData = useDeleteBookmarkFolderModalStatus();
+  const { close: closeBookmarkFolderDeleteModal } = useDeleteBookmarkFolderModalActions();
   const isOpened = deleteBookmarkFolderModalData?.isOpened ?? false;
   const isOpened = deleteBookmarkFolderModalData?.isOpened ?? false;
 
 
   async function deleteBookmark() {
   async function deleteBookmark() {

+ 2 - 2
apps/app/src/client/components/PageAccessoriesModal/PageAttachment.tsx

@@ -7,8 +7,8 @@ import { LoadingSpinner } from '@growi/ui/dist/components';
 
 
 import { useIsGuestUser, useIsReadOnlyUser } from '~/states/context';
 import { useIsGuestUser, useIsReadOnlyUser } from '~/states/context';
 import { useCurrentPageData, useCurrentPageId } from '~/states/page';
 import { useCurrentPageData, useCurrentPageId } from '~/states/page';
+import { useDeleteAttachmentModalActions } from '~/states/ui/modal/delete-attachment';
 import { useSWRxAttachments } from '~/stores/attachment';
 import { useSWRxAttachments } from '~/stores/attachment';
-import { useDeleteAttachmentModal } from '~/stores/modal';
 
 
 import { PageAttachmentList } from '../PageAttachment/PageAttachmentList';
 import { PageAttachmentList } from '../PageAttachment/PageAttachmentList';
 import PaginationWrapper from '../PaginationWrapper';
 import PaginationWrapper from '../PaginationWrapper';
@@ -33,7 +33,7 @@ const PageAttachment = (): JSX.Element => {
 
 
   // SWRs
   // SWRs
   const { data: dataAttachments, remove } = useSWRxAttachments(pageId, pageNumber);
   const { data: dataAttachments, remove } = useSWRxAttachments(pageId, pageNumber);
-  const { open: openDeleteAttachmentModal } = useDeleteAttachmentModal();
+  const { open: openDeleteAttachmentModal } = useDeleteAttachmentModalActions();
   const markdown = currentPage?.revision?.body;
   const markdown = currentPage?.revision?.body;
 
 
   // Custom hooks
   // Custom hooks

+ 3 - 2
apps/app/src/client/components/PageAttachment/DeleteAttachmentModal.tsx

@@ -9,7 +9,7 @@ import {
 } from 'reactstrap';
 } from 'reactstrap';
 
 
 import { toastSuccess, toastError } from '~/client/util/toastr';
 import { toastSuccess, toastError } from '~/client/util/toastr';
-import { useDeleteAttachmentModal } from '~/stores/modal';
+import { useDeleteAttachmentModalStatus, useDeleteAttachmentModalActions } from '~/states/ui/modal/delete-attachment';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 import { Username } from '../../../components/User/Username';
 import { Username } from '../../../components/User/Username';
@@ -27,7 +27,8 @@ export const DeleteAttachmentModal: React.FC = () => {
   const [deleteError, setDeleteError] = useState<string>('');
   const [deleteError, setDeleteError] = useState<string>('');
 
 
   const { t } = useTranslation();
   const { t } = useTranslation();
-  const { data: deleteAttachmentModal, close: closeDeleteAttachmentModal } = useDeleteAttachmentModal();
+  const deleteAttachmentModal = useDeleteAttachmentModalStatus();
+  const { close: closeDeleteAttachmentModal } = useDeleteAttachmentModalActions();
   const isOpen = deleteAttachmentModal?.isOpened;
   const isOpen = deleteAttachmentModal?.isOpened;
   const attachment = deleteAttachmentModal?.attachment;
   const attachment = deleteAttachmentModal?.attachment;
   const remove = deleteAttachmentModal?.remove;
   const remove = deleteAttachmentModal?.remove;

+ 2 - 2
apps/app/src/client/components/ReactMarkdownComponents/RichAttachment.tsx

@@ -6,8 +6,8 @@ import Image from 'next/image';
 import prettyBytes from 'pretty-bytes';
 import prettyBytes from 'pretty-bytes';
 
 
 import { useIsGuestUser, useIsReadOnlyUser, useIsSharedUser } from '~/states/context';
 import { useIsGuestUser, useIsReadOnlyUser, useIsSharedUser } from '~/states/context';
+import { useDeleteAttachmentModalActions } from '~/states/ui/modal/delete-attachment';
 import { useSWRxAttachment } from '~/stores/attachment';
 import { useSWRxAttachment } from '~/stores/attachment';
-import { useDeleteAttachmentModal } from '~/stores/modal';
 
 
 import styles from './RichAttachment.module.scss';
 import styles from './RichAttachment.module.scss';
 
 
@@ -21,7 +21,7 @@ export const RichAttachment = React.memo((props: RichAttachmentProps) => {
   const { attachmentId, attachmentName } = props;
   const { attachmentId, attachmentName } = props;
   const { t } = useTranslation();
   const { t } = useTranslation();
   const { data: attachment, remove } = useSWRxAttachment(attachmentId);
   const { data: attachment, remove } = useSWRxAttachment(attachmentId);
-  const { open: openDeleteAttachmentModal } = useDeleteAttachmentModal();
+  const { open: openDeleteAttachmentModal } = useDeleteAttachmentModalActions();
 
 
   const isGuestUser = useIsGuestUser();
   const isGuestUser = useIsGuestUser();
   const isSharedUser = useIsSharedUser();
   const isSharedUser = useIsSharedUser();

+ 54 - 0
apps/app/src/states/ui/modal/delete-attachment.ts

@@ -0,0 +1,54 @@
+import type { IAttachmentHasId } from '@growi/core';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
+import { useCallback } from 'react';
+
+type Remove = (body: { attachment_id: string }) => Promise<void>;
+
+export type DeleteAttachmentModalStatus = {
+  isOpened: boolean;
+  attachment?: IAttachmentHasId;
+  remove?: Remove;
+};
+
+export type DeleteAttachmentModalActions = {
+  open: (attachment: IAttachmentHasId, remove: Remove) => void;
+  close: () => void;
+};
+
+// Atom for delete attachment modal state
+const deleteAttachmentModalAtom = atom<DeleteAttachmentModalStatus>({
+  isOpened: false,
+  attachment: undefined,
+  remove: undefined,
+});
+
+/**
+ * Hook for managing delete attachment modal state
+ * Returns read-only modal status for optimal performance
+ */
+export const useDeleteAttachmentModalStatus =
+  (): DeleteAttachmentModalStatus => {
+    return useAtomValue(deleteAttachmentModalAtom);
+  };
+
+/**
+ * Hook for managing delete attachment modal actions
+ * Returns actions for opening and closing the modal with stable references
+ */
+export const useDeleteAttachmentModalActions =
+  (): DeleteAttachmentModalActions => {
+    const setStatus = useSetAtom(deleteAttachmentModalAtom);
+
+    const open = useCallback(
+      (attachment: IAttachmentHasId, remove: Remove) => {
+        setStatus({ isOpened: true, attachment, remove });
+      },
+      [setStatus],
+    );
+
+    const close = useCallback(() => {
+      setStatus({ isOpened: false, attachment: undefined, remove: undefined });
+    }, [setStatus]);
+
+    return { open, close };
+  };

+ 66 - 0
apps/app/src/states/ui/modal/delete-bookmark-folder.ts

@@ -0,0 +1,66 @@
+import { atom, useAtomValue, useSetAtom } from 'jotai';
+import { useCallback } from 'react';
+
+import type { BookmarkFolderItems } from '../../../interfaces/bookmark-info';
+import type { onDeletedBookmarkFolderFunction } from '../../../interfaces/ui';
+
+type IDeleteBookmarkFolderModalOption = {
+  onDeleted?: onDeletedBookmarkFolderFunction;
+};
+
+export type DeleteBookmarkFolderModalStatus = {
+  isOpened: boolean;
+  bookmarkFolder?: BookmarkFolderItems;
+  opts?: IDeleteBookmarkFolderModalOption;
+};
+
+export type DeleteBookmarkFolderModalActions = {
+  open: (
+    bookmarkFolder?: BookmarkFolderItems,
+    opts?: IDeleteBookmarkFolderModalOption,
+  ) => void;
+  close: () => void;
+};
+
+// Atom for delete bookmark folder modal state
+const deleteBookmarkFolderModalAtom = atom<DeleteBookmarkFolderModalStatus>({
+  isOpened: false,
+});
+
+/**
+ * Hook for managing delete bookmark folder modal state
+ * Returns read-only modal status for optimal performance
+ */
+export const useDeleteBookmarkFolderModalStatus =
+  (): DeleteBookmarkFolderModalStatus => {
+    return useAtomValue(deleteBookmarkFolderModalAtom);
+  };
+
+/**
+ * Hook for managing delete bookmark folder modal actions
+ * Returns actions for opening and closing the modal with stable references
+ */
+export const useDeleteBookmarkFolderModalActions =
+  (): DeleteBookmarkFolderModalActions => {
+    const setStatus = useSetAtom(deleteBookmarkFolderModalAtom);
+
+    const open = useCallback(
+      (
+        bookmarkFolder?: BookmarkFolderItems,
+        opts?: IDeleteBookmarkFolderModalOption,
+      ) => {
+        setStatus({ isOpened: true, bookmarkFolder, opts });
+      },
+      [setStatus],
+    );
+
+    const close = useCallback(() => {
+      setStatus({
+        isOpened: false,
+        bookmarkFolder: undefined,
+        opts: undefined,
+      });
+    }, [setStatus]);
+
+    return { open, close };
+  };

+ 70 - 0
apps/app/src/states/ui/modal/update-user-group-confirm.ts

@@ -0,0 +1,70 @@
+import type { IUserGroupHasId } from '@growi/core';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
+import { useCallback } from 'react';
+
+export type UpdateUserGroupConfirmModalStatus = {
+  isOpened: boolean;
+  targetGroup?: IUserGroupHasId;
+  updateData?: Partial<IUserGroupHasId>;
+  onConfirm?: (
+    targetGroup: IUserGroupHasId,
+    updateData: Partial<IUserGroupHasId>,
+    forceUpdateParents: boolean,
+  ) => Promise<void>;
+};
+
+export type UpdateUserGroupConfirmModalActions = {
+  open: (
+    targetGroup: IUserGroupHasId,
+    updateData: Partial<IUserGroupHasId>,
+    onConfirm?: (...args: unknown[]) => Promise<void>,
+  ) => void;
+  close: () => void;
+};
+
+// Atom for update user group confirm modal state
+const updateUserGroupConfirmModalAtom = atom<UpdateUserGroupConfirmModalStatus>(
+  {
+    isOpened: false,
+  },
+);
+
+/**
+ * Hook for managing update user group confirm modal state
+ * Returns read-only modal status for optimal performance
+ */
+export const useUpdateUserGroupConfirmModalStatus =
+  (): UpdateUserGroupConfirmModalStatus => {
+    return useAtomValue(updateUserGroupConfirmModalAtom);
+  };
+
+/**
+ * Hook for managing update user group confirm modal actions
+ * Returns actions for opening and closing the modal with stable references
+ */
+export const useUpdateUserGroupConfirmModalActions =
+  (): UpdateUserGroupConfirmModalActions => {
+    const setStatus = useSetAtom(updateUserGroupConfirmModalAtom);
+
+    const open = useCallback(
+      (
+        targetGroup: IUserGroupHasId,
+        updateData: Partial<IUserGroupHasId>,
+        onConfirm?: (...args: unknown[]) => Promise<void>,
+      ) => {
+        setStatus({ isOpened: true, targetGroup, updateData, onConfirm });
+      },
+      [setStatus],
+    );
+
+    const close = useCallback(() => {
+      setStatus({
+        isOpened: false,
+        targetGroup: undefined,
+        updateData: undefined,
+        onConfirm: undefined,
+      });
+    }, [setStatus]);
+
+    return { open, close };
+  };