PageAttachment.jsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* eslint-disable react/no-access-state-in-setstate */
  2. import React from 'react';
  3. import PropTypes from 'prop-types';
  4. import { withTranslation } from 'react-i18next';
  5. import PageAttachmentList from './PageAttachment/PageAttachmentList';
  6. import DeleteAttachmentModal from './PageAttachment/DeleteAttachmentModal';
  7. import PaginationWrapper from './PaginationWrapper';
  8. import { withUnstatedContainers } from './UnstatedUtils';
  9. import AppContainer from '../services/AppContainer';
  10. import PageContainer from '../services/PageContainer';
  11. class PageAttachment extends React.Component {
  12. constructor(props) {
  13. super(props);
  14. this.state = {
  15. activePage: 1,
  16. totalAttachments: 0,
  17. limit: Infinity,
  18. attachments: [],
  19. inUse: {},
  20. attachmentToDelete: null,
  21. deleting: false,
  22. deleteError: '',
  23. };
  24. this.handlePage = this.handlePage.bind(this);
  25. this.onAttachmentDeleteClicked = this.onAttachmentDeleteClicked.bind(this);
  26. this.onAttachmentDeleteClickedConfirm = this.onAttachmentDeleteClickedConfirm.bind(this);
  27. }
  28. async handlePage(selectedPage) {
  29. const { pageId } = this.props.pageContainer.state;
  30. const page = selectedPage;
  31. if (!pageId) { return }
  32. const res = await this.props.appContainer.apiv3Get('/attachment/list', { pageId, page });
  33. const attachments = res.data.paginateResult.docs;
  34. const totalAttachments = res.data.paginateResult.totalDocs;
  35. const pagingLimit = res.data.paginateResult.limit;
  36. const inUse = {};
  37. for (const attachment of attachments) {
  38. inUse[attachment._id] = this.checkIfFileInUse(attachment);
  39. }
  40. this.setState({
  41. activePage: selectedPage,
  42. totalAttachments,
  43. limit: pagingLimit,
  44. attachments,
  45. inUse,
  46. });
  47. }
  48. async componentDidMount() {
  49. await this.handlePage(1);
  50. this.setState({
  51. activePage: 1,
  52. });
  53. }
  54. checkIfFileInUse(attachment) {
  55. const { markdown } = this.props.pageContainer.state;
  56. if (markdown.match(attachment._id)) {
  57. return true;
  58. }
  59. return false;
  60. }
  61. onAttachmentDeleteClicked(attachment) {
  62. this.setState({
  63. attachmentToDelete: attachment,
  64. });
  65. }
  66. onAttachmentDeleteClickedConfirm(attachment) {
  67. const attachmentId = attachment._id;
  68. this.setState({
  69. deleting: true,
  70. });
  71. this.props.appContainer.apiPost('/attachments.remove', { attachment_id: attachmentId })
  72. .then((res) => {
  73. this.setState({
  74. attachments: this.state.attachments.filter((at) => {
  75. // comparing ObjectId
  76. // eslint-disable-next-line eqeqeq
  77. return at._id != attachmentId;
  78. }),
  79. attachmentToDelete: null,
  80. deleting: false,
  81. });
  82. }).catch((err) => {
  83. this.setState({
  84. deleteError: 'Something went wrong.',
  85. deleting: false,
  86. });
  87. });
  88. }
  89. isUserLoggedIn() {
  90. return this.props.appContainer.currentUser != null;
  91. }
  92. render() {
  93. const { t } = this.props;
  94. if (this.state.attachments.length === 0) {
  95. return t('No_attachments_yet');
  96. }
  97. let deleteAttachmentModal = '';
  98. if (this.isUserLoggedIn()) {
  99. const attachmentToDelete = this.state.attachmentToDelete;
  100. const deleteModalClose = () => {
  101. this.setState({ attachmentToDelete: null, deleteError: '' });
  102. };
  103. const showModal = attachmentToDelete !== null;
  104. let deleteInUse = null;
  105. if (attachmentToDelete !== null) {
  106. deleteInUse = this.state.inUse[attachmentToDelete._id] || false;
  107. }
  108. deleteAttachmentModal = (
  109. <DeleteAttachmentModal
  110. isOpen={showModal}
  111. animation="false"
  112. toggle={deleteModalClose}
  113. attachmentToDelete={attachmentToDelete}
  114. inUse={deleteInUse}
  115. deleting={this.state.deleting}
  116. deleteError={this.state.deleteError}
  117. onAttachmentDeleteClickedConfirm={this.onAttachmentDeleteClickedConfirm}
  118. />
  119. );
  120. }
  121. return (
  122. <>
  123. <PageAttachmentList
  124. attachments={this.state.attachments}
  125. inUse={this.state.inUse}
  126. onAttachmentDeleteClicked={this.onAttachmentDeleteClicked}
  127. isUserLoggedIn={this.isUserLoggedIn()}
  128. />
  129. {deleteAttachmentModal}
  130. <PaginationWrapper
  131. activePage={this.state.activePage}
  132. changePage={this.handlePage}
  133. totalItemsCount={this.state.totalAttachments}
  134. pagingLimit={this.state.limit}
  135. align="center"
  136. />
  137. </>
  138. );
  139. }
  140. }
  141. /**
  142. * Wrapper component for using unstated
  143. */
  144. const PageAttachmentWrapper = withUnstatedContainers(PageAttachment, [AppContainer, PageContainer]);
  145. PageAttachment.propTypes = {
  146. t: PropTypes.func.isRequired,
  147. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  148. pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
  149. };
  150. export default withTranslation()(PageAttachmentWrapper);