TrashPageAlert.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import React, { useCallback } from 'react';
  2. import { UserPicture } from '@growi/ui/dist/components/User/UserPicture';
  3. import { format } from 'date-fns';
  4. import { useRouter } from 'next/router';
  5. import { useTranslation } from 'react-i18next';
  6. import { unlink } from '~/client/services/page-operation';
  7. import { toastError } from '~/client/util/toastr';
  8. import { usePageDeleteModal, usePutBackPageModal } from '~/stores/modal';
  9. import {
  10. useCurrentPagePath, useSWRxPageInfo, useSWRxCurrentPage, useIsTrashPage,
  11. } from '~/stores/page';
  12. import { useIsAbleToShowTrashPageManagementButtons } from '~/stores/ui';
  13. import { useCurrentUser } from '~/stores/context';
  14. import { useSWRxBookmarkFolderAndChild } from '~/stores/bookmark-folder';
  15. import { useSWRxUserBookmarks } from '~/stores/bookmark';
  16. const onDeletedHandler = (pathOrPathsToDelete) => {
  17. if (typeof pathOrPathsToDelete !== 'string') {
  18. return;
  19. }
  20. window.location.href = '/';
  21. };
  22. export const TrashPageAlert = (): JSX.Element => {
  23. const { t } = useTranslation();
  24. const router = useRouter();
  25. const { data: isAbleToShowTrashPageManagementButtons } = useIsAbleToShowTrashPageManagementButtons();
  26. const { data: pageData } = useSWRxCurrentPage();
  27. const { data: isTrashPage } = useIsTrashPage();
  28. const pageId = pageData?._id;
  29. const pagePath = pageData?.path;
  30. const { data: pageInfo } = useSWRxPageInfo(pageId ?? null);
  31. const { open: openDeleteModal } = usePageDeleteModal();
  32. const { open: openPutBackPageModal } = usePutBackPageModal();
  33. const { data: currentPagePath } = useCurrentPagePath();
  34. const { data: currentUser } = useCurrentUser();
  35. const { mutate: mutateBookmarkFolders } = useSWRxBookmarkFolderAndChild(currentUser?._id);
  36. const { mutate: mutateUserBookmarks } = useSWRxUserBookmarks(currentUser?._id);
  37. const deleteUser = pageData?.deleteUser;
  38. const deletedAt = pageData?.deletedAt ? format(new Date(pageData?.deletedAt), 'yyyy/MM/dd HH:mm') : '';
  39. const revisionId = pageData?.revision?._id;
  40. const openPutbackPageModalHandler = useCallback(() => {
  41. if (pageId == null || pagePath == null) {
  42. return;
  43. }
  44. const putBackedHandler = () => {
  45. if (currentPagePath == null) {
  46. return;
  47. }
  48. try {
  49. unlink(currentPagePath);
  50. mutateBookmarkFolders();
  51. mutateUserBookmarks();
  52. router.push(`/${pageId}`);
  53. }
  54. catch (err) {
  55. toastError(err);
  56. }
  57. };
  58. openPutBackPageModal({ pageId, path: pagePath }, { onPutBacked: putBackedHandler });
  59. }, [currentPagePath, openPutBackPageModal, pageId, pagePath, router, mutateBookmarkFolders, mutateUserBookmarks]);
  60. const openPageDeleteModalHandler = useCallback(() => {
  61. if (pageId === undefined || revisionId === undefined || pagePath === undefined) {
  62. return;
  63. }
  64. const pageToDelete = {
  65. data: {
  66. _id: pageId,
  67. revision: revisionId,
  68. path: pagePath,
  69. },
  70. meta: pageInfo,
  71. };
  72. openDeleteModal([pageToDelete], { onDeleted: onDeletedHandler });
  73. }, [openDeleteModal, pageId, pageInfo, pagePath, revisionId]);
  74. const renderTrashPageManagementButtons = useCallback(() => {
  75. return (
  76. <>
  77. <button
  78. type="button"
  79. className="btn btn-info rounded-pill btn-sm ml-auto mr-2"
  80. onClick={openPutbackPageModalHandler}
  81. data-toggle="modal"
  82. data-testid="put-back-button"
  83. >
  84. <i className="icon-action-undo" aria-hidden="true"></i> { t('Put Back') }
  85. </button>
  86. <button
  87. type="button"
  88. className="btn btn-danger rounded-pill btn-sm"
  89. disabled={!(pageInfo?.isAbleToDeleteCompletely ?? false)}
  90. onClick={openPageDeleteModalHandler}
  91. >
  92. <i className="icon-fire" aria-hidden="true"></i> { t('Delete Completely') }
  93. </button>
  94. </>
  95. );
  96. }, [openPageDeleteModalHandler, openPutbackPageModalHandler, pageInfo?.isAbleToDeleteCompletely, t]);
  97. if (!isTrashPage) {
  98. return <></>;
  99. }
  100. return (
  101. <>
  102. <div className="alert alert-warning py-3 pl-4 d-flex flex-column flex-lg-row" data-testid="trash-page-alert">
  103. <div className="flex-grow-1">
  104. This page is in the trash <i className="icon-trash" aria-hidden="true"></i>.
  105. <br />
  106. <UserPicture user={deleteUser} />
  107. <span className="ml-2">
  108. Deleted by { deleteUser?.name } at <span data-vrt-blackout-datetime>{deletedAt ?? pageData?.updatedAt}</span>
  109. </span>
  110. </div>
  111. <div className="pt-1 d-flex align-items-end align-items-lg-center">
  112. { isAbleToShowTrashPageManagementButtons && renderTrashPageManagementButtons()}
  113. </div>
  114. </div>
  115. </>
  116. );
  117. };