PageAccessoriesModal.jsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import React, { useCallback, useMemo, useState } from 'react';
  2. import PropTypes from 'prop-types';
  3. import {
  4. Modal, ModalBody, ModalHeader, TabContent, TabPane,
  5. } from 'reactstrap';
  6. import { withTranslation } from 'react-i18next';
  7. import PageListIcon from './Icons/PageListIcon';
  8. import TimeLineIcon from './Icons/TimeLineIcon';
  9. import HistoryIcon from './Icons/HistoryIcon';
  10. import AttachmentIcon from './Icons/AttachmentIcon';
  11. import ShareLinkIcon from './Icons/ShareLinkIcon';
  12. import { withUnstatedContainers } from './UnstatedUtils';
  13. import PageContainer from '~/client/services/PageContainer';
  14. import PageAccessoriesContainer from '~/client/services/PageAccessoriesContainer';
  15. import PageAttachment from './PageAttachment';
  16. import PageTimeline from './PageTimeline';
  17. import DescendantsPageList from './DescendantsPageList';
  18. import PageHistory from './PageHistory';
  19. import ShareLink from './ShareLink/ShareLink';
  20. import { CustomNavTab } from './CustomNavigation/CustomNav';
  21. import ExpandOrContractButton from './ExpandOrContractButton';
  22. const PageAccessoriesModal = (props) => {
  23. const {
  24. t, pageContainer, pageAccessoriesContainer, onClose, isGuestUser, isSharedUser,
  25. } = props;
  26. const isLinkSharingDisabled = pageAccessoriesContainer.appContainer.config.disableLinkSharing;
  27. const { switchActiveTab } = pageAccessoriesContainer;
  28. const { activeTab, activeComponents } = pageAccessoriesContainer.state;
  29. const [isWindowExpanded, setIsWindowExpanded] = useState(false);
  30. const navTabMapping = useMemo(() => {
  31. return {
  32. pagelist: {
  33. Icon: PageListIcon,
  34. i18n: t('page_list'),
  35. index: 0,
  36. isLinkEnabled: v => !isSharedUser,
  37. },
  38. timeline: {
  39. Icon: TimeLineIcon,
  40. i18n: t('Timeline View'),
  41. index: 1,
  42. isLinkEnabled: v => !isSharedUser,
  43. },
  44. pageHistory: {
  45. Icon: HistoryIcon,
  46. i18n: t('History'),
  47. index: 2,
  48. isLinkEnabled: v => !isGuestUser && !isSharedUser,
  49. },
  50. attachment: {
  51. Icon: AttachmentIcon,
  52. i18n: t('attachment_data'),
  53. index: 3,
  54. },
  55. shareLink: {
  56. Icon: ShareLinkIcon,
  57. i18n: t('share_links.share_link_management'),
  58. index: 4,
  59. isLinkEnabled: v => !isGuestUser && !isSharedUser && !isLinkSharingDisabled,
  60. },
  61. };
  62. }, [t, isGuestUser, isSharedUser, isLinkSharingDisabled]);
  63. const closeModalHandler = useCallback(() => {
  64. if (onClose == null) {
  65. return;
  66. }
  67. onClose();
  68. }, [onClose]);
  69. const expandWindow = () => {
  70. setIsWindowExpanded(true);
  71. };
  72. const contractWindow = () => {
  73. setIsWindowExpanded(false);
  74. };
  75. const buttons = (
  76. <div className="d-flex flex-nowrap">
  77. <ExpandOrContractButton
  78. isWindowExpanded={isWindowExpanded}
  79. expandWindow={expandWindow}
  80. contractWindow={contractWindow}
  81. />
  82. <button type="button" className="close" onClick={closeModalHandler} aria-label="Close">
  83. <span aria-hidden="true">&times;</span>
  84. </button>
  85. </div>
  86. );
  87. return (
  88. <React.Fragment>
  89. <Modal
  90. size="xl"
  91. isOpen={props.isOpen}
  92. toggle={closeModalHandler}
  93. className={`grw-page-accessories-modal ${isWindowExpanded ? 'grw-modal-expanded' : ''} `}
  94. >
  95. <ModalHeader className="p-0" toggle={closeModalHandler} close={buttons}>
  96. <CustomNavTab
  97. activeTab={activeTab}
  98. navTabMapping={navTabMapping}
  99. onNavSelected={switchActiveTab}
  100. breakpointToHideInactiveTabsDown="md"
  101. hideBorderBottom
  102. />
  103. </ModalHeader>
  104. <ModalBody className="overflow-auto grw-modal-body-style">
  105. {/* Do not use CustomTabContent because of performance problem:
  106. the 'navTabMapping[tabId].Content' for PageAccessoriesModal depends on activeComponents */}
  107. <TabContent activeTab={activeTab}>
  108. <TabPane tabId="pagelist">
  109. {activeComponents.has('pagelist') && <DescendantsPageList path={pageContainer.state.path} />}
  110. </TabPane>
  111. <TabPane tabId="timeline">
  112. {activeComponents.has('timeline') && <PageTimeline /> }
  113. </TabPane>
  114. {!isGuestUser && (
  115. <TabPane tabId="pageHistory">
  116. {activeComponents.has('pageHistory') && <PageHistory /> }
  117. </TabPane>
  118. )}
  119. <TabPane tabId="attachment">
  120. {activeComponents.has('attachment') && <PageAttachment />}
  121. </TabPane>
  122. {!isGuestUser && (
  123. <TabPane tabId="shareLink">
  124. {activeComponents.has('shareLink') && <ShareLink />}
  125. </TabPane>
  126. )}
  127. </TabContent>
  128. </ModalBody>
  129. </Modal>
  130. </React.Fragment>
  131. );
  132. };
  133. /**
  134. * Wrapper component for using unstated
  135. */
  136. const PageAccessoriesModalWrapper = withUnstatedContainers(PageAccessoriesModal, [PageContainer, PageAccessoriesContainer]);
  137. PageAccessoriesModal.propTypes = {
  138. t: PropTypes.func.isRequired, // i18next
  139. pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
  140. pageAccessoriesContainer: PropTypes.instanceOf(PageAccessoriesContainer).isRequired,
  141. isGuestUser: PropTypes.bool.isRequired,
  142. isSharedUser: PropTypes.bool.isRequired,
  143. isOpen: PropTypes.bool.isRequired,
  144. onClose: PropTypes.func,
  145. };
  146. export default withTranslation()(PageAccessoriesModalWrapper);