PageSelectModal.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import type { FC } from 'react';
  2. import { Suspense, useState, useCallback } from 'react';
  3. import nodePath from 'path';
  4. import type { Nullable } from '@growi/core';
  5. import { useTranslation } from 'next-i18next';
  6. import {
  7. Modal, ModalHeader, ModalBody, ModalFooter, Button,
  8. } from 'reactstrap';
  9. import type { IPageForItem } from '~/interfaces/page';
  10. import { useTargetAndAncestors, useIsGuestUser, useIsReadOnlyUser } from '~/stores/context';
  11. import { usePageSelectModal } from '~/stores/modal';
  12. import { useCurrentPagePath, useCurrentPageId, useSWRxCurrentPage } from '~/stores/page';
  13. import { ItemsTree } from '../ItemsTree';
  14. import ItemsTreeContentSkeleton from '../ItemsTree/ItemsTreeContentSkeleton';
  15. import { usePagePathRenameHandler } from '../PageEditor/page-path-rename-utils';
  16. import type { ItemNode } from '../TreeItem';
  17. import { TreeItemForModal } from './TreeItemForModal';
  18. export const PageSelectModal: FC = () => {
  19. const {
  20. data: PageSelectModalData,
  21. close: closeModal,
  22. } = usePageSelectModal();
  23. const isOpened = PageSelectModalData?.isOpened ?? false;
  24. const [clickedParentPagePath, setClickedParentPagePath] = useState<string | null>(null);
  25. const { t } = useTranslation();
  26. const { data: isGuestUser } = useIsGuestUser();
  27. const { data: isReadOnlyUser } = useIsReadOnlyUser();
  28. const { data: currentPath } = useCurrentPagePath();
  29. const { data: targetId } = useCurrentPageId();
  30. const { data: targetAndAncestorsData } = useTargetAndAncestors();
  31. const { data: currentPage } = useSWRxCurrentPage();
  32. const pagePathRenameHandler = usePagePathRenameHandler(currentPage);
  33. const onClickTreeItem = useCallback((page: IPageForItem) => {
  34. const parentPagePath = page.path;
  35. if (parentPagePath == null) {
  36. return;
  37. }
  38. setClickedParentPagePath(parentPagePath);
  39. }, []);
  40. const onClickCancel = useCallback(() => {
  41. setClickedParentPagePath(null);
  42. closeModal();
  43. }, [closeModal]);
  44. const onClickDone = useCallback(() => {
  45. if (clickedParentPagePath != null) {
  46. const currentPageTitle = nodePath.basename(currentPage?.path ?? '') || '/';
  47. const newPagePath = nodePath.resolve(clickedParentPagePath, currentPageTitle);
  48. pagePathRenameHandler(newPagePath);
  49. }
  50. closeModal();
  51. }, [clickedParentPagePath, closeModal, currentPage?.path, pagePathRenameHandler]);
  52. const targetPathOrId = targetId || currentPath;
  53. const path = currentPath || '/';
  54. if (isGuestUser == null) {
  55. return null;
  56. }
  57. const markTarget = (children: ItemNode[], targetPathOrId?: Nullable<string>): void => {
  58. if (targetPathOrId == null) {
  59. return;
  60. }
  61. children.forEach((node) => {
  62. if (node.page._id === targetPathOrId || node.page.path === targetPathOrId) {
  63. node.page.isTarget = true;
  64. }
  65. else {
  66. node.page.isTarget = false;
  67. }
  68. return node;
  69. });
  70. };
  71. return (
  72. <Modal
  73. isOpen={isOpened}
  74. toggle={closeModal}
  75. centered
  76. size="sm"
  77. >
  78. <ModalHeader toggle={closeModal}>{t('page_select_modal.select_page_location')}</ModalHeader>
  79. <ModalBody>
  80. <Suspense fallback={<ItemsTreeContentSkeleton />}>
  81. <ItemsTree
  82. CustomTreeItem={TreeItemForModal}
  83. isEnableActions={!isGuestUser}
  84. isReadOnlyUser={!!isReadOnlyUser}
  85. targetPath={path}
  86. targetPathOrId={targetPathOrId}
  87. targetAndAncestorsData={targetAndAncestorsData}
  88. onClickTreeItem={onClickTreeItem}
  89. />
  90. </Suspense>
  91. </ModalBody>
  92. <ModalFooter>
  93. <Button color="secondary" onClick={onClickCancel}>{t('Cancel')}</Button>
  94. <Button color="primary" onClick={onClickDone}>{t('Done')}</Button>
  95. </ModalFooter>
  96. </Modal>
  97. );
  98. };