Просмотр исходного кода

integrate delete attachment modal

ryoji-s 2 лет назад
Родитель
Сommit
377781c170

+ 2 - 2
apps/app/src/components/Layout/BasicLayout.tsx

@@ -10,7 +10,7 @@ import Sidebar from '../Sidebar';
 import { RawLayout } from './RawLayout';
 
 const AlertSiteUrlUndefined = dynamic(() => import('../AlertSiteUrlUndefined').then(mod => mod.AlertSiteUrlUndefined), { ssr: false });
-const AttachmentDeleteModal = dynamic(() => import('../PageAttachment/AttachmentDeleteModal').then(mod => mod.AttachmentDeleteModal), { ssr: false });
+const DeleteAttachmentModal = dynamic(() => import('../PageAttachment/DeleteAttachmentModal').then(mod => mod.DeleteAttachmentModal), { ssr: false });
 const HotkeysManager = dynamic(() => import('../Hotkeys/HotkeysManager'), { ssr: false });
 // const PageCreateModal = dynamic(() => import('../client/js/components/PageCreateModal'), { ssr: false });
 const GrowiNavbarBottom = dynamic(() => import('../Navbar/GrowiNavbarBottom').then(mod => mod.GrowiNavbarBottom), { ssr: false });
@@ -56,7 +56,7 @@ export const BasicLayout = ({ children, className }: Props): JSX.Element => {
         <PageDeleteModal />
         <PageRenameModal />
         <PageAccessoriesModal />
-        <AttachmentDeleteModal />
+        <DeleteAttachmentModal />
       </DndProvider>
 
       <PagePresentationModal />

+ 8 - 58
apps/app/src/components/PageAttachment.tsx

@@ -2,13 +2,13 @@ import React, {
   useCallback, useMemo, useState,
 } from 'react';
 
-import { HasObjectId, IAttachment } from '@growi/core';
+import { IAttachmentHasId } from '^/../../packages/core/dist';
 
 import { useSWRxAttachments } from '~/stores/attachment';
 import { useIsGuestUser } from '~/stores/context';
+import { useDeleteAttachmentModal } from '~/stores/modal';
 import { useSWRxCurrentPage, useCurrentPageId } from '~/stores/page';
 
-import { DeleteAttachmentModal } from './PageAttachment/DeleteAttachmentModal';
 import { PageAttachmentList } from './PageAttachment/PageAttachmentList';
 import PaginationWrapper from './PaginationWrapper';
 
@@ -19,21 +19,18 @@ const checkIfFileInUse = (markdown: string, attachment): boolean => {
 
 const PageAttachment = (): JSX.Element => {
 
-  const { data: currentPage } = useSWRxCurrentPage();
-  const markdown = currentPage?.revision.body;
-
   // Static SWRs
   const { data: pageId } = useCurrentPageId();
   const { data: isGuestUser } = useIsGuestUser();
 
   // States
   const [pageNumber, setPageNumber] = useState(1);
-  const [attachmentToDelete, setAttachmentToDelete] = useState<(IAttachment & HasObjectId) | null>(null);
-  const [deleting, setDeleting] = useState(false);
-  const [deleteError, setDeleteError] = useState('');
 
   // SWRs
   const { data: dataAttachments, remove } = useSWRxAttachments(pageId, pageNumber);
+  const { open: openDeleteAttachmentModal } = useDeleteAttachmentModal();
+  const { data: currentPage } = useSWRxCurrentPage();
+  const markdown = currentPage?.revision.body;
 
   // Custom hooks
   const inUseAttachmentsMap: { [id: string]: boolean } | undefined = useMemo(() => {
@@ -54,29 +51,9 @@ const PageAttachment = (): JSX.Element => {
     setPageNumber(newPageNumber);
   }, []);
 
-  const onAttachmentDeleteClicked = useCallback((attachment) => {
-    setAttachmentToDelete(attachment);
-  }, []);
-
-  const onAttachmentDeleteClickedConfirmHandler = useCallback(async(attachment: IAttachment & HasObjectId) => {
-    setDeleting(true);
-
-    try {
-      await remove({ attachment_id: attachment._id });
-
-      setAttachmentToDelete(null);
-      setDeleting(false);
-    }
-    catch {
-      setDeleteError('Something went wrong.');
-      setDeleting(false);
-    }
-  }, [remove]);
-
-  const onToggleHandler = useCallback(() => {
-    setAttachmentToDelete(null);
-    setDeleteError('');
-  }, []);
+  const onAttachmentDeleteClicked = useCallback((attachment: IAttachmentHasId) => {
+    openDeleteAttachmentModal(attachment, remove);
+  }, [openDeleteAttachmentModal, remove]);
 
   // Renderers
   const renderPageAttachmentList = useCallback(() => {
@@ -98,30 +75,6 @@ const PageAttachment = (): JSX.Element => {
     );
   }, [dataAttachments, inUseAttachmentsMap, isGuestUser, onAttachmentDeleteClicked]);
 
-  const renderDeleteAttachmentModal = useCallback(() => {
-    if (isGuestUser) {
-      return <></>;
-    }
-
-    if (dataAttachments == null || dataAttachments.attachments.length === 0 || attachmentToDelete == null) {
-      return <></>;
-    }
-
-    const isOpen = attachmentToDelete != null;
-
-    return (
-      <DeleteAttachmentModal
-        isOpen={isOpen}
-        toggle={onToggleHandler}
-        attachmentToDelete={attachmentToDelete}
-        deleting={deleting}
-        deleteError={deleteError}
-        onAttachmentDeleteClickedConfirm={onAttachmentDeleteClickedConfirmHandler}
-      />
-    );
-  // eslint-disable-next-line max-len
-  }, [attachmentToDelete, dataAttachments, deleteError, deleting, isGuestUser, onAttachmentDeleteClickedConfirmHandler, onToggleHandler]);
-
   const renderPaginationWrapper = useCallback(() => {
     if (dataAttachments == null || dataAttachments.attachments.length === 0) {
       return <></>;
@@ -141,9 +94,6 @@ const PageAttachment = (): JSX.Element => {
   return (
     <div data-testid="page-attachment">
       {renderPageAttachmentList()}
-
-      {renderDeleteAttachmentModal()}
-
       {renderPaginationWrapper()}
     </div>
   );

+ 4 - 4
apps/app/src/components/PageAttachment/AttachmentDeleteModal.tsx

@@ -26,10 +26,10 @@ export const AttachmentDeleteModal: React.FC = () => {
   const [deleting, setDeleting] = useState<boolean>(false);
   const [deleteError, setDeleteError] = useState<string>('');
 
-  const { data: attachmentDeleteModal, close: closeAttachmentDeleteModal } = useAttachmentDeleteModal();
-  const isOpen = attachmentDeleteModal?.isOpened;
-  const attachment = attachmentDeleteModal?.attachment;
-  const remove = attachmentDeleteModal?.remove;
+  const { data: deleteAttachmentModal, close: closeAttachmentDeleteModal } = useAttachmentDeleteModal();
+  const isOpen = deleteAttachmentModal?.isOpened;
+  const attachment = deleteAttachmentModal?.attachment;
+  const remove = deleteAttachmentModal?.remove;
 
   const toggleHandler = useCallback(() => {
     closeAttachmentDeleteModal();

+ 0 - 106
apps/app/src/components/PageAttachment/DeleteAttachmentModal.tsx

@@ -1,106 +0,0 @@
-/* eslint-disable react/prop-types */
-import React, { useCallback } from 'react';
-
-import { HasObjectId, IAttachment } from '@growi/core';
-import { UserPicture } from '@growi/ui/dist/components/User/UserPicture';
-import {
-  Button,
-  Modal, ModalHeader, ModalBody, ModalFooter,
-} from 'reactstrap';
-
-import { Username } from '../User/Username';
-
-import styles from './DeleteAttachmentModal.module.scss';
-
-
-function iconNameByFormat(format: string): string {
-  if (format.match(/image\/.+/i)) {
-    return 'icon-picture';
-  }
-
-  return 'icon-doc';
-}
-
-
-type Props = {
-  isOpen: boolean,
-  toggle: () => void,
-  attachmentToDelete: IAttachment & HasObjectId | null,
-  deleting: boolean,
-  deleteError: string,
-  onAttachmentDeleteClickedConfirm?: (attachment: IAttachment & HasObjectId) => Promise<void>,
-}
-
-export const DeleteAttachmentModal = (props: Props): JSX.Element => {
-
-  const {
-    isOpen, toggle,
-    attachmentToDelete, deleting, deleteError,
-    onAttachmentDeleteClickedConfirm,
-  } = props;
-
-  const onDeleteConfirm = useCallback(() => {
-    if (attachmentToDelete == null || onAttachmentDeleteClickedConfirm == null) {
-      return;
-    }
-    onAttachmentDeleteClickedConfirm(attachmentToDelete);
-  }, [attachmentToDelete, onAttachmentDeleteClickedConfirm]);
-
-  const renderByFileFormat = useCallback((attachment) => {
-    const content = (attachment.fileFormat.match(/image\/.+/i))
-      // eslint-disable-next-line @next/next/no-img-element
-      ? <img src={attachment.filePathProxied} alt="deleting image" />
-      : '';
-
-
-    return (
-      <div className="attachment-delete-image">
-        <p>
-          <i className={iconNameByFormat(attachment.fileFormat)}></i> {attachment.originalName}
-        </p>
-        <p>
-          uploaded by <UserPicture user={attachment.creator} size="sm"></UserPicture> <Username user={attachment.creator}></Username>
-        </p>
-        {content}
-      </div>
-    );
-  }, []);
-
-  let deletingIndicator = <></>;
-  if (deleting) {
-    deletingIndicator = <div className="speeding-wheel-sm"></div>;
-  }
-  if (deleteError) {
-    deletingIndicator = <span>{deleteError}</span>;
-  }
-
-
-  return (
-    <Modal
-      isOpen={isOpen}
-      className={`${styles['attachment-delete-modal']} attachment-delete-modal`}
-      size="lg"
-      aria-labelledby="contained-modal-title-lg"
-      fade={false}
-    >
-      <ModalHeader tag="h4" toggle={toggle} className="bg-danger text-light">
-        <span id="contained-modal-title-lg">Delete attachment?</span>
-      </ModalHeader>
-      <ModalBody>
-        {renderByFileFormat(attachmentToDelete)}
-      </ModalBody>
-      <ModalFooter>
-        <div className="mr-3 d-inline-block">
-          {deletingIndicator}
-        </div>
-        <Button
-          color="danger"
-          onClick={onDeleteConfirm}
-          disabled={deleting}
-        >Delete!
-        </Button>
-      </ModalFooter>
-    </Modal>
-  );
-
-};

+ 1 - 1
apps/app/src/components/PageAttachment/PageAttachmentList.tsx

@@ -7,7 +7,7 @@ import { useTranslation } from 'next-i18next';
 type Props = {
   attachments: (IAttachment & HasObjectId)[],
   inUse: { [id: string]: boolean },
-  onAttachmentDeleteClicked?: (attachment: IAttachment & HasObjectId) => void,
+  onAttachmentDeleteClicked: (attachment: IAttachment & HasObjectId) => void,
   isUserLoggedIn?: boolean,
 }
 

+ 4 - 4
apps/app/src/components/ReactMarkdownComponents/Attachment.tsx

@@ -4,7 +4,7 @@ import { UserPicture } from '@growi/ui/dist/components/User/UserPicture';
 import prettyBytes from 'pretty-bytes';
 
 import { useSWRxAttachment } from '~/stores/attachment';
-import { useAttachmentDeleteModal } from '~/stores/modal';
+import { useDeleteAttachmentModal } from '~/stores/modal';
 
 export const Attachment: React.FC<{
   attachmentId: string,
@@ -12,13 +12,13 @@ export const Attachment: React.FC<{
   attachmentName: string
 }> = React.memo(({ attachmentId, url, attachmentName }) => {
   const { data: attachment, remove } = useSWRxAttachment(attachmentId);
-  const { open: openAttachmentDeleteModal } = useAttachmentDeleteModal();
+  const { open: openDeleteAttachmentModal } = useDeleteAttachmentModal();
   const onClickTrashButtonHandler = useCallback(() => {
     if (attachment == null) {
       return;
     }
-    openAttachmentDeleteModal(attachment, remove);
-  }, [attachment, openAttachmentDeleteModal, remove]);
+    openDeleteAttachmentModal(attachment, remove);
+  }, [attachment, openDeleteAttachmentModal, remove]);
 
   if (attachment == null) {
     return (

+ 6 - 6
apps/app/src/stores/modal.tsx

@@ -610,20 +610,20 @@ export const useTemplateModal = (): SWRResponse<TemplateModalStatus, Error> & Te
 };
 
 /**
- * AttachmentDeleteModal
+ * DeleteAttachmentModal
  */
 type Remove =
   (body: {
     attachment_id: string;
   }) => Promise<void>
 
-type AttachmentDeleteModalStatus = {
+type DeleteAttachmentModalStatus = {
   isOpened: boolean,
   attachment?: IAttachmentHasId,
   remove?: Remove,
 }
 
-type AttachmentDeleteModalUtils = {
+type DeleteAttachmentModalUtils = {
   open(
     attachment: IAttachmentHasId,
     remove: Remove,
@@ -631,13 +631,13 @@ type AttachmentDeleteModalUtils = {
   close(): void,
 }
 
-export const useAttachmentDeleteModal = (): SWRResponse<AttachmentDeleteModalStatus, Error> & AttachmentDeleteModalUtils => {
-  const initialStatus: AttachmentDeleteModalStatus = {
+export const useDeleteAttachmentModal = (): SWRResponse<DeleteAttachmentModalStatus, Error> & DeleteAttachmentModalUtils => {
+  const initialStatus: DeleteAttachmentModalStatus = {
     isOpened: false,
     attachment: undefined,
     remove: undefined,
   };
-  const swrResponse = useStaticSWR<AttachmentDeleteModalStatus, Error>('attachmentDeleteModal', undefined, { fallbackData: initialStatus });
+  const swrResponse = useStaticSWR<DeleteAttachmentModalStatus, Error>('deleteAttachmentModal', undefined, { fallbackData: initialStatus });
   const { mutate } = swrResponse;
 
   const open = useCallback((attachment: IAttachmentHasId, remove: Remove) => {

+ 2 - 4
packages/ui/src/components/Attachment.tsx

@@ -5,7 +5,7 @@ import { UserPicture } from './User/UserPicture';
 type AttachmentProps = {
   attachment: IAttachmentHasId,
   inUse: boolean,
-  onAttachmentDeleteClicked?: (attachment: IAttachmentHasId) => void,
+  onAttachmentDeleteClicked: (attachment: IAttachmentHasId) => void,
   isUserLoggedIn?: boolean,
 };
 
@@ -16,9 +16,7 @@ export const Attachment = (props: AttachmentProps): JSX.Element => {
   } = props;
 
   const _onAttachmentDeleteClicked = () => {
-    if (onAttachmentDeleteClicked != null) {
-      onAttachmentDeleteClicked(attachment);
-    }
+    onAttachmentDeleteClicked(attachment);
   };
 
   const formatIcon = (attachment.fileFormat.match(/image\/.+/i)) ? 'icon-picture' : 'icon-doc';