PageAccessoriesModal.jsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 PageAccessoriesContainer from '../services/PageAccessoriesContainer';
  14. import PageAttachment from './PageAttachment';
  15. import PageTimeline from './PageTimeline';
  16. import PageList from './PageList';
  17. import PageHistory from './PageHistory';
  18. import ShareLink from './ShareLink/ShareLink';
  19. import { CustomNavTab } from './CustomNavigation/CustomNav';
  20. import ExpandOrContractButton from './ExpandOrContractButton';
  21. const PageAccessoriesModal = (props) => {
  22. const {
  23. t, pageAccessoriesContainer, onClose, isGuestUser, isSharedUser, isNotFoundPage,
  24. } = props;
  25. const isLinkSharingDisabled = pageAccessoriesContainer.appContainer.config.disableLinkSharing;
  26. const { switchActiveTab } = pageAccessoriesContainer;
  27. const { activeTab, activeComponents } = pageAccessoriesContainer.state;
  28. const [isWindowExpanded, setIsWindowExpanded] = useState(false);
  29. const navTabMapping = useMemo(() => {
  30. return {
  31. pagelist: {
  32. Icon: PageListIcon,
  33. i18n: t('page_list'),
  34. index: 0,
  35. isLinkEnabled: v => !isSharedUser,
  36. },
  37. timeline: {
  38. Icon: TimeLineIcon,
  39. i18n: t('Timeline View'),
  40. index: 1,
  41. isLinkEnabled: v => !isSharedUser,
  42. },
  43. pageHistory: {
  44. Icon: HistoryIcon,
  45. i18n: t('History'),
  46. index: 2,
  47. isLinkEnabled: v => !isGuestUser && !isSharedUser && !isNotFoundPage,
  48. },
  49. attachment: {
  50. Icon: AttachmentIcon,
  51. i18n: t('attachment_data'),
  52. index: 3,
  53. isLinkEnabled: v => !isNotFoundPage,
  54. },
  55. shareLink: {
  56. Icon: ShareLinkIcon,
  57. i18n: t('share_links.share_link_management'),
  58. index: 4,
  59. isLinkEnabled: v => !isGuestUser && !isSharedUser && !isNotFoundPage && !isLinkSharingDisabled,
  60. },
  61. };
  62. }, [t, isGuestUser, isSharedUser, isNotFoundPage, 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') && <PageList />}
  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, [PageAccessoriesContainer]);
  137. PageAccessoriesModal.propTypes = {
  138. t: PropTypes.func.isRequired, // i18next
  139. pageAccessoriesContainer: PropTypes.instanceOf(PageAccessoriesContainer).isRequired,
  140. isGuestUser: PropTypes.bool.isRequired,
  141. isSharedUser: PropTypes.bool.isRequired,
  142. isNotFoundPage: PropTypes.bool.isRequired,
  143. isOpen: PropTypes.bool.isRequired,
  144. onClose: PropTypes.func,
  145. };
  146. export default withTranslation()(PageAccessoriesModalWrapper);